Files
tutti/tools/scripts/desktop-release-artifact-merge.test.mjs
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

161 lines
4.8 KiB
JavaScript

import assert from "node:assert/strict";
import {
mkdir,
mkdtemp,
readFile,
readdir,
rm,
writeFile
} from "node:fs/promises";
import { createRequire } from "node:module";
import test from "node:test";
import os from "node:os";
import path from "node:path";
import YAML from "yaml";
import {
mergeMacosReleaseArtifacts,
resolveUpdaterFileName
} from "../../apps/desktop/scripts/merge-macos-release-artifacts.mjs";
const desktopRequire = createRequire(
new URL("../../apps/desktop/package.json", import.meta.url)
);
const { findFile } = desktopRequire("electron-updater/out/providers/Provider");
async function createArchitectureArtifacts(root, version, architecture) {
const artifactDir = path.join(
root,
`tutti-desktop-release-assets-macos-${architecture}`
);
await mkdir(artifactDir, { recursive: true });
const stem = `Tutti-${version}-mac-${architecture}`;
await Promise.all([
writeFile(path.join(artifactDir, `${stem}.dmg`), `dmg-${architecture}`),
writeFile(path.join(artifactDir, `${stem}.zip`), `zip-${architecture}`),
writeFile(
path.join(artifactDir, `${stem}.zip.blockmap`),
`blockmap-${architecture}`
)
]);
}
function withProcessArchitecture(architecture, callback) {
const descriptor = Object.getOwnPropertyDescriptor(process, "arch");
Object.defineProperty(process, "arch", {
configurable: true,
enumerable: true,
value: architecture
});
try {
return callback();
} finally {
Object.defineProperty(process, "arch", descriptor);
}
}
function selectMacUpdaterZip(files, architecture) {
return withProcessArchitecture(architecture, () => {
let resolvedFiles = files.map((info) => ({
info,
url: new URL(info.url, "https://updates.example.test/")
}));
const isArm64 = (file) =>
file.url.pathname.includes("arm64") || file.info.url.includes("arm64");
if (architecture === "arm64" && resolvedFiles.some(isArm64)) {
resolvedFiles = resolvedFiles.filter(isArm64);
} else {
resolvedFiles = resolvedFiles.filter((file) => !isArm64(file));
}
return findFile(resolvedFiles, "zip", ["pkg", "dmg"]);
});
}
test("macOS matrix artifacts merge into one architecture-aware updater manifest", async () => {
const tempRoot = await mkdtemp(
path.join(os.tmpdir(), "tutti-macos-release-merge-")
);
const inputDirectory = path.join(tempRoot, "input");
const outputDirectory = path.join(tempRoot, "output");
const version = "1.2.3-rc.4";
try {
await Promise.all(
["x64", "arm64", "universal"].map((architecture) =>
createArchitectureArtifacts(inputDirectory, version, architecture)
)
);
const result = await mergeMacosReleaseArtifacts({
inputDirectory,
outputDirectory,
releaseChannel: "rc",
releaseDate: "2026-07-16T00:00:00.000Z",
releaseVersion: version
});
const metadata = YAML.parse(
await readFile(path.join(outputDirectory, "rc-mac.yml"), "utf8")
);
const outputNames = await readdir(outputDirectory);
assert.equal(result.updaterFileName, "rc-mac.yml");
assert.equal(outputNames.length, 10);
assert.deepEqual(
metadata.files.map((file) => file.url),
[
`Tutti-${version}-mac-x64.zip`,
`Tutti-${version}-mac-arm64.zip`,
`Tutti-${version}-mac-universal.zip`
]
);
assert.equal(metadata.path, `Tutti-${version}-mac-x64.zip`);
assert.equal(metadata.sha512, metadata.files[0].sha512);
assert.equal(metadata.releaseDate, "2026-07-16T00:00:00.000Z");
for (const file of metadata.files) {
assert.equal(typeof file.sha512, "string");
assert.ok(file.sha512.length > 40);
assert.equal(typeof file.size, "number");
}
assert.match(
selectMacUpdaterZip(metadata.files, "x64").url.pathname,
/-mac-x64\.zip$/
);
assert.match(
selectMacUpdaterZip(metadata.files, "arm64").url.pathname,
/-mac-arm64\.zip$/
);
} finally {
await rm(tempRoot, { force: true, recursive: true });
}
});
test("electron-updater accepts universal ZIP metadata on both macOS architectures", () => {
const universalFiles = [
{
sha512: "universal-sha512",
size: 123,
url: "Tutti-1.2.3-mac-universal.zip"
}
];
assert.match(
selectMacUpdaterZip(universalFiles, "x64").url.pathname,
/-mac-universal\.zip$/
);
assert.match(
selectMacUpdaterZip(universalFiles, "arm64").url.pathname,
/-mac-universal\.zip$/
);
});
test("macOS updater channel names stay compatible with electron-updater", () => {
assert.equal(resolveUpdaterFileName("stable"), "latest-mac.yml");
assert.equal(resolveUpdaterFileName("rc"), "rc-mac.yml");
assert.equal(resolveUpdaterFileName("beta"), "beta-mac.yml");
assert.throws(
() => resolveUpdaterFileName("nightly"),
/Unsupported desktop release channel/
);
});