Files
ctms/frontend/scripts/create-desktop-release-provenance.mjs
Cheng Zhou e3489f3b06
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled
build(release): stage local macOS v0.1.0 distribution
2026-07-17 11:31:11 +08:00

80 lines
3.4 KiB
JavaScript

import { mkdir, readFile, writeFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { loadDesktopReleasePolicy, resolveDesktopReleasePolicy } from "./desktop-release-policy.mjs";
const frontendDir = fileURLToPath(new URL("../", import.meta.url));
const packageInfo = JSON.parse(await readFile(resolve(frontendDir, "package.json"), "utf8"));
const args = process.argv.slice(2);
const value = (name) => {
const index = args.indexOf(name);
return index >= 0 ? args[index + 1] : undefined;
};
const policy = await loadDesktopReleasePolicy();
const resolution = resolveDesktopReleasePolicy(packageInfo.version, policy);
const tag = value("--tag") || process.env.GITHUB_REF_NAME;
const commit = value("--commit") || process.env.GITHUB_SHA;
const macosSigning = value("--macos-signing");
const windowsSigning = value("--windows-signing");
const releaseStage = value("--stage") || "complete";
const outputPath = resolve(
frontendDir,
value("--output") || "src-tauri/target/desktop-release-feed/DESKTOP-RELEASE-PROVENANCE.json",
);
const failures = [];
const assert = (condition, message) => {
if (!condition) failures.push(message);
};
assert(tag === `v${packageInfo.version}`, `Release provenance tag must be v${packageInfo.version}.`);
assert(/^[0-9a-f]{40}$/i.test(commit || ""), "Release provenance commit must be a full 40-character SHA.");
assert(macosSigning === resolution.macosSigning, `macOS signing mode must be ${resolution.macosSigning}.`);
assert(windowsSigning === resolution.windowsSigning, `Windows signing mode must be ${resolution.windowsSigning}.`);
assert(["complete", "macos-first"].includes(releaseStage), "Release provenance stage must be complete or macos-first.");
if (releaseStage === "macos-first") {
assert(
resolution.macosLocalExactTagFallback === true && resolution.windowsDelivery === "deferred-same-tag",
`v${packageInfo.version} does not approve a staged local macOS-first release.`,
);
}
if (failures.length > 0) {
throw new Error(`Desktop release provenance creation failed:\n${failures.map((item) => ` - ${item}`).join("\n")}`);
}
const provenance = {
schemaVersion: 1,
product: "CTMS Desktop",
version: packageInfo.version,
tag,
commit,
platformSigningMode: resolution.platformSigningMode,
platformSigning: {
macos: macosSigning,
windows: windowsSigning,
},
updaterSigning: "required-and-verified",
artifactLabel: resolution.artifactLabel,
distribution: resolution.distribution,
stage: releaseStage,
platformAvailability:
releaseStage === "macos-first"
? { macos: "available", windows: "pending-same-tag" }
: { macos: "available", windows: "available" },
updaterFeedActivation:
releaseStage === "macos-first" ? "withheld-pending-combined-verification" : "combined-platform-verification-required",
warnings: resolution.warningRequired
? [
"macOS is ad-hoc signed and not Apple-notarized; Gatekeeper warnings are expected.",
"Windows is not Authenticode-signed or RFC 3161 timestamped; SmartScreen warnings are expected.",
"Verify the release tag, commit, updater signatures, and SHA256SUMS.txt through a trusted channel before installation.",
]
: [],
};
await mkdir(dirname(outputPath), { recursive: true });
await writeFile(outputPath, `${JSON.stringify(provenance, null, 2)}\n`);
console.log(`Desktop release provenance created at ${outputPath}`);