feat(release): add important flag to nightly feed manifests (#2378)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
52d8c6051a
commit
f92ff1111a
|
|
@ -9,6 +9,11 @@ on:
|
|||
schedule:
|
||||
- cron: "30 13 * * *" # 13:30 UTC = 19:00 IST daily
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
important:
|
||||
description: 'Mark this nightly as an important update (escalates the in-app restart prompt). Retro-flag an already-published nightly by re-running only the publish-feed job with this input set.'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
guard:
|
||||
|
|
@ -201,6 +206,7 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NIGHTLY_VERSION: ${{ needs.guard.outputs.version }}
|
||||
NIGHTLY_IMPORTANT: ${{ inputs.important || 'false' }}
|
||||
run: |
|
||||
# Forge stamps package.json to VERSION without +build metadata and
|
||||
# publishes to v<that>. Match it.
|
||||
|
|
@ -208,7 +214,9 @@ jobs:
|
|||
tag="v$version"
|
||||
mkdir -p dist
|
||||
gh release download "$tag" --dir dist --clobber
|
||||
node scripts/feed.mjs dist "$version" nightly
|
||||
important_flag=""
|
||||
[ "$NIGHTLY_IMPORTANT" = "true" ] && important_flag="--important"
|
||||
node scripts/feed.mjs dist "$version" nightly $important_flag
|
||||
shopt -s nullglob
|
||||
assets=(dist/nightly*.yml dist/*.blockmap)
|
||||
if [ ${#assets[@]} -eq 0 ]; then echo "no feed assets generated" >&2; exit 1; fi
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
// ESM (mirrors nightly-version.mjs) so CI runs `node scripts/feed.mjs` directly
|
||||
// and vitest unit-tests the pure functions. The only non-stdlib reach is the
|
||||
// blockmap wrapper (Task 1).
|
||||
// Pass --important to emit `important: true` in each generated yml. An
|
||||
// already-published nightly can be retro-flagged by re-running the feed job
|
||||
// with --important set (or editing the yml and running
|
||||
// `gh release upload TAG nightly*.yml --clobber`).
|
||||
import { readdirSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { writeBlockmap } from "./blockmap.mjs";
|
||||
|
|
@ -34,7 +38,9 @@ export function feedFilename(channel, platform) {
|
|||
// buildYml serializes one platform's feed. files is [{ url, sha512, size }];
|
||||
// for mac the arm64 entry comes first. The deprecated top-level path/sha512
|
||||
// point at files[0]. blockMapSize is never written (forces sidecar differential).
|
||||
export function buildYml(version, files, releaseDate) {
|
||||
// When important is true, emits `important: true` after releaseDate so the
|
||||
// in-app update prompt is escalated.
|
||||
export function buildYml(version, files, releaseDate, important = false) {
|
||||
const lines = [`version: ${version}`, "files:"];
|
||||
for (const f of files) {
|
||||
lines.push(` - url: ${f.url}`);
|
||||
|
|
@ -44,12 +50,13 @@ export function buildYml(version, files, releaseDate) {
|
|||
lines.push(`path: ${files[0].url}`);
|
||||
lines.push(`sha512: ${files[0].sha512}`);
|
||||
lines.push(`releaseDate: '${releaseDate}'`);
|
||||
if (important) lines.push("important: true");
|
||||
return lines.join("\n") + "\n";
|
||||
}
|
||||
|
||||
// generateFeeds writes the yml + sidecar blockmaps for every platform present in
|
||||
// dir. version may carry +build metadata (nightly); strip it for the yml.
|
||||
async function generateFeeds(dir, rawVersion, channel, releaseDate) {
|
||||
async function generateFeeds(dir, rawVersion, channel, releaseDate, important = false) {
|
||||
const version = rawVersion.split("+")[0];
|
||||
const sel = selectInstallers(readdirSync(dir), version);
|
||||
const groups = [
|
||||
|
|
@ -64,18 +71,19 @@ async function generateFeeds(dir, rawVersion, channel, releaseDate) {
|
|||
const { sha512, size } = await writeBlockmap(join(dir, name));
|
||||
files.push({ url: name, sha512, size });
|
||||
}
|
||||
writeFileSync(join(dir, feedFilename(channel, platform)), buildYml(version, files, releaseDate));
|
||||
writeFileSync(join(dir, feedFilename(channel, platform)), buildYml(version, files, releaseDate, important));
|
||||
}
|
||||
}
|
||||
|
||||
// CLI: node scripts/feed.mjs <dir> <version> <channel>
|
||||
// CLI: node scripts/feed.mjs <dir> <version> <channel> [--important]
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
const [, , dir, version, channel] = process.argv;
|
||||
if (!dir || !version || !channel) {
|
||||
process.stderr.write("usage: node feed.mjs <dir> <version> <channel>\n");
|
||||
process.exit(2);
|
||||
}
|
||||
generateFeeds(dir, version, channel, new Date().toISOString()).catch((err) => {
|
||||
const important = process.argv.includes("--important");
|
||||
generateFeeds(dir, version, channel, new Date().toISOString(), important).catch((err) => {
|
||||
process.stderr.write(`${err.stack || err}\n`);
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -69,4 +69,27 @@ describe("buildYml", () => {
|
|||
expect(lines[5]).toBe(" - url: Agent.Orchestrator-darwin-x64-0.10.4.zip");
|
||||
expect(yml).toContain("path: Agent.Orchestrator-darwin-arm64-0.10.4.zip");
|
||||
});
|
||||
|
||||
it("omits important key when flag is false (byte-identical to old output)", () => {
|
||||
const yml = buildYml(
|
||||
"0.10.4",
|
||||
[{ url: "Agent.Orchestrator.Setup.0.10.4.exe", sha512: "AA/BB+cc==", size: 123 }],
|
||||
"2026-06-27T12:00:00.000Z",
|
||||
false,
|
||||
);
|
||||
expect(yml).not.toContain("important");
|
||||
});
|
||||
|
||||
it("emits important: true as top-level key when flag is true", () => {
|
||||
const yml = buildYml(
|
||||
"0.10.4",
|
||||
[{ url: "Agent.Orchestrator.Setup.0.10.4.exe", sha512: "AA/BB+cc==", size: 123 }],
|
||||
"2026-06-27T12:00:00.000Z",
|
||||
true,
|
||||
);
|
||||
expect(yml).toContain("important: true\n");
|
||||
// must still have all existing fields
|
||||
expect(yml).toContain("version: 0.10.4");
|
||||
expect(yml).toContain("releaseDate:");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue