fix: harden upgrade publication and refresh

This commit is contained in:
golem
2026-08-25 00:16:20 -06:00
parent d29dc86383
commit eb7c2c18b3
8 changed files with 267 additions and 32 deletions
+39 -4
View File
@@ -1,7 +1,7 @@
import assert from "node:assert/strict";
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { mkdtemp, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { basename, dirname, join } from "node:path";
import { extractAbi, renderContractsModule, syncArtifacts } from "./sync-web-artifacts.mjs";
import { publishManifest } from "./publish-web-manifest.mjs";
@@ -89,9 +89,44 @@ await withFixture(async (root) => {
const outputPath = join(root, "deployment.json");
await writeFile(activePath, JSON.stringify(manifest));
// Catches a publisher that copies pending, secret-bearing, or malformed live state into the browser bundle.
await publishManifest({ activePath, outputPath });
// Catches a publisher that writes the browser destination directly instead of replacing a complete same-directory file.
const operations = [];
await publishManifest({
activePath,
outputPath,
io: {
writeFile: async (...args) => { operations.push(["write", args[0]]); await writeFile(...args); },
rename: async (...args) => { operations.push(["rename", ...args]); await rename(...args); },
rm,
},
});
assert.deepEqual(JSON.parse(await readFile(outputPath, "utf8")), manifest);
assert.equal(operations.length, 2);
assert.equal(operations[0][0], "write");
assert.equal(dirname(operations[0][1]), dirname(outputPath));
assert.notEqual(operations[0][1], outputPath);
assert.deepEqual(operations[1], ["rename", operations[0][1], outputPath]);
// Catches a failed replacement truncating the published manifest or leaking its staging file.
const preserved = Buffer.from("preserved browser manifest\n");
await writeFile(outputPath, preserved);
let failedStage;
await assert.rejects(
() => publishManifest({
activePath,
outputPath,
io: {
writeFile: async (...args) => { failedStage = args[0]; await writeFile(...args); },
rename: async () => { throw new Error("injected browser replacement failure"); },
rm,
},
}),
/injected browser replacement failure/,
);
assert.deepEqual(await readFile(outputPath), preserved);
assert.equal((await readdir(root)).includes(basename(failedStage)), false);
// Catches a publisher that copies pending, secret-bearing, or malformed live state into the browser bundle.
for (const invalid of [
{ ...manifest, deploymentBlock: 0 },
{ ...manifest, rpcUrl: "https://token@example.test" },