@kungfu-tech/buildchain 3.0.9-alpha.9 → 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 -10
- 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 -4
- package/dist/site/artifact-schemas.json +0 -8
- package/dist/site/buildchain-contract.json +103 -397
- package/dist/site/buildchain-site.json +302 -386
- package/dist/site/capability-registry.json +9 -11
- package/dist/site/cli-registry.json +8 -53
- package/dist/site/controller-registry.json +48 -8
- package/dist/site/kfd-claims.json +129 -167
- package/dist/site/kfd-upstream-aggregate.json +9 -9
- package/dist/site/manual-registry.json +18 -49
- package/dist/site/node-api-registry.json +4345 -7345
- package/dist/site/page-registry.json +278 -346
- package/dist/site/public-surface-audit.json +85 -404
- package/dist/site/publication-authority-registry.json +11 -1
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +3 -9
- 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 +78 -35
- package/docs/MAP.md +8 -5
- package/docs/auditable-demo.md +2 -2
- package/docs/aws-us-elastic-runner-burst-plane.md +7 -59
- package/docs/cli-reference.md +15 -213
- package/docs/cli.md +14 -14
- package/docs/dev-alpha-candidate-patrol.md +3 -11
- package/docs/dev-delivery-warrant.md +29 -194
- 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 -554
- 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 -5
- package/package.json +19 -19
- 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-channel-identity.js +3 -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 +20 -67
- package/packages/core/dev-delivery-warrant.js +50 -138
- 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 -16
- 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 -64
- package/scripts/dev-delivery-warrant.mjs +61 -86
- 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 +8 -27
- 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 +3 -20
- 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/dev-delivery-authority-v2.schema.json +0 -253
- 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/dev-delivery-authority-v2.schema.json +0 -442
- 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/dev-delivery-qualification-landing-adr.md +0 -137
- 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-authority.js +0 -996
- package/packages/core/dev-delivery-native-proof.js +0 -418
- 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-authority.mjs +0 -368
- package/scripts/dev-delivery-native-run.mjs +0 -235
- package/scripts/dev-delivery-two-phase-resume.mjs +0 -90
- package/scripts/dev-delivery-two-phase.mjs +0 -577
- 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 -86
|
@@ -1,115 +1,121 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import crypto from "node:crypto";
|
|
3
2
|
import fs from "node:fs";
|
|
4
|
-
import { execFileSync } from "node:child_process";
|
|
5
|
-
import { createRequire } from "node:module";
|
|
6
3
|
import path from "node:path";
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
7
5
|
import { pathToFileURL } from "node:url";
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
createBuildchainKfd1Witness,
|
|
8
|
+
createBuildchainKfd2Claims,
|
|
9
|
+
createBuildchainKfd3ArtifactWitness,
|
|
10
|
+
createBuildchainKfd3PrebuildWitness,
|
|
11
|
+
} from "../packages/core/buildchain-kfd-claims.js";
|
|
12
|
+
import {
|
|
13
|
+
BUILDCHAIN_KFD1_CONTRACT_WORLD_WITNESS_PATH,
|
|
14
|
+
BUILDCHAIN_KFD2_CLAIMS_DIR,
|
|
15
|
+
BUILDCHAIN_KFD3_ARTIFACT_WITNESS_PATH,
|
|
16
|
+
BUILDCHAIN_KFD3_PREBUILD_WITNESS_PATH,
|
|
17
|
+
} from "../packages/core/buildchain-layout.js";
|
|
15
18
|
import { writeGitHubOutputs } from "./build-contract-core.mjs";
|
|
16
|
-
|
|
17
|
-
const evidenceSources = { "KFD-1": "dist/site/release-passport-check-manifest.json", "KFD-2": "dist/site/kfd-claims.json", "KFD-3": "dist/site/public-surface-audit.json", "KFD-4": "packages/core/kfd-product-gates.js", "KFD-5": "packages/core/kfd-product-gates.js", "KFD-7": "packages/core/kfd-product-gates.js", "KFD-10": "packages/core/dev-delivery-warrant.js" };
|
|
19
|
+
|
|
18
20
|
function parseArgs(argv = process.argv.slice(2)) {
|
|
19
|
-
const args = {
|
|
21
|
+
const args = {
|
|
22
|
+
cwd: process.cwd(),
|
|
23
|
+
outputDir: ".buildchain/kfd",
|
|
24
|
+
sourceSha: process.env.BUILDCHAIN_SOURCE_SHA || "",
|
|
25
|
+
};
|
|
20
26
|
for (let index = 0; index < argv.length; index += 1) {
|
|
21
27
|
const arg = argv[index];
|
|
22
|
-
if (arg === "--cwd")
|
|
23
|
-
|
|
24
|
-
else if (arg === "--
|
|
25
|
-
|
|
26
|
-
else
|
|
28
|
+
if (arg === "--cwd") {
|
|
29
|
+
args.cwd = argv[++index] || args.cwd;
|
|
30
|
+
} else if (arg === "--output-dir") {
|
|
31
|
+
args.outputDir = argv[++index] || args.outputDir;
|
|
32
|
+
} else if (arg === "--source-sha") {
|
|
33
|
+
args.sourceSha = argv[++index] || args.sourceSha;
|
|
34
|
+
} else if (arg === "--help") {
|
|
35
|
+
args.help = true;
|
|
36
|
+
} else {
|
|
37
|
+
throw new Error(`unknown argument: ${arg}`);
|
|
38
|
+
}
|
|
27
39
|
}
|
|
28
40
|
return args;
|
|
29
41
|
}
|
|
42
|
+
|
|
30
43
|
function gitSha(cwd) {
|
|
31
|
-
try {
|
|
44
|
+
try {
|
|
45
|
+
return execFileSync("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" }).trim();
|
|
46
|
+
} catch {
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
32
49
|
}
|
|
33
|
-
|
|
34
|
-
function
|
|
35
|
-
function relative(root, filePath) { return path.relative(root, filePath).replace(/\\/g, "/"); }
|
|
36
|
-
function writeJson(root, relativePath, value) {
|
|
37
|
-
const filePath = path.join(root, relativePath);
|
|
50
|
+
|
|
51
|
+
function writeJson(filePath, value) {
|
|
38
52
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
39
53
|
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
|
|
40
|
-
return { path: relativePath, sha256: fileDigest(filePath), filePath };
|
|
41
54
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
|
|
56
|
+
function toRepoRelative(cwd, filePath) {
|
|
57
|
+
return path.relative(cwd, filePath).replace(/\\/g, "/");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function generateBuildchainKfdWitnesses({
|
|
61
|
+
cwd = process.cwd(),
|
|
62
|
+
outputDir = ".buildchain/kfd",
|
|
63
|
+
sourceSha = "",
|
|
64
|
+
emitOutputs = true,
|
|
65
|
+
} = {}) {
|
|
66
|
+
const root = path.resolve(cwd);
|
|
67
|
+
const outDir = path.resolve(root, outputDir);
|
|
68
|
+
const resolvedSourceSha = sourceSha || gitSha(root);
|
|
45
69
|
const outputPath = (canonicalPath) => path.join(outDir, path.relative(".buildchain/kfd", canonicalPath));
|
|
46
|
-
const paths = {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
const paths = {
|
|
71
|
+
kfd1Witness: outputPath(BUILDCHAIN_KFD1_CONTRACT_WORLD_WITNESS_PATH),
|
|
72
|
+
kfd3PrebuildWitness: outputPath(BUILDCHAIN_KFD3_PREBUILD_WITNESS_PATH),
|
|
73
|
+
kfd3ArtifactWitness: outputPath(BUILDCHAIN_KFD3_ARTIFACT_WITNESS_PATH),
|
|
74
|
+
kfd2ClaimsDir: outputPath(BUILDCHAIN_KFD2_CLAIMS_DIR),
|
|
75
|
+
};
|
|
76
|
+
writeJson(paths.kfd1Witness, createBuildchainKfd1Witness({ root, sourceSha: resolvedSourceSha }));
|
|
77
|
+
writeJson(paths.kfd3PrebuildWitness, createBuildchainKfd3PrebuildWitness({ root, sourceSha: resolvedSourceSha }));
|
|
78
|
+
writeJson(paths.kfd3ArtifactWitness, createBuildchainKfd3ArtifactWitness({ root, sourceSha: resolvedSourceSha }));
|
|
79
|
+
const witnessFiles = {
|
|
80
|
+
"kfd-1-witness": toRepoRelative(root, paths.kfd1Witness),
|
|
81
|
+
"kfd-3-prebuild-witness": toRepoRelative(root, paths.kfd3PrebuildWitness),
|
|
82
|
+
"kfd-3-artifact-witness": toRepoRelative(root, paths.kfd3ArtifactWitness),
|
|
83
|
+
};
|
|
51
84
|
const kfd2ClaimPaths = createBuildchainKfd2Claims({ root, witnessFiles }).map((claim) => {
|
|
52
|
-
const slug = String(claim.id || "claim")
|
|
53
|
-
|
|
85
|
+
const slug = String(claim.id || "claim")
|
|
86
|
+
.replace(/^claim:/, "")
|
|
87
|
+
.replace(/[^0-9A-Za-z._-]+/g, "-")
|
|
88
|
+
.replace(/^-+|-+$/g, "") || "claim";
|
|
89
|
+
const claimPath = path.join(paths.kfd2ClaimsDir, `${slug}.json`);
|
|
90
|
+
writeJson(claimPath, claim);
|
|
91
|
+
return claimPath;
|
|
54
92
|
});
|
|
55
|
-
const outputs = {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const profile = readJson(path.join(kfdRoot, "verifier/fixtures/kfd-7/valid-domain-profile.json"));
|
|
66
|
-
profile.evidenceObligations = profile.evidenceObligations.map((entry) => ({ ...entry, status: "passed", artifactRefs: ["qualification-proof"], residualRisk: "Bound to the retained Buildchain product gate cut; independent certification remains external." }));
|
|
67
|
-
profile.activation = { decision: "activate", evidenceCut: `git://${REPOSITORY}@${sourceSha}`, independentReview: "review://protected-release-review", productWitnesses: ["qualification-proof"], residualRisk: "The product gate is non-qualifying and non-self-certifying." };
|
|
68
|
-
profile.domainProfile = { ...profile.domainProfile, product: "Buildchain", implementation: `git+https://github.com/${REPOSITORY}@${sourceSha}`, qualificationStatus: "qualified" };
|
|
69
|
-
return [["domain-profile", profile]];
|
|
70
|
-
}
|
|
71
|
-
async function generateProductGate(root, outDir, standard, sourceSha, checkedAt) {
|
|
72
|
-
const records = productRecords(root, standard, sourceSha).map(([role, value], index) => ({ role, ...writeJson(outDir, `records/${standard}-${index}.json`, value) }));
|
|
73
|
-
const kinds = standard === "kfd-4" ? [["projection-fsck", "projection-fsck"], ["negative", "negative-fixture"]] : standard === "kfd-5" ? [["negative", "negative-fixture"]] : [["qualification-proof", "qualification-proof"], ["independent-review", "independent-review"], ["negative", "negative-fixture"]];
|
|
74
|
-
const evidence = kinds.map(([id, kind]) => ({ id, kind, ...writeJson(outDir, `evidence/${standard}-${id}.json`, { schemaVersion: 1, contract: "kungfu-buildchain-kfd-adopter-evidence-reference", id, kind, source: { repository: REPOSITORY, sha: sourceSha }, observedAt: checkedAt, status: "retained", nonClaim: "This product-owned reference does not independently qualify or certify KFD adoption." }) }));
|
|
75
|
-
const input = { schemaVersion: 1, contract: KFD_PRODUCT_GATE_INPUT_CONTRACT, standard, standardRevision: kfdStandards.standards[standard].revision, source: { repository: REPOSITORY, sha: sourceSha }, evidenceCut: { generatedAt: checkedAt, expiresAt: new Date(Date.parse(checkedAt) + 86400000).toISOString() }, records: records.map(({ role, path, sha256 }) => ({ role, path, sha256 })), evidence: evidence.map(({ id, kind, path, sha256 }) => ({ id, kind, path, sha256 })), responsibility: { owner: REPOSITORY, evidenceOwner: "Buildchain maintainers", proofOwner: "Buildchain release gate" }, nonClaims: ["A passed product gate does not qualify, certify, activate, or independently approve KFD adoption."] };
|
|
76
|
-
const gate = await evaluateKfdProductGate({ cwd: outDir, input, expectedSourceSha: sourceSha, checkedAt });
|
|
77
|
-
if (gate.status !== "passed" || !validateKfdProductGateResult(gate, { expectedSourceSha: sourceSha, checkedAt }).valid) throw new Error(`${standard} product gate failed: ${JSON.stringify(gate.issues)}`);
|
|
78
|
-
writeJson(outDir, `${standard}/product-gate.json`, gate);
|
|
79
|
-
return gate;
|
|
80
|
-
}
|
|
81
|
-
export async function generateBuildchainKfdAdopterRelease({ cwd = process.cwd(), outputDir = ".buildchain/kfd/adopter-release", sourceSha = "", checkedAt = new Date().toISOString(), emitOutputs = true } = {}) {
|
|
82
|
-
const root = path.resolve(cwd), outDir = path.resolve(root, outputDir);
|
|
83
|
-
if (!/^[0-9a-f]{40}$/.test(sourceSha) || !Number.isFinite(Date.parse(checkedAt))) throw new Error("source SHA and checked-at must be exact");
|
|
84
|
-
for (const sourcePath of Object.values(evidenceSources)) if (!fs.statSync(path.join(root, sourcePath)).isFile()) throw new Error(`required Buildchain evidence source is missing: ${sourcePath}`);
|
|
85
|
-
const packageArtifactRoot = installedKfdPackageArtifactRoot(), gates = [];
|
|
86
|
-
for (const standard of ["kfd-4", "kfd-5", "kfd-7"]) gates.push(await generateProductGate(root, outDir, standard, sourceSha, checkedAt));
|
|
87
|
-
const sourceRoot = kfdProductGateDigest({ repository: REPOSITORY, sourceSha, files: [...new Set(Object.values(evidenceSources))].sort().map((sourcePath) => ({ path: sourcePath, sha256: fileDigest(path.join(root, sourcePath)) })) });
|
|
88
|
-
let manifest = initAdopterManifest({ manifestId: "buildchain-v3-full-cut", adopterId: REPOSITORY, artifactKind: "git-commit", artifactCoordinate: `${REPOSITORY}@${sourceSha}`, artifactRoot: sourceRoot, scope: "Buildchain v3 release and protected delivery authority", packageArtifactRoot, verifiedAt: checkedAt, maxAgeSeconds: 86400, packageRoot: kfdRoot });
|
|
89
|
-
const gateById = new Map(gates.map((gate) => [gate.standard.toUpperCase(), gate]));
|
|
90
|
-
for (const id of ["KFD-1", "KFD-2", "KFD-3", "KFD-4", "KFD-5", "KFD-7"]) {
|
|
91
|
-
const row = manifest.decisions.find((entry) => entry.id === id);
|
|
92
|
-
const sourcePath = evidenceSources[id];
|
|
93
|
-
const sourceEvidence = (kind, rootValue = fileDigest(path.join(root, sourcePath))) => ({ kind, coordinate: `git+https://github.com/${REPOSITORY}@${sourceSha}#${sourcePath}`, root: rootValue, observedAt: checkedAt, kfdPackageRoot: packageArtifactRoot });
|
|
94
|
-
row.state = "candidate"; row.usage = "used"; row.implementationEvidence = [sourceEvidence("implementation")]; row.verificationEvidence = [sourceEvidence("verification", gateById.get(id)?.gateRoot)]; row.gaps = ["Independent decision-specific assessment and certification remain external."];
|
|
93
|
+
const outputs = {
|
|
94
|
+
"kfd-1-witness-jsons": toRepoRelative(root, paths.kfd1Witness),
|
|
95
|
+
"kfd-2-claim-jsons": kfd2ClaimPaths.map((claimPath) => toRepoRelative(root, claimPath)).join(","),
|
|
96
|
+
"kfd-3-prebuild-witness-jsons": toRepoRelative(root, paths.kfd3PrebuildWitness),
|
|
97
|
+
"kfd-3-artifact-witness-jsons": toRepoRelative(root, paths.kfd3ArtifactWitness),
|
|
98
|
+
"source-sha": resolvedSourceSha,
|
|
99
|
+
"output-dir": toRepoRelative(root, outDir),
|
|
100
|
+
};
|
|
101
|
+
if (emitOutputs) {
|
|
102
|
+
writeGitHubOutputs(outputs);
|
|
95
103
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const gatePath = writeJson(outDir, "kfd-adopter-manifest-gate.json", manifestGate).filePath, support = createKfdLegacySupportMatrixProjection({ manifest, manifestGate });
|
|
102
|
-
if (!validateKfdLegacySupportMatrixProjection(support, { manifest, manifestGate }).valid) throw new Error("generated KFD support projection failed");
|
|
103
|
-
const supportPath = writeJson(outDir, "kfd-support.json", support).filePath;
|
|
104
|
-
const outputs = { "kfd-adopter-manifest-json": relative(root, manifestPath), "kfd-adopter-manifest-gate-json": relative(root, gatePath), "kfd-support-matrix-json": relative(root, supportPath), "kfd-product-gate-jsons": gates.map((gate) => relative(root, path.join(outDir, gate.standard, "product-gate.json"))).join(","), "kfd-adopter-manifest-root": manifestGate.authority.manifestRoot, "kfd-adopter-gate-root": manifestGate.gateRoot, "kfd-package-artifact-root": packageArtifactRoot, "source-sha": sourceSha };
|
|
105
|
-
if (emitOutputs) writeGitHubOutputs(outputs);
|
|
106
|
-
return { schemaVersion: 1, contract: "kungfu-buildchain-kfd-adopter-release-generation", status: "passed", qualifying: false, selfCertified: false, outputs };
|
|
104
|
+
return {
|
|
105
|
+
schemaVersion: 1,
|
|
106
|
+
contract: "kungfu-buildchain-self-kfd-witness-generation",
|
|
107
|
+
outputs,
|
|
108
|
+
};
|
|
107
109
|
}
|
|
110
|
+
|
|
108
111
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
109
112
|
try {
|
|
110
113
|
const args = parseArgs();
|
|
111
|
-
if (args.help)
|
|
112
|
-
|
|
114
|
+
if (args.help) {
|
|
115
|
+
process.stdout.write("Usage: generate-buildchain-kfd-witnesses [--cwd <repo>] [--output-dir <dir>] [--source-sha <sha>]\n");
|
|
116
|
+
process.exit(0);
|
|
117
|
+
}
|
|
118
|
+
process.stdout.write(`${JSON.stringify(generateBuildchainKfdWitnesses(args), null, 2)}\n`);
|
|
113
119
|
} catch (error) {
|
|
114
120
|
console.error(`buildchain self KFD witnesses: ${error.message}`);
|
|
115
121
|
process.exitCode = 1;
|
|
@@ -46,26 +46,22 @@ function routerInputs(inputBlock) {
|
|
|
46
46
|
|
|
47
47
|
function routerOutputs(outputBlock) {
|
|
48
48
|
const forwarded = outputBlock
|
|
49
|
-
.replace(
|
|
50
|
-
/^ value: \$\{\{ jobs\.[^.]+\.outputs\.([a-z0-9-]+) \|\| jobs\.[^.]+\.outputs\.\1 \}\}$/gm,
|
|
51
|
-
" value: ${{ jobs.alpha.outputs.$1 || jobs.stable.outputs.$1 }}",
|
|
52
|
-
)
|
|
53
|
-
.replace(/^ value: \$\{\{ jobs\.[^.]+\.outputs\.([^ }]+) \}\}$/gm, " value: ${{ jobs.alpha.outputs.$1 || jobs.stable.outputs.$1 }}")
|
|
49
|
+
.replace(/^ value: \$\{\{ jobs\.[^.]+\.outputs\.([^ }]+) \}\}$/gm, " value: ${{ jobs.override.outputs.$1 || jobs.alpha.outputs.$1 || jobs.stable.outputs.$1 }}")
|
|
54
50
|
.replaceAll("build-lifecycle", "build-channel-router")
|
|
55
|
-
.replace("value: ${{ jobs.alpha.outputs.controller-plan-artifact || jobs.stable.outputs.controller-plan-artifact }}", "value: ${{ jobs.controller-plan.outputs.controller-plan-artifact }}")
|
|
56
|
-
.replace("value: ${{ jobs.alpha.outputs.controller-plan-json || jobs.stable.outputs.controller-plan-json }}", "value: ${{ jobs.controller-plan.outputs.controller-plan-json }}")
|
|
57
|
-
.replace("value: ${{ jobs.alpha.outputs.controller-plan-digest || jobs.stable.outputs.controller-plan-digest }}", "value: ${{ jobs.controller-plan.outputs.controller-plan-digest }}")
|
|
58
|
-
.replace("value: ${{ jobs.alpha.outputs.controller-receipt-artifact || jobs.stable.outputs.controller-receipt-artifact }}", "value: ${{ jobs.controller-receipt.outputs.controller-receipt-artifact }}")
|
|
59
|
-
.replace("value: ${{ jobs.alpha.outputs.controller-receipt-json || jobs.stable.outputs.controller-receipt-json }}", "value: ${{ jobs.controller-receipt.outputs.controller-receipt-json }}")
|
|
60
|
-
.replace("value: ${{ jobs.alpha.outputs.controller-receipt-digest || jobs.stable.outputs.controller-receipt-digest }}", "value: ${{ jobs.controller-receipt.outputs.controller-receipt-digest }}")
|
|
61
|
-
.replace("value: ${{ jobs.alpha.outputs.controller-receipt-status || jobs.stable.outputs.controller-receipt-status }}", "value: ${{ jobs.controller-receipt.outputs.controller-receipt-status }}")
|
|
51
|
+
.replace("value: ${{ jobs.override.outputs.controller-plan-artifact || jobs.alpha.outputs.controller-plan-artifact || jobs.stable.outputs.controller-plan-artifact }}", "value: ${{ jobs.controller-plan.outputs.controller-plan-artifact }}")
|
|
52
|
+
.replace("value: ${{ jobs.override.outputs.controller-plan-json || jobs.alpha.outputs.controller-plan-json || jobs.stable.outputs.controller-plan-json }}", "value: ${{ jobs.controller-plan.outputs.controller-plan-json }}")
|
|
53
|
+
.replace("value: ${{ jobs.override.outputs.controller-plan-digest || jobs.alpha.outputs.controller-plan-digest || jobs.stable.outputs.controller-plan-digest }}", "value: ${{ jobs.controller-plan.outputs.controller-plan-digest }}")
|
|
54
|
+
.replace("value: ${{ jobs.override.outputs.controller-receipt-artifact || jobs.alpha.outputs.controller-receipt-artifact || jobs.stable.outputs.controller-receipt-artifact }}", "value: ${{ jobs.controller-receipt.outputs.controller-receipt-artifact }}")
|
|
55
|
+
.replace("value: ${{ jobs.override.outputs.controller-receipt-json || jobs.alpha.outputs.controller-receipt-json || jobs.stable.outputs.controller-receipt-json }}", "value: ${{ jobs.controller-receipt.outputs.controller-receipt-json }}")
|
|
56
|
+
.replace("value: ${{ jobs.override.outputs.controller-receipt-digest || jobs.alpha.outputs.controller-receipt-digest || jobs.stable.outputs.controller-receipt-digest }}", "value: ${{ jobs.controller-receipt.outputs.controller-receipt-digest }}")
|
|
57
|
+
.replace("value: ${{ jobs.override.outputs.controller-receipt-status || jobs.alpha.outputs.controller-receipt-status || jobs.stable.outputs.controller-receipt-status }}", "value: ${{ jobs.controller-receipt.outputs.controller-receipt-status }}")
|
|
62
58
|
.replace(
|
|
63
|
-
/( credential-island-macos-artifact:\n(?: .*\n)*? value:) \$\{\{ jobs\.alpha\.outputs\.artifact-name \|\| jobs\.stable\.outputs\.artifact-name \}\}/,
|
|
64
|
-
"$1 ${{ jobs.alpha.outputs.credential-island-macos-artifact || jobs.stable.outputs.credential-island-macos-artifact }}",
|
|
59
|
+
/( credential-island-macos-artifact:\n(?: .*\n)*? value:) \$\{\{ jobs\.override\.outputs\.artifact-name \|\| jobs\.alpha\.outputs\.artifact-name \|\| jobs\.stable\.outputs\.artifact-name \}\}/,
|
|
60
|
+
"$1 ${{ jobs.override.outputs.credential-island-macos-artifact || jobs.alpha.outputs.credential-island-macos-artifact || jobs.stable.outputs.credential-island-macos-artifact }}",
|
|
65
61
|
)
|
|
66
62
|
.replace(
|
|
67
|
-
/( credential-island-macos-manifest-artifact:\n(?: .*\n)*? value:) \$\{\{ jobs\.alpha\.outputs\.manifest-artifact-name \|\| jobs\.stable\.outputs\.manifest-artifact-name \}\}/,
|
|
68
|
-
"$1 ${{ jobs.alpha.outputs.credential-island-macos-manifest-artifact || jobs.stable.outputs.credential-island-macos-manifest-artifact }}",
|
|
63
|
+
/( credential-island-macos-manifest-artifact:\n(?: .*\n)*? value:) \$\{\{ jobs\.override\.outputs\.manifest-artifact-name \|\| jobs\.alpha\.outputs\.manifest-artifact-name \|\| jobs\.stable\.outputs\.manifest-artifact-name \}\}/,
|
|
64
|
+
"$1 ${{ jobs.override.outputs.credential-island-macos-manifest-artifact || jobs.alpha.outputs.credential-island-macos-manifest-artifact || jobs.stable.outputs.credential-island-macos-manifest-artifact }}",
|
|
69
65
|
);
|
|
70
66
|
return [
|
|
71
67
|
" buildchain-channel:",
|
|
@@ -85,6 +81,12 @@ function forwardedInputs(names) {
|
|
|
85
81
|
return names
|
|
86
82
|
.map((name) => {
|
|
87
83
|
if (name === "buildchain-ref") return ` buildchain-ref: \${{ needs.resolve-channel.outputs.buildchain-ref }}`;
|
|
84
|
+
if (name === "buildchain-expected-channel") {
|
|
85
|
+
return " buildchain-expected-channel: ${{ needs.resolve-channel.outputs.channel }}";
|
|
86
|
+
}
|
|
87
|
+
if (name === "buildchain-expected-major") {
|
|
88
|
+
return " buildchain-expected-major: ${{ needs.resolve-channel.outputs.major }}";
|
|
89
|
+
}
|
|
88
90
|
if (name === "buildchain-contract-lock-path") {
|
|
89
91
|
return " buildchain-contract-lock-path: ${{ needs.resolve-channel.outputs.contract-lock-path }}";
|
|
90
92
|
}
|
|
@@ -158,6 +160,7 @@ function routerControllerReceiptJob() {
|
|
|
158
160
|
needs:
|
|
159
161
|
- resolve-channel
|
|
160
162
|
- controller-plan
|
|
163
|
+
- override
|
|
161
164
|
- alpha
|
|
162
165
|
- stable
|
|
163
166
|
if: \${{ always() && needs.controller-plan.result == 'success' }}
|
|
@@ -188,9 +191,9 @@ function routerControllerReceiptJob() {
|
|
|
188
191
|
env:
|
|
189
192
|
BUILDCHAIN_CONTROLLER_PLAN_PATH: .buildchain/controller/plan.json
|
|
190
193
|
BUILDCHAIN_CONTROLLER_STAGES_JSON: >-
|
|
191
|
-
[{"id":"resolve-channel","status":"\${{ needs.resolve-channel.result }}"},{"id":"alpha","status":"\${{ needs.alpha.result }}"},{"id":"stable","status":"\${{ needs.stable.result }}"},{"id":"aggregate","status":"\${{ needs.resolve-channel.outputs.channel == 'alpha' && needs.alpha.result || needs.stable.result }}"}]
|
|
192
|
-
BUILDCHAIN_CONTROLLER_EVIDENCE_JSON: \${{ (needs.alpha.outputs.controller-receipt-digest != '' || needs.stable.outputs.controller-receipt-digest != '') && format('[{{"kind":"nested-controller-receipt","digest":"{0}"}}]', needs.alpha.outputs.controller-receipt-digest || needs.stable.outputs.controller-receipt-digest) || '[]' }}
|
|
193
|
-
BUILDCHAIN_CONTROLLER_REASON_CODE: \${{ ((needs.resolve-channel.outputs.channel == 'alpha' && needs.alpha.result == 'success') || (needs.resolve-channel.outputs.channel == 'stable' && needs.stable.result == 'success')) && '' || 'nested-build-incomplete' }}
|
|
194
|
+
[{"id":"resolve-channel","status":"\${{ needs.resolve-channel.result }}"},{"id":"override","status":"\${{ needs.override.result }}"},{"id":"alpha","status":"\${{ needs.alpha.result }}"},{"id":"stable","status":"\${{ needs.stable.result }}"},{"id":"aggregate","status":"\${{ needs.resolve-channel.outputs.runtime-override == 'true' && needs.override.result || needs.resolve-channel.outputs.channel == 'alpha' && needs.alpha.result || needs.stable.result }}"}]
|
|
195
|
+
BUILDCHAIN_CONTROLLER_EVIDENCE_JSON: \${{ (needs.override.outputs.controller-receipt-digest != '' || needs.alpha.outputs.controller-receipt-digest != '' || needs.stable.outputs.controller-receipt-digest != '') && format('[{{"kind":"nested-controller-receipt","digest":"{0}"}}]', needs.override.outputs.controller-receipt-digest || needs.alpha.outputs.controller-receipt-digest || needs.stable.outputs.controller-receipt-digest) || '[]' }}
|
|
196
|
+
BUILDCHAIN_CONTROLLER_REASON_CODE: \${{ ((needs.resolve-channel.outputs.runtime-override == 'true' && needs.override.result == 'success') || (needs.resolve-channel.outputs.runtime-override != 'true' && needs.resolve-channel.outputs.channel == 'alpha' && needs.alpha.result == 'success') || (needs.resolve-channel.outputs.runtime-override != 'true' && needs.resolve-channel.outputs.channel == 'stable' && needs.stable.result == 'success')) && '' || 'nested-build-incomplete' }}
|
|
194
197
|
BUILDCHAIN_CONTROLLER_REASON_SUMMARY: Nested build controller did not complete successfully
|
|
195
198
|
BUILDCHAIN_CONTROLLER_RECEIPT_ARTIFACT: buildchain-channel-controller-receipt-\${{ github.sha }}
|
|
196
199
|
BUILDCHAIN_CONTROLLER_RECEIPT_PATH: .buildchain/controller/receipt.json
|
|
@@ -221,6 +224,7 @@ function routerAggregateJob() {
|
|
|
221
224
|
name: Summarize build contract
|
|
222
225
|
needs:
|
|
223
226
|
- resolve-channel
|
|
227
|
+
- override
|
|
224
228
|
- alpha
|
|
225
229
|
- stable
|
|
226
230
|
- controller-receipt
|
|
@@ -231,13 +235,19 @@ function routerAggregateJob() {
|
|
|
231
235
|
shell: bash
|
|
232
236
|
env:
|
|
233
237
|
CHANNEL: \${{ needs.resolve-channel.outputs.channel }}
|
|
238
|
+
RUNTIME_OVERRIDE: \${{ needs.resolve-channel.outputs.runtime-override }}
|
|
239
|
+
OVERRIDE_RESULT: \${{ needs.override.result }}
|
|
234
240
|
ALPHA_RESULT: \${{ needs.alpha.result }}
|
|
235
241
|
STABLE_RESULT: \${{ needs.stable.result }}
|
|
236
242
|
CONTROLLER_RECEIPT_RESULT: \${{ needs.controller-receipt.result }}
|
|
237
243
|
run: |
|
|
238
244
|
set -euo pipefail
|
|
239
245
|
selected_result="\${STABLE_RESULT}"
|
|
240
|
-
if [[ "\${
|
|
246
|
+
if [[ "\${RUNTIME_OVERRIDE}" = "true" ]]; then
|
|
247
|
+
selected_result="\${OVERRIDE_RESULT}"
|
|
248
|
+
elif [[ "\${CHANNEL}" = "alpha" ]]; then
|
|
249
|
+
selected_result="\${ALPHA_RESULT}"
|
|
250
|
+
fi
|
|
241
251
|
if [[ "\${selected_result}" != "success" || "\${CONTROLLER_RECEIPT_RESULT}" != "success" ]]; then
|
|
242
252
|
echo "::error::Buildchain channel router did not qualify: channel=\${CHANNEL} selected=\${selected_result} controller-receipt=\${CONTROLLER_RECEIPT_RESULT}"
|
|
243
253
|
exit 1
|
|
@@ -262,13 +272,29 @@ function splitBuildJobsByChannel(workflow, names, major) {
|
|
|
262
272
|
if (index < 0) throw new Error("generated workflow is missing the build job");
|
|
263
273
|
const inputs = forwardedInputs(names);
|
|
264
274
|
const jobs = `
|
|
275
|
+
override:
|
|
276
|
+
name: Build trusted runtime override
|
|
277
|
+
needs:
|
|
278
|
+
- resolve-channel
|
|
279
|
+
- controller-plan
|
|
280
|
+
if: \${{ needs.resolve-channel.outputs.runtime-override == 'true' }}
|
|
281
|
+
uses: ./.github/workflows/.build.yml
|
|
282
|
+
permissions:
|
|
283
|
+
actions: read
|
|
284
|
+
contents: read
|
|
285
|
+
issues: write
|
|
286
|
+
id-token: write
|
|
287
|
+
with:
|
|
288
|
+
${inputs}
|
|
289
|
+
secrets: inherit
|
|
290
|
+
|
|
265
291
|
alpha:
|
|
266
292
|
name: Build alpha channel
|
|
267
293
|
needs:
|
|
268
294
|
- resolve-channel
|
|
269
295
|
- controller-plan
|
|
270
|
-
if: \${{ needs.resolve-channel.outputs.channel == 'alpha' }}
|
|
271
|
-
uses:
|
|
296
|
+
if: \${{ needs.resolve-channel.outputs.runtime-override != 'true' && needs.resolve-channel.outputs.channel == 'alpha' }}
|
|
297
|
+
uses: ./.github/workflows/.build.yml
|
|
272
298
|
permissions:
|
|
273
299
|
actions: read
|
|
274
300
|
contents: read
|
|
@@ -283,8 +309,8 @@ ${inputs}
|
|
|
283
309
|
needs:
|
|
284
310
|
- resolve-channel
|
|
285
311
|
- controller-plan
|
|
286
|
-
if: \${{ needs.resolve-channel.outputs.channel == 'stable' }}
|
|
287
|
-
uses:
|
|
312
|
+
if: \${{ needs.resolve-channel.outputs.runtime-override != 'true' && needs.resolve-channel.outputs.channel == 'stable' }}
|
|
313
|
+
uses: ./.github/workflows/.build.yml
|
|
288
314
|
permissions:
|
|
289
315
|
actions: read
|
|
290
316
|
contents: read
|
|
@@ -355,6 +381,10 @@ export function generateChannelBuildWorkflow(source) {
|
|
|
355
381
|
splitBuildJobsByChannel(generateChannelBuildWorkflowBase(source), names, major),
|
|
356
382
|
)
|
|
357
383
|
.replaceAll("runs-on: ubuntu-24.04", "runs-on: ${{ fromJSON(inputs.control-runner-json) }}")
|
|
384
|
+
.replace(
|
|
385
|
+
" buildchain-ref: ${{ steps.channel.outputs.buildchain-ref }}\n",
|
|
386
|
+
" buildchain-ref: ${{ steps.channel.outputs.buildchain-ref }}\n major: ${{ steps.channel.outputs.major }}\n runtime-override: ${{ steps.channel.outputs.runtime-override }}\n",
|
|
387
|
+
)
|
|
358
388
|
.replace(
|
|
359
389
|
"\npermissions:\n contents: read\n",
|
|
360
390
|
"\npermissions:\n actions: read\n contents: read\n",
|
|
@@ -21,6 +21,8 @@ const internalInputs = new Set([
|
|
|
21
21
|
"promotion-target-ref",
|
|
22
22
|
"promotion-override-used",
|
|
23
23
|
"publication-authority-workflow-path",
|
|
24
|
+
"buildchain-expected-channel",
|
|
25
|
+
"buildchain-expected-major",
|
|
24
26
|
]);
|
|
25
27
|
|
|
26
28
|
function blockBetween(source, start, end) {
|
|
@@ -91,7 +93,7 @@ function publicOutputs(outputBlock) {
|
|
|
91
93
|
return [...routed, ...forwarded].join("\n");
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
function forwardedInputs(inputNames, { includeInternal = true, unsupportedInputs = [] } = {}) {
|
|
96
|
+
function forwardedInputs(inputNames, { includeInternal = true, major = 2, unsupportedInputs = [], workflowPath = ".github/workflows/.release-candidate-promote.yml" } = {}) {
|
|
95
97
|
const unsupported = new Set(unsupportedInputs);
|
|
96
98
|
return inputNames
|
|
97
99
|
.filter((name) => includeInternal || !internalInputs.has(name))
|
|
@@ -100,6 +102,7 @@ function forwardedInputs(inputNames, { includeInternal = true, unsupportedInputs
|
|
|
100
102
|
const routed = {
|
|
101
103
|
"buildchain-ref": "runtime-sha",
|
|
102
104
|
"buildchain-contract-lock-path": "contract-lock-path",
|
|
105
|
+
"buildchain-expected-channel": "channel",
|
|
103
106
|
channel: "publication-channel",
|
|
104
107
|
"target-ref": "target-ref",
|
|
105
108
|
"promotion-router-ref": "router-ref",
|
|
@@ -117,8 +120,11 @@ function forwardedInputs(inputNames, { includeInternal = true, unsupportedInputs
|
|
|
117
120
|
if (name === "promotion-override-used") {
|
|
118
121
|
return ` ${name}: \${{ needs.resolve-promotion.outputs.override-used == 'true' }}`;
|
|
119
122
|
}
|
|
123
|
+
if (name === "buildchain-expected-major") {
|
|
124
|
+
return ` buildchain-expected-major: "${major}"`;
|
|
125
|
+
}
|
|
120
126
|
if (name === "publication-authority-workflow-path") {
|
|
121
|
-
return
|
|
127
|
+
return ` publication-authority-workflow-path: ${workflowPath}`;
|
|
122
128
|
}
|
|
123
129
|
return routed
|
|
124
130
|
? ` ${name}: \${{ needs.resolve-promotion.outputs.${routed} }}`
|
|
@@ -189,11 +195,13 @@ export function generateChannelPromotionWorkflow(source, { major = 2, shellRouti
|
|
|
189
195
|
}
|
|
190
196
|
const alphaForwarded = forwardedInputs(inputNames, {
|
|
191
197
|
includeInternal: alphaRoute.forwardInternalInputs,
|
|
192
|
-
|
|
198
|
+
major,
|
|
199
|
+
unsupportedInputs: alphaRoute.unsupportedInputs, workflowPath: alphaRoute.workflowPath,
|
|
193
200
|
});
|
|
194
201
|
const stableForwarded = forwardedInputs(inputNames, {
|
|
195
202
|
includeInternal: stableRoute.forwardInternalInputs,
|
|
196
|
-
|
|
203
|
+
major,
|
|
204
|
+
unsupportedInputs: stableRoute.unsupportedInputs, workflowPath: stableRoute.workflowPath,
|
|
197
205
|
});
|
|
198
206
|
return `# Generated by scripts/generate-channel-promotion-workflow.mjs. Do not edit directly.
|
|
199
207
|
name: Release Candidate Promote
|
|
@@ -259,8 +267,9 @@ jobs:
|
|
|
259
267
|
exit 1
|
|
260
268
|
fi
|
|
261
269
|
|
|
262
|
-
if [[ "\${ref}" =~ ^[0-
|
|
263
|
-
remote_url="https://github.com/\${repository}.git"
|
|
270
|
+
if [[ "\${ref}" =~ ^[0-9a-fA-F]{40}$ ]]; then sha="\${ref,,}"; else
|
|
271
|
+
remote_url="https://github.com/\${repository}.git"
|
|
272
|
+
refs="$(git ls-remote "\${remote_url}" "refs/heads/\${ref}" "refs/tags/\${ref}" "refs/tags/\${ref}^{}")"
|
|
264
273
|
head_sha="$(printf '%s\\n' "\${refs}" | awk -v name="refs/heads/\${ref}" '$2 == name { print tolower($1) }')"
|
|
265
274
|
tag_sha="$(printf '%s\\n' "\${refs}" | awk -v peeled="refs/tags/\${ref}^{}" -v name="refs/tags/\${ref}" '$2 == peeled { print tolower($1); found=1 } $2 == name && !found { fallback=tolower($1) } END { if (!found && fallback != "") print fallback }')"
|
|
266
275
|
if [[ -n "\${head_sha}" && -n "\${tag_sha}" && "\${head_sha}" != "\${tag_sha}" ]]; then echo "::error::Promotion router ref is ambiguous between branch and tag"; exit 1; fi
|
|
@@ -364,14 +364,13 @@ const manualMetaById = new Map(Object.entries({
|
|
|
364
364
|
"publish-transaction": { capabilityGroup: "release-passport-trust", audience: ["release-operator"], maturity: "stable", order: 120 },
|
|
365
365
|
"release-tail-contract": { capabilityGroup: "release-passport-trust", audience: ["release-operator", "agent", "maintainer"], maturity: "draft", order: 122 },
|
|
366
366
|
"release-tail-provider-plane": { capabilityGroup: "release-passport-trust", audience: ["release-operator", "agent", "maintainer"], maturity: "preview", order: 123 },
|
|
367
|
-
"publication-rehearsal": { capabilityGroup: "release-passport-trust", audience: ["release-operator", "agent", "maintainer"], maturity: "preview", order: 124 },
|
|
368
367
|
"release-activation-transaction": { capabilityGroup: "release-passport-trust", audience: ["release-operator", "agent"], maturity: "preview", order: 125 },
|
|
369
368
|
"release-candidate": { capabilityGroup: "reusable-build", audience: ["release-operator", "consumer"], maturity: "stable", order: 130 },
|
|
370
369
|
"release-train": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer", "agent"], maturity: "preview", order: 132 },
|
|
371
|
-
"next-development-transition": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer", "agent"], maturity: "preview", order: 133 },
|
|
372
370
|
"stable-candidate-patrol": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer"], maturity: "preview", order: 135 },
|
|
373
371
|
"dev-qualification-patrol": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer", "agent"], maturity: "preview", order: 136 },
|
|
374
372
|
"dev-alpha-candidate-patrol": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer", "agent"], maturity: "preview", order: 137 },
|
|
373
|
+
"v4-canonical-contracts": { capabilityGroup: "governance-versioning", audience: ["developer", "maintainer", "agent"], maturity: "preview", order: 138 },
|
|
375
374
|
"observed-evidence-patrol": { capabilityGroup: "governance-versioning", audience: ["release-operator", "consumer", "agent"], maturity: "preview", order: 140 },
|
|
376
375
|
"engineering-housekeeper": { capabilityGroup: "governance-versioning", audience: ["maintainer", "consumer", "agent"], maturity: "preview", order: 145 },
|
|
377
376
|
"reusable-build-surface": { capabilityGroup: "reusable-build", audience: ["consumer", "release-operator"], maturity: "stable", order: 200 },
|
|
@@ -412,6 +411,10 @@ function pageCapabilityMeta(relPath, category) {
|
|
|
412
411
|
if (manual) {
|
|
413
412
|
return manualMeta(manual.id);
|
|
414
413
|
}
|
|
414
|
+
const docMeta = category === "manual" ? manualMetaById.get(path.basename(relPath, ".md")) : null;
|
|
415
|
+
if (docMeta) {
|
|
416
|
+
return docMeta;
|
|
417
|
+
}
|
|
415
418
|
if (category === "action") {
|
|
416
419
|
return { capabilityGroup: capabilityGroup("api-cli-reference"), audience: ["developer", "agent"], maturity: "stable" };
|
|
417
420
|
}
|
|
@@ -734,7 +737,6 @@ function buildSiteBundle() {
|
|
|
734
737
|
"docs/reusable-build-surface.md",
|
|
735
738
|
"docs/release-candidate.md",
|
|
736
739
|
"docs/release-train.md",
|
|
737
|
-
"docs/next-development-transition.md",
|
|
738
740
|
"docs/stable-candidate-patrol.md",
|
|
739
741
|
"docs/dev-qualification-patrol.md",
|
|
740
742
|
"docs/dev-alpha-candidate-patrol.md",
|
|
@@ -927,11 +929,8 @@ function buildSiteBundle() {
|
|
|
927
929
|
"buildchain.release.json",
|
|
928
930
|
"release-passport-check-manifest.json",
|
|
929
931
|
"schemas/release-passport-v1.schema.json",
|
|
930
|
-
"schemas/publication-rehearsal-capsule-v1.schema.json",
|
|
931
|
-
"schemas/release-tail-capabilities-v1.schema.json",
|
|
932
|
-
"schemas/release-tail-provider-bindings-v1.schema.json",
|
|
933
932
|
"schemas/kfd-agent-hub-adoption.schema.json",
|
|
934
|
-
"schemas/kfd-product-gate-input-v1.schema.json",
|
|
933
|
+
"schemas/kfd-product-gate-input-v1.schema.json",
|
|
935
934
|
"kfd-support.json",
|
|
936
935
|
"artifact-evidence.json",
|
|
937
936
|
"product-mechanism.json",
|
|
@@ -964,11 +963,8 @@ function buildSiteBundle() {
|
|
|
964
963
|
"artifact-schemas.json",
|
|
965
964
|
"release-passport-check-manifest.json",
|
|
966
965
|
"schemas/release-passport-v1.schema.json",
|
|
967
|
-
"schemas/publication-rehearsal-capsule-v1.schema.json",
|
|
968
|
-
"schemas/release-tail-capabilities-v1.schema.json",
|
|
969
|
-
"schemas/release-tail-provider-bindings-v1.schema.json",
|
|
970
966
|
"schemas/kfd-agent-hub-adoption.schema.json",
|
|
971
|
-
"schemas/kfd-product-gate-input-v1.schema.json",
|
|
967
|
+
"schemas/kfd-product-gate-input-v1.schema.json",
|
|
972
968
|
"buildchain-contract.json",
|
|
973
969
|
"kfd-claims.json",
|
|
974
970
|
"product-mechanism.json",
|
|
@@ -1097,11 +1093,8 @@ function buildSiteBundle() {
|
|
|
1097
1093
|
"artifact-schemas.json",
|
|
1098
1094
|
"release-passport-check-manifest.json",
|
|
1099
1095
|
"schemas/release-passport-v1.schema.json",
|
|
1100
|
-
"schemas/publication-rehearsal-capsule-v1.schema.json",
|
|
1101
|
-
"schemas/release-tail-capabilities-v1.schema.json",
|
|
1102
|
-
"schemas/release-tail-provider-bindings-v1.schema.json",
|
|
1103
1096
|
"schemas/kfd-agent-hub-adoption.schema.json",
|
|
1104
|
-
"schemas/kfd-product-gate-input-v1.schema.json",
|
|
1097
|
+
"schemas/kfd-product-gate-input-v1.schema.json",
|
|
1105
1098
|
"buildchain-contract.json",
|
|
1106
1099
|
"kfd-upstream-aggregate.json",
|
|
1107
1100
|
"kfd-claims.json",
|
|
@@ -1274,20 +1267,8 @@ function buildSiteBundle() {
|
|
|
1274
1267
|
"artifact-schemas.json": artifactSchemas,
|
|
1275
1268
|
"release-passport-check-manifest.json": createReleasePassportCheckManifest(),
|
|
1276
1269
|
"schemas/release-passport-v1.schema.json": RELEASE_PASSPORT_SCHEMA,
|
|
1277
|
-
"schemas/publication-rehearsal-capsule-v1.schema.json": readJson(
|
|
1278
|
-
"contracts/publication-rehearsal-capsule-v1.schema.json",
|
|
1279
|
-
),
|
|
1280
|
-
"schemas/release-tail-capabilities-v1.schema.json": readJson(
|
|
1281
|
-
"contracts/release-tail-capabilities-v1.schema.json",
|
|
1282
|
-
),
|
|
1283
|
-
"schemas/release-tail-provider-bindings-v1.schema.json": readJson(
|
|
1284
|
-
"contracts/release-tail-provider-bindings-v1.schema.json",
|
|
1285
|
-
),
|
|
1286
1270
|
"schemas/kfd-agent-hub-adoption.schema.json": KFD_AGENT_HUB_ADOPTION_SCHEMA,
|
|
1287
1271
|
"schemas/kfd-product-gate-input-v1.schema.json": KFD_PRODUCT_GATE_INPUT_SCHEMA,
|
|
1288
|
-
"schemas/dev-delivery-authority-v2.schema.json": readJson(
|
|
1289
|
-
"contracts/dev-delivery-authority-v2.schema.json",
|
|
1290
|
-
),
|
|
1291
1272
|
"badge-endpoint-registry.json": badgeEndpointRegistry,
|
|
1292
1273
|
"publication-registry.json": publicationRegistry,
|
|
1293
1274
|
"buildchain-contract.json": createBuildchainContractWorld({ root, controllerRegistry }),
|
|
@@ -1,12 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execFileSync, spawn } from "node:child_process";
|
|
3
3
|
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
4
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
6
|
|
|
6
7
|
const INTERNAL_COMMAND = "--buildchain-internal-git-fetch";
|
|
8
|
+
const CMD_META_CHARACTERS = /([()\][%!^`"<>&|;, *?])/g;
|
|
7
9
|
const TIMEOUT_EXIT_CODE = 124;
|
|
8
10
|
const scriptPath = fileURLToPath(import.meta.url);
|
|
9
11
|
|
|
12
|
+
function cmdEscapeCommand(value) {
|
|
13
|
+
return String(value).replace(CMD_META_CHARACTERS, "^$1");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function cmdEscapeArgument(value) {
|
|
17
|
+
let text = String(value);
|
|
18
|
+
text = text.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
|
|
19
|
+
text = text.replace(/(?=(\\+?)?)\1$/g, "$1$1");
|
|
20
|
+
return `"${text}"`.replace(CMD_META_CHARACTERS, "^$1");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function resolveGitInvocation(args, env = process.env) {
|
|
24
|
+
if (process.platform !== "win32") return { command: "git", args };
|
|
25
|
+
const gitShim = String(env.PATH || "")
|
|
26
|
+
.split(path.delimiter)
|
|
27
|
+
.map((directory) => path.join(directory, "git.cmd"))
|
|
28
|
+
.find((candidate) => fs.existsSync(candidate));
|
|
29
|
+
if (!gitShim) return { command: "git", args };
|
|
30
|
+
const shellCommand = [
|
|
31
|
+
cmdEscapeCommand(gitShim),
|
|
32
|
+
...args.map(cmdEscapeArgument),
|
|
33
|
+
].join(" ");
|
|
34
|
+
return {
|
|
35
|
+
command: env.ComSpec || env.comspec || process.env.ComSpec || process.env.comspec || "cmd.exe",
|
|
36
|
+
args: ["/d", "/s", "/c", `"${shellCommand}"`],
|
|
37
|
+
windowsVerbatimArguments: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
10
41
|
async function terminateProcessTree(child, graceMs) {
|
|
11
42
|
if (!child?.pid) return;
|
|
12
43
|
if (process.platform === "win32") {
|
|
@@ -63,12 +94,14 @@ async function runInternalGitFetch() {
|
|
|
63
94
|
50,
|
|
64
95
|
Number(process.env.BUILDCHAIN_GIT_TIMEOUT_GRACE_MS || 2000),
|
|
65
96
|
);
|
|
66
|
-
const
|
|
97
|
+
const invocation = resolveGitInvocation(payload.args);
|
|
98
|
+
const child = spawn(invocation.command, invocation.args, {
|
|
67
99
|
cwd: payload.cwd,
|
|
68
100
|
env: process.env,
|
|
69
101
|
detached: process.platform !== "win32",
|
|
70
102
|
stdio: ["ignore", "pipe", "pipe"],
|
|
71
103
|
windowsHide: true,
|
|
104
|
+
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
|
72
105
|
});
|
|
73
106
|
const stdout = [];
|
|
74
107
|
const stderr = [];
|