@kungfu-tech/buildchain 4.0.2-alpha.9 → 4.0.3-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 +14 -5
- package/CONTRIBUTING.md +58 -0
- package/README.md +3 -3
- package/actions/promote-buildchain-ref/README.md +1 -1
- package/actions/release-candidate-promote/README.md +31 -0
- package/architecture/agent-change-map.md +190 -126
- package/architecture/{v4-architecture-constitution.md → architecture-constitution.md} +33 -30
- package/architecture/{v3-core-mechanism-inventory.md → baseline-core-mechanism-inventory.md} +1 -1
- package/architecture/{v4-bootstrap-authority.json → bootstrap-authority.json} +3 -3
- package/architecture/{v3-v4-capability-closure.md → capability-parity-closure.md} +3 -3
- package/architecture/{v3-v4-live-capability-inventory.json → capability-parity-live-capability-inventory.json} +4 -4
- package/architecture/{v4-capability-state-machine-manifest.json → capability-state-machine-manifest.json} +2 -2
- package/architecture/{v4-capability-state-machine-manifest.schema.json → capability-state-machine-manifest.schema.json} +2 -2
- package/architecture/ci-lane-change-budget.json +384 -0
- package/architecture/{v4-cross-platform-adopter-qualification.json → cross-platform-adopter-qualification.json} +4 -4
- package/architecture/{v4-delivery-authority-parity.json → delivery-authority-parity.json} +17 -17
- package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.json → delivery-warrant-shadow-bootstrap-plan.json} +4 -4
- package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.md → delivery-warrant-shadow-bootstrap-plan.md} +7 -7
- package/architecture/{v4-floating-consumer-policy.json → floating-consumer-policy.json} +2 -2
- package/architecture/{v4-floating-consumer-policy.md → floating-consumer-policy.md} +1 -1
- package/architecture/implementation-naming.json +1273 -0
- package/architecture/internal-capabilities.json +201 -154
- package/architecture/maintainability-debt.json +205 -146
- package/architecture/maintainability-policy.json +37 -33
- package/architecture/{v4-next-development-parity.json → next-development-parity.json} +12 -12
- package/architecture/{v4-partial-mutation-recovery-qualification.json → partial-mutation-recovery-qualification.json} +8 -5
- package/architecture/{v4-platform-stage-checkpoints.json → platform-stage-checkpoints.json} +3 -3
- package/architecture/{v4-provider-operation-journal-contract.json → provider-operation-journal-contract.json} +10 -7
- package/architecture/publication-facade-patches.json +64 -0
- package/architecture/{v4-publication-rehearsal-parity.json → publication-rehearsal-parity.json} +4 -4
- package/architecture/{v4-release-activation-shadow-domain.json → release-activation-shadow-domain.json} +9 -6
- package/architecture/release-tail-contract-inventory.json +6 -6
- package/architecture/{v4-release-topology.json → release-topology.json} +163 -72
- package/architecture/{v4-release-train-parity.json → release-train-parity.json} +2 -2
- package/architecture/{v4-runtime-ref-resume-authority.json → runtime-ref-resume-authority.json} +1 -1
- package/architecture/{v4-runtime-semantic-closure.json → runtime-semantic-closure.json} +2 -2
- package/architecture/{v4-rust-libnode-bridge-evaluation.json → rust-libnode-bridge-evaluation.json} +3 -3
- package/architecture/{v4-rust-libnode-bridge-spike.md → rust-libnode-bridge-spike.md} +6 -6
- package/architecture/rust-wasm-production-authority.json +58 -0
- package/architecture/{v4-stable-publication-fence.json → stable-publication-fence.json} +7 -4
- package/architecture/{v4-stage-capsule-contract.json → stage-capsule-contract.json} +1 -1
- package/architecture/{v4-stage-capsule-qualification.json → stage-capsule-qualification.json} +8 -8
- package/architecture/{v4-stage-capsule-resume-planner.json → stage-capsule-resume-planner.json} +2 -2
- package/architecture/{v4-stage-capsule-store-contract.json → stage-capsule-store-contract.json} +4 -4
- package/architecture/{v4-tail-reseal-parity.json → tail-reseal-parity.json} +35 -33
- package/architecture/universal-workflow-bootstrap.json +176 -0
- package/architecture/universal-workflow-fault-campaign.json +72 -0
- package/architecture/universal-workflow-train-admission.json +40 -0
- package/architecture/workflow-taxonomy.json +1462 -0
- package/bin/buildchain.mjs +10 -10
- package/bin/internal/adopter-delivery-cli.mjs +9 -9
- package/contracts/buildchain-v2-residuals-v1.json +57 -48
- package/contracts/dev-delivery-authority-v2.schema.json +16 -2
- package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
- package/contracts/v4-canonical-contracts-v1.schema.json +1 -0
- package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/Cargo.lock +1 -1
- package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/Cargo.toml +1 -1
- package/crates/{buildchain-v4-bridge → buildchain-host-bridge}/src/main.rs +3 -3
- package/dist/site/buildchain-contract.json +98 -53
- package/dist/site/buildchain-site.json +351 -102
- package/dist/site/capability-registry.json +7 -7
- package/dist/site/controller-registry.json +50 -13
- package/dist/site/kfd-claims.json +2773 -1052
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +14 -14
- package/dist/site/node-api-registry.json +13176 -10733
- package/dist/site/page-registry.json +332 -83
- package/dist/site/public-surface-audit.json +3227 -1222
- package/dist/site/publication-authority-registry.json +1135 -363
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +18 -9
- package/dist/site/schemas/dev-delivery-authority-v2.schema.json +16 -2
- package/dist/site/site-manifest.json +18 -18
- package/dist/site/workflow-registry.json +5367 -1931
- package/docs/MAP.md +5 -3
- package/docs/auditable-demo.md +1 -1
- package/docs/cli.md +21 -8
- package/docs/dev-delivery-warrant.md +1 -1
- package/docs/engineering-housekeeper.md +3 -3
- package/docs/kfd-support.md +26 -2
- package/docs/next-development-transition.md +26 -3
- package/docs/node-api-reference.md +618 -358
- package/docs/oci-publication.md +173 -0
- package/docs/publication-authority.md +2 -2
- package/docs/publish-transaction.md +36 -3
- package/docs/release-candidate.md +3 -3
- package/docs/release-flow.md +67 -19
- package/docs/release-governance.md +8 -8
- package/docs/release-passport.md +27 -2
- package/docs/reusable-build-surface.md +17 -1
- package/docs/v4-adopter-delivery.md +4 -4
- package/docs/v4-canonical-contracts.md +7 -7
- package/docs/v4-delivery-warrant-read-candidate.md +3 -3
- package/docs/v4-delivery-warrant-semantic-diff.md +3 -3
- package/docs/v4-production-release.md +77 -8
- package/docs/v4-publication-rehearsal.md +3 -3
- package/docs/v4-runtime-ref-resume-authority.md +2 -2
- package/docs/v4-rust-wasm-production-authority.md +58 -0
- package/docs/v4-stage-capsule.md +9 -9
- package/docs/v4-tail-reseal.md +2 -2
- package/docs/workflow-catalog.md +155 -0
- package/docs/workflow-path-migration.md +109 -0
- package/package.json +39 -24
- package/packages/compatibility/adopter-delivery.js +16 -0
- package/packages/compatibility/cross-platform-adopter-qualification.js +12 -0
- package/packages/compatibility/floating-consumer-policy.js +14 -0
- package/packages/compatibility/publication-qualification.js +11 -0
- package/packages/compatibility/publication-rehearsal.js +18 -0
- package/packages/compatibility/runtime-ref-resume-authority.js +13 -0
- package/packages/compatibility/tail-reseal-receipt.js +7 -0
- package/packages/compatibility/tail-reseal.js +11 -0
- package/packages/core/{v4-adopter-delivery-parity.js → adopter-delivery-parity.js} +12 -12
- package/packages/core/{v4-adopter-delivery.js → adopter-delivery.js} +24 -24
- package/packages/core/artifact-verification-envelope.js +5 -5
- package/packages/core/buildchain-contract.js +6 -6
- package/packages/core/buildchain-domain.wasm +0 -0
- package/packages/core/buildchain-kfd-claims.js +2 -2
- package/packages/core/buildchain-publication-authority.js +43 -26
- package/packages/core/{v4-canonical-contracts.js → canonical-contracts.js} +39 -103
- package/packages/core/ci-lane-change-budget.js +14 -1
- package/packages/core/controller-evidence.js +4 -1
- package/packages/core/{v4-cross-platform-adopter-qualification.js → cross-platform-adopter-qualification.js} +19 -19
- package/packages/core/{v4-delivery-warrant-fixture-runner.js → delivery-warrant-fixture-runner.js} +36 -32
- package/packages/core/{v4-delivery-warrant-read-candidate.js → delivery-warrant-read-candidate.js} +40 -40
- package/packages/core/{v4-delivery-warrant-semantic-diff-gate.js → delivery-warrant-semantic-diff-gate.js} +58 -59
- package/packages/core/{v4-delivery-warrant-shadow-adapter.js → delivery-warrant-shadow-adapter.js} +15 -15
- package/packages/core/dev-delivery-candidate-identity.js +40 -6
- package/packages/core/dev-delivery-execution-transfer.js +6 -6
- package/packages/core/dev-delivery-native-proof.js +12 -8
- package/packages/core/dev-delivery-warrant-legacy-recovery.js +1 -1
- package/packages/core/dev-delivery-warrant-native-compatibility.js +4 -4
- package/packages/core/dev-delivery-warrant-state.js +14 -15
- package/packages/core/dev-delivery-warrant.js +15 -5
- package/packages/core/domain-wasm-artifact.js +7 -0
- package/packages/core/domain-wasm.js +216 -0
- package/packages/core/{v4-floating-consumer-evidence.js → floating-consumer-evidence.js} +14 -14
- package/packages/core/{v4-floating-consumer-policy.js → floating-consumer-policy.js} +28 -30
- package/packages/core/{v4-floating-consumer-release-passport.js → floating-consumer-release-passport.js} +25 -25
- package/packages/core/github-governance-authority.js +4 -4
- package/packages/core/index.js +4 -8
- package/packages/core/kfd-adopter-manifest.js +46 -47
- package/packages/core/next-development-projection.js +26 -3
- package/packages/core/next-development-transition.js +5 -6
- package/packages/core/oci-compose-qualification.js +143 -0
- package/packages/core/oci-publication-bundle.js +281 -0
- package/packages/core/oci-publication-graph.js +206 -0
- package/packages/core/paper-agent-entry.js +30 -4
- package/packages/core/paper-fleet.js +1 -1
- package/packages/core/paper-runtime-channels.js +348 -0
- package/packages/core/paper-scaffold-content.js +10 -0
- package/packages/core/paper.js +37 -71
- package/packages/core/partial-mutation-recovery-qualification.js +18 -0
- package/packages/core/{v4-platform-stage-checkpoints.js → platform-stage-checkpoints.js} +37 -37
- package/packages/core/product-publication.js +59 -0
- package/packages/core/{v4-protected-publication-source.js → protected-publication-source.js} +22 -24
- package/packages/core/provider-operation-journal.js +62 -0
- package/packages/core/{v4-provider-readback-idempotency.js → provider-readback-idempotency.js} +40 -125
- package/packages/core/public-export-compatibility.js +33 -0
- package/packages/core/publication-development.js +72 -0
- package/packages/core/{v4-publication-qualification.js → publication-qualification.js} +17 -17
- package/packages/core/{v4-publication-rehearsal-capsule.js → publication-rehearsal-capsule.js} +23 -23
- package/packages/core/publication-rehearsal-projection.js +2 -2
- package/packages/core/{v4-publication-rehearsal-provider-bindings.js → publication-rehearsal-provider-bindings.js} +4 -4
- package/packages/core/publication-rehearsal-runtime.js +21 -21
- package/packages/core/{v4-publication-rehearsal.js → publication-rehearsal.js} +33 -33
- package/packages/core/publication-sealed-bundle.js +78 -13
- package/packages/core/release-activation-shadow.js +32 -0
- package/packages/core/release-candidate.js +6 -6
- package/packages/core/release-invocation.js +64 -0
- package/packages/core/release-line-dry-run.js +1 -1
- package/packages/core/release-passport-contract.js +5 -5
- package/packages/core/release-passport.js +41 -40
- package/packages/core/release-tail-product-capabilities.js +9 -0
- package/packages/core/release-tail-provider-plane.js +68 -1048
- package/packages/core/{v4-runtime-ref-resume-authority.js → runtime-ref-resume-authority.js} +36 -40
- package/packages/core/{v4-runtime-selector-persistence.js → runtime-selector-persistence.js} +7 -7
- package/packages/core/stable-publication-fence.js +28 -0
- package/packages/core/{v4-stage-capsule-local-store.js → stage-capsule-local-store.js} +56 -54
- package/packages/core/{v4-stage-capsule-qualification-campaign.js → stage-capsule-qualification-campaign.js} +37 -38
- package/packages/core/{v4-stage-capsule-qualification.js → stage-capsule-qualification.js} +28 -29
- package/packages/core/{v4-stage-capsule-resume-planner.js → stage-capsule-resume-planner.js} +29 -29
- package/packages/core/{v4-stage-capsule-store.js → stage-capsule-store.js} +59 -56
- package/packages/core/{v4-stage-capsule.js → stage-capsule.js} +45 -45
- package/packages/core/{v4-tail-reseal-contract.js → tail-reseal-contract.js} +6 -6
- package/packages/core/{v4-tail-reseal-github.js → tail-reseal-github.js} +12 -12
- package/packages/core/{v4-tail-reseal-receipt.js → tail-reseal-receipt.js} +22 -22
- package/packages/core/{v4-tail-reseal.js → tail-reseal.js} +29 -29
- package/packages/core/universal-workflow-bootstrap.js +586 -0
- package/scripts/{v4-architecture.mjs → architecture.mjs} +6 -6
- package/scripts/binary-publication-evidence.mjs +135 -0
- package/scripts/{v4-bridge-bootstrap.mjs → bridge-bootstrap.mjs} +14 -18
- package/scripts/{v4-bridge-evidence.mjs → bridge-evidence.mjs} +8 -8
- package/scripts/build-contract-core.mjs +1 -14
- package/scripts/build-domain-wasm.mjs +177 -0
- package/scripts/{v3-v4-capability-catalog.mjs → capability-parity-catalog.mjs} +19 -19
- package/scripts/check-action-bundles.mjs +12 -2
- package/scripts/{check-v3-v4-capability-inventory.mjs → check-capability-parity-inventory.mjs} +42 -42
- package/scripts/check-ci-lane-change-budget.mjs +4 -1
- package/scripts/check-core-mechanism-inventory.mjs +8 -4
- package/scripts/{check-v4-floating-consumer-policy-contract.mjs → check-floating-consumer-policy-contract.mjs} +10 -10
- package/scripts/check-implementation-naming.mjs +135 -0
- package/scripts/check-inventory.mjs +39 -47
- package/scripts/check-maintainability.mjs +25 -115
- package/scripts/{check-v4-public-dogfood-contract.mjs → check-public-dogfood-contract.mjs} +37 -24
- package/scripts/{check-v4-release-topology.mjs → check-release-topology.mjs} +131 -52
- package/scripts/{check-v4-runtime-semantic-closure.mjs → check-runtime-semantic-closure.mjs} +23 -17
- package/scripts/check-universal-workflow-bootstrap.mjs +266 -0
- package/scripts/check-workflow-taxonomy.mjs +6 -0
- package/scripts/{v4-consumer-policy.mjs → consumer-policy.mjs} +15 -15
- package/scripts/copy-domain-wasm.mjs +14 -0
- package/scripts/{v4-cross-platform-adopter-qualification.mjs → cross-platform-adopter-qualification.mjs} +9 -9
- package/scripts/{v4-declarative-promotion-admission.mjs → declarative-promotion-admission.mjs} +4 -4
- package/scripts/dev-delivery-authority-command-adapters.mjs +1 -1
- package/scripts/dev-delivery-authority.mjs +8 -8
- package/scripts/dev-delivery-source-proof-reuse.mjs +2 -1
- package/scripts/dev-delivery-warrant-options.mjs +15 -10
- package/scripts/dev-delivery-warrant-store.mjs +98 -13
- package/scripts/dev-delivery-warrant-transition.mjs +109 -0
- package/scripts/dev-delivery-warrant.mjs +80 -103
- package/scripts/dev-pr-auto-merge.mjs +15 -15
- package/scripts/dev-pr-delivery-warrant.mjs +1 -1
- package/scripts/generate-channel-build-workflow.mjs +7 -2
- package/scripts/generate-channel-promotion-workflow.mjs +19 -34
- package/scripts/generate-release-candidate-passport.mjs +23 -23
- package/scripts/generate-site-bundle.mjs +28 -28
- package/scripts/generate-universal-workflow-facades.mjs +498 -0
- package/scripts/generate-workflow-taxonomy.mjs +25 -0
- package/scripts/github-output.mjs +31 -0
- package/scripts/{v4-host-adapter.mjs → host-adapter.mjs} +1 -1
- package/scripts/implementation-references.mjs +25 -0
- package/scripts/init-repo.mjs +1 -1
- package/scripts/maintainability-metrics.mjs +16 -5
- package/scripts/maintainability-public-surface.mjs +115 -0
- package/scripts/next-development-review.mjs +313 -0
- package/scripts/oci-compose-preview.mjs +261 -0
- package/scripts/paper-work-fleet-cli.mjs +2 -0
- package/scripts/{v4-platform-stage-checkpoint-rehearsal.mjs → platform-stage-checkpoint-rehearsal.mjs} +17 -17
- package/scripts/{v4-product-publication-intent.mjs → product-publication-intent.mjs} +28 -13
- package/scripts/publication-candidate-kind.mjs +93 -0
- package/scripts/publication-candidate-sealer.mjs +16 -1
- package/scripts/{v4-publication-rehearsal-fixture.mjs → publication-rehearsal-fixture.mjs} +5 -5
- package/scripts/publication-settlement.mjs +211 -0
- package/scripts/release-asset-client.mjs +91 -0
- package/scripts/{v4-release-candidate-adapter.mjs → release-candidate-adapter.mjs} +4 -4
- package/scripts/release-candidate-resolver.mjs +24 -35
- package/scripts/release-tail.mjs +5 -5
- package/scripts/resume-from-candidate-run.mjs +35 -42
- package/scripts/site-capability-metadata.mjs +9 -0
- package/scripts/source-verification-evidence.mjs +344 -0
- package/scripts/stable-candidate-qualification.mjs +1 -1
- package/scripts/{v4-stage-capsule-qualification.mjs → stage-capsule-qualification.mjs} +62 -62
- package/scripts/{v4-stage-capsule-resume-rehearsal.mjs → stage-capsule-resume-rehearsal.mjs} +6 -6
- package/scripts/{v4-tail-reseal-macos-rehearsal.mjs → tail-reseal-macos-rehearsal.mjs} +9 -9
- package/scripts/{v4-tail-reseal.mjs → tail-reseal.mjs} +19 -19
- package/scripts/universal-facade-maintainability.mjs +91 -0
- package/scripts/universal-workflow-backflow.mjs +212 -0
- package/scripts/universal-workflow-engine.mjs +620 -0
- package/scripts/universal-workflow-self-dogfood.mjs +205 -0
- package/scripts/verify-version-state-delta.mjs +175 -0
- package/scripts/{v4-warrant-shadow-plan.mjs → warrant-shadow-plan.mjs} +6 -6
- package/scripts/workflow-taxonomy.mjs +507 -0
- package/templates/native-dev-delivery.yml +4 -7
- package/templates/universal-buildchain-bootstrap-recovery.yml +282 -0
- package/templates/universal-buildchain-bootstrap.yml +28 -0
- package/actions/v4-release-candidate-promote/README.md +0 -3
- package/packages/core/v4-partial-mutation-recovery-qualification.js +0 -395
- package/packages/core/v4-product-publication.js +0 -387
- package/packages/core/v4-provider-operation-journal.js +0 -531
- package/packages/core/v4-release-activation-shadow.js +0 -519
- package/packages/core/v4-release-invocation.js +0 -425
- package/packages/core/v4-stable-publication-fence.js +0 -357
- /package/architecture/{v4-adopter-delivery-parity.json → adopter-delivery-parity.json} +0 -0
- /package/architecture/{v3-core-mechanism-inventory.json → baseline-core-mechanism-inventory.json} +0 -0
- /package/architecture/{v4-canonical-contract-fixtures.json → canonical-contract-fixtures.json} +0 -0
- /package/architecture/{v4-compatibility-facts-parity.json → compatibility-facts-parity.json} +0 -0
- /package/architecture/{v4-delivery-warrant-shadow-bootstrap-plan.schema.json → delivery-warrant-shadow-bootstrap-plan.schema.json} +0 -0
- /package/architecture/{v4-delivery-warrant-shadow-fixtures.json → delivery-warrant-shadow-fixtures.json} +0 -0
- /package/architecture/{v4-delivery-warrant-shadow-fixtures.schema.json → delivery-warrant-shadow-fixtures.schema.json} +0 -0
- /package/architecture/{v4-exception-ledger.json → exception-ledger.json} +0 -0
- /package/architecture/{v4-exception-ledger.schema.json → exception-ledger.schema.json} +0 -0
- /package/architecture/{v4-release-invocation-fixtures.json → release-invocation-fixtures.json} +0 -0
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import { normalizeDevDeliveryAuthorityState } from "../packages/core/dev-delivery-authority-state.js";
|
|
8
8
|
|
|
9
9
|
const STATE_PATH = "queue.json";
|
|
10
|
+
const READ_ATTEMPTS = 3;
|
|
10
11
|
|
|
11
12
|
function text(value = "") {
|
|
12
13
|
return String(value ?? "").trim();
|
|
@@ -20,6 +21,14 @@ function exactSha(value, label) {
|
|
|
20
21
|
return normalized;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
function positiveInteger(value, label) {
|
|
25
|
+
const parsed = Number(value);
|
|
26
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
27
|
+
throw new Error(`${label} must be a positive integer`);
|
|
28
|
+
}
|
|
29
|
+
return parsed;
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
function normalizeRepository(value) {
|
|
24
33
|
const normalized = text(value);
|
|
25
34
|
const match = normalized.match(/^([^/\s]+)\/([^/\s]+)$/);
|
|
@@ -35,18 +44,20 @@ function encodeRef(ref) {
|
|
|
35
44
|
return ref.split("/").map(encodeURIComponent).join("/");
|
|
36
45
|
}
|
|
37
46
|
|
|
38
|
-
function
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
);
|
|
47
|
+
function decodeGitHubBlobEnvelope(raw) {
|
|
48
|
+
if (!/"encoding"\s*:\s*"base64"/.test(raw)) return raw;
|
|
49
|
+
const blob = JSON.parse(raw);
|
|
50
|
+
if (blob?.encoding !== "base64") return raw;
|
|
43
51
|
return Buffer.from(
|
|
44
52
|
String(blob.content || "").replace(/\s+/g, ""),
|
|
45
53
|
"base64",
|
|
46
54
|
).toString("utf8");
|
|
47
55
|
}
|
|
48
56
|
|
|
49
|
-
function validateStoredState(
|
|
57
|
+
function validateStoredState(
|
|
58
|
+
queue,
|
|
59
|
+
{ allowLegacyBaselineReadback = false } = {},
|
|
60
|
+
) {
|
|
50
61
|
const body = structuredClone(queue || {});
|
|
51
62
|
const embeddedStateRoot = body.stateRoot;
|
|
52
63
|
delete body.stateRoot;
|
|
@@ -59,7 +70,7 @@ function validateStoredState(queue, { allowLegacyV3Readback = false } = {}) {
|
|
|
59
70
|
) {
|
|
60
71
|
normalizeDevDeliveryAuthorityState(queue);
|
|
61
72
|
} else {
|
|
62
|
-
normalizeDevDeliveryQueue(queue, {
|
|
73
|
+
normalizeDevDeliveryQueue(queue, { allowLegacyBaselineReadback });
|
|
63
74
|
}
|
|
64
75
|
return queue;
|
|
65
76
|
}
|
|
@@ -71,6 +82,7 @@ export class GitHubDevDeliveryStore {
|
|
|
71
82
|
apiUrl = "https://api.github.com",
|
|
72
83
|
fetchImpl = globalThis.fetch,
|
|
73
84
|
createInitialState = createDevDeliveryQueue,
|
|
85
|
+
readAttempts = READ_ATTEMPTS,
|
|
74
86
|
} = {}) {
|
|
75
87
|
this.repository = normalizeRepository(repository);
|
|
76
88
|
if (!fetchImpl) throw new Error("fetch is required");
|
|
@@ -82,6 +94,22 @@ export class GitHubDevDeliveryStore {
|
|
|
82
94
|
this.apiUrl = apiUrl.replace(/\/+$/, "");
|
|
83
95
|
this.fetch = fetchImpl;
|
|
84
96
|
this.createInitialState = createInitialState;
|
|
97
|
+
this.readAttempts = positiveInteger(readAttempts, "readAttempts");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async retryParseableRead(operation) {
|
|
101
|
+
let failure;
|
|
102
|
+
for (let attempt = 1; attempt <= this.readAttempts; attempt += 1) {
|
|
103
|
+
try {
|
|
104
|
+
return await operation();
|
|
105
|
+
} catch (error) {
|
|
106
|
+
failure = error;
|
|
107
|
+
if (!(error instanceof SyntaxError) || attempt === this.readAttempts) {
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
throw failure;
|
|
85
113
|
}
|
|
86
114
|
|
|
87
115
|
async request(method, requestPath, body) {
|
|
@@ -108,7 +136,52 @@ export class GitHubDevDeliveryStore {
|
|
|
108
136
|
return data;
|
|
109
137
|
}
|
|
110
138
|
|
|
111
|
-
async
|
|
139
|
+
async requestRaw(method, requestPath) {
|
|
140
|
+
const response = await this.fetch(`${this.apiUrl}${requestPath}`, {
|
|
141
|
+
method,
|
|
142
|
+
headers: {
|
|
143
|
+
accept: "application/vnd.github.raw+json",
|
|
144
|
+
authorization: `Bearer ${this.token}`,
|
|
145
|
+
"x-github-api-version": "2022-11-28",
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
const raw = await response.text();
|
|
149
|
+
if (!response.ok) {
|
|
150
|
+
let message = raw || `${method} ${requestPath} failed`;
|
|
151
|
+
try {
|
|
152
|
+
message = JSON.parse(raw)?.message || message;
|
|
153
|
+
} catch {
|
|
154
|
+
// Raw blob responses are not required to be JSON.
|
|
155
|
+
}
|
|
156
|
+
const error = new Error(message);
|
|
157
|
+
error.status = response.status;
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
return raw;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async read({
|
|
164
|
+
stateRef,
|
|
165
|
+
protectedBase,
|
|
166
|
+
now,
|
|
167
|
+
allowLegacyBaselineReadback = false,
|
|
168
|
+
}) {
|
|
169
|
+
return this.retryParseableRead(async () =>
|
|
170
|
+
this.readOnce({
|
|
171
|
+
stateRef,
|
|
172
|
+
protectedBase,
|
|
173
|
+
now,
|
|
174
|
+
allowLegacyBaselineReadback,
|
|
175
|
+
}),
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async readOnce({
|
|
180
|
+
stateRef,
|
|
181
|
+
protectedBase,
|
|
182
|
+
now,
|
|
183
|
+
allowLegacyBaselineReadback = false,
|
|
184
|
+
}) {
|
|
112
185
|
let ref;
|
|
113
186
|
try {
|
|
114
187
|
ref = await this.request(
|
|
@@ -129,12 +202,24 @@ export class GitHubDevDeliveryStore {
|
|
|
129
202
|
}
|
|
130
203
|
const commitSha = exactSha(ref?.object?.sha, "state ref commit");
|
|
131
204
|
const readback = await this.readCommit(commitSha, {
|
|
132
|
-
|
|
205
|
+
allowLegacyBaselineReadback,
|
|
133
206
|
});
|
|
134
207
|
return { exists: true, ...readback };
|
|
135
208
|
}
|
|
136
209
|
|
|
137
|
-
async readCommit(
|
|
210
|
+
async readCommit(
|
|
211
|
+
commitShaInput,
|
|
212
|
+
{ allowLegacyBaselineReadback = false } = {},
|
|
213
|
+
) {
|
|
214
|
+
return this.retryParseableRead(async () =>
|
|
215
|
+
this.readCommitOnce(commitShaInput, { allowLegacyBaselineReadback }),
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async readCommitOnce(
|
|
220
|
+
commitShaInput,
|
|
221
|
+
{ allowLegacyBaselineReadback = false } = {},
|
|
222
|
+
) {
|
|
138
223
|
const commitSha = exactSha(commitShaInput, "state commit");
|
|
139
224
|
const commit = await this.request(
|
|
140
225
|
"GET",
|
|
@@ -149,13 +234,13 @@ export class GitHubDevDeliveryStore {
|
|
|
149
234
|
);
|
|
150
235
|
if (!entry?.sha)
|
|
151
236
|
throw new Error(`${commitSha} does not contain ${STATE_PATH}`);
|
|
152
|
-
const
|
|
237
|
+
const raw = await this.requestRaw(
|
|
153
238
|
"GET",
|
|
154
239
|
`/repos/${this.repository.fullName}/git/blobs/${entry.sha}`,
|
|
155
240
|
);
|
|
156
|
-
const bytes =
|
|
241
|
+
const bytes = decodeGitHubBlobEnvelope(raw);
|
|
157
242
|
const queue = validateStoredState(JSON.parse(bytes), {
|
|
158
|
-
|
|
243
|
+
allowLegacyBaselineReadback,
|
|
159
244
|
});
|
|
160
245
|
return { commitSha, queue, bytes };
|
|
161
246
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { recoverExpiredDevDeliveryWarrant } from "../packages/core/dev-delivery-warrant.js";
|
|
2
|
+
|
|
3
|
+
async function recoverExpiredLeaseBeforeReselection({
|
|
4
|
+
store,
|
|
5
|
+
options,
|
|
6
|
+
loaded,
|
|
7
|
+
initialLoaded,
|
|
8
|
+
}) {
|
|
9
|
+
const recovery = recoverExpiredDevDeliveryWarrant(loaded.queue, {
|
|
10
|
+
now: options.now,
|
|
11
|
+
});
|
|
12
|
+
if (recovery.receipt.expectedOldStateRoot !== loaded.queue.stateRoot) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
"expired Warrant recovery receipt expected-old root does not match the loaded authority",
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
await store.write({
|
|
18
|
+
stateRef: options.stateRef,
|
|
19
|
+
queue: recovery.queue,
|
|
20
|
+
expectedCommitSha: loaded.commitSha,
|
|
21
|
+
expectedStateRoot: loaded.queue.stateRoot,
|
|
22
|
+
receiptRoot: recovery.receiptRoot,
|
|
23
|
+
});
|
|
24
|
+
const reloaded = await store.read({
|
|
25
|
+
stateRef: options.stateRef,
|
|
26
|
+
protectedBase: options.branch,
|
|
27
|
+
now: options.now,
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
loaded: reloaded,
|
|
31
|
+
concurrencyRecovery: {
|
|
32
|
+
schema: "kungfu.buildchain.dev-delivery-concurrency-recovery/v1",
|
|
33
|
+
action: "expired-lease-recovered-before-reselection",
|
|
34
|
+
initialCommitSha: initialLoaded.commitSha,
|
|
35
|
+
recoveredStateRoot: recovery.queue.stateRoot,
|
|
36
|
+
observedCommitSha: reloaded.commitSha,
|
|
37
|
+
observedStateRoot: reloaded.queue.stateRoot,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function persistDevDeliveryTransition({
|
|
43
|
+
store,
|
|
44
|
+
options,
|
|
45
|
+
loaded,
|
|
46
|
+
initialLoaded,
|
|
47
|
+
changed,
|
|
48
|
+
transitionFor,
|
|
49
|
+
}) {
|
|
50
|
+
let concurrencyRecovery = null;
|
|
51
|
+
if (
|
|
52
|
+
options.execute &&
|
|
53
|
+
options.command === "select" &&
|
|
54
|
+
changed.recoveryReceipt?.action === "recovered-expired-lease"
|
|
55
|
+
) {
|
|
56
|
+
const recovery = await recoverExpiredLeaseBeforeReselection({
|
|
57
|
+
store,
|
|
58
|
+
options,
|
|
59
|
+
loaded,
|
|
60
|
+
initialLoaded,
|
|
61
|
+
});
|
|
62
|
+
loaded = recovery.loaded;
|
|
63
|
+
changed = transitionFor(options.command, loaded.queue, options);
|
|
64
|
+
concurrencyRecovery = recovery.concurrencyRecovery;
|
|
65
|
+
}
|
|
66
|
+
if (!options.execute || changed.queue.stateRoot === loaded.queue.stateRoot)
|
|
67
|
+
return { loaded, changed, write: null, concurrencyRecovery };
|
|
68
|
+
if (changed.receipt.expectedOldStateRoot !== loaded.queue.stateRoot) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
"transition receipt expected-old root does not match the loaded authority",
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const write = await store.write({
|
|
75
|
+
stateRef: options.stateRef,
|
|
76
|
+
queue: changed.queue,
|
|
77
|
+
expectedCommitSha: loaded.commitSha,
|
|
78
|
+
expectedStateRoot: loaded.queue.stateRoot,
|
|
79
|
+
receiptRoot: changed.receiptRoot,
|
|
80
|
+
});
|
|
81
|
+
return { loaded, changed, write, concurrencyRecovery };
|
|
82
|
+
} catch (error) {
|
|
83
|
+
if (options.command !== "settle" || options.expectedOldStateRoot)
|
|
84
|
+
throw error;
|
|
85
|
+
const latest = await store.read({
|
|
86
|
+
stateRef: options.stateRef,
|
|
87
|
+
protectedBase: options.branch,
|
|
88
|
+
now: options.now,
|
|
89
|
+
});
|
|
90
|
+
const reconciled = transitionFor(options.command, latest.queue, options);
|
|
91
|
+
if (
|
|
92
|
+
reconciled.queue.stateRoot !== latest.queue.stateRoot ||
|
|
93
|
+
reconciled.receipt.action !== "duplicate-terminal-event-noop"
|
|
94
|
+
)
|
|
95
|
+
throw error;
|
|
96
|
+
return {
|
|
97
|
+
loaded: latest,
|
|
98
|
+
changed: reconciled,
|
|
99
|
+
write: null,
|
|
100
|
+
concurrencyRecovery: {
|
|
101
|
+
schema: "kungfu.buildchain.dev-delivery-concurrency-recovery/v1",
|
|
102
|
+
action: "terminal-settlement-race-noop",
|
|
103
|
+
initialCommitSha: initialLoaded.commitSha,
|
|
104
|
+
observedCommitSha: latest.commitSha,
|
|
105
|
+
observedStateRoot: latest.queue.stateRoot,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -10,16 +10,17 @@ import {
|
|
|
10
10
|
heartbeatDevDeliveryWarrant,
|
|
11
11
|
observeDevDeliveryQueue,
|
|
12
12
|
qualifyDevDeliveryWarrant,
|
|
13
|
-
recoverExpiredDevDeliveryWarrant,
|
|
14
13
|
reconcileDevDeliveryTerminalEvidence,
|
|
15
14
|
selectDevDeliveryWarrant,
|
|
16
15
|
settleDevDeliveryTerminalEvent,
|
|
17
16
|
submitDevDeliveryCandidate,
|
|
18
17
|
} from "../packages/core/dev-delivery-warrant.js";
|
|
19
18
|
import { recoverLegacyTerminalDevDeliveryQueue } from "../packages/core/dev-delivery-warrant-legacy-recovery.js";
|
|
20
|
-
import {
|
|
19
|
+
import { reuseExactActiveDevDeliverySourceProof } from "../packages/core/dev-delivery-candidate-identity.js";
|
|
20
|
+
import { runDeliveryWarrantReadCandidate } from "../packages/core/delivery-warrant-read-candidate.js";
|
|
21
21
|
|
|
22
22
|
import { GitHubDevDeliveryStore } from "./dev-delivery-warrant-store.mjs";
|
|
23
|
+
import { persistDevDeliveryTransition } from "./dev-delivery-warrant-transition.mjs";
|
|
23
24
|
import { devDeliveryCliOptions } from "./dev-delivery-warrant-options.mjs";
|
|
24
25
|
export { GitHubDevDeliveryStore, devDeliveryCliOptions };
|
|
25
26
|
|
|
@@ -199,54 +200,60 @@ function transitionFor(command, queue, options) {
|
|
|
199
200
|
"native command contract root does not match native-command",
|
|
200
201
|
);
|
|
201
202
|
}
|
|
203
|
+
const input = {
|
|
204
|
+
pullRequestNumber: positiveInteger(
|
|
205
|
+
options.pullRequestNumber,
|
|
206
|
+
"pullRequestNumber",
|
|
207
|
+
),
|
|
208
|
+
sourceHead: exactSha(options.sourceHead, "sourceHead"),
|
|
209
|
+
...(options.sourceRoot ? { sourceRoot: options.sourceRoot } : {}),
|
|
210
|
+
...(options.assignmentRoot
|
|
211
|
+
? { assignmentRoot: options.assignmentRoot }
|
|
212
|
+
: {}),
|
|
213
|
+
...(options.initiativeRoot
|
|
214
|
+
? { initiativeRoot: options.initiativeRoot }
|
|
215
|
+
: {}),
|
|
216
|
+
sourceIdentityRoot: exactRoot(
|
|
217
|
+
options.sourceIdentityRoot,
|
|
218
|
+
"sourceIdentityRoot",
|
|
219
|
+
),
|
|
220
|
+
sourcePatchRoot: exactRoot(options.sourcePatchRoot, "sourcePatchRoot"),
|
|
221
|
+
sourceProofRoot: exactRoot(options.sourceProofRoot, "sourceProofRoot"),
|
|
222
|
+
planRoot: exactRoot(options.planRoot, "planRoot"),
|
|
223
|
+
closureRoot: exactRoot(options.closureRoot, "closureRoot"),
|
|
224
|
+
dependencyRoot: exactRoot(options.dependencyRoot, "dependencyRoot"),
|
|
225
|
+
toolchainRoot: exactRoot(options.toolchainRoot, "toolchainRoot"),
|
|
226
|
+
...(options.environmentRoot
|
|
227
|
+
? {
|
|
228
|
+
environmentRoot: exactRoot(
|
|
229
|
+
options.environmentRoot,
|
|
230
|
+
"environmentRoot",
|
|
231
|
+
),
|
|
232
|
+
}
|
|
233
|
+
: {}),
|
|
234
|
+
...(nativeCommandContract ? { nativeCommandContract } : {}),
|
|
235
|
+
affectedPaths: jsonList(options.affectedPaths, "affected paths"),
|
|
236
|
+
shardEvidenceRoots: jsonList(
|
|
237
|
+
options.shardEvidenceRoots,
|
|
238
|
+
"shard evidence roots",
|
|
239
|
+
),
|
|
240
|
+
sourceWorkflowRunId: options.sourceWorkflowRunId
|
|
241
|
+
? positiveInteger(options.sourceWorkflowRunId, "sourceWorkflowRunId")
|
|
242
|
+
: 0,
|
|
243
|
+
deliveryClass: options.deliveryClass,
|
|
244
|
+
priority: options.priority || "ordinary",
|
|
245
|
+
...(options.releaseBlockerPriority
|
|
246
|
+
? {
|
|
247
|
+
releaseBlockerPriority: jsonObject(
|
|
248
|
+
options.releaseBlockerPriority,
|
|
249
|
+
"release blocker priority",
|
|
250
|
+
),
|
|
251
|
+
}
|
|
252
|
+
: {}),
|
|
253
|
+
};
|
|
202
254
|
return submitDevDeliveryCandidate(
|
|
203
255
|
queue,
|
|
204
|
-
|
|
205
|
-
pullRequestNumber: positiveInteger(
|
|
206
|
-
options.pullRequestNumber,
|
|
207
|
-
"pullRequestNumber",
|
|
208
|
-
),
|
|
209
|
-
sourceHead: exactSha(options.sourceHead, "sourceHead"),
|
|
210
|
-
assignmentRoot: exactRoot(options.assignmentRoot, "assignmentRoot"),
|
|
211
|
-
initiativeRoot: exactRoot(options.initiativeRoot, "initiativeRoot"),
|
|
212
|
-
sourceIdentityRoot: exactRoot(
|
|
213
|
-
options.sourceIdentityRoot,
|
|
214
|
-
"sourceIdentityRoot",
|
|
215
|
-
),
|
|
216
|
-
sourcePatchRoot: exactRoot(options.sourcePatchRoot, "sourcePatchRoot"),
|
|
217
|
-
sourceProofRoot: exactRoot(options.sourceProofRoot, "sourceProofRoot"),
|
|
218
|
-
planRoot: exactRoot(options.planRoot, "planRoot"),
|
|
219
|
-
closureRoot: exactRoot(options.closureRoot, "closureRoot"),
|
|
220
|
-
dependencyRoot: exactRoot(options.dependencyRoot, "dependencyRoot"),
|
|
221
|
-
toolchainRoot: exactRoot(options.toolchainRoot, "toolchainRoot"),
|
|
222
|
-
...(options.environmentRoot
|
|
223
|
-
? {
|
|
224
|
-
environmentRoot: exactRoot(
|
|
225
|
-
options.environmentRoot,
|
|
226
|
-
"environmentRoot",
|
|
227
|
-
),
|
|
228
|
-
}
|
|
229
|
-
: {}),
|
|
230
|
-
...(nativeCommandContract ? { nativeCommandContract } : {}),
|
|
231
|
-
affectedPaths: jsonList(options.affectedPaths, "affected paths"),
|
|
232
|
-
shardEvidenceRoots: jsonList(
|
|
233
|
-
options.shardEvidenceRoots,
|
|
234
|
-
"shard evidence roots",
|
|
235
|
-
),
|
|
236
|
-
sourceWorkflowRunId: options.sourceWorkflowRunId
|
|
237
|
-
? positiveInteger(options.sourceWorkflowRunId, "sourceWorkflowRunId")
|
|
238
|
-
: 0,
|
|
239
|
-
deliveryClass: options.deliveryClass,
|
|
240
|
-
priority: options.priority || "ordinary",
|
|
241
|
-
...(options.releaseBlockerPriority
|
|
242
|
-
? {
|
|
243
|
-
releaseBlockerPriority: jsonObject(
|
|
244
|
-
options.releaseBlockerPriority,
|
|
245
|
-
"release blocker priority",
|
|
246
|
-
),
|
|
247
|
-
}
|
|
248
|
-
: {}),
|
|
249
|
-
},
|
|
256
|
+
reuseExactActiveDevDeliverySourceProof(queue.activeWarrant, input),
|
|
250
257
|
{ now: options.now },
|
|
251
258
|
);
|
|
252
259
|
}
|
|
@@ -356,7 +363,7 @@ async function observeQueue(loaded, options) {
|
|
|
356
363
|
throw new Error("readMode must be v3 or v4");
|
|
357
364
|
let observation = observeDevDeliveryQueue(loaded.queue, {
|
|
358
365
|
now: options.now,
|
|
359
|
-
|
|
366
|
+
allowLegacyBaselineReadback: true,
|
|
360
367
|
});
|
|
361
368
|
let readCandidate;
|
|
362
369
|
if (readMode === "v4") {
|
|
@@ -377,7 +384,7 @@ async function observeQueue(loaded, options) {
|
|
|
377
384
|
);
|
|
378
385
|
return { receiptRoot: evidence.evidenceRoot };
|
|
379
386
|
});
|
|
380
|
-
readCandidate = await
|
|
387
|
+
readCandidate = await runDeliveryWarrantReadCandidate(loaded.queue, {
|
|
381
388
|
qualification,
|
|
382
389
|
expectedQualificationRoot: options.readQualificationRoot,
|
|
383
390
|
expectedSources: {
|
|
@@ -437,7 +444,7 @@ export async function runDevDeliveryCommand(optionsInput = {}, clientInput) {
|
|
|
437
444
|
stateRef: options.stateRef,
|
|
438
445
|
protectedBase: options.branch,
|
|
439
446
|
now: options.now,
|
|
440
|
-
|
|
447
|
+
allowLegacyBaselineReadback: ["observe", "recover-legacy-terminal"].includes(
|
|
441
448
|
options.command,
|
|
442
449
|
),
|
|
443
450
|
});
|
|
@@ -461,51 +468,16 @@ export async function runDevDeliveryCommand(optionsInput = {}, clientInput) {
|
|
|
461
468
|
}
|
|
462
469
|
if (options.command === "observe") return observeQueue(loaded, options);
|
|
463
470
|
const initialLoaded = loaded;
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
write = await store.write({
|
|
475
|
-
stateRef: options.stateRef,
|
|
476
|
-
queue: changed.queue,
|
|
477
|
-
expectedCommitSha: loaded.commitSha,
|
|
478
|
-
expectedStateRoot: loaded.queue.stateRoot,
|
|
479
|
-
receiptRoot: changed.receiptRoot,
|
|
480
|
-
});
|
|
481
|
-
} catch (error) {
|
|
482
|
-
if (options.command !== "settle" || options.expectedOldStateRoot)
|
|
483
|
-
throw error;
|
|
484
|
-
const latest = await store.read({
|
|
485
|
-
stateRef: options.stateRef,
|
|
486
|
-
protectedBase: options.branch,
|
|
487
|
-
now: options.now,
|
|
488
|
-
});
|
|
489
|
-
const reconciled = transitionFor(options.command, latest.queue, options);
|
|
490
|
-
const reconciledMutates =
|
|
491
|
-
reconciled.queue.stateRoot !== latest.queue.stateRoot;
|
|
492
|
-
if (
|
|
493
|
-
reconciledMutates ||
|
|
494
|
-
reconciled.receipt.action !== "duplicate-terminal-event-noop"
|
|
495
|
-
)
|
|
496
|
-
throw error;
|
|
497
|
-
loaded = latest;
|
|
498
|
-
changed = reconciled;
|
|
499
|
-
mutates = false;
|
|
500
|
-
concurrencyRecovery = {
|
|
501
|
-
schema: "kungfu.buildchain.dev-delivery-concurrency-recovery/v1",
|
|
502
|
-
action: "terminal-settlement-race-noop",
|
|
503
|
-
initialCommitSha: initialLoaded.commitSha,
|
|
504
|
-
observedCommitSha: latest.commitSha,
|
|
505
|
-
observedStateRoot: latest.queue.stateRoot,
|
|
506
|
-
};
|
|
507
|
-
}
|
|
508
|
-
}
|
|
471
|
+
const persisted = await persistDevDeliveryTransition({
|
|
472
|
+
store,
|
|
473
|
+
options,
|
|
474
|
+
loaded,
|
|
475
|
+
initialLoaded,
|
|
476
|
+
changed: transitionFor(options.command, loaded.queue, options),
|
|
477
|
+
transitionFor,
|
|
478
|
+
});
|
|
479
|
+
loaded = persisted.loaded;
|
|
480
|
+
concurrencyRecovery = persisted.concurrencyRecovery || concurrencyRecovery;
|
|
509
481
|
return {
|
|
510
482
|
schema: "kungfu.buildchain.dev-delivery-command-result/v1",
|
|
511
483
|
ok: true,
|
|
@@ -514,16 +486,21 @@ export async function runDevDeliveryCommand(optionsInput = {}, clientInput) {
|
|
|
514
486
|
stateRef: options.stateRef,
|
|
515
487
|
before: { commitSha: loaded.commitSha, stateRoot: loaded.queue.stateRoot },
|
|
516
488
|
after: {
|
|
517
|
-
commitSha: write?.commitSha || loaded.commitSha,
|
|
518
|
-
stateRoot: changed.queue.stateRoot,
|
|
489
|
+
commitSha: persisted.write?.commitSha || loaded.commitSha,
|
|
490
|
+
stateRoot: persisted.changed.queue.stateRoot,
|
|
519
491
|
},
|
|
520
492
|
mutationAuthorized: options.execute,
|
|
521
|
-
mutationApplied: Boolean(write),
|
|
493
|
+
mutationApplied: Boolean(persisted.write),
|
|
522
494
|
concurrencyRecovery,
|
|
523
|
-
receipt: changed.receipt,
|
|
524
|
-
receiptRoot: changed.receiptRoot,
|
|
525
|
-
warrant:
|
|
526
|
-
|
|
495
|
+
receipt: persisted.changed.receipt,
|
|
496
|
+
receiptRoot: persisted.changed.receiptRoot,
|
|
497
|
+
warrant:
|
|
498
|
+
persisted.changed.warrant ||
|
|
499
|
+
persisted.changed.queue.activeWarrant ||
|
|
500
|
+
null,
|
|
501
|
+
observation: observeDevDeliveryQueue(persisted.changed.queue, {
|
|
502
|
+
now: options.now,
|
|
503
|
+
}),
|
|
527
504
|
};
|
|
528
505
|
}
|
|
529
506
|
|
|
@@ -723,7 +723,6 @@ function renderAdmissionComment(receipt, receiptRoot) {
|
|
|
723
723
|
"GitHub auto-merge state is observed evidence only; it is not Buildchain admission authority.",
|
|
724
724
|
].join("\n");
|
|
725
725
|
}
|
|
726
|
-
|
|
727
726
|
async function publishAdmissionDiagnostic(client, options, receipt, receiptRoot) {
|
|
728
727
|
const marker = `<!-- ${AGENT_ADMISSION_MARKER} pr=${receipt.pullRequestNumber} head=${receipt.expectedHeadSha} -->`;
|
|
729
728
|
const body = renderAdmissionComment(receipt, receiptRoot);
|
|
@@ -743,7 +742,6 @@ async function publishAdmissionDiagnostic(client, options, receipt, receiptRoot)
|
|
|
743
742
|
}
|
|
744
743
|
return { commentId: comment?.id || null, commentUrl: comment?.html_url || "", statusPublished: Boolean(status) };
|
|
745
744
|
}
|
|
746
|
-
|
|
747
745
|
function createAdmissionReceipt({ options, pr = {}, state, reason, readiness, decision = {}, queue = null, warrant = null }) {
|
|
748
746
|
return createDevPrAdmissionReceipt({ options, pr, state, reason, readiness, decision, queue, warrant, labels: labelsOf(pr), nextAction: nextAdmissionAction });
|
|
749
747
|
}
|
|
@@ -751,16 +749,21 @@ function createAdmissionReceipt({ options, pr = {}, state, reason, readiness, de
|
|
|
751
749
|
function targetedFailure({ options, pr, state, reason, readiness, decision, queue }) {
|
|
752
750
|
const receipt = createAdmissionReceipt({ options, pr, state, reason, readiness, decision, queue });
|
|
753
751
|
return {
|
|
754
|
-
schema: AGENT_ADMISSION_RESULT_SCHEMA,
|
|
755
|
-
|
|
756
|
-
mode: options.dryRun ? "plan" : "execute",
|
|
757
|
-
outcome: "targeted-admission-failed",
|
|
758
|
-
receipt,
|
|
759
|
-
receiptRoot: contentRoot(receipt),
|
|
760
|
-
diagnostic: null,
|
|
752
|
+
schema: AGENT_ADMISSION_RESULT_SCHEMA, ok: false, mode: options.dryRun ? "plan" : "execute",
|
|
753
|
+
outcome: "targeted-admission-failed", receipt, receiptRoot: contentRoot(receipt), diagnostic: null,
|
|
761
754
|
};
|
|
762
755
|
}
|
|
763
|
-
|
|
756
|
+
async function readTargetPullRequest(client, number, options) {
|
|
757
|
+
let { pollMergeableAttempts: attempts, pollMergeableDelayMs: delayMs } = options;
|
|
758
|
+
for (; attempts > 1; attempts -= 1) {
|
|
759
|
+
try {
|
|
760
|
+
return await client.getPullRequest(number, { attempts, delayMs });
|
|
761
|
+
} catch {
|
|
762
|
+
await delay(delayMs);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
return client.getPullRequest(number, { attempts, delayMs });
|
|
766
|
+
}
|
|
764
767
|
export async function runDevPrAdmission(optionsInput = {}, clientInput) {
|
|
765
768
|
const options = normalizeOptions(optionsInput);
|
|
766
769
|
if (!options.targetBranch) throw new Error("target branch is required");
|
|
@@ -776,12 +779,9 @@ export async function runDevPrAdmission(optionsInput = {}, clientInput) {
|
|
|
776
779
|
|
|
777
780
|
let pr;
|
|
778
781
|
try {
|
|
779
|
-
pr = await client
|
|
780
|
-
attempts: options.pollMergeableAttempts,
|
|
781
|
-
delayMs: options.pollMergeableDelayMs,
|
|
782
|
-
});
|
|
782
|
+
pr = await readTargetPullRequest(client, options.targetPullRequestNumber, options);
|
|
783
783
|
} catch (error) {
|
|
784
|
-
return targetedFailure({ options, pr: {}, state: "
|
|
784
|
+
return targetedFailure({ options, pr: {}, state: "blocked", reason: "pull-request-read-failed" });
|
|
785
785
|
}
|
|
786
786
|
|
|
787
787
|
const readinessFence = createPreReadinessQueueFence({ client, options, sleep: delay });
|
|
@@ -143,7 +143,7 @@ export async function readCurrentDeliveryQueueState(client, repository, targetBr
|
|
|
143
143
|
const { queue } = await store.read({
|
|
144
144
|
stateRef: defaultDevDeliveryStateRef(targetBranch),
|
|
145
145
|
protectedBase: targetBranch,
|
|
146
|
-
|
|
146
|
+
allowLegacyBaselineReadback: true,
|
|
147
147
|
});
|
|
148
148
|
return queue;
|
|
149
149
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
|
+
import { writeWorkflowSource } from "./workflow-taxonomy.mjs";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { migrateUniversalWorkflowFacade } from "./generate-universal-workflow-facades.mjs";
|
|
6
8
|
|
|
7
9
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
8
10
|
const sourcePath = path.join(root, ".github/workflows/.build.yml");
|
|
@@ -403,7 +405,10 @@ export function generateChannelBuildWorkflow(source) {
|
|
|
403
405
|
].join("\n"),
|
|
404
406
|
)
|
|
405
407
|
.replace("\n alpha:\n", `\n${routerControllerPlanJob()}\n\n alpha:\n`);
|
|
406
|
-
return
|
|
408
|
+
return migrateUniversalWorkflowFacade(
|
|
409
|
+
`${generated.trimEnd()}\n\n${routerControllerReceiptJob()}\n\n${routerAggregateJob()}\n`,
|
|
410
|
+
".github/workflows/build.yml",
|
|
411
|
+
);
|
|
407
412
|
}
|
|
408
413
|
|
|
409
414
|
function main() {
|
|
@@ -417,7 +422,7 @@ function main() {
|
|
|
417
422
|
}
|
|
418
423
|
return;
|
|
419
424
|
}
|
|
420
|
-
|
|
425
|
+
writeWorkflowSource(root, path.relative(root, targetPath), generated);
|
|
421
426
|
}
|
|
422
427
|
|
|
423
428
|
const isMain = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
|