Skip to content

Commit 60edbb1

Browse files
committed
feat: report synced release versions
1 parent 4cfd323 commit 60edbb1

File tree

3 files changed

+163
-0
lines changed

3 files changed

+163
-0
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,15 @@ jobs:
4949
GH_TOKEN: ${{ secrets.GH_TOKEN }}
5050
GITHUB_TOKEN: ${{ github.token }}
5151
run: pnpm run sync:releases
52+
- name: Show fetched release versions
53+
run: pnpm run report:releases
5254
- name: Static HTML export with Next.js
5355
env:
5456
GH_TOKEN: ${{ secrets.GH_TOKEN }}
5557
GITHUB_TOKEN: ${{ github.token }}
5658
run: pnpm run build
59+
- name: Export release version manifest
60+
run: pnpm run report:releases -- --write out/release-versions.json
5761
- name: Upload to Bucket
5862
uses: JohnGuan/oss-upload-action@main
5963
with:

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"scripts": {
1212
"dev": "next dev --turbopack",
1313
"build": "next build",
14+
"report:releases": "tsx scripts/report-release-versions.ts",
1415
"sync:releases": "tsx scripts/generate-releases.ts",
1516
"start": "next start",
1617
"lint": "eslint ."

scripts/report-release-versions.ts

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import { projects } from '@/projects.config';
2+
import type { Release } from '@/types';
3+
import fs from 'fs/promises';
4+
import path from 'path';
5+
6+
type ReleaseVersionEntry = {
7+
project: string;
8+
repo: string;
9+
latest: {
10+
version: string;
11+
tag_name: string;
12+
published_at: string | null;
13+
html_url: string;
14+
prerelease: boolean;
15+
assets_count: number;
16+
} | null;
17+
};
18+
19+
function parseArgs(args: string[]) {
20+
let writePath: string | undefined;
21+
22+
for (let index = 0; index < args.length; index += 1) {
23+
const arg = args[index];
24+
25+
if (arg === '--write') {
26+
writePath = args[index + 1];
27+
index += 1;
28+
}
29+
}
30+
31+
return { writePath };
32+
}
33+
34+
async function readLatestRelease(repo: string): Promise<Release | null> {
35+
const releasesPath = path.join(process.cwd(), 'data', repo, 'releases.json');
36+
const raw = await fs.readFile(releasesPath, 'utf8');
37+
const releases = JSON.parse(raw) as Release[];
38+
39+
return releases[0] ?? null;
40+
}
41+
42+
async function collectReleaseVersions() {
43+
return Promise.all(
44+
projects.map(async (project): Promise<ReleaseVersionEntry> => {
45+
const latest = await readLatestRelease(project.repo);
46+
47+
return {
48+
project: project.title,
49+
repo: project.repo,
50+
latest: latest
51+
? {
52+
version: latest.name || latest.tag_name,
53+
tag_name: latest.tag_name,
54+
published_at: latest.published_at,
55+
html_url: latest.html_url,
56+
prerelease: latest.prerelease,
57+
assets_count: latest.assets.length,
58+
}
59+
: null,
60+
};
61+
})
62+
);
63+
}
64+
65+
function formatPublishedAt(publishedAt: string | null) {
66+
return publishedAt ?? 'Unknown';
67+
}
68+
69+
function printConsoleReport(entries: ReleaseVersionEntry[]) {
70+
console.log('Release versions used for this build:');
71+
72+
for (const entry of entries) {
73+
if (!entry.latest) {
74+
console.log(`- ${entry.project} (${entry.repo}): no releases found`);
75+
continue;
76+
}
77+
78+
const prereleaseLabel = entry.latest.prerelease ? ' [pre-release]' : '';
79+
console.log(
80+
`- ${entry.project} (${entry.repo}): ${entry.latest.version}${prereleaseLabel} | published ${formatPublishedAt(entry.latest.published_at)} | assets ${entry.latest.assets_count}`
81+
);
82+
}
83+
}
84+
85+
async function appendGitHubSummary(entries: ReleaseVersionEntry[]) {
86+
const summaryPath = process.env.GITHUB_STEP_SUMMARY;
87+
88+
if (!summaryPath) {
89+
return;
90+
}
91+
92+
const generatedAt = new Date().toISOString();
93+
const sha = process.env.GITHUB_SHA ?? 'local';
94+
const lines = [
95+
'## Release Versions Used For Build',
96+
'',
97+
`Generated at: \`${generatedAt}\``,
98+
'',
99+
`Commit: \`${sha}\``,
100+
'',
101+
'| Project | Repo | Version | Published At | Release |',
102+
'| --- | --- | --- | --- | --- |',
103+
...entries.map((entry) => {
104+
if (!entry.latest) {
105+
return `| ${entry.project} | \`${entry.repo}\` | No releases found | Unknown | - |`;
106+
}
107+
108+
const version = `\`${entry.latest.version}${entry.latest.prerelease ? ' (pre-release)' : ''}\``;
109+
const releaseLink = `[GitHub](${entry.latest.html_url})`;
110+
111+
return `| ${entry.project} | \`${entry.repo}\` | ${version} | ${formatPublishedAt(entry.latest.published_at)} | ${releaseLink} |`;
112+
}),
113+
'',
114+
];
115+
116+
await fs.appendFile(summaryPath, `${lines.join('\n')}\n`, 'utf8');
117+
}
118+
119+
async function writeManifest(entries: ReleaseVersionEntry[], outputPath: string) {
120+
const absoluteOutputPath = path.isAbsolute(outputPath)
121+
? outputPath
122+
: path.join(process.cwd(), outputPath);
123+
124+
await fs.mkdir(path.dirname(absoluteOutputPath), { recursive: true });
125+
await fs.writeFile(
126+
absoluteOutputPath,
127+
JSON.stringify(
128+
{
129+
generated_at: new Date().toISOString(),
130+
git_sha: process.env.GITHUB_SHA ?? null,
131+
run_id: process.env.GITHUB_RUN_ID ?? null,
132+
entries,
133+
},
134+
null,
135+
2
136+
),
137+
'utf8'
138+
);
139+
140+
console.log(`Release version manifest written to ${absoluteOutputPath}`);
141+
}
142+
143+
async function main() {
144+
const { writePath } = parseArgs(process.argv.slice(2));
145+
const entries = await collectReleaseVersions();
146+
147+
printConsoleReport(entries);
148+
await appendGitHubSummary(entries);
149+
150+
if (writePath) {
151+
await writeManifest(entries, writePath);
152+
}
153+
}
154+
155+
main().catch((error) => {
156+
console.error('Failed to report release versions:', error);
157+
process.exit(1);
158+
});

0 commit comments

Comments
 (0)