Skip to content

Commit ceb8a2c

Browse files
committed
feat: source of truth for version support
1 parent 3051a44 commit ceb8a2c

File tree

8 files changed

+231
-20
lines changed

8 files changed

+231
-20
lines changed

src/data.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const { Octokit } = require('@octokit/rest');
44
const ExpiryMap = require('expiry-map');
55
const pMemoize = require('p-memoize');
66
const semver = require('semver');
7+
const fs = require('fs');
8+
const path = require('path');
79

810
let octokit = null;
911
const getOctokit = async () => {
@@ -30,15 +32,28 @@ const getOctokit = async () => {
3032
return octokit;
3133
};
3234

33-
const getReleasesOrUpdate = pMemoize(
35+
const getVersionsOrUpdate = pMemoize(
3436
async () => {
3537
const response = await fetch.default('https://electronjs.org/headers/index.json');
3638
const releases = await response.json();
37-
return releases.sort((a, b) => semver.compare(b.version, a.version));
39+
const support = JSON.parse(fs.readFileSync(path.join(__dirname, 'versions-support.json')));
40+
return {
41+
support: support.map((version) => {
42+
const stableRelease =
43+
releases.find((release) => release.version === `${version.major}.0.0`) !== undefined;
44+
const endOfLife = version.endOfLife;
45+
return {
46+
...version,
47+
isSupported: !endOfLife || new Date() <= new Date(endOfLife),
48+
isStable: stableRelease,
49+
};
50+
}),
51+
releases: releases.sort((a, b) => semver.compare(b.version, a.version)),
52+
};
3853
},
3954
{
4055
cache: new ExpiryMap(60 * 1000),
41-
cacheKey: () => 'releases',
56+
cacheKey: () => 'versions',
4257
},
4358
);
4459

@@ -158,7 +173,7 @@ const getTSDefs = pMemoize(
158173

159174
module.exports = {
160175
getGitHubRelease,
161-
getReleasesOrUpdate,
176+
getVersionsOrUpdate,
162177
getActiveReleasesOrUpdate,
163178
getAllSudowoodoReleasesOrUpdate,
164179
getPR,

src/index.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const exphbs = require('express-handlebars');
33
const path = require('path');
44

55
const a = require('./utils/a');
6-
const { getReleasesOrUpdate, getActiveReleasesOrUpdate } = require('./data');
6+
const { getVersionsOrUpdate, getActiveReleasesOrUpdate } = require('./data');
77

88
const app = express();
99

@@ -25,7 +25,23 @@ app.get(
2525
'/releases.json',
2626
a(async (req, res) => {
2727
res.setHeader('Access-Control-Allow-Origin', '*');
28-
res.json(await getReleasesOrUpdate());
28+
res.json((await getVersionsOrUpdate()).releases);
29+
}),
30+
);
31+
32+
app.get(
33+
'/versions.json',
34+
a(async (req, res) => {
35+
res.setHeader('Access-Control-Allow-Origin', '*');
36+
res.json(await getVersionsOrUpdate());
37+
}),
38+
);
39+
40+
app.get(
41+
'/support.json',
42+
a(async (req, res) => {
43+
res.setHeader('Access-Control-Allow-Origin', '*');
44+
res.json((await getVersionsOrUpdate()).support);
2945
}),
3046
);
3147

src/routes/history.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const { Router } = require('express');
22

33
const a = require('../utils/a');
4-
const { getReleasesOrUpdate } = require('../data');
4+
const { getVersionsOrUpdate } = require('../data');
55

66
const router = new Router();
77

@@ -14,7 +14,7 @@ router.get('/', (req, res) =>
1414
router.get(
1515
'/:date',
1616
a(async (req, res) => {
17-
const releases = await getReleasesOrUpdate();
17+
const { releases } = await getVersionsOrUpdate();
1818
const onDate = releases.filter((r) => r.date === req.params.date);
1919
if (onDate.length === 0) return res.redirect('/history');
2020
res.render('date', {

src/routes/home.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const Handlebars = require('handlebars');
33
const semver = require('semver');
44

55
const a = require('../utils/a');
6-
const { getReleasesOrUpdate, getActiveReleasesOrUpdate } = require('../data');
6+
const { getVersionsOrUpdate, getActiveReleasesOrUpdate } = require('../data');
77
const { timeSince, minutesSince } = require('../utils/format-time');
88

99
const router = new Router();
@@ -62,8 +62,8 @@ Handlebars.registerPartial('releaseSquare', function (release) {
6262
router.get(
6363
'/',
6464
a(async (req, res) => {
65-
const [releases, activeReleases] = await Promise.all([
66-
getReleasesOrUpdate(),
65+
const [{ releases, support }, activeReleases] = await Promise.all([
66+
getVersionsOrUpdate(),
6767
getActiveReleasesOrUpdate(),
6868
]);
6969
const lastNightly = releases.find((r) => semver.parse(r.version).prerelease[0] === 'nightly');
@@ -74,7 +74,10 @@ router.get(
7474
);
7575
const lastStable = releases.find((r) => semver.parse(r.version).prerelease.length === 0);
7676
const stableMajor = semver.parse(lastStable.version).major;
77-
const latestSupported = [stableMajor, stableMajor - 1, stableMajor - 2].map((major) =>
77+
const supportedMajors = support
78+
.filter((version) => version.isSupported && version.isStable)
79+
.map((version) => version.major);
80+
const latestSupported = supportedMajors.map((major) =>
7881
releases.find((r) => semver.parse(r.version).major === major),
7982
);
8083
if (semver.parse(lastPreRelease.version).major <= stableMajor) {

src/routes/pr.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ const { Router } = require('express');
22
const semver = require('semver');
33

44
const a = require('../utils/a');
5-
const { compareTagToCommit, getReleasesOrUpdate, getPR, getPRComments } = require('../data');
5+
const { compareTagToCommit, getVersionsOrUpdate, getPR, getPRComments } = require('../data');
66

77
const router = new Router();
88

99
async function getPRReleaseStatus(prNumber) {
10-
const releases = [...(await getReleasesOrUpdate())].reverse();
10+
const releases = [...(await getVersionsOrUpdate()).releases].reverse();
1111
const [prInfo, comments] = await Promise.all([getPR(prNumber), getPRComments(prNumber)]);
1212
if (!prInfo) return null;
1313

src/routes/release.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const Prism = require('prismjs');
88
const semver = require('semver');
99

1010
const a = require('../utils/a');
11-
const { getGitHubRelease, getReleasesOrUpdate, getTSDefs } = require('../data');
11+
const { getGitHubRelease, getVersionsOrUpdate, getTSDefs } = require('../data');
1212

1313
const window = new JSDOM('').window;
1414
const DOMPurify = createDOMPurify(window);
@@ -59,7 +59,7 @@ Handlebars.registerHelper('markdownMergeHeaders', function (contentArr) {
5959
});
6060

6161
async function getValidVersionRange(startVersion, endVersion, res) {
62-
const allReleases = await getReleasesOrUpdate();
62+
const { releases: allReleases } = await getVersionsOrUpdate();
6363

6464
const parsedStart = semver.parse(startVersion);
6565
const parsedEnd = semver.parse(endVersion);
@@ -182,9 +182,9 @@ router.get(
182182
'/:version',
183183
a(async (req, res) => {
184184
const version = req.params.version;
185-
const [release, allReleases] = await Promise.all([
185+
const [release, { releases: allReleases }] = await Promise.all([
186186
getGitHubRelease(version),
187-
getReleasesOrUpdate(),
187+
getVersionsOrUpdate(),
188188
]);
189189
if (!release) {
190190
return res.redirect('/');

src/routes/releases.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const { Router } = require('express');
22
const paginate = require('express-paginate');
33
const Handlebars = require('handlebars');
44
const a = require('../utils/a');
5-
const { getGitHubRelease, getReleasesOrUpdate } = require('../data');
5+
const { getGitHubRelease, getVersionsOrUpdate } = require('../data');
66
const semver = require('semver');
77

88
const router = new Router();
@@ -75,7 +75,7 @@ router.get(
7575
filter = ({ version }) => version.includes('nightly');
7676
}
7777

78-
const releases = await getReleasesOrUpdate();
78+
const { releases } = await getVersionsOrUpdate();
7979
const { page, limit, version } = req.query;
8080
const releasesFromChannel = releases.filter(filter);
8181
const major = Number(version);

src/versions-support.json

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
[
2+
{
3+
"major": 26,
4+
"alpha": "2023-06-01",
5+
"beta": "2023-06-27",
6+
"stable": "2023-08-08",
7+
"endOfLife": null
8+
},
9+
{
10+
"major": 25,
11+
"alpha": "2023-04-10",
12+
"beta": "2023-05-02",
13+
"stable": "2023-05-30",
14+
"endOfLife": "2023-12-05"
15+
},
16+
{
17+
"major": 24,
18+
"alpha": "2023-02-09",
19+
"beta": "2023-03-07",
20+
"stable": "2023-04-04",
21+
"endOfLife": "2023-10-03"
22+
},
23+
{
24+
"major": 23,
25+
"alpha": "2022-12-01",
26+
"beta": "2023-01-10",
27+
"stable": "2023-02-07",
28+
"endOfLife": "2023-08-08"
29+
},
30+
{
31+
"major": 22,
32+
"alpha": "2022-09-29",
33+
"beta": "2022-10-25",
34+
"stable": "2022-11-29",
35+
"endOfLife": "2023-10-10"
36+
},
37+
{
38+
"major": 21,
39+
"alpha": "2022-08-04",
40+
"beta": "2022-08-30",
41+
"stable": "2022-09-27",
42+
"endOfLife": "2023-04-04"
43+
},
44+
{
45+
"major": 20,
46+
"alpha": "2022-05-26",
47+
"beta": "2022-06-21",
48+
"stable": "2022-08-02",
49+
"endOfLife": "2023-02-07"
50+
},
51+
{
52+
"major": 19,
53+
"alpha": "2022-03-31",
54+
"beta": "2022-04-26",
55+
"stable": "2022-05-24",
56+
"endOfLife": "2022-11-29"
57+
},
58+
{
59+
"major": 18,
60+
"alpha": "2022-02-03",
61+
"beta": "2022-03-03",
62+
"stable": "2022-03-29",
63+
"endOfLife": "2022-09-27"
64+
},
65+
{
66+
"major": 17,
67+
"alpha": "2021-11-18",
68+
"beta": "2022-01-06",
69+
"stable": "2022-02-01",
70+
"endOfLife": "2022-08-02"
71+
},
72+
{
73+
"major": 16,
74+
"alpha": "2021-09-23",
75+
"beta": "2021-10-20",
76+
"stable": "2021-11-16",
77+
"endOfLife": "2022-05-24"
78+
},
79+
{
80+
"major": 15,
81+
"alpha": "2021-07-20",
82+
"beta": "2021-09-01",
83+
"stable": "2021-09-21",
84+
"endOfLife": "2022-05-24"
85+
},
86+
{
87+
"major": 14,
88+
"alpha": null,
89+
"beta": "2021-05-27",
90+
"stable": "2021-08-31",
91+
"endOfLife": "2022-03-29"
92+
},
93+
{
94+
"major": 13,
95+
"alpha": null,
96+
"beta": "2021-03-04",
97+
"stable": "2021-05-25",
98+
"endOfLife": "2022-02-01"
99+
},
100+
{
101+
"major": 12,
102+
"alpha": null,
103+
"beta": "2020-11-19",
104+
"stable": "2021-03-02",
105+
"endOfLife": "2021-11-16"
106+
},
107+
{
108+
"major": 11,
109+
"alpha": null,
110+
"beta": "2020-08-27",
111+
"stable": "2020-11-17",
112+
"endOfLife": "2021-08-31"
113+
},
114+
{
115+
"major": 10,
116+
"alpha": null,
117+
"beta": "2020-05-21",
118+
"stable": "2020-08-25",
119+
"endOfLife": "2021-05-25"
120+
},
121+
{
122+
"major": 9,
123+
"alpha": null,
124+
"beta": "2020-02-06",
125+
"stable": "2020-05-19",
126+
"endOfLife": "2021-03-02"
127+
},
128+
{
129+
"major": 8,
130+
"alpha": null,
131+
"beta": "2019-10-24",
132+
"stable": "2020-02-04",
133+
"endOfLife": "2020-11-17"
134+
},
135+
{
136+
"major": 7,
137+
"alpha": null,
138+
"beta": "2019-08-01",
139+
"stable": "2019-10-22",
140+
"endOfLife": "2020-08-25"
141+
},
142+
{
143+
"major": 6,
144+
"alpha": null,
145+
"beta": "2019-04-25",
146+
"stable": "2019-07-30",
147+
"endOfLife": "2020-05-19"
148+
},
149+
{
150+
"major": 5,
151+
"alpha": null,
152+
"beta": "2019-01-22",
153+
"stable": "2019-04-23",
154+
"endOfLife": "2020-02-04"
155+
},
156+
{
157+
"major": 4,
158+
"alpha": null,
159+
"beta": "2018-10-11",
160+
"stable": "2018-12-20",
161+
"endOfLife": "2019-10-22"
162+
},
163+
{
164+
"major": 3,
165+
"alpha": null,
166+
"beta": "2018-06-21",
167+
"stable": "2018-09-18",
168+
"endOfLife": "2019-07-30"
169+
},
170+
{
171+
"major": 2,
172+
"alpha": null,
173+
"beta": "2018-02-21",
174+
"stable": "2018-05-01",
175+
"endOfLife": "2019-04-23"
176+
}
177+
]

0 commit comments

Comments
 (0)