Skip to content

Commit 61985cc

Browse files
kjaroshtorokati44
authored andcommitted
Add stable releases
1 parent 34da2b1 commit 61985cc

File tree

7 files changed

+122
-26
lines changed

7 files changed

+122
-26
lines changed

package-lock.json

+9-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@
1919
"react": "^18",
2020
"react-device-detect": "^2.2.3",
2121
"react-dom": "^18",
22-
"recharts": "^2.12.7"
22+
"recharts": "^2.12.7",
23+
"semver": "^7.6.3"
2324
},
2425
"devDependencies": {
2526
"@types/d3": "^7.4.3",
2627
"@types/jsdom": "^21.1.7",
2728
"@types/node": "^22",
2829
"@types/react": "^18",
2930
"@types/react-dom": "^18",
31+
"@types/semver": "^7.5.8",
3032
"@typescript-eslint/eslint-plugin": "^8.0.0",
3133
"@typescript-eslint/parser": "^8.0.0",
3234
"d3": "^7.9.0",

src/app/downloads/config.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,21 @@ import { SummaryStatistics } from "@/app/compatibility/avm2/report_utils";
1414

1515
export const repository = { owner: "ruffle-rs", repo: "ruffle" };
1616

17+
export const maxMinor = 3;
18+
export const maxMajor = 2;
1719
export const maxNightlies = 5;
1820

1921
export const githubReleasesUrl = `https://github.com/${repository.owner}/${repository.repo}/releases`;
22+
export const githubStableReleasesUrl = `${githubReleasesUrl}?q=prerelease:false`;
23+
export const githubNightlyReleasesUrl = `${githubReleasesUrl}?q=prerelease:true`;
2024

2125
export interface GithubRelease {
2226
id: number;
2327
name: string;
2428
prerelease: boolean;
2529
downloads: ReleaseDownloads;
2630
url: string;
31+
tag: string;
2732
avm2_report_asset_id?: number;
2833
}
2934

src/app/downloads/github.tsx

+41
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ import {
55
DownloadKey,
66
FilenamePatterns,
77
GithubRelease,
8+
maxMajor,
9+
maxMinor,
810
maxNightlies,
911
ReleaseDownloads,
1012
repository,
1113
} from "@/app/downloads/config";
1214
import { Octokit } from "octokit";
1315
import { RestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods";
1416
import { parse } from "node-html-parser";
17+
import semver from "semver/preload";
1518

1619
function createGithubAuth() {
1720
if (process.env.GITHUB_TOKEN) {
@@ -56,6 +59,7 @@ export async function getLatestReleases(): Promise<GithubRelease[]> {
5659
name: release.name || release.tag_name,
5760
prerelease: release.prerelease,
5861
url: release.html_url,
62+
tag: release.tag_name,
5963
downloads,
6064
avm2_report_asset_id,
6165
});
@@ -67,6 +71,43 @@ export async function getLatestReleases(): Promise<GithubRelease[]> {
6771
}
6872
}
6973

74+
export async function getLatestRelease(): Promise<GithubRelease> {
75+
const releases = await getLatestReleases();
76+
const stableReleases = releases.filter((release) => !release.prerelease);
77+
return stableReleases.length > 0 ? stableReleases[0] : releases[0];
78+
}
79+
80+
export function filterLatestStableReleases(
81+
releases: GithubRelease[],
82+
): GithubRelease[] {
83+
let newestMajor = null;
84+
const currentMajorReleases = new Map();
85+
const olderMajors = new Map();
86+
for (const release of releases) {
87+
if (release.prerelease) {
88+
continue;
89+
}
90+
const version = release.tag.replace(/^v/, "");
91+
const major = semver.major(version);
92+
const majorMinor = `${major}.${semver.minor(version)}`;
93+
if (!newestMajor) {
94+
newestMajor = major;
95+
}
96+
if (major === newestMajor) {
97+
if (!currentMajorReleases.has(majorMinor)) {
98+
currentMajorReleases.set(majorMinor, release);
99+
}
100+
} else {
101+
if (!olderMajors.has(major)) {
102+
olderMajors.set(major, release);
103+
}
104+
}
105+
}
106+
return Array.from(currentMajorReleases.values())
107+
.slice(0, maxMinor)
108+
.concat(Array.from(olderMajors.values()).slice(0, maxMajor - 1));
109+
}
110+
70111
export async function getWeeklyContributions(): Promise<
71112
RestEndpointMethodTypes["repos"]["getCommitActivityStats"]["response"]
72113
> {

src/app/downloads/page.tsx

+11-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ import {
1818
githubReleasesUrl,
1919
maxNightlies,
2020
} from "@/app/downloads/config";
21-
import { getLatestReleases } from "@/app/downloads/github";
21+
import {
22+
filterLatestStableReleases,
23+
getLatestReleases,
24+
} from "@/app/downloads/github";
2225

2326
function WebDownload({ latest }: { latest: GithubRelease | null }) {
2427
return (
@@ -95,18 +98,21 @@ function DesktopDownload({ latest }: { latest: GithubRelease | null }) {
9598

9699
export default async function Page() {
97100
const releases = await getLatestReleases();
98-
const latest = releases.length > 0 ? releases[0] : null;
101+
const stableReleases = filterLatestStableReleases(releases);
99102
const nightlies = releases
100103
.filter((release) => release.prerelease)
101104
.slice(0, maxNightlies);
105+
const latestStable =
106+
stableReleases.length > 0 ? stableReleases[0] : releases[0];
102107
return (
103108
<Container size="xl" className={classes.container}>
104109
<Stack gap="xl">
105110
<ExtensionList />
106-
<WebDownload latest={latest} />
107-
<DesktopDownload latest={latest} />
111+
<WebDownload latest={latestStable} />
112+
<DesktopDownload latest={latestStable} />
108113

109-
<ReleaseList releases={nightlies} />
114+
<ReleaseList releases={stableReleases} nightly={false} />
115+
<ReleaseList releases={nightlies} nightly={true} />
110116
</Stack>
111117
</Container>
112118
);

src/app/downloads/releases.tsx

+51-15
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ import {
2020
desktopLinks,
2121
type DownloadLink,
2222
extensionLinks,
23+
githubNightlyReleasesUrl,
2324
type GithubRelease,
24-
githubReleasesUrl,
25+
githubStableReleasesUrl,
2526
webLinks,
2627
} from "@/app/downloads/config";
2728

@@ -52,8 +53,8 @@ function DownloadLink({
5253
}
5354

5455
function ReleaseRow(release: GithubRelease) {
55-
// The nightly prefix is a bit superfluous here
56-
const name = release.name.replace(/^Nightly /, "");
56+
// The prefix is a bit superfluous here
57+
const name = release.name.replace(/^Nightly /, "").replace(/^Release /, "");
5758
return (
5859
<TableTr>
5960
<TableTd>
@@ -114,20 +115,55 @@ function ReleaseCompactBox(release: GithubRelease) {
114115
);
115116
}
116117

117-
export function ReleaseList({ releases }: { releases: GithubRelease[] }) {
118+
function ReleaseIntro({ nightly }: { nightly: boolean }) {
119+
if (!nightly) {
120+
return (
121+
<>
122+
<Title id="releases">Stable Releases</Title>
123+
<Text>
124+
If none of the above are suitable for you, you can manually download
125+
one of the latest stable releases. Older versions are available on{" "}
126+
<Link href={githubStableReleasesUrl} target="_blank">
127+
GitHub
128+
</Link>
129+
.
130+
</Text>
131+
</>
132+
);
133+
} else {
134+
return (
135+
<>
136+
<Title id="nightly-releases">Nightly Releases</Title>
137+
<Text>
138+
If you want to try out the latest updates and cutting-edge features,
139+
you can download the latest nightly release. These are automatically
140+
built every day (approximately midnight UTC, unless there are no
141+
changes on that day) and they offer early access to new enhancements,
142+
bug fixes, and improvements before they're officially rolled out.
143+
Older nightly releases are available on{" "}
144+
<Link href={githubNightlyReleasesUrl} target="_blank">
145+
GitHub
146+
</Link>
147+
.
148+
</Text>
149+
</>
150+
);
151+
}
152+
}
153+
154+
export function ReleaseList({
155+
releases,
156+
nightly,
157+
}: {
158+
releases: GithubRelease[];
159+
nightly: boolean;
160+
}) {
161+
if (releases.length == 0) {
162+
return <></>;
163+
}
118164
return (
119165
<Stack>
120-
<Title id="nightly-releases">Nightly Releases</Title>
121-
<Text>
122-
If none of the above are suitable for you, you can manually download the
123-
latest Nightly release. These are automatically built every day
124-
(approximately midnight UTC), unless there are no changes on that day.{" "}
125-
Older nightly releases are available on{" "}
126-
<Link href={githubReleasesUrl} target="_blank">
127-
GitHub
128-
</Link>
129-
.
130-
</Text>
166+
<ReleaseIntro nightly={nightly} />
131167
<Table
132168
horizontalSpacing="md"
133169
verticalSpacing="md"

src/app/page.tsx

+2-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import Image from "next/image";
1313
import { IconCheck } from "@tabler/icons-react";
1414
import React from "react";
15-
import { getLatestReleases } from "@/app/downloads/github";
15+
import { getLatestRelease } from "@/app/downloads/github";
1616

1717
const InteractiveLogo = dynamic(() => import("../components/logo"), {
1818
ssr: false,
@@ -23,9 +23,7 @@ const Installers = dynamic(() => import("./installers"), {
2323
});
2424

2525
export default async function Home() {
26-
const releases = await getLatestReleases();
27-
const latest = releases.length > 0 ? releases[0] : null;
28-
26+
const latest = await getLatestRelease();
2927
return (
3028
<Container size="xl" className={classes.container}>
3129
<InteractiveLogo className={classes.logo} />

0 commit comments

Comments
 (0)