Files
workinf_Blender_Wasm/tools/web/reuse-wbv2-source-dependencies.mjs
mes123456 c334bb1437
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
feat(web): reuse verified source dependencies
2026-09-03 13:50:55 +08:00

96 lines
5.3 KiB
JavaScript

import assert from "node:assert/strict";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const abs = (file) => path.join(root, file);
const read = (file) => fs.readFileSync(abs(file), "utf8");
const json = (file) => JSON.parse(read(file));
const sha = (file) => crypto.createHash("sha256").update(fs.readFileSync(abs(file))).digest("hex");
const arg = (name) => {
const index = process.argv.indexOf(name);
return index >= 0 ? process.argv[index + 1] : null;
};
const task = arg("--task");
if (!task || !process.argv.includes("--write")) throw new Error("usage: node tools/web/reuse-wbv2-source-dependencies.mjs --task <task-id> --write");
const inventoryPath = "tests/golden/WBV2/dynamic-inventory.json";
const inventory = json(inventoryPath);
const index = json("tests/golden/WBV2/task-index.json");
const plan = json(index.source.path);
const record = plan.tasks.find((candidate) => candidate.id === task);
const module = record?.module;
assert.ok(module?.dependencyReuse?.length, `task ${task} has no dependency reuse map`);
const bindings = json("tests/golden/WBV2/dynamic-coverage-bindings.json");
const bindingByUnit = new Map(bindings.filter((binding) => binding.status === "VERIFIED").map((binding) => [binding.unitId, binding]));
function validateEvidence(evidencePath) {
const evidence = json(evidencePath);
assert.equal(evidence.browser, "chromium", `evidence is not Chromium: ${evidencePath}`);
assert.equal(evidence.queueMutation, false, `evidence mutated queue: ${evidencePath}`);
const fixturePaths = Array.isArray(evidence.fixtures) ? evidence.fixtures : evidence.fixture ? [evidence.fixture] : [];
assert.ok(fixturePaths.length, `evidence has no fixture(s): ${evidencePath}`);
const entries = Array.isArray(evidence.fixtures) ? fixturePaths.map((fixture) => evidence[fixture]) : [evidence];
for (const entry of entries) {
assert.ok(entry && entry.error === undefined, `evidence fixture failed: ${evidencePath}`);
if (entry.saveReopenExact !== undefined) assert.equal(entry.saveReopenExact, true);
if (entry.deterministicExact !== undefined) assert.equal(entry.deterministicExact, true);
if (entry.exact !== undefined) assert.equal(entry.exact, true);
}
if (Array.isArray(evidence.fixtures)) {
for (const fixture of fixturePaths) assert.equal(evidence.fixtureSha256?.[fixture], sha(fixture), `fixture hash drift: ${fixture}`);
} else {
assert.equal(evidence.fixtureSha256, sha(evidence.fixture), `fixture hash drift: ${evidence.fixture}`);
}
return { path: evidencePath, sha256: sha(evidencePath), fixtures: fixturePaths };
}
const proofs = [];
const reusedEvidence = new Map();
for (const dependency of module.dependencyReuse) {
const unit = inventory.units.find((candidate) => candidate.id === dependency.unitId);
assert.ok(unit, `dynamic unit missing: ${dependency.unitId}`);
assert.equal(unit.coverageStatus, "UNVERIFIED", `dependency unit is already verified: ${dependency.unitId}`);
const representative = bindingByUnit.get(dependency.representativeUnitId);
assert.ok(representative, `verified representative binding missing: ${dependency.representativeUnitId}`);
assert.equal(representative.sourceTreeSha256, inventory.authority.sourceTreeSha256);
assert.ok(fs.existsSync(abs(dependency.proofSource)), `dependency proof source missing: ${dependency.proofSource}`);
const proofText = read(dependency.proofSource);
assert.ok(proofText.includes(dependency.marker), `dependency marker missing: ${dependency.marker}`);
assert.ok(fs.existsSync(abs(unit.locations?.[0]?.path)), `dependency source missing: ${unit.locations?.[0]?.path}`);
assert.ok(read(unit.locations[0].path).includes(dependency.marker), `dependency source marker missing: ${dependency.marker}`);
const evidence = validateEvidence(dependency.productionEvidence);
reusedEvidence.set(evidence.path, evidence);
proofs.push({
unitId: dependency.unitId,
sourceLocation: unit.locations?.[0],
representativeUnitId: dependency.representativeUnitId,
representativeBinding: { task: representative.task, productionEvidence: representative.productionEvidence },
proofSource: dependency.proofSource,
proofSourceSha256: sha(dependency.proofSource),
marker: dependency.marker,
productionEvidence: evidence,
sourceTreeSha256: inventory.authority.sourceTreeSha256,
});
}
const reportPath = module.evidencePaths?.[0] ?? `tests/golden/${task}/source-dependency-reuse-production.json`;
const report = {
schemaVersion: 1,
task,
operation: "SOURCE_DEPENDENCY_REUSE_CHROMIUM_RECEIPT",
status: "PASS",
browser: "chromium",
queueMutation: false,
sourceUnits: module.coverageBindings,
sourceTreeSha256: inventory.authority.sourceTreeSha256,
dependencyProofs: proofs,
reusedEvidence: [...reusedEvidence.values()],
efficiency: { existingChromiumReceiptsReused: reusedEvidence.size, browserRuns: 0, buildRuns: 0, policy: "verified-downstream-receipt-plus-source-dependency" },
};
fs.mkdirSync(path.dirname(abs(reportPath)), { recursive: true });
fs.writeFileSync(abs(reportPath), `${JSON.stringify(report, null, 2)}\n`);
process.stdout.write(`wbv2-source-dependency-reuse-ok task=${task} units=${proofs.length} receipts=${reusedEvidence.size} browserRuns=0\n`);