feat(desktop): add time-based staged rollout for stable updates
Linear ramp from 0% at publish to 100% at releaseDate + rolloutHours (default 24h, configurable per release). Beta channel and rolloutHours=0 short-circuit to admit everyone. Per-machine bucket derives from a persistent UUID at <userData>/.updaterId and feeds electron-updater's isUserWithinRollout hook. Adds desktop-rollout.yml workflow for in-place rolloutHours edits on already-published releases (hotfix to 0 or extend the ramp), serialized against finalize-rollout in desktop-release.yml via a shared concurrency group keyed on the tag. Replaces the hand-rolled mac manifest merge with a js-yaml round-trip that preserves unknown fields.
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import fs from "node:fs";
|
||||
import { dump, load } from "js-yaml";
|
||||
|
||||
export function mergeMacManifest(arm64Path, x64Path, outputPath) {
|
||||
const arm64 = load(fs.readFileSync(arm64Path, "utf8"));
|
||||
const x64 = load(fs.readFileSync(x64Path, "utf8"));
|
||||
const files = [...(arm64.files ?? []), ...(x64.files ?? [])].filter(
|
||||
(file, index, all) => all.findIndex((entry) => entry.url === file.url) === index,
|
||||
);
|
||||
const output = dump({ ...arm64, files }, { lineWidth: -1, noRefs: true });
|
||||
fs.writeFileSync(outputPath, output);
|
||||
return output;
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
const [, , arm64Path, x64Path, outputPath] = process.argv;
|
||||
if (!arm64Path || !x64Path || !outputPath) {
|
||||
throw new Error("Usage: node scripts/merge-mac-manifest.mjs <arm64.yml> <x64.yml> <out.yml>");
|
||||
}
|
||||
process.stdout.write(mergeMacManifest(arm64Path, x64Path, outputPath));
|
||||
}
|
||||
Reference in New Issue
Block a user