@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
package/scripts/{v4-stage-capsule-resume-rehearsal.mjs → stage-capsule-resume-rehearsal.mjs}
RENAMED
|
@@ -4,8 +4,8 @@ import fs from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { domainCanonicalBytes } from "../packages/core/canonical-contracts.js";
|
|
8
|
+
import { planStageCapsuleResume } from "../packages/core/stage-capsule-resume-planner.js";
|
|
9
9
|
|
|
10
10
|
const repoRoot = path.resolve(
|
|
11
11
|
path.dirname(fileURLToPath(import.meta.url)),
|
|
@@ -22,7 +22,7 @@ if (!platform) throw new Error("--platform is required");
|
|
|
22
22
|
|
|
23
23
|
const declaration = JSON.parse(
|
|
24
24
|
fs.readFileSync(
|
|
25
|
-
path.join(repoRoot, "architecture/
|
|
25
|
+
path.join(repoRoot, "architecture/platform-stage-checkpoints.json"),
|
|
26
26
|
"utf8",
|
|
27
27
|
),
|
|
28
28
|
);
|
|
@@ -38,13 +38,13 @@ const fixture = JSON.parse(
|
|
|
38
38
|
"utf8",
|
|
39
39
|
),
|
|
40
40
|
);
|
|
41
|
-
const first =
|
|
42
|
-
const second =
|
|
41
|
+
const first = planStageCapsuleResume(fixture);
|
|
42
|
+
const second = planStageCapsuleResume(structuredClone(fixture));
|
|
43
43
|
if (first.planRoot !== second.planRoot)
|
|
44
44
|
throw new Error("resume planner is not deterministic");
|
|
45
45
|
|
|
46
46
|
process.stdout.write(
|
|
47
|
-
|
|
47
|
+
domainCanonicalBytes({
|
|
48
48
|
schema: "buildchain-v4-stage-capsule-resume-rehearsal/v1",
|
|
49
49
|
mode: "shadow-only",
|
|
50
50
|
platform,
|
|
@@ -6,8 +6,8 @@ import os from "node:os";
|
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { pathToFileURL } from "node:url";
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { domainContentRoot } from "../packages/core/canonical-contracts.js";
|
|
10
|
+
import { verifyTailResealPlatform } from "./tail-reseal.mjs";
|
|
11
11
|
|
|
12
12
|
function flag(args, name, fallback = "") {
|
|
13
13
|
const index = args.indexOf(`--${name}`);
|
|
@@ -56,12 +56,12 @@ function writeCandidate(root, request, content) {
|
|
|
56
56
|
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
57
57
|
fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
|
|
58
58
|
return {
|
|
59
|
-
artifactRoot:
|
|
59
|
+
artifactRoot: domainContentRoot("tail-reseal-artifact-files", [file]),
|
|
60
60
|
manifestRoot: fileRoot(manifestPath),
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
export function
|
|
64
|
+
export function rehearseTailResealMacos({
|
|
65
65
|
fixturePath = "contracts/fixtures/v4-tail-reseal-v1/valid.json",
|
|
66
66
|
outputPath = "",
|
|
67
67
|
} = {}) {
|
|
@@ -69,20 +69,20 @@ export function rehearseV4TailResealMacos({
|
|
|
69
69
|
fs.readFileSync(path.resolve(fixturePath), "utf8"),
|
|
70
70
|
);
|
|
71
71
|
const workRoot = fs.mkdtempSync(
|
|
72
|
-
path.join(os.tmpdir(), "buildchain-
|
|
72
|
+
path.join(os.tmpdir(), "buildchain-tail-macos-"),
|
|
73
73
|
);
|
|
74
74
|
try {
|
|
75
75
|
const retainedRoots = writeCandidate(workRoot, request, "unsigned");
|
|
76
76
|
const platform = request.platforms.find(({ id }) => id === "macos-arm64");
|
|
77
77
|
Object.assign(platform, retainedRoots);
|
|
78
|
-
const retained =
|
|
78
|
+
const retained = verifyTailResealPlatform({
|
|
79
79
|
request,
|
|
80
80
|
platformId: "macos-arm64",
|
|
81
81
|
artifactRoot: workRoot,
|
|
82
82
|
mode: "retained",
|
|
83
83
|
});
|
|
84
84
|
writeCandidate(workRoot, request, "signed-and-notarized");
|
|
85
|
-
const resealed =
|
|
85
|
+
const resealed = verifyTailResealPlatform({
|
|
86
86
|
request,
|
|
87
87
|
platformId: "macos-arm64",
|
|
88
88
|
artifactRoot: workRoot,
|
|
@@ -100,7 +100,7 @@ export function rehearseV4TailResealMacos({
|
|
|
100
100
|
};
|
|
101
101
|
const evidence = {
|
|
102
102
|
...payload,
|
|
103
|
-
evidenceRoot:
|
|
103
|
+
evidenceRoot: domainContentRoot("tail-reseal-admission", payload),
|
|
104
104
|
};
|
|
105
105
|
if (outputPath) {
|
|
106
106
|
const output = path.resolve(outputPath);
|
|
@@ -118,7 +118,7 @@ if (
|
|
|
118
118
|
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
119
119
|
) {
|
|
120
120
|
try {
|
|
121
|
-
const evidence =
|
|
121
|
+
const evidence = rehearseTailResealMacos({
|
|
122
122
|
fixturePath: flag(
|
|
123
123
|
process.argv.slice(2),
|
|
124
124
|
"fixture",
|
|
@@ -6,13 +6,13 @@ import path from "node:path";
|
|
|
6
6
|
import { pathToFileURL } from "node:url";
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "../packages/core/
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
9
|
+
TAIL_RESEAL_PLATFORMS,
|
|
10
|
+
normalizeTailResealRequest,
|
|
11
|
+
planTailReseal,
|
|
12
|
+
} from "../packages/core/tail-reseal.js";
|
|
13
|
+
import { createTailResealReceipt } from "../packages/core/tail-reseal-receipt.js";
|
|
14
|
+
import { validateTailResealGitHubEvidence } from "../packages/core/tail-reseal-github.js";
|
|
15
|
+
import { domainContentRoot } from "../packages/core/canonical-contracts.js";
|
|
16
16
|
|
|
17
17
|
function flag(args, name, fallback = "") {
|
|
18
18
|
const index = args.indexOf(`--${name}`);
|
|
@@ -137,7 +137,7 @@ async function admitFromGitHub(request) {
|
|
|
137
137
|
token,
|
|
138
138
|
),
|
|
139
139
|
]);
|
|
140
|
-
return
|
|
140
|
+
return validateTailResealGitHubEvidence({
|
|
141
141
|
request,
|
|
142
142
|
sourceCommit,
|
|
143
143
|
sourceRun,
|
|
@@ -183,14 +183,14 @@ function resolvePayload(root, relative, platformId) {
|
|
|
183
183
|
return absolute;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
export function
|
|
186
|
+
export function verifyTailResealPlatform({
|
|
187
187
|
request,
|
|
188
188
|
platformId,
|
|
189
189
|
artifactRoot,
|
|
190
190
|
mode = "retained",
|
|
191
191
|
providerReadbackRoot = null,
|
|
192
192
|
} = {}) {
|
|
193
|
-
const normalized =
|
|
193
|
+
const normalized = normalizeTailResealRequest(request);
|
|
194
194
|
const platform = normalized.platforms.find(({ id }) => id === platformId);
|
|
195
195
|
if (!platform)
|
|
196
196
|
throw new Error(`tail reseal request does not bind platform ${platformId}`);
|
|
@@ -243,7 +243,7 @@ export function verifyV4TailResealPlatform({
|
|
|
243
243
|
);
|
|
244
244
|
if (files.length === 0)
|
|
245
245
|
throw new Error(`${platformId} manifest has no retained files`);
|
|
246
|
-
const observedArtifactRoot =
|
|
246
|
+
const observedArtifactRoot = domainContentRoot(
|
|
247
247
|
"tail-reseal-artifact-files",
|
|
248
248
|
files,
|
|
249
249
|
);
|
|
@@ -290,21 +290,21 @@ function collectReadbacks(directory) {
|
|
|
290
290
|
throw new Error(`duplicate tail reseal readback for ${value.platformId}`);
|
|
291
291
|
byPlatform.set(value.platformId, value);
|
|
292
292
|
}
|
|
293
|
-
return
|
|
293
|
+
return TAIL_RESEAL_PLATFORMS.map((platformId) => {
|
|
294
294
|
if (!byPlatform.has(platformId))
|
|
295
295
|
throw new Error(`missing tail reseal readback for ${platformId}`);
|
|
296
296
|
return byPlatform.get(platformId);
|
|
297
297
|
});
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
export function
|
|
300
|
+
export function runTailResealCli(args = process.argv.slice(2)) {
|
|
301
301
|
const [command, ...options] = args;
|
|
302
302
|
const requestPath = flag(options, "request");
|
|
303
303
|
if (command === "plan") {
|
|
304
|
-
const request =
|
|
304
|
+
const request = normalizeTailResealRequest(
|
|
305
305
|
readJson(required(requestPath, "--request"), "tail reseal request"),
|
|
306
306
|
);
|
|
307
|
-
const plan =
|
|
307
|
+
const plan = planTailReseal(request);
|
|
308
308
|
const output = writeJson(
|
|
309
309
|
flag(options, "output", ".buildchain/tail-reseal/plan.json"),
|
|
310
310
|
plan,
|
|
@@ -331,7 +331,7 @@ export function runV4TailResealCli(args = process.argv.slice(2)) {
|
|
|
331
331
|
return plan;
|
|
332
332
|
}
|
|
333
333
|
if (command === "admit") {
|
|
334
|
-
const request =
|
|
334
|
+
const request = normalizeTailResealRequest(
|
|
335
335
|
readJson(required(requestPath, "--request"), "tail reseal request"),
|
|
336
336
|
);
|
|
337
337
|
return admitFromGitHub(request).then((admission) => {
|
|
@@ -347,7 +347,7 @@ export function runV4TailResealCli(args = process.argv.slice(2)) {
|
|
|
347
347
|
});
|
|
348
348
|
}
|
|
349
349
|
if (command === "verify-platform") {
|
|
350
|
-
const readback =
|
|
350
|
+
const readback = verifyTailResealPlatform({
|
|
351
351
|
request: readJson(required(requestPath, "--request")),
|
|
352
352
|
platformId: required(flag(options, "platform"), "--platform"),
|
|
353
353
|
artifactRoot: flag(options, "artifact-root", process.cwd()),
|
|
@@ -371,7 +371,7 @@ export function runV4TailResealCli(args = process.argv.slice(2)) {
|
|
|
371
371
|
}
|
|
372
372
|
if (command === "seal") {
|
|
373
373
|
const request = readJson(required(requestPath, "--request"));
|
|
374
|
-
const receipt =
|
|
374
|
+
const receipt = createTailResealReceipt({
|
|
375
375
|
request,
|
|
376
376
|
plan: readJson(required(flag(options, "plan"), "--plan")),
|
|
377
377
|
readbacks: collectReadbacks(
|
|
@@ -409,7 +409,7 @@ if (
|
|
|
409
409
|
process.argv[1] &&
|
|
410
410
|
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
411
411
|
) {
|
|
412
|
-
|
|
412
|
+
runTailResealCli().catch((error) => {
|
|
413
413
|
console.error(`tail-reseal: ${error.message}`);
|
|
414
414
|
process.exitCode = 1;
|
|
415
415
|
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
|
+
|
|
5
|
+
function loadUniversalFacadeMigration(root) {
|
|
6
|
+
const contract = JSON.parse(
|
|
7
|
+
fs.readFileSync(
|
|
8
|
+
path.join(root, "architecture/universal-workflow-bootstrap.json"),
|
|
9
|
+
"utf8",
|
|
10
|
+
),
|
|
11
|
+
);
|
|
12
|
+
const retired = new Set(contract.retiredWorkflowSurfaces || []);
|
|
13
|
+
const paths = (contract.bootstrapGovernedWorkflows || []).filter(
|
|
14
|
+
(entry) =>
|
|
15
|
+
entry !== contract.bootstrap?.publicWorkflow && !retired.has(entry),
|
|
16
|
+
);
|
|
17
|
+
const sourceRevision = contract.migration?.facadeSourceRevision || "";
|
|
18
|
+
if (!/^[0-9a-f]{40}$/u.test(sourceRevision)) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
"universal facade migration requires an exact facadeSourceRevision",
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
paths: new Set(paths),
|
|
25
|
+
sourceRevision,
|
|
26
|
+
postMigration: new Set(contract.migration?.postMigrationWorkflows || []),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function verifyUniversalFacadeMigration(root) {
|
|
31
|
+
execFileSync(
|
|
32
|
+
process.execPath,
|
|
33
|
+
["scripts/generate-universal-workflow-facades.mjs", "--check"],
|
|
34
|
+
{ cwd: root, stdio: "pipe" },
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function governUniversalFacadeWorkflowMetrics({
|
|
39
|
+
root,
|
|
40
|
+
current,
|
|
41
|
+
workflowMetricsAtRevision,
|
|
42
|
+
}) {
|
|
43
|
+
const migration = loadUniversalFacadeMigration(root);
|
|
44
|
+
verifyUniversalFacadeMigration(root);
|
|
45
|
+
const frozen = workflowMetricsAtRevision(root, migration.sourceRevision);
|
|
46
|
+
const governed = { ...current, workflows: { ...current.workflows } };
|
|
47
|
+
for (const file of migration.postMigration) {
|
|
48
|
+
if (frozen[file] || !migration.paths.has(file))
|
|
49
|
+
throw new Error(`invalid post-migration workflow declaration ${file}`);
|
|
50
|
+
migration.paths.delete(file);
|
|
51
|
+
}
|
|
52
|
+
for (const file of migration.paths) {
|
|
53
|
+
if (!frozen[file])
|
|
54
|
+
throw new Error(`frozen universal facade source is missing ${file}`);
|
|
55
|
+
governed.workflows[file] = frozen[file];
|
|
56
|
+
}
|
|
57
|
+
return { governed, migration };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function isGeneratedFacadePublicTransition({
|
|
61
|
+
entry,
|
|
62
|
+
kind,
|
|
63
|
+
migration,
|
|
64
|
+
baseContract,
|
|
65
|
+
currentContract,
|
|
66
|
+
}) {
|
|
67
|
+
if (kind !== "workflow" || !migration?.paths.has(entry.path) || !baseContract)
|
|
68
|
+
return false;
|
|
69
|
+
const { inputs: currentInputs, ...currentRest } = currentContract;
|
|
70
|
+
const { inputs: previousInputs, ...previousRest } = baseContract;
|
|
71
|
+
if (JSON.stringify(currentRest) !== JSON.stringify(previousRest))
|
|
72
|
+
return false;
|
|
73
|
+
const added = currentInputs.filter(
|
|
74
|
+
(input) => !previousInputs.includes(input),
|
|
75
|
+
);
|
|
76
|
+
const removed = previousInputs.filter(
|
|
77
|
+
(input) => !currentInputs.includes(input),
|
|
78
|
+
);
|
|
79
|
+
return (
|
|
80
|
+
removed.length === 0 &&
|
|
81
|
+
added.length === 1 &&
|
|
82
|
+
added[0] === "universal-request-json"
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
governUniversalFacadeWorkflowMetrics,
|
|
88
|
+
isGeneratedFacadePublicTransition,
|
|
89
|
+
loadUniversalFacadeMigration,
|
|
90
|
+
verifyUniversalFacadeMigration,
|
|
91
|
+
};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import {
|
|
6
|
+
validateUniversalWorkflowRequest,
|
|
7
|
+
universalWorkflowRequestRoot,
|
|
8
|
+
} from "../packages/core/universal-workflow-bootstrap.js";
|
|
9
|
+
const SHA = /^[0-9a-f]{40}$/u;
|
|
10
|
+
const ROOT = /^sha256:[0-9a-f]{64}$/u;
|
|
11
|
+
|
|
12
|
+
function fail(message) {
|
|
13
|
+
throw new Error(message);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function canonical(value) {
|
|
17
|
+
if (Array.isArray(value)) return value.map(canonical);
|
|
18
|
+
if (value && typeof value === "object")
|
|
19
|
+
return Object.fromEntries(
|
|
20
|
+
Object.keys(value)
|
|
21
|
+
.sort((left, right) => Buffer.from(left).compare(Buffer.from(right)))
|
|
22
|
+
.map((key) => [key, canonical(value[key])]),
|
|
23
|
+
);
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function contentRoot(domain, value) {
|
|
28
|
+
const hash = crypto.createHash("sha256");
|
|
29
|
+
hash.update(domain, "utf8");
|
|
30
|
+
hash.update(Buffer.from([0]));
|
|
31
|
+
hash.update(`${JSON.stringify(canonical(value))}\n`, "utf8");
|
|
32
|
+
return `sha256:${hash.digest("hex")}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function validateTerminalReceipt(value, request) {
|
|
36
|
+
if (
|
|
37
|
+
value?.schema !==
|
|
38
|
+
"kungfu-buildchain-v4-universal-workflow-terminal-receipt/v1" ||
|
|
39
|
+
value.status !== "succeeded" ||
|
|
40
|
+
value.runtime?.repository !== request.candidate.repository ||
|
|
41
|
+
value.runtime?.sha !== request.candidate.expectedSha ||
|
|
42
|
+
value.requestRoot !== universalWorkflowRequestRoot(request) ||
|
|
43
|
+
!SHA.test(value.runtime?.sha || "") ||
|
|
44
|
+
!ROOT.test(value.receiptRoot || "")
|
|
45
|
+
)
|
|
46
|
+
fail(
|
|
47
|
+
"successful exact-candidate terminal receipt is required for backflow",
|
|
48
|
+
);
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function createUniversalBackflowPlan({
|
|
53
|
+
request: requestValue,
|
|
54
|
+
receipt,
|
|
55
|
+
}) {
|
|
56
|
+
const request = validateUniversalWorkflowRequest(requestValue);
|
|
57
|
+
if (request.mode !== "train") fail("only Train delivery can create backflow");
|
|
58
|
+
if (request.capability.id !== "release-candidate-promote")
|
|
59
|
+
fail("only a release-candidate-promote delivery can create backflow");
|
|
60
|
+
if (request.payload?.inputs?.["dry-run"] !== false)
|
|
61
|
+
fail("only a non-dry-run release delivery can create backflow");
|
|
62
|
+
const terminal = validateTerminalReceipt(receipt, request);
|
|
63
|
+
const marker = `<!-- buildchain-universal-backflow:${request.candidate.expectedSha} -->`;
|
|
64
|
+
const binding = {
|
|
65
|
+
schema: "kungfu-buildchain-v4-universal-workflow-backflow/v1",
|
|
66
|
+
repository: request.candidate.repository,
|
|
67
|
+
pullRequest: request.candidate.reviewPullRequest,
|
|
68
|
+
baseRef: "dev/v4/v4.0",
|
|
69
|
+
trainSha: request.candidate.expectedSha,
|
|
70
|
+
consumerRepository: request.consumer.repository,
|
|
71
|
+
consumerSha: request.consumer.sourceSha,
|
|
72
|
+
requestRoot: terminal.requestRoot,
|
|
73
|
+
terminalReceiptRoot: terminal.receiptRoot,
|
|
74
|
+
};
|
|
75
|
+
const backflowRoot = contentRoot("universal-workflow-backflow", binding);
|
|
76
|
+
return {
|
|
77
|
+
...binding,
|
|
78
|
+
marker,
|
|
79
|
+
backflowRoot,
|
|
80
|
+
body: [
|
|
81
|
+
marker,
|
|
82
|
+
"## Universal Train backflow",
|
|
83
|
+
"",
|
|
84
|
+
`- Train SHA: \`${binding.trainSha}\``,
|
|
85
|
+
`- Consumer: \`${binding.consumerRepository}@${binding.consumerSha}\``,
|
|
86
|
+
`- Request root: \`${binding.requestRoot}\``,
|
|
87
|
+
`- Terminal receipt root: \`${binding.terminalReceiptRoot}\``,
|
|
88
|
+
`- Backflow root: \`${backflowRoot}\``,
|
|
89
|
+
"",
|
|
90
|
+
"This receipt binds a successful consumer delivery to the protected Train-to-dev backflow PR; it does not designate the Train candidate as a Buildchain release.",
|
|
91
|
+
].join("\n"),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function githubHeaders(token) {
|
|
96
|
+
return {
|
|
97
|
+
accept: "application/vnd.github+json",
|
|
98
|
+
authorization: `Bearer ${token}`,
|
|
99
|
+
"content-type": "application/json",
|
|
100
|
+
"user-agent": "buildchain-universal-backflow",
|
|
101
|
+
"x-github-api-version": "2022-11-28",
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function githubJson({ path, method = "GET", token, body, fetchImpl }) {
|
|
106
|
+
const api = String(
|
|
107
|
+
process.env.GITHUB_API_URL || "https://api.github.com",
|
|
108
|
+
).replace(/\/+$/u, "");
|
|
109
|
+
const response = await fetchImpl(`${api}${path}`, {
|
|
110
|
+
method,
|
|
111
|
+
headers: githubHeaders(token),
|
|
112
|
+
body: body === undefined ? undefined : JSON.stringify(body),
|
|
113
|
+
});
|
|
114
|
+
const text = await response.text();
|
|
115
|
+
const value = text ? JSON.parse(text) : {};
|
|
116
|
+
if (!response.ok)
|
|
117
|
+
fail(
|
|
118
|
+
`GitHub API ${method} ${path} failed with ${response.status}: ${value.message || text}`,
|
|
119
|
+
);
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export async function upsertUniversalBackflow({
|
|
124
|
+
request,
|
|
125
|
+
receipt,
|
|
126
|
+
token,
|
|
127
|
+
fetchImpl = globalThis.fetch,
|
|
128
|
+
}) {
|
|
129
|
+
const admitted = validateUniversalWorkflowRequest(request);
|
|
130
|
+
if (
|
|
131
|
+
admitted.mode !== "train" ||
|
|
132
|
+
admitted.capability.id !== "release-candidate-promote" ||
|
|
133
|
+
admitted.payload?.inputs?.["dry-run"] !== false
|
|
134
|
+
) {
|
|
135
|
+
return {
|
|
136
|
+
schema: "kungfu-buildchain-v4-universal-workflow-backflow-result/v1",
|
|
137
|
+
action: "skipped",
|
|
138
|
+
reason: "not-a-successful-non-dry-run-release-delivery",
|
|
139
|
+
backflowRoot: "",
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (!token) fail("GH_TOKEN is required for protected backflow");
|
|
143
|
+
if (typeof fetchImpl !== "function") fail("fetch is required for backflow");
|
|
144
|
+
const plan = createUniversalBackflowPlan({ request: admitted, receipt });
|
|
145
|
+
const encodedRepository = plan.repository;
|
|
146
|
+
const pull = await githubJson({
|
|
147
|
+
path: `/repos/${encodedRepository}/pulls/${plan.pullRequest}`,
|
|
148
|
+
token,
|
|
149
|
+
fetchImpl,
|
|
150
|
+
});
|
|
151
|
+
if (
|
|
152
|
+
pull.state !== "open" ||
|
|
153
|
+
pull.base?.ref !== plan.baseRef ||
|
|
154
|
+
pull.head?.repo?.full_name !== plan.repository ||
|
|
155
|
+
pull.head?.sha !== plan.trainSha
|
|
156
|
+
)
|
|
157
|
+
fail("backflow PR no longer binds the exact admitted Train candidate");
|
|
158
|
+
const comments = await githubJson({
|
|
159
|
+
path: `/repos/${encodedRepository}/issues/${plan.pullRequest}/comments?per_page=100`,
|
|
160
|
+
token,
|
|
161
|
+
fetchImpl,
|
|
162
|
+
});
|
|
163
|
+
const existing = comments.find((comment) =>
|
|
164
|
+
String(comment.body || "").includes(plan.marker),
|
|
165
|
+
);
|
|
166
|
+
const comment = existing
|
|
167
|
+
? await githubJson({
|
|
168
|
+
path: `/repos/${encodedRepository}/issues/comments/${existing.id}`,
|
|
169
|
+
method: "PATCH",
|
|
170
|
+
token,
|
|
171
|
+
body: { body: plan.body },
|
|
172
|
+
fetchImpl,
|
|
173
|
+
})
|
|
174
|
+
: await githubJson({
|
|
175
|
+
path: `/repos/${encodedRepository}/issues/${plan.pullRequest}/comments`,
|
|
176
|
+
method: "POST",
|
|
177
|
+
token,
|
|
178
|
+
body: { body: plan.body },
|
|
179
|
+
fetchImpl,
|
|
180
|
+
});
|
|
181
|
+
return {
|
|
182
|
+
schema: "kungfu-buildchain-v4-universal-workflow-backflow-result/v1",
|
|
183
|
+
action: existing ? "updated" : "created",
|
|
184
|
+
pullRequest: plan.pullRequest,
|
|
185
|
+
trainSha: plan.trainSha,
|
|
186
|
+
terminalReceiptRoot: plan.terminalReceiptRoot,
|
|
187
|
+
backflowRoot: plan.backflowRoot,
|
|
188
|
+
commentUrl: comment.html_url,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function main() {
|
|
193
|
+
const request = JSON.parse(
|
|
194
|
+
process.env.BUILDCHAIN_UNIVERSAL_REQUEST_JSON ||
|
|
195
|
+
fail("request is required"),
|
|
196
|
+
);
|
|
197
|
+
const receipt = JSON.parse(
|
|
198
|
+
process.env.BUILDCHAIN_UNIVERSAL_TERMINAL_RECEIPT_JSON ||
|
|
199
|
+
fail("terminal receipt is required"),
|
|
200
|
+
);
|
|
201
|
+
const result = await upsertUniversalBackflow({
|
|
202
|
+
request,
|
|
203
|
+
receipt,
|
|
204
|
+
token: process.env.GH_TOKEN || process.env.GITHUB_TOKEN,
|
|
205
|
+
});
|
|
206
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const isMain =
|
|
210
|
+
process.argv[1] &&
|
|
211
|
+
fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
212
|
+
if (isMain) await main();
|