完善桌面端发布稳定化门禁
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { access, readFile } from "node:fs/promises";
|
||||
import { createHash } from "node:crypto";
|
||||
import { basename, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
@@ -18,6 +19,10 @@ const feedPath = resolve(
|
||||
);
|
||||
const artifactDir = optionValue("--artifacts-dir") || process.env.DESKTOP_UPDATE_ARTIFACTS_DIR;
|
||||
const expectedBaseUrl = optionValue("--base-url") || process.env.DESKTOP_UPDATE_BASE_URL;
|
||||
const checksumManifestPath =
|
||||
optionValue("--checksum-manifest") ||
|
||||
process.env.DESKTOP_UPDATE_CHECKSUM_MANIFEST ||
|
||||
(artifactDir ? resolve(artifactDir, "SHA256SUMS.txt") : undefined);
|
||||
|
||||
const fail = (message) => failures.push(message);
|
||||
const assert = (condition, message) => {
|
||||
@@ -32,6 +37,55 @@ const assertFileExists = async (path, description) => {
|
||||
}
|
||||
};
|
||||
|
||||
const sha256 = async (path) => createHash("sha256").update(await readFile(path)).digest("hex");
|
||||
|
||||
const readChecksumManifest = async () => {
|
||||
if (!checksumManifestPath) return undefined;
|
||||
try {
|
||||
const source = await readFile(checksumManifestPath, "utf8");
|
||||
const checksums = new Map();
|
||||
for (const line of source.split(/\r?\n/)) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed) continue;
|
||||
const match = trimmed.match(/^([a-f0-9]{64})\s+\*?(.+)$/i);
|
||||
if (!match) {
|
||||
fail(`Checksum manifest contains an invalid line: ${line}`);
|
||||
continue;
|
||||
}
|
||||
checksums.set(basename(match[2]), match[1].toLowerCase());
|
||||
}
|
||||
return checksums;
|
||||
} catch (error) {
|
||||
fail(`Cannot read checksum manifest ${checksumManifestPath}: ${error.message}`);
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const assertChecksum = async (checksums, path, description) => {
|
||||
if (!checksums) return;
|
||||
const name = basename(path);
|
||||
const expected = checksums.get(name);
|
||||
assert(Boolean(expected), `Checksum manifest must include ${description}: ${name}`);
|
||||
if (expected) {
|
||||
const actual = await sha256(path);
|
||||
assert(actual === expected, `${description} checksum mismatch for ${name}.`);
|
||||
}
|
||||
};
|
||||
|
||||
const assertManifestEntries = async (checksums) => {
|
||||
if (!checksums || !artifactDir) return;
|
||||
for (const [name, expected] of checksums.entries()) {
|
||||
const path = resolve(artifactDir, name);
|
||||
await assertFileExists(path, `checksum manifest entry ${name}`);
|
||||
try {
|
||||
const actual = await sha256(path);
|
||||
assert(actual === expected, `Checksum manifest entry mismatch for ${name}.`);
|
||||
} catch (error) {
|
||||
fail(`Cannot verify checksum manifest entry ${name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let feed;
|
||||
try {
|
||||
feed = JSON.parse(await readFile(feedPath, "utf8"));
|
||||
@@ -40,6 +94,8 @@ try {
|
||||
}
|
||||
|
||||
if (feed) {
|
||||
const checksums = await readChecksumManifest();
|
||||
await assertManifestEntries(checksums);
|
||||
const normalizedFeedVersion = String(feed.version || "").replace(/^v/, "");
|
||||
const platforms = feed.platforms || {};
|
||||
const darwinArm = platforms["darwin-aarch64"];
|
||||
@@ -80,14 +136,21 @@ if (feed) {
|
||||
|
||||
if (artifactDir) {
|
||||
const artifactPath = resolve(artifactDir, basename(url.pathname));
|
||||
const signaturePath = `${artifactPath}.sig`;
|
||||
await assertFileExists(artifactPath, `${platform} updater artifact`);
|
||||
await assertFileExists(`${artifactPath}.sig`, `${platform} updater artifact signature`);
|
||||
await assertFileExists(signaturePath, `${platform} updater artifact signature`);
|
||||
await assertChecksum(checksums, artifactPath, `${platform} updater artifact`);
|
||||
await assertChecksum(checksums, signaturePath, `${platform} updater artifact signature`);
|
||||
}
|
||||
}
|
||||
|
||||
if (darwinArm?.url && darwinIntel?.url) {
|
||||
assert(darwinArm.url === darwinIntel.url, "Universal macOS latest.json must point both darwin architectures at the same artifact.");
|
||||
}
|
||||
|
||||
if (artifactDir) {
|
||||
await assertChecksum(checksums, feedPath, "latest.json");
|
||||
}
|
||||
}
|
||||
|
||||
if (failures.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user