@kungfu-tech/buildchain 3.0.9-alpha.8 → 4.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +39 -0
- package/README.md +17 -13
- package/actions/promote-buildchain-ref/README.md +0 -10
- package/actions/release-tail/README.md +6 -10
- package/architecture/internal-capabilities.json +502 -0
- package/architecture/maintainability-baseline.json +59 -0
- package/architecture/maintainability-policy.json +1384 -0
- package/architecture/release-tail-contract-inventory.json +587 -0
- package/architecture/v3-core-mechanism-inventory.json +1043 -0
- package/architecture/v3-core-mechanism-inventory.md +67 -0
- package/architecture/v4-adopter-delivery-parity.json +47 -0
- package/architecture/v4-architecture-constitution.md +210 -0
- package/architecture/v4-bootstrap-authority.json +56 -0
- package/architecture/v4-canonical-contract-fixtures.json +105 -0
- package/architecture/v4-capability-state-machine-manifest.json +480 -0
- package/architecture/v4-capability-state-machine-manifest.schema.json +202 -0
- package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.json +830 -0
- package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.md +223 -0
- package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.schema.json +318 -0
- package/architecture/v4-delivery-warrant-shadow-fixtures.json +227 -0
- package/architecture/v4-delivery-warrant-shadow-fixtures.schema.json +67 -0
- package/architecture/v4-exception-ledger.json +5 -0
- package/architecture/v4-exception-ledger.schema.json +56 -0
- package/architecture/v4-partial-mutation-recovery-qualification.json +65 -0
- package/architecture/v4-platform-stage-checkpoints.json +97 -0
- package/architecture/v4-provider-operation-journal-contract.json +113 -0
- package/architecture/v4-release-activation-shadow-domain.json +61 -0
- package/architecture/v4-release-train-parity.json +68 -0
- package/architecture/v4-rust-libnode-bridge-evaluation.json +107 -0
- package/architecture/v4-rust-libnode-bridge-spike.md +85 -0
- package/architecture/v4-stable-publication-fence.json +66 -0
- package/architecture/v4-stage-capsule-contract.json +90 -0
- package/architecture/v4-stage-capsule-qualification.json +99 -0
- package/architecture/v4-stage-capsule-resume-planner.json +52 -0
- package/architecture/v4-stage-capsule-store-contract.json +72 -0
- package/bin/buildchain.mjs +15 -6
- package/contracts/auditable-demo-scenario-v1.schema.json +1 -1
- package/contracts/buildchain-v2-residuals-v1.json +2 -2
- package/contracts/fixtures/v4-delivery-warrant-trace-v1/golden.json +158 -0
- package/contracts/fixtures/v4-delivery-warrant-trace-v1/property.json +380 -0
- package/contracts/fixtures/v4-delivery-warrant-trace-v1/replay.json +163 -0
- package/contracts/fixtures/v4-partial-mutation-recovery-v1/shared.json +155 -0
- package/contracts/fixtures/v4-provider-operation-journal-v1/shared.json +457 -0
- package/contracts/fixtures/v4-provider-readback-idempotency-v1/shared.json +682 -0
- package/contracts/fixtures/v4-release-activation-shadow-v1/shared.json +53 -0
- package/contracts/fixtures/v4-stable-publication-fence-v1/shared.json +56 -0
- package/contracts/fixtures/v4-stage-capsule-resume-v1/late-platform-failure.json +176 -0
- package/contracts/fixtures/v4-stage-capsule-store-v1/shared.json +132 -0
- package/contracts/fixtures/v4-stage-capsule-v1/shared.json +111 -0
- package/contracts/v4-canonical-contracts-v1.schema.json +182 -0
- package/contracts/v4-delivery-warrant-semantic-diff-report-v1.schema.json +284 -0
- package/contracts/v4-delivery-warrant-trace-v1.schema.json +215 -0
- package/contracts/v4-host-contract-v1.schema.json +135 -0
- package/contracts/v4-partial-mutation-recovery-v1.schema.json +168 -0
- package/contracts/v4-provider-operation-journal-v1.schema.json +381 -0
- package/contracts/v4-release-activation-shadow-v1.schema.json +186 -0
- package/contracts/v4-stable-publication-fence-v1.schema.json +125 -0
- package/contracts/v4-stage-capsule-resume-v1.schema.json +225 -0
- package/contracts/v4-stage-capsule-store-v1.schema.json +154 -0
- package/contracts/v4-stage-capsule-v1.schema.json +178 -0
- package/crates/buildchain-v4-bridge/Cargo.lock +213 -0
- package/crates/buildchain-v4-bridge/Cargo.toml +12 -0
- package/crates/buildchain-v4-bridge/src/main.rs +495 -0
- package/dist/site/agent-index.json +0 -3
- package/dist/site/artifact-schemas.json +0 -6
- package/dist/site/buildchain-contract.json +103 -397
- package/dist/site/buildchain-site.json +302 -270
- package/dist/site/capability-registry.json +9 -11
- package/dist/site/cli-registry.json +8 -30
- package/dist/site/controller-registry.json +48 -8
- package/dist/site/kfd-claims.json +129 -142
- package/dist/site/kfd-upstream-aggregate.json +9 -9
- package/dist/site/manual-registry.json +18 -49
- package/dist/site/node-api-registry.json +1882 -4118
- package/dist/site/page-registry.json +278 -230
- package/dist/site/public-surface-audit.json +87 -185
- package/dist/site/publication-authority-registry.json +11 -1
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +3 -7
- package/dist/site/schemas/kfd-support-projection-v1.schema.json +106 -0
- package/dist/site/site-manifest.json +22 -38
- package/dist/site/workflow-registry.json +80 -35
- package/docs/MAP.md +8 -4
- package/docs/auditable-demo.md +2 -2
- package/docs/aws-us-elastic-runner-burst-plane.md +7 -59
- package/docs/cli-reference.md +15 -92
- package/docs/cli.md +14 -14
- package/docs/dev-alpha-candidate-patrol.md +3 -11
- package/docs/dev-delivery-warrant.md +28 -100
- package/docs/engineering-housekeeper.md +12 -4
- package/docs/getting-started.md +1 -1
- package/docs/install.md +5 -5
- package/docs/kfd-support.md +2 -7
- package/docs/lifecycle-protocol.md +2 -4
- package/docs/node-api-reference.md +414 -523
- package/docs/release-flow.md +31 -31
- package/docs/release-governance.md +16 -28
- package/docs/release-passport.md +2 -15
- package/docs/release-tail-contract.md +13 -6
- package/docs/release-tail-provider-plane.md +13 -19
- package/docs/release-train.md +4 -4
- package/docs/reusable-build-surface.md +14 -27
- package/docs/site-bundle-contract.md +1 -5
- package/docs/stable-candidate-patrol.md +7 -7
- package/docs/v4-canonical-contracts.md +92 -0
- package/docs/v4-delivery-warrant-read-candidate.md +73 -0
- package/docs/v4-delivery-warrant-semantic-diff.md +75 -0
- package/docs/v4-production-release.md +63 -0
- package/docs/v4-stage-capsule.md +193 -0
- package/docs/versioning.md +3 -3
- package/package.json +19 -17
- package/packages/core/adopter-delivery-gate.js +576 -0
- package/packages/core/adopter-delivery-json.js +66 -0
- package/packages/core/artifact-signing.js +0 -61
- package/packages/core/artifact-verification-envelope.js +5 -5
- package/packages/core/build-facts.js +12 -4
- package/packages/core/buildchain-agent-manuals.js +0 -2
- package/packages/core/buildchain-config.js +4 -69
- package/packages/core/buildchain-contract.js +232 -46
- package/packages/core/buildchain-kfd-claims.js +1 -1
- package/packages/core/channel-candidate.js +0 -8
- package/packages/core/channel-promotion-baseline.js +0 -52
- package/packages/core/controller-evidence.js +3 -4
- package/packages/core/dev-alpha-candidate-selection.js +2 -10
- package/packages/core/dev-delivery-warrant-cancellation.js +0 -1
- package/packages/core/dev-delivery-warrant-settlement.js +1 -5
- package/packages/core/dev-delivery-warrant.js +12 -52
- package/packages/core/diagnostics.js +3 -8
- package/packages/core/github-governance-authority.js +3 -1
- package/packages/core/kfd-adopter-category-driver.js +167 -0
- package/packages/core/kfd-adopter-manifest.js +47 -46
- package/packages/core/kfd-gate.js +15 -45
- package/packages/core/paper-agent-entry.js +7 -16
- package/packages/core/paper-fleet.js +2 -2
- package/packages/core/paper-repository.js +2 -3
- package/packages/core/paper-scaffold-content.js +2 -23
- package/packages/core/paper.js +11 -43
- package/packages/core/publication-reproducibility.js +4 -4
- package/packages/core/release-line-bootstrap.js +21 -8
- package/packages/core/release-passport-contract.js +5 -5
- package/packages/core/release-passport.js +20 -131
- package/packages/core/self-dogfood-version.js +48 -35
- package/packages/core/spawn-command.js +232 -8
- package/packages/core/v4-adopter-delivery-parity.js +219 -0
- package/packages/core/v4-canonical-contracts.js +284 -0
- package/packages/core/v4-delivery-warrant-fixture-runner.js +371 -0
- package/packages/core/v4-delivery-warrant-read-candidate.js +279 -0
- package/packages/core/v4-delivery-warrant-semantic-diff-gate.js +352 -0
- package/packages/core/v4-delivery-warrant-shadow-adapter.js +447 -0
- package/packages/core/v4-partial-mutation-recovery-qualification.js +395 -0
- package/packages/core/v4-platform-stage-checkpoints.js +471 -0
- package/packages/core/v4-provider-operation-journal.js +531 -0
- package/packages/core/v4-provider-readback-idempotency.js +394 -0
- package/packages/core/v4-release-activation-shadow.js +519 -0
- package/packages/core/v4-stable-publication-fence.js +357 -0
- package/packages/core/v4-stage-capsule-local-store.js +426 -0
- package/packages/core/v4-stage-capsule-qualification-campaign.js +512 -0
- package/packages/core/v4-stage-capsule-qualification.js +456 -0
- package/packages/core/v4-stage-capsule-resume-planner.js +397 -0
- package/packages/core/v4-stage-capsule-store.js +401 -0
- package/packages/core/v4-stage-capsule.js +319 -0
- package/scripts/assemble-self-publication-admission.mjs +1 -1
- package/scripts/audit-publication-control-plane.mjs +5 -5
- package/scripts/auditable-demo-bundle-verification.mjs +3 -2
- package/scripts/auditable-demo-platform.mjs +2 -2
- package/scripts/auditable-demo-renditions.mjs +1 -1
- package/scripts/auditable-demo.mjs +2 -2
- package/scripts/aws-macos-jit-controller-core.mjs +13 -346
- package/scripts/aws-macos-jit-controller-runtime.mjs +2 -210
- package/scripts/aws-macos-jit-controller.mjs +37 -275
- package/scripts/aws-macos-jit-core.mjs +3 -41
- package/scripts/aws-macos-jit.mjs +0 -12
- package/scripts/aws-windows-jit-campaign.mjs +2 -2
- package/scripts/aws-windows-jit-controller-core.mjs +1 -1
- package/scripts/aws-windows-jit-controller.mjs +3 -3
- package/scripts/build-contract-core.mjs +3 -8
- package/scripts/build-standalone-binary.mjs +3 -14
- package/scripts/buildchain-channel-router.mjs +4 -0
- package/scripts/buildchain-cli-help.mjs +7 -13
- package/scripts/buildchain-contract-lock.mjs +0 -6
- package/scripts/check-action-bundles.mjs +3 -4
- package/scripts/check-internal-architecture.mjs +7 -6
- package/scripts/check-inventory.mjs +30 -25
- package/scripts/check-v4-public-dogfood-contract.mjs +270 -0
- package/scripts/create-release-bundle.mjs +8 -4
- package/scripts/dev-alpha-candidate-patrol.mjs +1 -22
- package/scripts/dev-delivery-proof.mjs +2 -54
- package/scripts/dev-delivery-warrant.mjs +59 -77
- package/scripts/dev-pr-auto-merge.mjs +4 -30
- package/scripts/dev-pr-delivery-warrant.mjs +0 -55
- package/scripts/dispatch-artifact-signing-authority.mjs +7 -4
- package/scripts/generate-buildchain-kfd-witnesses.mjs +94 -88
- package/scripts/generate-channel-build-workflow.mjs +54 -24
- package/scripts/generate-channel-promotion-workflow.mjs +15 -6
- package/scripts/generate-site-bundle.mjs +5 -21
- package/scripts/git-fetch-process-tree.mjs +34 -1
- package/scripts/init-repo.mjs +64 -159
- package/scripts/inspect-artifact-signing-requests.mjs +0 -6
- package/scripts/locked-source-checkout.mjs +3 -4
- package/scripts/maintainability-metrics.mjs +8 -2
- package/scripts/npm-publish-dry-run.mjs +2 -2
- package/scripts/npm-publish-transaction.mjs +2 -2
- package/scripts/publication-commit-evidence.mjs +23 -69
- package/scripts/release-candidate-resolver.mjs +11 -17
- package/scripts/release-tail.mjs +3 -49
- package/scripts/resume-from-candidate-run.mjs +9 -123
- package/scripts/run-lifecycle-core.mjs +12 -13
- package/scripts/seal-artifact-signing-requests.mjs +17 -21
- package/scripts/site-capability-metadata.mjs +2 -7
- package/scripts/stable-candidate-qualification.mjs +10 -10
- package/scripts/v4-architecture.mjs +12 -2
- package/scripts/v4-bridge-bootstrap.mjs +141 -0
- package/scripts/v4-bridge-evidence.mjs +141 -0
- package/scripts/v4-host-adapter.mjs +182 -0
- package/scripts/v4-platform-stage-checkpoint-rehearsal.mjs +207 -0
- package/scripts/v4-stage-capsule-qualification.mjs +528 -0
- package/scripts/v4-stage-capsule-resume-rehearsal.mjs +57 -0
- package/scripts/v4-warrant-shadow-plan.mjs +601 -0
- package/scripts/verify-golden-path.mjs +5 -5
- package/scripts/web-surface-cloudfront-rewrite.mjs +15 -15
- package/scripts/web-surface-core.mjs +2 -8
- package/scripts/workflow-call-contract.mjs +5 -184
- package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-perspective.json +0 -16
- package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-replay.json +0 -57
- package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +0 -47
- package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +0 -47
- package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +0 -40
- package/contracts/next-development-request-v1.schema.json +0 -66
- package/contracts/next-development-transition-v1.schema.json +0 -292
- package/contracts/publication-rehearsal-capsule-v1.schema.json +0 -173
- package/dist/site/schemas/publication-rehearsal-capsule-v1.schema.json +0 -269
- package/dist/site/schemas/release-tail-capabilities-v1.schema.json +0 -353
- package/dist/site/schemas/release-tail-provider-bindings-v1.schema.json +0 -94
- package/docs/next-development-transition.md +0 -119
- package/docs/publication-rehearsal.md +0 -94
- package/packages/core/buildchain-compatibility-proof.js +0 -631
- package/packages/core/dev-delivery-native-proof.js +0 -333
- package/packages/core/dev-delivery-warrant-shadow.js +0 -502
- package/packages/core/next-development-candidate-reservation.js +0 -186
- package/packages/core/next-development-controller.js +0 -726
- package/packages/core/next-development-projection.js +0 -288
- package/packages/core/next-development-transition.js +0 -738
- package/packages/core/publication-rehearsal-projection.js +0 -173
- package/packages/core/publication-rehearsal-runtime.js +0 -921
- package/scripts/aws-macos-jit-instance-rehydrate.mjs +0 -260
- package/scripts/aws-macos-jit-source-rebind.mjs +0 -724
- package/scripts/dev-delivery-native-run.mjs +0 -187
- package/scripts/dev-delivery-two-phase.mjs +0 -598
- package/scripts/generate-next-development-guidance.mjs +0 -49
- package/scripts/materialize-self-release-candidate-version.mjs +0 -137
- package/scripts/next-development-self-dogfood-harness.mjs +0 -409
- package/scripts/next-development-self-dogfood.mjs +0 -532
- package/scripts/next-development-transition.mjs +0 -47
- package/scripts/release-candidate-tail-reseal.mjs +0 -426
- package/templates/native-dev-delivery.yml +0 -82
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import crypto from "node:crypto";
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { pathToFileURL } from "node:url";
|
|
6
|
-
|
|
7
|
-
const CONTRACT = "kungfu-buildchain-release-candidate-tail-reseal/v1";
|
|
8
|
-
const SHA = /^[0-9a-f]{40}$/u;
|
|
9
|
-
const ROOT = /^sha256:[0-9a-f]{64}$/u;
|
|
10
|
-
const REQUIRED_PLATFORMS = ["linux-arm64", "linux-x64", "macos-arm64", "windows-x64"];
|
|
11
|
-
const REQUIRED_SUCCESS_JOBS = [
|
|
12
|
-
"build / Linux ARM64",
|
|
13
|
-
"build / Linux x64",
|
|
14
|
-
"build / macOS ARM64",
|
|
15
|
-
"build / Windows x64",
|
|
16
|
-
"build / Control detached signing Linux ARM64",
|
|
17
|
-
"build / Control detached signing Linux x64",
|
|
18
|
-
"build / Control detached signing macOS ARM64",
|
|
19
|
-
"build / Control detached signing Windows x64",
|
|
20
|
-
"build / Finalize signed artifact Linux ARM64",
|
|
21
|
-
"build / Finalize signed artifact Linux x64",
|
|
22
|
-
"build / Finalize signed artifact Windows x64",
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
function required(value, label) {
|
|
26
|
-
const result = String(value ?? "").trim();
|
|
27
|
-
if (!result) throw new Error(`${label} is required`);
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function exactSha(value, label) {
|
|
32
|
-
const result = required(value, label);
|
|
33
|
-
if (!SHA.test(result)) throw new Error(`${label} must be an exact lowercase Git SHA`);
|
|
34
|
-
return result;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function contentRoot(value, label) {
|
|
38
|
-
const result = required(value, label);
|
|
39
|
-
if (!ROOT.test(result)) throw new Error(`${label} must be a sha256 content root`);
|
|
40
|
-
return result;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function integer(value, label) {
|
|
44
|
-
const result = Number(value);
|
|
45
|
-
if (!Number.isSafeInteger(result) || result <= 0) throw new Error(`${label} must be a positive integer`);
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function object(value, label) {
|
|
50
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
|
|
51
|
-
return value;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function readJson(file, label = file) {
|
|
55
|
-
try {
|
|
56
|
-
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
57
|
-
} catch (error) {
|
|
58
|
-
throw new Error(`could not read ${label}: ${error.message}`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function writeJson(file, value) {
|
|
63
|
-
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
64
|
-
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function sha256Json(value) {
|
|
68
|
-
return `sha256:${crypto.createHash("sha256").update(JSON.stringify(value)).digest("hex")}`;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function sha256File(file) {
|
|
72
|
-
const hash = crypto.createHash("sha256");
|
|
73
|
-
const descriptor = fs.openSync(file, "r");
|
|
74
|
-
const buffer = Buffer.allocUnsafe(1024 * 1024);
|
|
75
|
-
try {
|
|
76
|
-
for (;;) {
|
|
77
|
-
const count = fs.readSync(descriptor, buffer, 0, buffer.length, null);
|
|
78
|
-
if (count === 0) break;
|
|
79
|
-
hash.update(buffer.subarray(0, count));
|
|
80
|
-
}
|
|
81
|
-
} finally {
|
|
82
|
-
fs.closeSync(descriptor);
|
|
83
|
-
}
|
|
84
|
-
return `sha256:${hash.digest("hex")}`;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function appendOutputs(values) {
|
|
88
|
-
const output = process.env.GITHUB_OUTPUT;
|
|
89
|
-
if (!output) return;
|
|
90
|
-
const lines = [];
|
|
91
|
-
for (const [name, value] of Object.entries(values)) {
|
|
92
|
-
const text = String(value ?? "");
|
|
93
|
-
if (text.includes("\n")) {
|
|
94
|
-
const marker = `BUILDCHAIN_${crypto.randomBytes(8).toString("hex")}`;
|
|
95
|
-
lines.push(`${name}<<${marker}\n${text}\n${marker}`);
|
|
96
|
-
} else {
|
|
97
|
-
lines.push(`${name}=${text}`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
fs.appendFileSync(output, `${lines.join("\n")}\n`);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async function githubJson(repository, apiPath, token) {
|
|
104
|
-
const response = await fetch(`https://api.github.com/repos/${repository}${apiPath}`, {
|
|
105
|
-
headers: {
|
|
106
|
-
accept: "application/vnd.github+json",
|
|
107
|
-
authorization: `Bearer ${required(token, "GITHUB_TOKEN")}`,
|
|
108
|
-
"x-github-api-version": "2022-11-28",
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
if (!response.ok) throw new Error(`GitHub API ${apiPath} failed: HTTP ${response.status}`);
|
|
112
|
-
return response.json();
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
async function pagedGithubItems(repository, apiPath, key, token) {
|
|
116
|
-
const values = [];
|
|
117
|
-
for (let page = 1; ; page += 1) {
|
|
118
|
-
const separator = apiPath.includes("?") ? "&" : "?";
|
|
119
|
-
const response = await githubJson(repository, `${apiPath}${separator}per_page=100&page=${page}`, token);
|
|
120
|
-
const items = Array.isArray(response?.[key]) ? response[key] : [];
|
|
121
|
-
values.push(...items);
|
|
122
|
-
if (items.length < 100) return values;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export function normalizeTailResealRequest(raw) {
|
|
127
|
-
const request = object(raw, "tail reseal request");
|
|
128
|
-
if (request.contract !== CONTRACT) throw new Error(`tail reseal contract must be ${CONTRACT}`);
|
|
129
|
-
const source = object(request.source, "source");
|
|
130
|
-
const target = object(request.target, "target");
|
|
131
|
-
const candidateRuntime = object(request.candidateRuntime, "candidateRuntime");
|
|
132
|
-
const controller = object(request.consumerController, "consumerController");
|
|
133
|
-
const failure = object(request.failure, "failure");
|
|
134
|
-
const authority = object(request.authority, "authority");
|
|
135
|
-
const platforms = Array.isArray(request.platforms) ? request.platforms : [];
|
|
136
|
-
if (platforms.length !== REQUIRED_PLATFORMS.length) throw new Error("tail reseal requires exactly four platform bindings");
|
|
137
|
-
const normalizedPlatforms = platforms.map((entry, index) => {
|
|
138
|
-
const platform = object(entry, `platforms[${index}]`);
|
|
139
|
-
return {
|
|
140
|
-
id: required(platform.id, `platforms[${index}].id`),
|
|
141
|
-
name: required(platform.name, `platforms[${index}].name`),
|
|
142
|
-
runner: required(platform.runner, `platforms[${index}].runner`),
|
|
143
|
-
artifactName: required(platform.artifactName, `platforms[${index}].artifactName`),
|
|
144
|
-
artifactDigest: contentRoot(platform.artifactDigest, `platforms[${index}].artifactDigest`),
|
|
145
|
-
manifestArtifactName: required(platform.manifestArtifactName, `platforms[${index}].manifestArtifactName`),
|
|
146
|
-
manifestArtifactDigest: contentRoot(platform.manifestArtifactDigest, `platforms[${index}].manifestArtifactDigest`),
|
|
147
|
-
artifactPaths: required(platform.artifactPaths, `platforms[${index}].artifactPaths`),
|
|
148
|
-
};
|
|
149
|
-
}).sort((left, right) => left.id.localeCompare(right.id));
|
|
150
|
-
if (JSON.stringify(normalizedPlatforms.map(({ id }) => id)) !== JSON.stringify([...REQUIRED_PLATFORMS].sort())) {
|
|
151
|
-
throw new Error(`tail reseal platforms must be ${REQUIRED_PLATFORMS.join(", ")}`);
|
|
152
|
-
}
|
|
153
|
-
if (new Set(normalizedPlatforms.flatMap((entry) => [entry.artifactName, entry.manifestArtifactName])).size !== 8) {
|
|
154
|
-
throw new Error("tail reseal artifact names must be unique");
|
|
155
|
-
}
|
|
156
|
-
return {
|
|
157
|
-
contract: CONTRACT,
|
|
158
|
-
repository: required(request.repository, "repository"),
|
|
159
|
-
source: {
|
|
160
|
-
runId: integer(source.runId, "source.runId"),
|
|
161
|
-
runAttempt: integer(source.runAttempt, "source.runAttempt"),
|
|
162
|
-
sha: exactSha(source.sha, "source.sha"),
|
|
163
|
-
tree: exactSha(source.tree, "source.tree"),
|
|
164
|
-
workflowFile: required(source.workflowFile, "source.workflowFile").replace(/^\.github\/workflows\//u, ""),
|
|
165
|
-
workflowName: required(source.workflowName, "source.workflowName"),
|
|
166
|
-
},
|
|
167
|
-
target: {
|
|
168
|
-
channel: required(target.channel, "target.channel"),
|
|
169
|
-
ref: required(target.ref, "target.ref").replace(/^refs\/heads\//u, ""),
|
|
170
|
-
baseSha: exactSha(target.baseSha, "target.baseSha"),
|
|
171
|
-
version: required(target.version, "target.version"),
|
|
172
|
-
},
|
|
173
|
-
candidateRuntime: {
|
|
174
|
-
repository: required(candidateRuntime.repository, "candidateRuntime.repository"),
|
|
175
|
-
ref: required(candidateRuntime.ref, "candidateRuntime.ref"),
|
|
176
|
-
sha: exactSha(candidateRuntime.sha, "candidateRuntime.sha"),
|
|
177
|
-
contractDigest: contentRoot(candidateRuntime.contractDigest, "candidateRuntime.contractDigest"),
|
|
178
|
-
},
|
|
179
|
-
consumerController: {
|
|
180
|
-
repository: required(controller.repository, "consumerController.repository"),
|
|
181
|
-
sha: exactSha(controller.sha, "consumerController.sha"),
|
|
182
|
-
tree: exactSha(controller.tree, "consumerController.tree"),
|
|
183
|
-
},
|
|
184
|
-
failure: {
|
|
185
|
-
jobId: integer(failure.jobId, "failure.jobId"),
|
|
186
|
-
jobName: required(failure.jobName, "failure.jobName"),
|
|
187
|
-
stepName: required(failure.stepName, "failure.stepName"),
|
|
188
|
-
},
|
|
189
|
-
authority: {
|
|
190
|
-
repository: required(authority.repository, "authority.repository"),
|
|
191
|
-
runId: integer(authority.runId, "authority.runId"),
|
|
192
|
-
runtimeSha: exactSha(authority.runtimeSha, "authority.runtimeSha"),
|
|
193
|
-
resultArtifact: required(authority.resultArtifact, "authority.resultArtifact"),
|
|
194
|
-
resultArtifactDigest: contentRoot(authority.resultArtifactDigest, "authority.resultArtifactDigest"),
|
|
195
|
-
},
|
|
196
|
-
controllerPlanArtifact: required(request.controllerPlanArtifact, "controllerPlanArtifact"),
|
|
197
|
-
platforms: normalizedPlatforms,
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function exactArtifact(artifacts, name, digest, label) {
|
|
202
|
-
const matches = artifacts.filter((artifact) => artifact.name === name);
|
|
203
|
-
if (matches.length !== 1) throw new Error(`${label} must resolve to exactly one retained artifact`);
|
|
204
|
-
const artifact = matches[0];
|
|
205
|
-
if (artifact.expired === true) throw new Error(`${label} is expired`);
|
|
206
|
-
if (artifact.digest !== digest) throw new Error(`${label} digest mismatch`);
|
|
207
|
-
return artifact;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function validateTailResealEvent({ request, event, repository }) {
|
|
211
|
-
const allowedActions = new Set(["opened", "synchronize", "reopened", "ready_for_review"]);
|
|
212
|
-
if (request.repository !== repository) throw new Error("tail reseal repository differs from the caller repository");
|
|
213
|
-
if (!allowedActions.has(event.action)) {
|
|
214
|
-
throw new Error(`tail reseal requires a pull_request source event, got ${event.action || "<none>"}`);
|
|
215
|
-
}
|
|
216
|
-
if (event.pull_request?.head?.repo?.full_name !== repository) throw new Error("tail reseal rejects fork pull requests");
|
|
217
|
-
if (event.pull_request?.head?.sha !== request.source.sha) throw new Error("tail reseal source SHA differs from the exact PR head");
|
|
218
|
-
if (event.pull_request?.base?.ref !== request.target.ref || event.pull_request?.base?.sha !== request.target.baseSha) {
|
|
219
|
-
throw new Error("tail reseal target ref or frozen base SHA differs from the exact PR event");
|
|
220
|
-
}
|
|
221
|
-
if (request.target.channel !== "alpha" || !/^alpha\/v\d+\/v\d+\.\d+$/u.test(request.target.ref)) {
|
|
222
|
-
throw new Error("tail reseal is limited to an exact Alpha channel");
|
|
223
|
-
}
|
|
224
|
-
if (request.candidateRuntime.repository !== "kungfu-systems/buildchain" || request.candidateRuntime.ref !== "v3-alpha") {
|
|
225
|
-
throw new Error("tail reseal requires the deployed floating v3-alpha candidate contract");
|
|
226
|
-
}
|
|
227
|
-
if (request.consumerController.repository !== repository) throw new Error("tail reseal consumer controller must remain in the caller repository");
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function validateTailResealRun({ request, run }) {
|
|
231
|
-
const workflowFile = String(run.path || "").split("@")[0].replace(/^\.github\/workflows\//u, "");
|
|
232
|
-
const exactRun =
|
|
233
|
-
Number(run.id) === request.source.runId &&
|
|
234
|
-
Number(run.run_attempt) === request.source.runAttempt &&
|
|
235
|
-
run.event === "workflow_dispatch" &&
|
|
236
|
-
run.status === "completed" &&
|
|
237
|
-
run.conclusion === "failure" &&
|
|
238
|
-
run.head_sha === request.source.sha &&
|
|
239
|
-
workflowFile === request.source.workflowFile &&
|
|
240
|
-
run.name === request.source.workflowName;
|
|
241
|
-
if (!exactRun) throw new Error("tail reseal source run is not the exact retained failed Build run");
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function validateTailResealJobs({ request, jobs }) {
|
|
245
|
-
const byName = new Map(jobs.map((job) => [job.name, job]));
|
|
246
|
-
for (const name of REQUIRED_SUCCESS_JOBS) {
|
|
247
|
-
if (byName.get(name)?.conclusion !== "success") throw new Error(`tail reseal required source job did not succeed: ${name}`);
|
|
248
|
-
}
|
|
249
|
-
const failedJob = jobs.find((job) => Number(job.id) === request.failure.jobId);
|
|
250
|
-
const failedSteps = (failedJob?.steps || []).filter((step) => step.conclusion === "failure").map((step) => step.name);
|
|
251
|
-
const exactFailure =
|
|
252
|
-
failedJob?.name === request.failure.jobName &&
|
|
253
|
-
failedJob?.conclusion === "failure" &&
|
|
254
|
-
JSON.stringify(failedSteps) === JSON.stringify([request.failure.stepName]);
|
|
255
|
-
if (!exactFailure) throw new Error("tail reseal failure boundary differs from the single allowed macOS finalization step");
|
|
256
|
-
if (request.failure.jobName !== "build / Finalize signed artifact macOS ARM64" || request.failure.stepName !== "Recompute manifest over final signed bytes") {
|
|
257
|
-
throw new Error("tail reseal only accepts the known macOS finalization blocker");
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function validateTailResealArtifacts({ request, artifacts, authorityRun, authorityArtifacts }) {
|
|
262
|
-
for (const platform of request.platforms) {
|
|
263
|
-
exactArtifact(artifacts, platform.artifactName, platform.artifactDigest, `${platform.id} payload`);
|
|
264
|
-
exactArtifact(artifacts, platform.manifestArtifactName, platform.manifestArtifactDigest, `${platform.id} manifest`);
|
|
265
|
-
}
|
|
266
|
-
const controllerPlan = artifacts.filter((artifact) => artifact.name === request.controllerPlanArtifact);
|
|
267
|
-
if (controllerPlan.length !== 1 || controllerPlan[0].expired === true) throw new Error("tail reseal controller plan artifact is unavailable");
|
|
268
|
-
if (authorityRun.status !== "completed" || authorityRun.conclusion !== "success") throw new Error("tail reseal signing authority run is not successful");
|
|
269
|
-
exactArtifact(authorityArtifacts, request.authority.resultArtifact, request.authority.resultArtifactDigest, "macOS signing authority result");
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
function writeTailResealPlan(request) {
|
|
273
|
-
const output = path.resolve(process.env.BUILDCHAIN_TAIL_RESEAL_REQUEST_PATH || ".buildchain/tail-reseal/request.json");
|
|
274
|
-
writeJson(output, request);
|
|
275
|
-
appendOutputs({
|
|
276
|
-
enabled: "true",
|
|
277
|
-
"request-path": path.relative(process.cwd(), output),
|
|
278
|
-
"request-root": sha256Json(request),
|
|
279
|
-
"platforms-json": JSON.stringify(request.platforms),
|
|
280
|
-
"source-run-id": request.source.runId,
|
|
281
|
-
"source-run-attempt": request.source.runAttempt,
|
|
282
|
-
"source-sha": request.source.sha,
|
|
283
|
-
"source-tree": request.source.tree,
|
|
284
|
-
"target-channel": request.target.channel,
|
|
285
|
-
"target-ref": request.target.ref,
|
|
286
|
-
"target-version": request.target.version,
|
|
287
|
-
"candidate-runtime-ref": request.candidateRuntime.ref,
|
|
288
|
-
"candidate-runtime-sha": request.candidateRuntime.sha,
|
|
289
|
-
"candidate-runtime-contract-digest": request.candidateRuntime.contractDigest,
|
|
290
|
-
"consumer-controller-sha": request.consumerController.sha,
|
|
291
|
-
"authority-run-id": request.authority.runId,
|
|
292
|
-
"authority-result-artifact": request.authority.resultArtifact,
|
|
293
|
-
"controller-plan-artifact": request.controllerPlanArtifact,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
async function plan() {
|
|
298
|
-
const token = required(process.env.GITHUB_TOKEN, "GITHUB_TOKEN");
|
|
299
|
-
const raw = required(process.env.BUILDCHAIN_TAIL_RESEAL_REQUEST_JSON, "BUILDCHAIN_TAIL_RESEAL_REQUEST_JSON");
|
|
300
|
-
const request = normalizeTailResealRequest(JSON.parse(raw));
|
|
301
|
-
const event = readJson(required(process.env.GITHUB_EVENT_PATH, "GITHUB_EVENT_PATH"), "GitHub event");
|
|
302
|
-
const repository = required(process.env.GITHUB_REPOSITORY, "GITHUB_REPOSITORY");
|
|
303
|
-
validateTailResealEvent({ request, event, repository });
|
|
304
|
-
|
|
305
|
-
const [sourceCommit, controllerCommit, run, jobs, artifacts, authorityRun, authorityArtifacts] = await Promise.all([
|
|
306
|
-
githubJson(repository, `/git/commits/${request.source.sha}`, token),
|
|
307
|
-
githubJson(repository, `/git/commits/${request.consumerController.sha}`, token),
|
|
308
|
-
githubJson(repository, `/actions/runs/${request.source.runId}`, token),
|
|
309
|
-
pagedGithubItems(repository, `/actions/runs/${request.source.runId}/jobs?filter=latest`, "jobs", token),
|
|
310
|
-
pagedGithubItems(repository, `/actions/runs/${request.source.runId}/artifacts`, "artifacts", token),
|
|
311
|
-
githubJson(request.authority.repository, `/actions/runs/${request.authority.runId}`, token),
|
|
312
|
-
pagedGithubItems(request.authority.repository, `/actions/runs/${request.authority.runId}/artifacts`, "artifacts", token),
|
|
313
|
-
]);
|
|
314
|
-
if (sourceCommit.tree?.sha !== request.source.tree) throw new Error("tail reseal source tree mismatch");
|
|
315
|
-
if (controllerCommit.tree?.sha !== request.consumerController.tree) throw new Error("tail reseal consumer controller tree mismatch");
|
|
316
|
-
validateTailResealRun({ request, run });
|
|
317
|
-
validateTailResealJobs({ request, jobs });
|
|
318
|
-
validateTailResealArtifacts({ request, artifacts, authorityRun, authorityArtifacts });
|
|
319
|
-
writeTailResealPlan(request);
|
|
320
|
-
return request;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function locateManifest(root, platformId) {
|
|
324
|
-
const matches = [];
|
|
325
|
-
const visit = (directory) => {
|
|
326
|
-
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
327
|
-
const absolute = path.join(directory, entry.name);
|
|
328
|
-
if (entry.isDirectory()) visit(absolute);
|
|
329
|
-
else if (entry.name === "manifest.json") {
|
|
330
|
-
const value = readJson(absolute);
|
|
331
|
-
if (value?.contract === "kungfu-buildchain-artifact" && value?.platform?.id === platformId) matches.push({ absolute, value });
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
visit(root);
|
|
336
|
-
if (matches.length !== 1) throw new Error(`expected exactly one ${platformId} platform manifest under ${root}, found ${matches.length}`);
|
|
337
|
-
return matches[0];
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
export function verifyTailResealPlatform() {
|
|
341
|
-
const request = normalizeTailResealRequest(readJson(required(process.env.BUILDCHAIN_TAIL_RESEAL_REQUEST_PATH, "BUILDCHAIN_TAIL_RESEAL_REQUEST_PATH")));
|
|
342
|
-
const platformId = required(process.env.BUILDCHAIN_TAIL_RESEAL_PLATFORM_ID, "BUILDCHAIN_TAIL_RESEAL_PLATFORM_ID");
|
|
343
|
-
const platform = request.platforms.find((entry) => entry.id === platformId);
|
|
344
|
-
if (!platform) throw new Error(`tail reseal request does not bind platform ${platformId}`);
|
|
345
|
-
const root = path.resolve(process.env.BUILDCHAIN_TAIL_RESEAL_ARTIFACT_ROOT || ".");
|
|
346
|
-
const { absolute, value: manifest } = locateManifest(root, platformId);
|
|
347
|
-
if (manifest.artifactName !== platform.artifactName) throw new Error(`${platformId} manifest artifact name mismatch`);
|
|
348
|
-
if (manifest.git?.repository !== request.repository || manifest.git?.sha !== request.source.sha) throw new Error(`${platformId} manifest source mismatch`);
|
|
349
|
-
if (String(manifest.git?.runId || "") !== String(request.source.runId) || String(manifest.git?.runAttempt || "") !== String(request.source.runAttempt)) {
|
|
350
|
-
throw new Error(`${platformId} manifest original run mismatch`);
|
|
351
|
-
}
|
|
352
|
-
const files = Array.isArray(manifest.files) ? manifest.files : [];
|
|
353
|
-
if (files.length === 0) throw new Error(`${platformId} manifest has no files`);
|
|
354
|
-
for (const file of files) {
|
|
355
|
-
const relative = required(file.path || file.name, `${platformId} manifest file path`);
|
|
356
|
-
const absoluteFile = path.resolve(root, relative);
|
|
357
|
-
if (!absoluteFile.startsWith(`${root}${path.sep}`) || !fs.existsSync(absoluteFile) || !fs.statSync(absoluteFile).isFile()) {
|
|
358
|
-
throw new Error(`${platformId} manifest file is missing: ${relative}`);
|
|
359
|
-
}
|
|
360
|
-
if (Number(file.size ?? file.bytes) !== fs.statSync(absoluteFile).size) throw new Error(`${platformId} manifest file size mismatch: ${relative}`);
|
|
361
|
-
const expected = contentRoot(`sha256:${String(file.sha256 || "").replace(/^sha256:/u, "")}`, `${platformId} ${relative} digest`);
|
|
362
|
-
if (sha256File(absoluteFile) !== expected) throw new Error(`${platformId} manifest file digest mismatch: ${relative}`);
|
|
363
|
-
}
|
|
364
|
-
appendOutputs({ "manifest-path": path.relative(process.cwd(), absolute), "manifest-root": sha256File(absolute) });
|
|
365
|
-
return manifest;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
export function sealTailResealReceipt() {
|
|
369
|
-
const request = normalizeTailResealRequest(readJson(required(process.env.BUILDCHAIN_TAIL_RESEAL_REQUEST_PATH, "BUILDCHAIN_TAIL_RESEAL_REQUEST_PATH")));
|
|
370
|
-
const manifestsRoot = path.resolve(required(process.env.BUILDCHAIN_TAIL_RESEAL_MANIFESTS_ROOT, "BUILDCHAIN_TAIL_RESEAL_MANIFESTS_ROOT"));
|
|
371
|
-
const manifests = request.platforms.map((platform) => {
|
|
372
|
-
const { absolute, value } = locateManifest(manifestsRoot, platform.id);
|
|
373
|
-
if (value.artifactName !== platform.artifactName || value.git?.sha !== request.source.sha) throw new Error(`${platform.id} resealed manifest identity mismatch`);
|
|
374
|
-
return { platformId: platform.id, artifactName: platform.artifactName, manifestRoot: sha256File(absolute) };
|
|
375
|
-
});
|
|
376
|
-
const receipt = {
|
|
377
|
-
contract: CONTRACT,
|
|
378
|
-
action: "reused-tail-reseal",
|
|
379
|
-
repository: request.repository,
|
|
380
|
-
source: request.source,
|
|
381
|
-
target: request.target,
|
|
382
|
-
candidateRuntime: request.candidateRuntime,
|
|
383
|
-
recoveryTooling: {
|
|
384
|
-
ref: required(process.env.BUILDCHAIN_TAIL_RESEAL_TOOLING_REF, "BUILDCHAIN_TAIL_RESEAL_TOOLING_REF"),
|
|
385
|
-
sha: exactSha(process.env.BUILDCHAIN_TAIL_RESEAL_TOOLING_SHA, "BUILDCHAIN_TAIL_RESEAL_TOOLING_SHA"),
|
|
386
|
-
},
|
|
387
|
-
consumerController: request.consumerController,
|
|
388
|
-
originalFailure: request.failure,
|
|
389
|
-
signingAuthority: request.authority,
|
|
390
|
-
artifacts: request.platforms.map(({ id, artifactName, artifactDigest, manifestArtifactName, manifestArtifactDigest }) => ({
|
|
391
|
-
platformId: id,
|
|
392
|
-
artifactName,
|
|
393
|
-
originalArtifactDigest: artifactDigest,
|
|
394
|
-
manifestArtifactName,
|
|
395
|
-
originalManifestArtifactDigest: manifestArtifactDigest,
|
|
396
|
-
})),
|
|
397
|
-
resealedManifests: manifests,
|
|
398
|
-
skippedStages: ["install", "build", "verify", "platform-matrix"],
|
|
399
|
-
rerunStages: ["macos-signing-finalization", "aggregate", "candidate-passport"],
|
|
400
|
-
payloadPolicy: "reuse-exact-platform-bytes-except-authoritative-macos-signing-import",
|
|
401
|
-
currentRun: {
|
|
402
|
-
id: required(process.env.GITHUB_RUN_ID, "GITHUB_RUN_ID"),
|
|
403
|
-
attempt: required(process.env.GITHUB_RUN_ATTEMPT, "GITHUB_RUN_ATTEMPT"),
|
|
404
|
-
},
|
|
405
|
-
};
|
|
406
|
-
receipt.root = sha256Json(receipt);
|
|
407
|
-
const output = path.resolve(process.env.BUILDCHAIN_TAIL_RESEAL_RECEIPT_PATH || ".buildchain/tail-reseal/receipt.json");
|
|
408
|
-
writeJson(output, receipt);
|
|
409
|
-
appendOutputs({ "receipt-path": path.relative(process.cwd(), output), "receipt-root": receipt.root, "receipt-json": JSON.stringify(receipt) });
|
|
410
|
-
return receipt;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
export async function releaseCandidateTailResealCli(argv = process.argv.slice(2)) {
|
|
414
|
-
const command = argv[0];
|
|
415
|
-
if (command === "plan") return plan();
|
|
416
|
-
if (command === "verify-platform") return verifyTailResealPlatform();
|
|
417
|
-
if (command === "seal") return sealTailResealReceipt();
|
|
418
|
-
throw new Error("usage: release-candidate-tail-reseal.mjs <plan|verify-platform|seal>");
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
422
|
-
releaseCandidateTailResealCli().catch((error) => {
|
|
423
|
-
console.error(`::error::${String(error.message || error).replace(/\r?\n/gu, "%0A")}`);
|
|
424
|
-
process.exitCode = 1;
|
|
425
|
-
});
|
|
426
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
name: Protected Dev Delivery
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
repository_dispatch:
|
|
5
|
-
types: [buildchain-dev-delivery-wake]
|
|
6
|
-
workflow_dispatch:
|
|
7
|
-
inputs:
|
|
8
|
-
target-branch:
|
|
9
|
-
description: "Protected dev/vN/vN.M branch"
|
|
10
|
-
required: true
|
|
11
|
-
expected-pr-number:
|
|
12
|
-
description: "Exact ready and approved PR number"
|
|
13
|
-
required: true
|
|
14
|
-
type: number
|
|
15
|
-
expected-head-sha:
|
|
16
|
-
description: "Exact immutable PR head"
|
|
17
|
-
required: true
|
|
18
|
-
source-identity-root:
|
|
19
|
-
description: "Semantic source identity root"
|
|
20
|
-
required: true
|
|
21
|
-
source-patch-root:
|
|
22
|
-
description: "Semantic patch root"
|
|
23
|
-
required: true
|
|
24
|
-
assignment-root:
|
|
25
|
-
description: "Native Assignment root"
|
|
26
|
-
required: true
|
|
27
|
-
initiative-root:
|
|
28
|
-
description: "Parent Initiative root"
|
|
29
|
-
required: true
|
|
30
|
-
plan-root:
|
|
31
|
-
description: "Native qualification plan root"
|
|
32
|
-
required: true
|
|
33
|
-
closure-root:
|
|
34
|
-
description: "Affected closure root"
|
|
35
|
-
required: true
|
|
36
|
-
dependency-root:
|
|
37
|
-
description: "Dependency graph root"
|
|
38
|
-
required: true
|
|
39
|
-
toolchain-root:
|
|
40
|
-
description: "Native toolchain root"
|
|
41
|
-
required: true
|
|
42
|
-
affected-paths-json:
|
|
43
|
-
description: "JSON array representing the affected closure"
|
|
44
|
-
required: true
|
|
45
|
-
native-proof-json:
|
|
46
|
-
description: "Optional reusable native proof"
|
|
47
|
-
required: false
|
|
48
|
-
default: ""
|
|
49
|
-
|
|
50
|
-
permissions:
|
|
51
|
-
actions: write
|
|
52
|
-
contents: write
|
|
53
|
-
pull-requests: write
|
|
54
|
-
checks: read
|
|
55
|
-
statuses: write
|
|
56
|
-
|
|
57
|
-
jobs:
|
|
58
|
-
deliver:
|
|
59
|
-
uses: kungfu-systems/buildchain/.github/workflows/dev-pr-auto-merge.yml@v3
|
|
60
|
-
with:
|
|
61
|
-
target-branch: ${{ github.event.client_payload.targetBranch || inputs.target-branch }}
|
|
62
|
-
expected-pr-number: ${{ github.event.client_payload.pullRequestNumber || inputs.expected-pr-number }}
|
|
63
|
-
expected-head-sha: ${{ github.event.client_payload.sourceHead || inputs.expected-head-sha }}
|
|
64
|
-
source-workflow-run-id: ${{ github.event.client_payload.sourceWorkflowRunId || github.run_id }}
|
|
65
|
-
delivery-warrant-mode: required
|
|
66
|
-
assignment-root: ${{ github.event.client_payload.assignmentRoot || inputs.assignment-root }}
|
|
67
|
-
initiative-root: ${{ github.event.client_payload.initiativeRoot || inputs.initiative-root }}
|
|
68
|
-
source-identity-root: ${{ github.event.client_payload.sourceIdentityRoot || inputs.source-identity-root }}
|
|
69
|
-
source-patch-root: ${{ github.event.client_payload.sourcePatchRoot || inputs.source-patch-root }}
|
|
70
|
-
plan-root: ${{ github.event.client_payload.planRoot || inputs.plan-root }}
|
|
71
|
-
closure-root: ${{ github.event.client_payload.closureRoot || inputs.closure-root }}
|
|
72
|
-
dependency-root: ${{ github.event.client_payload.dependencyRoot || inputs.dependency-root }}
|
|
73
|
-
toolchain-root: ${{ github.event.client_payload.toolchainRoot || inputs.toolchain-root }}
|
|
74
|
-
affected-paths-json: ${{ github.event_name == 'repository_dispatch' && toJSON(github.event.client_payload.affectedPaths) || inputs.affected-paths-json }}
|
|
75
|
-
native-proof-json: ${{ inputs.native-proof-json || '' }}
|
|
76
|
-
native-command: cmake -S . -B build && cmake --build build --parallel && ctest --test-dir build --output-on-failure
|
|
77
|
-
native-heartbeat-seconds: 300
|
|
78
|
-
delivery-class: native-proof-required
|
|
79
|
-
landing-mode: queue
|
|
80
|
-
dry-run: false
|
|
81
|
-
secrets:
|
|
82
|
-
github-token: ${{ secrets.BUILDCHAIN_PROMOTION_TOKEN }}
|