@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,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { classifyDevDeliveryDelta, createIntegrationDeliveryProof,
|
|
4
|
+
import { classifyDevDeliveryDelta, createIntegrationDeliveryProof, createProjectCutReplayPlan, createProjectCutReplayProof, createSourceQualificationProof, verifyIntegrationDeliveryProof, verifyProjectCutReplayProof, verifySourceQualificationProof } from "../packages/core/dev-delivery-warrant.js";
|
|
5
5
|
|
|
6
6
|
function flag(args, name, fallback = "") {
|
|
7
7
|
const index = args.indexOf(`--${name}`);
|
|
@@ -49,11 +49,9 @@ export function devDeliveryProofCliOptions(args = [], environment = process.env)
|
|
|
49
49
|
closureRoot: flag(rest, "closure-root", environment.BUILDCHAIN_DEV_DELIVERY_CLOSURE_ROOT),
|
|
50
50
|
dependencyRoot: flag(rest, "dependency-root", environment.BUILDCHAIN_DEV_DELIVERY_DEPENDENCY_ROOT),
|
|
51
51
|
toolchainRoot: flag(rest, "toolchain-root", environment.BUILDCHAIN_DEV_DELIVERY_TOOLCHAIN_ROOT),
|
|
52
|
-
environmentRoot: flag(rest, "environment-root", environment.BUILDCHAIN_DEV_DELIVERY_ENVIRONMENT_ROOT),
|
|
53
52
|
affectedPaths: flag(rest, "affected-paths-json", environment.BUILDCHAIN_DEV_DELIVERY_AFFECTED_PATHS || "[]"),
|
|
54
53
|
shardEvidenceRoots: flag(rest, "shard-evidence-roots-json", environment.BUILDCHAIN_DEV_DELIVERY_SHARD_EVIDENCE_ROOTS || "[]"),
|
|
55
54
|
qualifiedAt: flag(rest, "qualified-at", environment.BUILDCHAIN_DEV_DELIVERY_QUALIFIED_AT),
|
|
56
|
-
qualifiedBase: flag(rest, "qualified-base", environment.BUILDCHAIN_DEV_DELIVERY_QUALIFIED_BASE),
|
|
57
55
|
sourceProofPath: flag(rest, "source-proof", environment.BUILDCHAIN_DEV_DELIVERY_SOURCE_PROOF),
|
|
58
56
|
sourceProofRoot: flag(rest, "source-proof-root", environment.BUILDCHAIN_DEV_DELIVERY_SOURCE_PROOF_ROOT),
|
|
59
57
|
warrantResultPath: flag(rest, "warrant-result", environment.BUILDCHAIN_DEV_DELIVERY_WARRANT_RESULT),
|
|
@@ -68,8 +66,6 @@ export function devDeliveryProofCliOptions(args = [], environment = process.env)
|
|
|
68
66
|
pullRequestNumber: flag(rest, "pull-request", environment.BUILDCHAIN_DEV_DELIVERY_PR_NUMBER),
|
|
69
67
|
changedPaths: flag(rest, "changed-paths-json", environment.BUILDCHAIN_DEV_DELIVERY_CHANGED_PATHS || "[]"),
|
|
70
68
|
graphKnown: boolean(flag(rest, "graph-known", environment.BUILDCHAIN_DEV_DELIVERY_GRAPH_KNOWN), false),
|
|
71
|
-
attributionComplete: boolean(flag(rest, "attribution-complete", environment.BUILDCHAIN_DEV_DELIVERY_ATTRIBUTION_COMPLETE), false),
|
|
72
|
-
renames: flag(rest, "renames-json", environment.BUILDCHAIN_DEV_DELIVERY_RENAMES || "[]"),
|
|
73
69
|
outputPath: flag(rest, "output", environment.BUILDCHAIN_DEV_DELIVERY_PROOF_OUTPUT || ".buildchain/dev-delivery/proof.json"),
|
|
74
70
|
json: hasFlag(rest, "json"),
|
|
75
71
|
};
|
|
@@ -121,64 +117,6 @@ export function runDevDeliveryProofCommand(options) {
|
|
|
121
117
|
},
|
|
122
118
|
});
|
|
123
119
|
}
|
|
124
|
-
if (options.command === "native") {
|
|
125
|
-
return createNativeQualificationProof({
|
|
126
|
-
repository: options.repository,
|
|
127
|
-
protectedBase: options.protectedBase,
|
|
128
|
-
sourceIdentityRoot: options.sourceIdentityRoot,
|
|
129
|
-
sourcePatchRoot: options.sourcePatchRoot,
|
|
130
|
-
planRoot: options.planRoot,
|
|
131
|
-
closureRoot: options.closureRoot,
|
|
132
|
-
dependencyRoot: options.dependencyRoot,
|
|
133
|
-
toolchainRoot: options.toolchainRoot,
|
|
134
|
-
environmentRoot: options.environmentRoot,
|
|
135
|
-
qualifiedBase: options.qualifiedBase,
|
|
136
|
-
affectedPaths: jsonList(options.affectedPaths, "affected paths"),
|
|
137
|
-
shardEvidenceRoots: jsonList(options.shardEvidenceRoots, "shard evidence roots", { required: true }),
|
|
138
|
-
qualifiedAt: options.qualifiedAt,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
if (options.command === "verify-native") {
|
|
142
|
-
return verifyNativeQualificationProof(jsonFile(options.sourceProofPath, "native proof"));
|
|
143
|
-
}
|
|
144
|
-
if (options.command === "classify-native") {
|
|
145
|
-
return createNativeProofReuseDecision({
|
|
146
|
-
proof: jsonFile(options.sourceProofPath, "native proof"),
|
|
147
|
-
current: {
|
|
148
|
-
sourceIdentityRoot: options.sourceIdentityRoot,
|
|
149
|
-
sourcePatchRoot: options.sourcePatchRoot,
|
|
150
|
-
planRoot: options.planRoot,
|
|
151
|
-
closureRoot: options.closureRoot,
|
|
152
|
-
dependencyRoot: options.dependencyRoot,
|
|
153
|
-
toolchainRoot: options.toolchainRoot,
|
|
154
|
-
environmentRoot: options.environmentRoot,
|
|
155
|
-
currentBase: options.currentBase,
|
|
156
|
-
graphKnown: options.graphKnown,
|
|
157
|
-
attributionComplete: options.attributionComplete,
|
|
158
|
-
changedPaths: jsonList(options.changedPaths, "changed paths"),
|
|
159
|
-
renames: jsonList(options.renames, "renames"),
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
if (options.command === "verify-native-reuse") {
|
|
164
|
-
return verifyNativeProofReuseDecision(jsonFile(options.qualificationReceiptPath, "native reuse decision"), {
|
|
165
|
-
proof: jsonFile(options.sourceProofPath, "native proof"),
|
|
166
|
-
current: {
|
|
167
|
-
sourceIdentityRoot: options.sourceIdentityRoot,
|
|
168
|
-
sourcePatchRoot: options.sourcePatchRoot,
|
|
169
|
-
planRoot: options.planRoot,
|
|
170
|
-
closureRoot: options.closureRoot,
|
|
171
|
-
dependencyRoot: options.dependencyRoot,
|
|
172
|
-
toolchainRoot: options.toolchainRoot,
|
|
173
|
-
environmentRoot: options.environmentRoot,
|
|
174
|
-
currentBase: options.currentBase,
|
|
175
|
-
graphKnown: options.graphKnown,
|
|
176
|
-
attributionComplete: options.attributionComplete,
|
|
177
|
-
changedPaths: jsonList(options.changedPaths, "changed paths"),
|
|
178
|
-
renames: jsonList(options.renames, "renames"),
|
|
179
|
-
},
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
120
|
if (options.command === "replay") {
|
|
183
121
|
return createProjectCutReplayPlan({
|
|
184
122
|
repository: options.repository,
|
|
@@ -230,7 +168,7 @@ export function runDevDeliveryProofCommand(options) {
|
|
|
230
168
|
}
|
|
231
169
|
|
|
232
170
|
function usage() {
|
|
233
|
-
return "Usage:\n buildchain dev proof <source|verify-source|classify|
|
|
171
|
+
return "Usage:\n buildchain dev proof <source|verify-source|classify|replay|replay-proof|verify-replay|integration|verify-integration> [options] [--output FILE] [--json]\n";
|
|
234
172
|
}
|
|
235
173
|
|
|
236
174
|
async function main() {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { cancelQueuedDevDeliveryCandidate, closeDevDeliveryWarrant, createDevDeliveryQueue, heartbeatDevDeliveryWarrant, observeDevDeliveryQueue,
|
|
5
|
-
import {
|
|
4
|
+
import { cancelQueuedDevDeliveryCandidate, closeDevDeliveryWarrant, createDevDeliveryQueue, heartbeatDevDeliveryWarrant, observeDevDeliveryQueue, recoverExpiredDevDeliveryWarrant, selectDevDeliveryWarrant, settleDevDeliveryTerminalEvent, submitDevDeliveryCandidate } from "../packages/core/dev-delivery-warrant.js";
|
|
5
|
+
import { runV4DeliveryWarrantReadCandidate } from "../packages/core/v4-delivery-warrant-read-candidate.js";
|
|
6
6
|
|
|
7
7
|
const STATE_PATH = "queue.json";
|
|
8
8
|
const STATE_REF_PREFIX = "buildchain/dev-delivery-warrant/";
|
|
@@ -73,14 +73,13 @@ function decodeBlob(blob) {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
export class GitHubDevDeliveryStore {
|
|
76
|
-
constructor({ repository, token, apiUrl = "https://api.github.com", fetchImpl = globalThis.fetch
|
|
76
|
+
constructor({ repository, token, apiUrl = "https://api.github.com", fetchImpl = globalThis.fetch } = {}) {
|
|
77
77
|
this.repository = normalizeRepository(repository);
|
|
78
78
|
if (!fetchImpl) throw new Error("fetch is required");
|
|
79
79
|
if (!token) throw new Error("GITHUB_TOKEN is required for the GitHub dev delivery store");
|
|
80
80
|
this.token = token;
|
|
81
81
|
this.apiUrl = apiUrl.replace(/\/+$/, "");
|
|
82
82
|
this.fetch = fetchImpl;
|
|
83
|
-
this.createInitialState = createInitialState;
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
async request(method, requestPath, body) {
|
|
@@ -114,7 +113,7 @@ export class GitHubDevDeliveryStore {
|
|
|
114
113
|
return {
|
|
115
114
|
exists: false,
|
|
116
115
|
commitSha: "",
|
|
117
|
-
queue:
|
|
116
|
+
queue: createDevDeliveryQueue({
|
|
118
117
|
repository: this.repository.fullName,
|
|
119
118
|
protectedBase,
|
|
120
119
|
now,
|
|
@@ -175,22 +174,6 @@ function warrantIdentity(queue, options) {
|
|
|
175
174
|
return { candidateId: active.candidateId, fencingToken, generation };
|
|
176
175
|
}
|
|
177
176
|
|
|
178
|
-
function jsonFile(file, label) {
|
|
179
|
-
if (!file) throw new Error(`${label} is required`);
|
|
180
|
-
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function jsonList(value, label) {
|
|
184
|
-
let parsed;
|
|
185
|
-
try {
|
|
186
|
-
parsed = JSON.parse(value || "[]");
|
|
187
|
-
} catch (cause) {
|
|
188
|
-
throw new Error(`${label} must be a JSON array: ${cause.message}`);
|
|
189
|
-
}
|
|
190
|
-
if (!Array.isArray(parsed)) throw new Error(`${label} must be a JSON array`);
|
|
191
|
-
return parsed;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
177
|
function transitionFor(command, queue, options) {
|
|
195
178
|
if (command === "submit") {
|
|
196
179
|
return submitDevDeliveryCandidate(
|
|
@@ -207,9 +190,6 @@ function transitionFor(command, queue, options) {
|
|
|
207
190
|
closureRoot: exactRoot(options.closureRoot, "closureRoot"),
|
|
208
191
|
dependencyRoot: exactRoot(options.dependencyRoot, "dependencyRoot"),
|
|
209
192
|
toolchainRoot: exactRoot(options.toolchainRoot, "toolchainRoot"),
|
|
210
|
-
...(options.environmentRoot ? { environmentRoot: exactRoot(options.environmentRoot, "environmentRoot") } : {}),
|
|
211
|
-
affectedPaths: jsonList(options.affectedPaths, "affected paths"),
|
|
212
|
-
sourceWorkflowRunId: options.sourceWorkflowRunId ? positiveInteger(options.sourceWorkflowRunId, "sourceWorkflowRunId") : 0,
|
|
213
193
|
deliveryClass: options.deliveryClass,
|
|
214
194
|
priority: options.priority || "ordinary",
|
|
215
195
|
},
|
|
@@ -228,20 +208,6 @@ function transitionFor(command, queue, options) {
|
|
|
228
208
|
leaseSeconds: options.leaseSeconds,
|
|
229
209
|
});
|
|
230
210
|
}
|
|
231
|
-
if (command === "qualify") {
|
|
232
|
-
return qualifyDevDeliveryWarrant(queue, warrantIdentity(queue, options), {
|
|
233
|
-
nativeProof: jsonFile(options.nativeProofPath, "native proof"),
|
|
234
|
-
reuseDecision: jsonFile(options.nativeReuseDecisionPath, "native reuse decision"),
|
|
235
|
-
current: {
|
|
236
|
-
currentBase: options.currentBase,
|
|
237
|
-
graphKnown: options.graphKnown,
|
|
238
|
-
attributionComplete: options.attributionComplete,
|
|
239
|
-
changedPaths: jsonList(options.changedPaths, "changed paths"),
|
|
240
|
-
renames: jsonList(options.renames, "renames"),
|
|
241
|
-
},
|
|
242
|
-
now: options.now,
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
211
|
if (command === "recover") return recoverExpiredDevDeliveryWarrant(queue, { now: options.now });
|
|
246
212
|
if (command === "close") {
|
|
247
213
|
return closeDevDeliveryWarrant(queue, warrantIdentity(queue, options), {
|
|
@@ -286,6 +252,50 @@ function transitionFor(command, queue, options) {
|
|
|
286
252
|
throw new Error(`unsupported dev delivery command ${command || "<empty>"}`);
|
|
287
253
|
}
|
|
288
254
|
|
|
255
|
+
async function observeQueue(loaded, options) {
|
|
256
|
+
const readMode = text(options.readMode || "v3").toLowerCase();
|
|
257
|
+
if (!["v3", "v4"].includes(readMode)) throw new Error("readMode must be v3 or v4");
|
|
258
|
+
let observation = observeDevDeliveryQueue(loaded.queue, { now: options.now });
|
|
259
|
+
let readCandidate;
|
|
260
|
+
if (readMode === "v4") {
|
|
261
|
+
const qualification = options.readQualification || JSON.parse(fs.readFileSync(options.readQualificationPath, "utf8"));
|
|
262
|
+
const retain =
|
|
263
|
+
options.retainReadEvidence ||
|
|
264
|
+
(async (evidence) => {
|
|
265
|
+
if (!options.readEvidenceOutput) throw new Error("readEvidenceOutput is required");
|
|
266
|
+
fs.mkdirSync(path.dirname(options.readEvidenceOutput), { recursive: true });
|
|
267
|
+
fs.writeFileSync(options.readEvidenceOutput, `${JSON.stringify(evidence, null, 2)}\n`);
|
|
268
|
+
return { receiptRoot: evidence.evidenceRoot };
|
|
269
|
+
});
|
|
270
|
+
readCandidate = await runV4DeliveryWarrantReadCandidate(loaded.queue, {
|
|
271
|
+
qualification,
|
|
272
|
+
expectedQualificationRoot: options.readQualificationRoot,
|
|
273
|
+
expectedSources: {
|
|
274
|
+
typescriptRevision: options.readTypescriptRevision,
|
|
275
|
+
rustRevision: options.readRustRevision,
|
|
276
|
+
validatorVersion: options.readValidatorVersion,
|
|
277
|
+
},
|
|
278
|
+
observedAt: options.now,
|
|
279
|
+
timeoutMs: positiveInteger(options.readTimeoutMs, "readTimeoutMs", 5_000),
|
|
280
|
+
signal: options.readSignal,
|
|
281
|
+
invokeRust: options.invokeV4ReadHost,
|
|
282
|
+
host: options.readHost,
|
|
283
|
+
retain,
|
|
284
|
+
});
|
|
285
|
+
observation = readCandidate.observation;
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
schema: "kungfu.buildchain.dev-delivery-command-result/v1",
|
|
289
|
+
ok: true,
|
|
290
|
+
mode: "observe",
|
|
291
|
+
readMode,
|
|
292
|
+
stateRef: options.stateRef,
|
|
293
|
+
stateCommit: loaded.commitSha,
|
|
294
|
+
observation,
|
|
295
|
+
...(readCandidate ? { readCandidate } : {}),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
289
299
|
export async function runDevDeliveryCommand(optionsInput = {}, clientInput) {
|
|
290
300
|
const options = {
|
|
291
301
|
...optionsInput,
|
|
@@ -310,16 +320,7 @@ export async function runDevDeliveryCommand(optionsInput = {}, clientInput) {
|
|
|
310
320
|
if (options.expectedOldStateRoot && loaded.queue.stateRoot !== options.expectedOldStateRoot) {
|
|
311
321
|
throw new Error(`expected-old state drift: ${loaded.queue.stateRoot} != ${options.expectedOldStateRoot}`);
|
|
312
322
|
}
|
|
313
|
-
if (options.command === "observe")
|
|
314
|
-
return {
|
|
315
|
-
schema: "kungfu.buildchain.dev-delivery-command-result/v1",
|
|
316
|
-
ok: true,
|
|
317
|
-
mode: "observe",
|
|
318
|
-
stateRef: options.stateRef,
|
|
319
|
-
stateCommit: loaded.commitSha,
|
|
320
|
-
observation: observeDevDeliveryQueue(loaded.queue, { now: options.now }),
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
+
if (options.command === "observe") return observeQueue(loaded, options);
|
|
323
324
|
const initialLoaded = loaded;
|
|
324
325
|
let changed = transitionFor(options.command, loaded.queue, options);
|
|
325
326
|
let mutates = changed.queue.stateRoot !== loaded.queue.stateRoot;
|
|
@@ -380,23 +381,6 @@ export async function runDevDeliveryCommand(optionsInput = {}, clientInput) {
|
|
|
380
381
|
};
|
|
381
382
|
}
|
|
382
383
|
|
|
383
|
-
export function runDevDeliveryShadowCommand(options = {}) {
|
|
384
|
-
if (bool(options.execute, false)) {
|
|
385
|
-
throw new Error("shadow qualification is effect-disabled and rejects --execute");
|
|
386
|
-
}
|
|
387
|
-
if (!options.inputPath) throw new Error("shadow qualification requires --input FILE");
|
|
388
|
-
const input = JSON.parse(fs.readFileSync(options.inputPath, "utf8"));
|
|
389
|
-
if (options.command === "shadow-plan") {
|
|
390
|
-
return planDevDeliveryWarrantShadow(input, {
|
|
391
|
-
maxConcurrency: positiveInteger(options.maxConcurrency, "maxConcurrency", 2),
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
if (options.command === "shadow-qualify") {
|
|
395
|
-
return qualifyDevDeliveryWarrantShadow(input);
|
|
396
|
-
}
|
|
397
|
-
throw new Error(`unsupported shadow command ${options.command || "<empty>"}`);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
384
|
function flag(args, name, fallback = "") {
|
|
401
385
|
const index = args.indexOf(`--${name}`);
|
|
402
386
|
return index === -1 ? fallback : args[index + 1] || "";
|
|
@@ -424,19 +408,10 @@ export function devDeliveryCliOptions(args = [], environment = process.env) {
|
|
|
424
408
|
sourceIdentityRoot: flag(rest, "source-identity-root", environment.BUILDCHAIN_DEV_DELIVERY_SOURCE_IDENTITY_ROOT),
|
|
425
409
|
sourcePatchRoot: flag(rest, "source-patch-root", environment.BUILDCHAIN_DEV_DELIVERY_SOURCE_PATCH_ROOT),
|
|
426
410
|
sourceProofRoot: flag(rest, "source-proof-root", environment.BUILDCHAIN_DEV_DELIVERY_SOURCE_PROOF_ROOT),
|
|
427
|
-
affectedPaths: flag(rest, "affected-paths-json", environment.BUILDCHAIN_DEV_DELIVERY_AFFECTED_PATHS || "[]"),
|
|
428
|
-
nativeProofPath: flag(rest, "native-proof", environment.BUILDCHAIN_DEV_DELIVERY_NATIVE_PROOF),
|
|
429
|
-
nativeReuseDecisionPath: flag(rest, "native-reuse-decision", environment.BUILDCHAIN_DEV_DELIVERY_NATIVE_REUSE_DECISION),
|
|
430
|
-
currentBase: flag(rest, "current-base", environment.BUILDCHAIN_DEV_DELIVERY_CURRENT_BASE),
|
|
431
|
-
changedPaths: flag(rest, "changed-paths-json", environment.BUILDCHAIN_DEV_DELIVERY_CHANGED_PATHS || "[]"),
|
|
432
|
-
graphKnown: ["1", "true", "yes", "on"].includes(flag(rest, "graph-known", environment.BUILDCHAIN_DEV_DELIVERY_GRAPH_KNOWN).trim().toLowerCase()),
|
|
433
|
-
attributionComplete: ["1", "true", "yes", "on"].includes(flag(rest, "attribution-complete", environment.BUILDCHAIN_DEV_DELIVERY_ATTRIBUTION_COMPLETE).trim().toLowerCase()),
|
|
434
|
-
renames: flag(rest, "renames-json", environment.BUILDCHAIN_DEV_DELIVERY_RENAMES || "[]"),
|
|
435
411
|
planRoot: flag(rest, "plan-root", environment.BUILDCHAIN_DEV_DELIVERY_PLAN_ROOT),
|
|
436
412
|
closureRoot: flag(rest, "closure-root", environment.BUILDCHAIN_DEV_DELIVERY_CLOSURE_ROOT),
|
|
437
413
|
dependencyRoot: flag(rest, "dependency-root", environment.BUILDCHAIN_DEV_DELIVERY_DEPENDENCY_ROOT),
|
|
438
414
|
toolchainRoot: flag(rest, "toolchain-root", environment.BUILDCHAIN_DEV_DELIVERY_TOOLCHAIN_ROOT),
|
|
439
|
-
environmentRoot: flag(rest, "environment-root", environment.BUILDCHAIN_DEV_DELIVERY_ENVIRONMENT_ROOT),
|
|
440
415
|
deliveryClass: flag(rest, "delivery-class", environment.BUILDCHAIN_DEV_DELIVERY_CLASS),
|
|
441
416
|
priority: flag(rest, "priority", environment.BUILDCHAIN_DEV_DELIVERY_PRIORITY || "ordinary"),
|
|
442
417
|
fencingToken: flag(rest, "fencing-token", environment.BUILDCHAIN_DEV_DELIVERY_FENCING_TOKEN),
|
|
@@ -446,9 +421,15 @@ export function devDeliveryCliOptions(args = [], environment = process.env) {
|
|
|
446
421
|
eventAction: flag(rest, "event-action", environment.BUILDCHAIN_DEV_DELIVERY_EVENT_ACTION),
|
|
447
422
|
evidenceRoot: flag(rest, "evidence-root", environment.BUILDCHAIN_DEV_DELIVERY_EVIDENCE_ROOT),
|
|
448
423
|
reason: flag(rest, "reason", environment.BUILDCHAIN_DEV_DELIVERY_REASON),
|
|
424
|
+
readMode: flag(rest, "read-mode", environment.BUILDCHAIN_V4_WARRANT_READ_MODE || "v3"),
|
|
425
|
+
readQualificationPath: flag(rest, "read-qualification", environment.BUILDCHAIN_V4_WARRANT_READ_QUALIFICATION),
|
|
426
|
+
readQualificationRoot: flag(rest, "read-qualification-root", environment.BUILDCHAIN_V4_WARRANT_READ_QUALIFICATION_ROOT),
|
|
427
|
+
readTypescriptRevision: flag(rest, "read-typescript-revision", environment.BUILDCHAIN_V4_WARRANT_TYPESCRIPT_REVISION),
|
|
428
|
+
readRustRevision: flag(rest, "read-rust-revision", environment.BUILDCHAIN_V4_WARRANT_RUST_REVISION),
|
|
429
|
+
readValidatorVersion: flag(rest, "read-validator-version", environment.BUILDCHAIN_V4_WARRANT_VALIDATOR_VERSION),
|
|
430
|
+
readTimeoutMs: flag(rest, "read-timeout-ms", environment.BUILDCHAIN_V4_WARRANT_READ_TIMEOUT_MS || "5000"),
|
|
431
|
+
readEvidenceOutput: flag(rest, "read-evidence-output", environment.BUILDCHAIN_V4_WARRANT_READ_EVIDENCE || ".buildchain/dev-delivery/v4-read-evidence.json"),
|
|
449
432
|
now: flag(rest, "now", environment.BUILDCHAIN_DEV_DELIVERY_NOW),
|
|
450
|
-
inputPath: flag(rest, "input", environment.BUILDCHAIN_DEV_DELIVERY_SHADOW_INPUT),
|
|
451
|
-
maxConcurrency: flag(rest, "max-concurrency", environment.BUILDCHAIN_DEV_DELIVERY_SHADOW_MAX_CONCURRENCY || "2"),
|
|
452
433
|
outputPath: flag(rest, "output", environment.BUILDCHAIN_DEV_DELIVERY_OUTPUT || ".buildchain/dev-delivery/result.json"),
|
|
453
434
|
execute: hasFlag(rest, "execute"),
|
|
454
435
|
json: hasFlag(rest, "json"),
|
|
@@ -456,7 +437,7 @@ export function devDeliveryCliOptions(args = [], environment = process.env) {
|
|
|
456
437
|
}
|
|
457
438
|
|
|
458
439
|
function usage() {
|
|
459
|
-
return "Usage:\n buildchain dev warrant <submit|select|heartbeat|
|
|
440
|
+
return "Usage:\n buildchain dev warrant <submit|select|heartbeat|recover|close|settle|cancel-queued|observe> --repository owner/repo --branch dev/vN/vN.M [--execute] [--output FILE] [--json]\n\nRead candidate:\n observe --read-mode v4 --read-qualification FILE --read-qualification-root sha256:... --read-typescript-revision SHA --read-rust-revision SHA --read-validator-version TOKEN [--read-evidence-output FILE]\n";
|
|
460
441
|
}
|
|
461
442
|
|
|
462
443
|
async function main() {
|
|
@@ -466,22 +447,16 @@ async function main() {
|
|
|
466
447
|
return;
|
|
467
448
|
}
|
|
468
449
|
const options = devDeliveryCliOptions(args);
|
|
469
|
-
if (!["submit", "select", "heartbeat", "
|
|
450
|
+
if (!["submit", "select", "heartbeat", "recover", "close", "settle", "cancel-queued", "observe"].includes(options.command)) {
|
|
470
451
|
throw new Error(usage().trim());
|
|
471
452
|
}
|
|
472
|
-
const
|
|
473
|
-
const result = shadow ? runDevDeliveryShadowCommand(options) : await runDevDeliveryCommand(options);
|
|
453
|
+
const result = await runDevDeliveryCommand(options);
|
|
474
454
|
fs.mkdirSync(path.dirname(options.outputPath), { recursive: true });
|
|
475
455
|
fs.writeFileSync(options.outputPath, `${JSON.stringify(result, null, 2)}\n`);
|
|
476
456
|
if (options.json) process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
477
457
|
else {
|
|
478
458
|
process.stdout.write(`Buildchain dev delivery ${options.command}: ${result.receipt?.reason || result.mode}\n`);
|
|
479
|
-
|
|
480
|
-
process.stdout.write(`Decision: ${result.decision}\n`);
|
|
481
|
-
process.stdout.write(`Evidence root: ${result.planRoot || result.qualificationRoot}\n`);
|
|
482
|
-
} else {
|
|
483
|
-
process.stdout.write(`State root: ${result.after?.stateRoot || result.observation.stateRoot}\n`);
|
|
484
|
-
}
|
|
459
|
+
process.stdout.write(`State root: ${result.after?.stateRoot || result.observation.stateRoot}\n`);
|
|
485
460
|
if (result.receiptRoot) process.stdout.write(`Receipt root: ${result.receiptRoot}\n`);
|
|
486
461
|
process.stdout.write(`Result: ${options.outputPath}\n`);
|
|
487
462
|
}
|
|
@@ -4,7 +4,7 @@ import { spawnSync } from "node:child_process";
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { verifyProjectCutReplayProof } from "../packages/core/dev-delivery-warrant.js";
|
|
7
|
-
import { admitExistingQueueEntry, createDevPrAdmissionReceipt,
|
|
7
|
+
import { admitExistingQueueEntry, createDevPrAdmissionReceipt, readDeliveryWarrantResult, runSourceQualification, runTargetedQueueAdmission } from "./dev-pr-delivery-warrant.mjs";
|
|
8
8
|
const DEFAULT_BLOCK_LABELS = ["blocked", "do-not-merge", "work-in-progress"];
|
|
9
9
|
const DEFAULT_ALLOWED_HEAD_PREFIXES = ["feature/", "fix/", "chore/", "docs/", "ci/", "refactor/"];
|
|
10
10
|
const DEFAULT_REQUIRED_CHECKS = ["check"];
|
|
@@ -70,7 +70,6 @@ function normalizeOptions(options = {}) {
|
|
|
70
70
|
allowedHeadPrefixes: splitList(options.allowedHeadPrefixes, DEFAULT_ALLOWED_HEAD_PREFIXES),
|
|
71
71
|
requiredChecks: splitList(options.requiredChecks, DEFAULT_REQUIRED_CHECKS),
|
|
72
72
|
queueAdmissionContext: String(options.queueAdmissionContext || "").trim(),
|
|
73
|
-
activeLeaseContext: String(options.activeLeaseContext || "").trim(),
|
|
74
73
|
requireApproval: boolOption(options.requireApproval, true),
|
|
75
74
|
sameRepositoryOnly: boolOption(options.sameRepositoryOnly, true),
|
|
76
75
|
maxMerges: intOption(options.maxMerges, 1),
|
|
@@ -219,20 +218,6 @@ async function setQueueAdmissionStatus(client, repository, sha, context, state)
|
|
|
219
218
|
return { context, state, sha };
|
|
220
219
|
}
|
|
221
220
|
|
|
222
|
-
async function setActiveLeaseStatus(client, repository, sha, context, state) {
|
|
223
|
-
if (!context) return null;
|
|
224
|
-
await client.request("POST", `/repos/${repository.owner}/${repository.repo}/statuses/${sha}`, {
|
|
225
|
-
body: {
|
|
226
|
-
state,
|
|
227
|
-
context,
|
|
228
|
-
description: state === "pending"
|
|
229
|
-
? "Buildchain reactivated this exact lease for merge-group qualification"
|
|
230
|
-
: "Buildchain released this exact lease after queue admission failed",
|
|
231
|
-
},
|
|
232
|
-
});
|
|
233
|
-
return { context, state, sha };
|
|
234
|
-
}
|
|
235
|
-
|
|
236
221
|
function skip(reason, details = {}) {
|
|
237
222
|
return { action: "skip", reason, ...details };
|
|
238
223
|
}
|
|
@@ -868,15 +853,11 @@ export async function runDevPrAdmission(optionsInput = {}, clientInput) {
|
|
|
868
853
|
let warrant = null;
|
|
869
854
|
try {
|
|
870
855
|
warrant = readDeliveryWarrantResult(options, pr);
|
|
871
|
-
await verifyCurrentDeliveryWarrant(client, options, pr, warrant);
|
|
872
856
|
} catch (error) {
|
|
873
857
|
return reject("blocked", error.code || "invalid-delivery-warrant");
|
|
874
858
|
}
|
|
875
859
|
const matchingEntry = initialQueue.entries.find((entry) =>
|
|
876
860
|
entry.pullRequestNumber === pr.number && entry.pullRequestHeadSha === options.expectedHeadSha);
|
|
877
|
-
if (matchingEntry && !options.dryRun) {
|
|
878
|
-
await setActiveLeaseStatus(client, options.repository, options.expectedHeadSha, options.activeLeaseContext, "pending");
|
|
879
|
-
}
|
|
880
861
|
const existing = await admitExistingQueueEntry({
|
|
881
862
|
options, pullRequest: pr, readiness, client, entry: matchingEntry, warrant,
|
|
882
863
|
createReceipt: createAdmissionReceipt,
|
|
@@ -912,7 +893,6 @@ async function reconcileEnqueueError({ client, options, pr, expectedHeadSha, ent
|
|
|
912
893
|
const exactEntry = queueReadback?.entries?.find((candidate) =>
|
|
913
894
|
candidate.pullRequestNumber === pr.number && candidate.pullRequestHeadSha === expectedHeadSha);
|
|
914
895
|
if (exactEntry) {
|
|
915
|
-
entry.activeLeaseStatus = await setActiveLeaseStatus(client, options.repository, expectedHeadSha, options.activeLeaseContext, "pending");
|
|
916
896
|
entry.action = "enqueued";
|
|
917
897
|
entry.reason = "already-enqueued-exact-head";
|
|
918
898
|
entry.queueEntry = exactEntry;
|
|
@@ -922,7 +902,6 @@ async function reconcileEnqueueError({ client, options, pr, expectedHeadSha, ent
|
|
|
922
902
|
return;
|
|
923
903
|
}
|
|
924
904
|
entry.queueAdmissionStatus = await setQueueAdmissionStatus(client, options.repository, expectedHeadSha, options.queueAdmissionContext, "failure");
|
|
925
|
-
entry.activeLeaseStatus = await setActiveLeaseStatus(client, options.repository, expectedHeadSha, options.activeLeaseContext, "failure");
|
|
926
905
|
entry.action = "skip";
|
|
927
906
|
entry.reason = "enqueue-rejected";
|
|
928
907
|
entry.enqueueError = {
|
|
@@ -1088,14 +1067,10 @@ export async function runDevPrAutoMerge(optionsInput = {}, clientInput) {
|
|
|
1088
1067
|
result.skipped.push(entry);
|
|
1089
1068
|
} else {
|
|
1090
1069
|
try {
|
|
1091
|
-
entry.activeLeaseStatus = await setActiveLeaseStatus(client, options.repository, expectedHeadSha, options.activeLeaseContext, "pending");
|
|
1092
1070
|
entry.queueAdmissionStatus = await setQueueAdmissionStatus(client, options.repository, expectedHeadSha, options.queueAdmissionContext, "success");
|
|
1093
|
-
const queueEntry = await
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
attempts: options.pollMergeableAttempts,
|
|
1097
|
-
delayMs: options.pollMergeableDelayMs,
|
|
1098
|
-
sleep: delay,
|
|
1071
|
+
const queueEntry = await client.enqueuePullRequest({
|
|
1072
|
+
pullRequestId: decision.pullRequestId,
|
|
1073
|
+
expectedHeadOid: expectedHeadSha,
|
|
1099
1074
|
});
|
|
1100
1075
|
entry.action = "enqueued";
|
|
1101
1076
|
entry.reason = "enqueued-with-expected-head";
|
|
@@ -1180,7 +1155,6 @@ export function cliOptions(args = [], environment = process.env) {
|
|
|
1180
1155
|
allowedHeadPrefixes: cliValue(args, "allowed-head-prefixes", environment.BUILDCHAIN_DEV_PR_ALLOWED_HEAD_PREFIXES),
|
|
1181
1156
|
requiredChecks: cliValue(args, "required-checks", environment.BUILDCHAIN_DEV_PR_REQUIRED_CHECKS),
|
|
1182
1157
|
queueAdmissionContext: cliValue(args, "queue-admission-context", environment.BUILDCHAIN_DEV_PR_QUEUE_ADMISSION_CONTEXT),
|
|
1183
|
-
activeLeaseContext: cliValue(args, "active-lease-context", environment.BUILDCHAIN_DEV_PR_ACTIVE_LEASE_CONTEXT),
|
|
1184
1158
|
diagnosticContext: cliValue(args, "diagnostic-context", environment.BUILDCHAIN_DEV_PR_DIAGNOSTIC_CONTEXT),
|
|
1185
1159
|
warrantMode: cliValue(args, "warrant-mode", environment.BUILDCHAIN_DEV_PR_WARRANT_MODE),
|
|
1186
1160
|
warrantResultPath: cliValue(args, "warrant-result", environment.BUILDCHAIN_DEV_PR_WARRANT_RESULT_PATH),
|
|
@@ -34,11 +34,6 @@ function exactActiveReadback(result) {
|
|
|
34
34
|
const warrant = result.observation.activeWarrant;
|
|
35
35
|
const candidate = result.observation.activeCandidate;
|
|
36
36
|
requireMatch(warrant?.schema === "kungfu.buildchain.dev-delivery-warrant/v1", "delivery-warrant-missing");
|
|
37
|
-
requireMatch((warrant.phase || "qualified") === "qualified", "delivery-warrant-not-qualified");
|
|
38
|
-
if (warrant.phase === "qualified") {
|
|
39
|
-
requireMatch(ROOT_PATTERN.test(String(warrant.nativeProofRoot || "")), "delivery-warrant-native-proof-missing");
|
|
40
|
-
requireMatch(ROOT_PATTERN.test(String(warrant.nativeProofReuseRoot || "")), "delivery-warrant-native-reuse-missing");
|
|
41
|
-
}
|
|
42
37
|
requireMatch(candidate?.candidateId === warrant.candidateId, "delivery-warrant-candidate-readback-missing");
|
|
43
38
|
requireMatch(!result.warrant || JSON.stringify(result.warrant) === JSON.stringify(warrant), "delivery-warrant-readback-mismatch");
|
|
44
39
|
return { warrant, candidate };
|
|
@@ -121,56 +116,6 @@ export function readDeliveryWarrantResult(options, pullRequest) {
|
|
|
121
116
|
};
|
|
122
117
|
}
|
|
123
118
|
|
|
124
|
-
export async function readCurrentDeliveryQueueState(client, repository, targetBranch) {
|
|
125
|
-
if (typeof client.getDevDeliveryQueueState === "function") {
|
|
126
|
-
return client.getDevDeliveryQueueState(targetBranch);
|
|
127
|
-
}
|
|
128
|
-
const stateRef = `buildchain/dev-delivery-warrant/${targetBranch.replaceAll("/", "-")}`;
|
|
129
|
-
const query = new URLSearchParams({ ref: stateRef });
|
|
130
|
-
const { data } = await client.request(
|
|
131
|
-
"GET",
|
|
132
|
-
`/repos/${repository.owner}/${repository.repo}/contents/queue.json?${query}`,
|
|
133
|
-
);
|
|
134
|
-
if (data?.type !== "file" || data?.encoding !== "base64" || !data?.content) {
|
|
135
|
-
mismatch("delivery-warrant-current-readback-invalid");
|
|
136
|
-
}
|
|
137
|
-
return JSON.parse(Buffer.from(String(data.content).replace(/\s+/g, ""), "base64").toString("utf8"));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export async function verifyCurrentDeliveryWarrant(client, options, pullRequest, warrant) {
|
|
141
|
-
if (!warrant) return;
|
|
142
|
-
let queue;
|
|
143
|
-
try {
|
|
144
|
-
queue = await readCurrentDeliveryQueueState(client, options.repository, options.targetBranch);
|
|
145
|
-
} catch {
|
|
146
|
-
mismatch("delivery-warrant-current-readback-failed");
|
|
147
|
-
}
|
|
148
|
-
const active = queue?.activeWarrant;
|
|
149
|
-
const candidate = queue?.candidates?.find((entry) => entry.candidateId === active?.candidateId);
|
|
150
|
-
requireMatch(active?.candidateId === warrant.candidateId, "delivery-warrant-no-longer-active");
|
|
151
|
-
requireMatch(active?.fencingToken === warrant.fencingToken, "delivery-warrant-current-fencing-mismatch");
|
|
152
|
-
requireMatch(Number(active?.generation) === Number(warrant.generation), "delivery-warrant-current-generation-mismatch");
|
|
153
|
-
requireMatch(Number(active?.pullRequestNumber) === Number(pullRequest.number), "delivery-warrant-current-pr-mismatch");
|
|
154
|
-
requireMatch(String(active?.sourceHead || "").toLowerCase() === options.expectedHeadSha, "delivery-warrant-current-head-mismatch");
|
|
155
|
-
requireMatch(["selected", "proving", "waiting", "blocked", "qualified"].includes(candidate?.status), "delivery-warrant-current-candidate-not-selected");
|
|
156
|
-
requireMatch(candidate?.sourceHead === active.sourceHead, "delivery-warrant-current-candidate-head-mismatch");
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export async function enqueueAfterStatusPropagation({ enqueue, input, attempts, delayMs, sleep }) {
|
|
160
|
-
let lastError;
|
|
161
|
-
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
162
|
-
try {
|
|
163
|
-
return await enqueue(input);
|
|
164
|
-
} catch (error) {
|
|
165
|
-
lastError = error;
|
|
166
|
-
const propagation = /required status(?:es| check).*failing|failing required status|cannot change this locked branch/i.test(String(error?.message || ""));
|
|
167
|
-
if (!propagation || attempt === attempts) throw error;
|
|
168
|
-
await sleep(delayMs);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
throw lastError;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
119
|
export async function runSourceQualification({ options, pullRequest, readiness, client, evaluate, admissionState, createReceipt, root, publishDiagnostic, reject }) {
|
|
175
120
|
const decision = await evaluate(pullRequest, { ...options, landingMode: options.landingMode, dryRun: true }, client);
|
|
176
121
|
if (decision.observedHeadSha && String(decision.observedHeadSha).toLowerCase() !== options.expectedHeadSha) {
|
|
@@ -39,15 +39,18 @@ export async function resolveArtifactSigningAuthorityRuntime({
|
|
|
39
39
|
const ref = resolveAuthorityDispatchRef(authorityRef);
|
|
40
40
|
const encodedRef = ref.split("/").map(encodeURIComponent).join("/");
|
|
41
41
|
const response = await requestImpl(
|
|
42
|
-
`/repos/${authorityRepo}/
|
|
42
|
+
`/repos/${authorityRepo}/git/ref/heads/${encodedRef}`,
|
|
43
43
|
{ token: required(token, "Buildchain authority dispatch token") },
|
|
44
44
|
);
|
|
45
|
-
|
|
46
|
-
if (!/^[0-9a-f]{40}$/u.test(sha)) {
|
|
45
|
+
if (response?.object?.type !== "commit") {
|
|
47
46
|
throw new Error(
|
|
48
|
-
"Buildchain signing authority ref
|
|
47
|
+
"Buildchain signing authority ref does not resolve to a commit",
|
|
49
48
|
);
|
|
50
49
|
}
|
|
50
|
+
const sha = String(response.object.sha || "");
|
|
51
|
+
if (!/^[0-9a-f]{40}$/u.test(sha)) {
|
|
52
|
+
throw new Error("Buildchain signing authority runtime SHA must be exact");
|
|
53
|
+
}
|
|
51
54
|
return { ref, sha };
|
|
52
55
|
}
|
|
53
56
|
|