chore: make Prettier + fix spelling, update upgrade/switch instructions, prefer ale...
[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:
42           'http://archive.mariadb.org/mariadb-{{ v }}/bintar-linux-x86_64/mariadb-{{ v }}-linux-x86_64.tar.gz'.replace(
43             /{{ v }}/g,
44             ver.version
45           )
46       });
47       all.releases.push({
48         version: ver.version,
49         lts: false,
50         channel: ver.channel,
51         date: ver.date,
52         os: 'linux',
53         arch: 'amd64',
54         download:
55           'http://archive.mariadb.org/mariadb-{{ v }}/bintar-linux-x86/mariadb-{{ v }}-linux-x86.tar.gz'.replace(
56             /{{ v }}/g,
57             ver.version
58           )
59       });
60
61       // windows
62       all.releases.push({
63         version: ver.version,
64         lts: false,
65         channel: ver.channel,
66         date: ver.date,
67         os: 'windows',
68         arch: 'amd64',
69         download:
70           'http://archive.mariadb.org/mariadb-{{ v }}/winx64-packages/mariadb-{{ v }}-winx64.zip'.replace(
71             /{{ v }}/g,
72             ver.version
73           )
74       });
75       all.releases.push({
76         version: ver.version,
77         lts: false,
78         channel: ver.channel,
79         date: ver.date,
80         os: 'windows',
81         arch: 'x86',
82         download:
83           'http://archive.mariadb.org/mariadb-{{ v }}/win32-packages/mariadb-{{ v }}-win32.zip'.replace(
84             /{{ v }}/g,
85             ver.version
86           )
87       });
88
89       // Note: versions are sorted most-recent first.
90       // We just assume that the brew version is most recent stable
91       // ... but we can't really know for sure
92
93       // TODO
94       brews.some(function (brew, i) {
95         // 10.3 => ^10.2(\b|\.)
96         var reBrewVer = new RegExp(
97           '^' + brew.version.replace(/\./, '\\.') + '(\\b|\\.)',
98           'g'
99         );
100         if (!ver.version.match(reBrewVer)) {
101           return;
102         }
103         all.releases.push({
104           version: ver.version,
105           lts: false,
106           channel: ver.channel,
107           date: ver.date,
108           os: 'macos',
109           arch: 'amd64',
110           download: brew.download.replace(/{{ v }}/g, ver.version)
111         });
112         brews.splice(i, 1); // remove
113         return true;
114       });
115     });
116
117     return all;
118   });
119
120   function mariaReleases() {
121     return request({
122       url: 'https://downloads.mariadb.org/mariadb/+releases/',
123       fail: true // https://git.coolaj86.com/coolaj86/request.js/issues/2
124     })
125       .then(failOnBadStatus)
126       .then(function (resp) {
127         // fragile, but simple
128
129         // Make release info go from this:
130         var html = resp.body;
131         //
132         // <tr>
133         //   <td><a href="/mariadb/10.0.38/">10.0.38</a></td>
134         //   <td>2019-01-31</td>
135         //   <td>Stable</td>
136         // </tr>
137
138         // To this:
139         var reLine = /\s*(<(tr|td)[^>]*>)\s*/g;
140         //
141         // <tr><tr><td><a href="/mariadb/10.0.38/">10.0.38</a></td><td>2019-01-31</td><td>Stable</td>
142         // </tr><tr><td><a href="/mariadb/10.0.37/">10.0.37</a></td><td>2018-11-01</td><td>Stable</td>
143         // </tr><tr><td><a href="/mariadb/10.0.36/">10.0.36</a></td><td>2018-08-01</td><td>Stable</td>
144         //
145         // To this:
146         var reVer =
147           /<tr>.*mariadb\/(10[^\/]+)\/">.*(20\d\d-\d\d-\d\d)<\/td><td>(\w+)<\/td>/;
148         //
149         // { "version": "10.0.36", "date": "2018-08-01", "channel": "stable" }
150
151         return html
152           .replace(reLine, '$1')
153           .split(/\n/)
154           .map(function (line) {
155             var m = line.match(reVer);
156             if (!m) {
157               return;
158             }
159             return {
160               version: m[1],
161               channel: mapChannel(m[3].toLowerCase()),
162               date: m[2]
163             };
164           })
165           .filter(Boolean);
166       })
167       .catch(function (err) {
168         console.error('Error fetching (official) MariaDB versions');
169         console.error(err);
170         return [];
171       });
172   }
173 };
174
175 function mapChannel(ch) {
176   if ('alpha' === ch) {
177     return 'dev';
178   }
179   // stable,rc,beta
180   return ch;
181 }
182
183 function failOnBadStatus(resp) {
184   if (resp.statusCode >= 400) {
185     var err = new Error('Non-successful status code: ' + resp.statusCode);
186     err.code = 'ESTATUS';
187     err.response = resp;
188     throw err;
189   }
190   return resp;
191 }
192
193 if (module === require.main) {
194   module.exports(require('@root/request')).then(function (all) {
195     console.info('official releases look like:');
196     console.info(JSON.stringify(all.releases.slice(0, 2), null, 2));
197     console.info('Homebrew releases look like:');
198     console.info(
199       JSON.stringify(
200         all.releases
201           .filter(function (rel) {
202             return 'macos' === rel.os;
203           })
204           .slice(0, 2),
205         null,
206         2
207       )
208     );
209   });
210 }