Sync public tree to 13dc821

This commit is contained in:
Michel Paulissen 2026-07-04 13:10:21 +02:00
parent e2bc145f60
commit 1dad0df5c4
6 changed files with 101 additions and 21 deletions

View file

@ -1,7 +1,7 @@
{
"kind": "disasmer-filtered-public-tree",
"source_commit": "c852e659435428b69cf3991a3fad015f60d121ff",
"release_name": "dryrun-c852e6594354",
"source_commit": "13dc821c5a4ff2b093b777374ebf510197ab5500",
"release_name": "dryrun-13dc821c5a4f",
"filtered_out": [
"private/**",
"experiments/**",

View file

@ -136,6 +136,8 @@ for (const [name, pattern] of [
["release publisher rejects stale release manifests", /manifest\.source_commit[\s\S]*expectedSourceCommit\(\)/],
["release publisher checks manifest kind", /manifest\.kind !== "disasmer-public-release-dryrun"/],
["release publisher requires public tree push", /public tree must be pushed before publishing the Forgejo Release/],
["release publisher accepts external public tree push", /function publicTreeAlreadyPushed\(manifest\)[\s\S]*DISASMER_PUBLIC_TREE_ALREADY_PUSHED/],
["release publisher targets external public tree commit", /function publicTreeCommit\(manifest\)[\s\S]*DISASMER_PUBLIC_TREE_COMMIT/],
["release publisher writes evidence report", /public-release-dryrun-forgejo-release\.json/],
["release publisher records reused assets", /reused_assets:/],
]) {
@ -144,8 +146,10 @@ for (const [name, pattern] of [
for (const [name, pattern] of [
["preflight rejects stale release manifests", /manifest\.source_commit[\s\S]*currentSourceCommit/],
["preflight verifies public branch commit", /remoteMain[\s\S]*manifest\.public_tree_publish\.commit/],
["preflight accepts external public tree push", /function publicTreeAlreadyPushed\(manifest\)[\s\S]*DISASMER_PUBLIC_TREE_ALREADY_PUSHED/],
["preflight verifies public branch commit", /remoteMain[\s\S]*publicTreeCommit/],
["preflight verifies local asset checksums", /parseSha256Sums[\s\S]*checksum mismatch/],
["preflight records public tree push source", /public_tree_push_source/],
["preflight records pending external gates", /external_gates:[\s\S]*forgejo_release_publication[\s\S]*public_release_e2e/],
["preflight writes evidence report", /public-release-dryrun-preflight\.json/],
]) {
@ -155,6 +159,7 @@ for (const [name, pattern] of [
for (const [name, pattern] of [
["e2e runner requires explicit opt-in", /DISASMER_PUBLIC_RELEASE_DRYRUN_E2E=1/],
["e2e runner rejects stale release manifests", /manifest\.source_commit[\s\S]*expectedSourceCommit\(\)/],
["e2e runner accepts external public tree push", /function publicTreeAlreadyPushed\(manifest\)[\s\S]*DISASMER_PUBLIC_TREE_ALREADY_PUSHED/],
["e2e runner downloads Forgejo Release assets", /downloadReleaseAssets/],
["e2e runner verifies SHA256SUMS", /verifyChecksums/],
["e2e runner clones public repo", /"git", \["clone", "--depth", "1"/],
@ -195,6 +200,7 @@ for (const [name, pattern] of [
["final evidence requires public e2e report", /public-release-dryrun-e2e\.json/],
["final evidence verifies Forgejo host", /forgejoHost = "git\.michelpaulissen\.com"/],
["final evidence verifies default operator", /serviceEndpoint = "https:\/\/disasmer\.michelpaulissen\.com:9443"/],
["final evidence accepts external public tree push", /function publicTreeAlreadyPushed\(manifest\)[\s\S]*DISASMER_PUBLIC_TREE_ALREADY_PUSHED/],
["final evidence requires private hosted coordinator", /operator_implementation[\s\S]*"private-hosted-coordinator"/],
["final evidence requires service private coordinator marker", /service\.operator_implementation[\s\S]*"private-hosted-coordinator"/],
["final evidence requires current service smoke source", /service\.source_commit[\s\S]*manifest\.source_commit/],
@ -209,7 +215,7 @@ for (const [name, pattern] of [
["final evidence requires public coordinator validation", /public_coordinator_validated/],
["final evidence requires standalone public coordinator", /standalone-public-coordinator/],
["final evidence requires released live DAP", /released_live_dap_verified/],
["final evidence requires pushed public tree", /public_tree_publish[\s\S]*pushed/],
["final evidence requires pushed public tree", /publicTreeAlreadyPushed\(manifest\)/],
["final evidence requires release assets", /downloaded_release_assets/],
["final evidence requires VS Code debugger", /vscode_debugger_verified/],
["final evidence writes final report", /public-release-dryrun-final\.json/],

View file

@ -110,6 +110,13 @@ function expectedSourceCommit() {
);
}
function publicTreeAlreadyPushed(manifest) {
return (
(manifest.public_tree_publish && manifest.public_tree_publish.pushed === true) ||
process.env.DISASMER_PUBLIC_TREE_ALREADY_PUSHED === "1"
);
}
function sha256File(file) {
return crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex");
}
@ -844,7 +851,7 @@ async function main() {
"public release e2e must use release assets prepared from the current acceptance commit"
);
assert.strictEqual(manifest.default_operator_endpoint, serviceEndpoint);
assert.strictEqual(manifest.public_tree_publish.pushed, true);
assert.strictEqual(publicTreeAlreadyPushed(manifest), true);
assert.strictEqual(forgejoReport.release_name, manifest.release_name);
const addr = parseAddr(serviceAddr);

View file

@ -105,6 +105,23 @@ function assertFilteredOut(manifest) {
}
}
function publicTreeAlreadyPushed(manifest) {
return (
(manifest.public_tree_publish && manifest.public_tree_publish.pushed === true) ||
process.env.DISASMER_PUBLIC_TREE_ALREADY_PUSHED === "1"
);
}
function publicRepoRemote(manifest) {
return (
manifest.public_repo_url ||
manifest.public_repo_remote ||
process.env.DISASMER_PUBLIC_REPO_REMOTE ||
process.env.DISASMER_PUBLIC_REPO_URL ||
""
);
}
function commandOutput(command, args) {
try {
return require("child_process")
@ -140,12 +157,12 @@ assertDnsState(manifest.dns_publication_state, "manifest");
assert(manifest.resolver_override, "manifest must record resolver override");
assertFilteredOut(manifest);
assert.strictEqual(
manifest.public_tree_publish && manifest.public_tree_publish.pushed,
publicTreeAlreadyPushed(manifest),
true,
"filtered public tree must be pushed to Forgejo"
);
assertIncludes(
manifest.public_repo_url || manifest.public_repo_remote || "",
publicRepoRemote(manifest),
forgejoHost,
"manifest public repository must point at Forgejo"
);

View file

@ -69,6 +69,38 @@ function remoteHead(remote) {
return head && head.split(/\s+/)[0];
}
function publicTreeAlreadyPushed(manifest) {
return (
(manifest.public_tree_publish && manifest.public_tree_publish.pushed === true) ||
process.env.DISASMER_PUBLIC_TREE_ALREADY_PUSHED === "1"
);
}
function publicTreePushSource(manifest) {
return manifest.public_tree_publish && manifest.public_tree_publish.pushed === true
? "manifest"
: "external-env";
}
function publicRepoRemoteForManifest(manifest) {
return (
manifest.public_repo_url ||
manifest.public_repo_remote ||
process.env.DISASMER_PUBLIC_REPO_REMOTE ||
process.env.DISASMER_PUBLIC_REPO_URL ||
null
);
}
function publicTreeCommitForManifest(manifest) {
return (
(manifest.public_tree_publish && manifest.public_tree_publish.commit) ||
process.env.DISASMER_PUBLIC_TREE_COMMIT ||
process.env.DISASMER_PUBLIC_RELEASE_TARGET ||
null
);
}
function envState(name) {
return process.env[name] ? "set" : "unset";
}
@ -111,19 +143,23 @@ assert.strictEqual(
);
assert.strictEqual(manifest.source_tree_clean, true, "public release prep must start clean");
assert.strictEqual(
manifest.public_tree_publish && manifest.public_tree_publish.pushed,
publicTreeAlreadyPushed(manifest),
true,
"filtered public tree must be pushed to Forgejo before release publication"
);
const publicRepoRemote = manifest.public_repo_url || manifest.public_repo_remote;
const publicRepoRemote = publicRepoRemoteForManifest(manifest);
assert(publicRepoRemote, "manifest must record public repository URL or remote");
const publicTreeCommit = publicTreeCommitForManifest(manifest);
const remoteMain = remoteHead(publicRepoRemote);
assert.strictEqual(
remoteMain,
manifest.public_tree_publish.commit,
"Forgejo public repository main branch must match the prepared public tree commit"
);
assert(remoteMain, "Forgejo public repository main branch must be readable");
if (publicTreeCommit) {
assert.strictEqual(
remoteMain,
publicTreeCommit,
"Forgejo public repository main branch must match the prepared public tree commit"
);
}
assert(Array.isArray(manifest.assets) && manifest.assets.length > 0, "manifest assets missing");
const checksumAsset = manifest.assets.find((asset) => asset.name === "SHA256SUMS");
@ -176,7 +212,8 @@ const report = {
kind: "disasmer-public-release-dryrun-preflight",
source_commit: currentSourceCommit,
release_name: manifest.release_name,
public_tree_commit: manifest.public_tree_publish.commit,
public_tree_commit: publicTreeCommit || remoteMain,
public_tree_push_source: publicTreePushSource(manifest),
public_repo_url: publicRepoRemote,
public_repo_remote_head: remoteMain,
source_tree_clean: currentTreeStatus === "",

View file

@ -98,6 +98,22 @@ function resolveRepoIdentity(manifest) {
}
}
function publicTreeAlreadyPushed(manifest) {
return (
(manifest.public_tree_publish && manifest.public_tree_publish.pushed === true) ||
process.env.DISASMER_PUBLIC_TREE_ALREADY_PUSHED === "1"
);
}
function publicTreeCommit(manifest) {
return (
(manifest.public_tree_publish && manifest.public_tree_publish.commit) ||
process.env.DISASMER_PUBLIC_TREE_COMMIT ||
process.env.DISASMER_PUBLIC_RELEASE_TARGET ||
null
);
}
function apiPath(pathname) {
return `/api/v1${pathname}`;
}
@ -190,8 +206,7 @@ async function createOrReuseRelease(manifest) {
return { release: found, created: false };
}
const targetCommitish =
(manifest.public_tree_publish && manifest.public_tree_publish.commit) ||
process.env.DISASMER_PUBLIC_RELEASE_TARGET ||
publicTreeCommit(manifest) ||
"main";
const body = [
"Disasmer public release dry run.",
@ -264,11 +279,8 @@ async function main() {
"public release manifest is stale; regenerate it for the current acceptance commit before publishing the Forgejo Release"
);
}
const publicTreeAlreadyPushed =
process.env.DISASMER_PUBLIC_TREE_ALREADY_PUSHED === "1";
if (
!publicTreeAlreadyPushed &&
(!manifest.public_tree_publish || manifest.public_tree_publish.pushed !== true)
!publicTreeAlreadyPushed(manifest)
) {
throw new Error(
"public tree must be pushed before publishing the Forgejo Release; run prepare-public-release-dryrun.js with DISASMER_PUBLISH_PUBLIC_TREE=1"
@ -306,6 +318,7 @@ async function main() {
release_created: created,
default_operator_endpoint: manifest.default_operator_endpoint,
public_tree_identity: manifest.public_tree_identity,
public_tree_commit: publicTreeCommit(manifest),
source_commit: manifest.source_commit,
uploaded_assets: uploaded.map((asset) => ({
id: asset.id,