0c3ca309eec8ba495fd367ea4ac4e6fb69af8aaa
[webi-installers/.git] / mariadb / releases.js
1 'use strict';
2
3 var brewReleases = require('../_common/brew.js');
4
5 module.exports = function (request) {
6   // So many places to get (incomplete) release info...
7   //
8   // MariaDB official
9   // - https://downloads.mariadb.org/mariadb/+releases/
10   // - http://archive.mariadb.org/
11   // Brew
12   // - https://formulae.brew.sh/api/formula/mariadb@10.3.json
13   // - https://formulae.brew.sh/docs/api/
14   // - https://formulae.brew.sh/formula/mariadb@10.2#default
15   //
16   // Note: This could be very fragile due to using the html
17   // as an API. It's pretty rather than minified, but that
18   // doesn't guarantee that it's meant as a consumable API.
19   //
20
21   var promises = [mariaReleases(), brewReleases(request, 'mariadb')];
22   return Promise.all(promises).then(function (many) {
23     var versions = many[0];
24     var brews = many[1];
25
26     var all = { download: '', releases: [] };
27
28     // linux x86
29     // linux x64
30     // windows x86
31     // windows x64
32     // (and mac, wedged-in from Homebrew)
33     versions.forEach(function (ver) {
34       all.releases.push({
35         version: ver.version,
36         lts: false,
37         channel: ver.channel,
38         date: ver.date,
39         os: 'linux',
40         arch: 'amd64',
41         download: 'http://archive.mariadb.org/mariadb-{{ v }}/bintar-linux-x86_64/mariadb-{{ v }}-linux-x86_64.tar.gz'.replace(
42           /{{ v }}/g,
43           ver.version
44         )
45       });
46       all.releases.push({
47         version: ver.version,
48         lts: false,
49         channel: ver.channel,
50         date: ver.date,
51         os: 'linux',
52         arch: 'amd64',
53         download: 'http://archive.mariadb.org/mariadb-{{ v }}/bintar-linux-x86/mariadb-{{ v }}-linux-x86.tar.gz'.replace(
54           /{{ v }}/g,
55           ver.version
56         )
57       });
58
59       // windows
60       all.releases.push({
61         version: ver.version,
62         lts: false,
63         channel: ver.channel,
64         date: ver.date,
65         os: 'windows',
66         arch: 'amd64',
67         download: 'http://archive.mariadb.org/mariadb-{{ v }}/winx64-packages/mariadb-{{ v }}-winx64.zip'.replace(
68           /{{ v }}/g,
69           ver.version
70         )
71       });
72       all.releases.push({
73         version: ver.version,
74         lts: false,
75         channel: ver.channel,
76         date: ver.date,
77         os: 'windows',
78         arch: 'x86',
79         download: 'http://archive.mariadb.org/mariadb-{{ v }}/win32-packages/mariadb-{{ v }}-win32.zip'.replace(
80           /{{ v }}/g,
81           ver.version
82         )
83       });
84
85       // Note: versions are sorted most-recent first.
86       // We just assume that the brew version is most recent stable
87       // ... but we can't really know for sure
88
89       // TODO
90       brews.some(function (brew, i) {
91         // 10.3 => ^10.2(\b|\.)
92         var reBrewVer = new RegExp(
93           '^' + brew.version.replace(/\./, '\\.') + '(\\b|\\.)',
94           'g'
95         );
96         if (!ver.version.match(reBrewVer)) {
97           return;
98         }
99         all.releases.push({
100           version: ver.version,
101           lts: false,
102           channel: ver.channel,
103           date: ver.date,
104           os: 'macos',
105           arch: 'amd64',
106           download: brew.download.replace(/{{ v }}/g, ver.version)
107         });
108         brews.splice(i, 1); // remove
109         return true;
110       });
111     });
112
113     return all;
114   });
115
116   function mariaReleases() {
117     return request({
118       url: 'https://downloads.mariadb.org/mariadb/+releases/',
119       fail: true // https://git.coolaj86.com/coolaj86/request.js/issues/2
120     })
121       .then(failOnBadStatus)
122       .then(function (resp) {
123         // fragile, but simple
124
125         // Make release info go from this:
126         var html = resp.body;
127         //
128         // <tr>
129         //   <td><a href="/mariadb/10.0.38/">10.0.38</a></td>
130         //   <td>2019-01-31</td>
131         //   <td>Stable</td>
132         // </tr>
133
134         // To this:
135         var reLine = /\s*(<(tr|td)[^>]*>)\s*/g;
136         //
137         // <tr><tr><td><a href="/mariadb/10.0.38/">10.0.38</a></td><td>2019-01-31</td><td>Stable</td>
138         // </tr><tr><td><a href="/mariadb/10.0.37/">10.0.37</a></td><td>2018-11-01</td><td>Stable</td>
139         // </tr><tr><td><a href="/mariadb/10.0.36/">10.0.36</a></td><td>2018-08-01</td><td>Stable</td>
140         //
141         // To this:
142         var reVer = /<tr>.*mariadb\/(10[^\/]+)\/">.*(20\d\d-\d\d-\d\d)<\/td><td>(\w+)<\/td>/;
143         //
144         // { "version": "10.0.36", "date": "2018-08-01", "channel": "stable" }
145
146         return html
147           .replace(reLine, '$1')
148           .split(/\n/)
149           .map(function (line) {
150             var m = line.match(reVer);
151             if (!m) {
152               return;
153             }
154             return {
155               version: m[1],
156               channel: mapChannel(m[3].toLowerCase()),
157               date: m[2]
158             };
159           })
160           .filter(Boolean);
161       })
162       .catch(function (err) {
163         console.error('Error fetching (official) MariaDB versions');
164         console.error(err);
165         return [];
166       });
167   }
168 };
169
170 function mapChannel(ch) {
171   if ('alpha' === ch) {
172     return 'dev';
173   }
174   // stable,rc,beta
175   return ch;
176 }
177
178 function failOnBadStatus(resp) {
179   if (resp.statusCode >= 400) {
180     var err = new Error('Non-successful status code: ' + resp.statusCode);
181     err.code = 'ESTATUS';
182     err.response = resp;
183     throw err;
184   }
185   return resp;
186 }
187
188 if (module === require.main) {
189   module.exports(require('@root/request')).then(function (all) {
190     console.info('official releases look like:');
191     console.info(JSON.stringify(all.releases.slice(0, 2), null, 2));
192     console.info('Homebrew releases look like:');
193     console.info(
194       JSON.stringify(
195         all.releases
196           .filter(function (rel) {
197             return 'macos' === rel.os;
198           })
199           .slice(0, 2),
200         null,
201         2
202       )
203     );
204   });
205 }