@kungfu-tech/buildchain 4.1.0-alpha.0 → 4.1.0-alpha.2
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 +30 -41
- package/CONTRIBUTING.md +6 -7
- package/architecture/action-taxonomy.json +5 -21
- package/architecture/agent-change-map.md +74 -56
- package/architecture/build-orchestration.json +8 -1
- package/architecture/ci-lane-change-budget.json +179 -69
- package/architecture/floating-consumer-policy.json +7 -17
- package/architecture/internal-capabilities.json +58 -72
- package/architecture/maintainability-debt.json +138 -52
- package/architecture/maintainability-policy.json +6 -15
- package/architecture/promotion-job-topology.json +39 -20
- package/architecture/release-topology.json +26 -37
- package/architecture/runtime-entry.json +26 -0
- package/architecture/runtime-resume-lineage.json +23 -0
- package/architecture/stage-capsule-qualification.json +2 -2
- package/architecture/universal-workflow-bootstrap.json +10 -25
- package/architecture/universal-workflow-capability-policy.json +61 -0
- package/architecture/universal-workflow-fault-campaign.json +18 -24
- package/architecture/workflow-taxonomy.json +0 -11
- package/contracts/fixtures/{v4-runtime-ref-resume-authority-v1 → runtime-resume-lineage-v2}/scenario.json +2 -3
- package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +2 -2
- package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
- package/contracts/promotion-invocation-v1.schema.json +0 -44
- package/contracts/promotion-request-v1.schema.json +0 -39
- package/contracts/runtime-resume-lineage-v2.schema.json +182 -0
- package/dist/site/buildchain-contract.json +472 -361
- package/dist/site/buildchain-site.json +99 -99
- package/dist/site/capability-registry.json +3 -3
- package/dist/site/cli-registry.json +4 -4
- package/dist/site/controller-registry.json +94 -78
- package/dist/site/kfd-claims.json +224 -343
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +15 -15
- package/dist/site/node-api-registry.json +239 -354
- package/dist/site/page-registry.json +80 -80
- package/dist/site/public-surface-audit.json +203 -254
- package/dist/site/publication-authority-registry.json +1 -24
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +1 -1
- package/dist/site/site-manifest.json +19 -19
- package/dist/site/workflow-registry.json +197 -357
- package/docs/MAP.md +3 -3
- package/docs/auditable-demo.md +4 -4
- package/docs/cli-reference.md +2 -2
- package/docs/code-organization.md +5 -4
- package/docs/controller-evidence.md +2 -2
- package/docs/dev-alpha-candidate-patrol.md +5 -5
- package/docs/dev-delivery-warrant.md +14 -24
- package/docs/engineering-housekeeper.md +3 -3
- package/docs/github-artifact-attestation.md +9 -12
- package/docs/github-governance-authority.md +4 -4
- package/docs/node-api-reference.md +153 -167
- package/docs/publication-artifacts.md +3 -4
- package/docs/publication-authority.md +2 -2
- package/docs/release-candidate.md +21 -27
- package/docs/release-governance.md +10 -10
- package/docs/release-promotion-request.md +11 -18
- package/docs/release-propagation.md +5 -6
- package/docs/release-tail-provider-plane.md +2 -3
- package/docs/reusable-build-surface.md +13 -7
- package/docs/runtime-entry.md +122 -0
- package/docs/runtime-train-validation.md +30 -41
- package/docs/v4-publication-rehearsal.md +5 -5
- package/docs/v4-stage-capsule.md +9 -10
- package/docs/web-surface-deployments.md +16 -20
- package/docs/workflow-catalog.md +0 -1
- package/package.json +6 -6
- package/packages/core/adoption/commands/init-repo.mjs +2 -2
- package/packages/core/adoption/cross-platform-adopter-qualification.js +2 -13
- package/packages/core/adoption/qualification/actions.js +3 -5
- package/packages/core/adoption/qualification/admission.js +2 -3
- package/packages/core/build/artifact/attestation.js +0 -1
- package/packages/core/build/artifact/contracts.js +1 -4
- package/packages/core/build/artifact/store.js +6 -5
- package/packages/core/build/artifact-signing.js +4 -10
- package/packages/core/build/binary/actions.js +15 -9
- package/packages/core/build/binary-publication-dispatch.js +2 -6
- package/packages/core/build/demo/action-context.js +2 -11
- package/packages/core/build/demo/binary-action.js +8 -10
- package/packages/core/build/gate/controller.js +0 -2
- package/packages/core/build/github-attestation/action.js +2 -7
- package/packages/core/build/github-attestation/admission.js +0 -8
- package/packages/core/build/github-attestation/transaction.js +1 -2
- package/packages/core/build/lifecycle/stage-action.js +2 -0
- package/packages/core/build/lifecycle/stage.js +6 -3
- package/packages/core/build/macos-credential-island/dmg-assembly.js +0 -2
- package/packages/core/build/macos-credential-island/lib.js +2 -6
- package/packages/core/build/plan/action-context.js +0 -7
- package/packages/core/build/plan/action.js +7 -11
- package/packages/core/build/plan/admission.js +6 -73
- package/packages/core/build/plan/configuration.js +1 -1
- package/packages/core/build/plan/environment.js +1 -1
- package/packages/core/build/plan/identity.js +1 -5
- package/packages/core/build/plan/resolve.js +7 -1
- package/packages/core/build/recovery/checkpoint.js +158 -0
- package/packages/core/build/recovery/transaction.js +51 -0
- package/packages/core/build/signing/authority-actions.js +2 -11
- package/packages/core/build/signing/control.js +0 -5
- package/packages/core/build/signing/controller-transaction.js +0 -1
- package/packages/core/build/signing/delegation.js +2 -4
- package/packages/core/build/signing/dispatch.js +10 -56
- package/packages/core/build/signing/intake.js +0 -4
- package/packages/core/build/signing/prepare.js +1 -1
- package/packages/core/build/signing/request.js +3 -8
- package/packages/core/build/source/checkout-action.js +6 -10
- package/packages/core/build/source/controller.js +1 -4
- package/packages/core/build/source/lifecycle.js +3 -13
- package/packages/core/build/stage-capsule/actions.js +3 -13
- package/packages/core/build/stage-capsule/campaign/resume.js +10 -5
- package/packages/core/build/stage-capsule/rehearsal/verify.js +3 -4
- package/packages/core/build/stage-capsule-resume-planner.js +0 -1
- package/packages/core/build/summary/aggregation.js +5 -5
- package/packages/core/build/summary/finalization.js +1 -1
- package/packages/core/build/verification/actions.js +3 -12
- package/packages/core/build/verification/runner.js +22 -20
- package/packages/core/consumer/floating-consumer-evidence.js +3 -21
- package/packages/core/consumer/floating-consumer-policy.js +2 -93
- package/packages/core/consumer/floating-consumer-release-passport.js +1 -34
- package/packages/core/consumer/policy-admission.js +1 -3
- package/packages/core/contracts/buildchain-contract.js +12 -146
- package/packages/core/contracts/workflow-yaml-contract.js +11 -1
- package/packages/core/dev-delivery/candidate/admission.js +3 -4
- package/packages/core/dev-delivery/candidate/coordinates.js +0 -8
- package/packages/core/dev-delivery/commands/dev-delivery-request.sh +5 -13
- package/packages/core/dev-delivery/commands/dev-delivery-source-proof-reuse.mjs +0 -3
- package/packages/core/dev-delivery/dev-delivery-contract-surface.js +4 -52
- package/packages/core/dev-delivery/dev-delivery-execution-transfer.js +2 -15
- package/packages/core/dev-delivery/native/action-context.js +4 -32
- package/packages/core/dev-delivery/native/provider-boundary.js +0 -2
- package/packages/core/dev-delivery/native/transactions.js +1 -2
- package/packages/core/dev-delivery/queue/reconciliation-action.js +6 -10
- package/packages/core/dev-delivery/source-proof/predicates.js +0 -6
- package/packages/core/dev-delivery/source-proof/reuse.js +0 -2
- package/packages/core/dev-delivery/source-proof/seal.js +0 -2
- package/packages/core/governance/alpha-candidate/action.js +1 -10
- package/packages/core/governance/audit/actions.js +1 -3
- package/packages/core/governance/audit/collection.js +1 -3
- package/packages/core/governance/audit/identity.js +3 -31
- package/packages/core/governance/audit/transactions.js +2 -4
- package/packages/core/governance/buildchain-publication-authority.js +0 -1
- package/packages/core/governance/commands/audit-github-governance.mjs +3 -2
- package/packages/core/governance/github-governance-authority.js +0 -5
- package/packages/core/governance/receipt-admission.js +0 -15
- package/packages/core/index.js +1 -1
- package/packages/core/observability/controller/identity.js +4 -5
- package/packages/core/observability/controller-evidence.js +5 -10
- package/packages/core/paper/commands/paper.mjs +6 -6
- package/packages/core/paper/operations/plans.js +2 -2
- package/packages/core/paper/operations/provisioning-validation.js +1 -1
- package/packages/core/paper/operations/scaffold-workflows.js +29 -12
- package/packages/core/paper/operations/scaffold.js +97 -69
- package/packages/core/paper/paper-agent-entry.js +0 -11
- package/packages/core/paper/paper-runtime-channels.js +21 -66
- package/packages/core/paper/paper-scaffold-content.js +1 -1
- package/packages/core/paper/paper.js +9 -5
- package/packages/core/paper/publication/candidate.js +0 -9
- package/packages/core/paper/publication-controller.js +2 -4
- package/packages/core/providers/github/artifact-attestation.js +1 -1
- package/packages/core/publication/authority/actions.js +9 -8
- package/packages/core/publication/authority/admission.js +0 -11
- package/packages/core/publication/authority/assembly.js +2 -7
- package/packages/core/publication/authority/control-plane.js +2 -2
- package/packages/core/publication/authority/governance.js +2 -9
- package/packages/core/publication/authority/request.js +7 -2
- package/packages/core/publication/authority/verification.js +3 -18
- package/packages/core/publication/binary/action.js +5 -7
- package/packages/core/publication/candidate/qualification-action.js +1 -6
- package/packages/core/publication/candidate/stage-capsules.js +1 -1
- package/packages/core/publication/npm/preview-action.js +9 -15
- package/packages/core/publication/oci/preview-actions.js +1 -10
- package/packages/core/publication/publication-artifact-candidate.js +2 -2
- package/packages/core/publication/publication-authority.js +2 -2
- package/packages/core/publication/publication-rehearsal-projection.js +3 -3
- package/packages/core/publication/settlement/actions.js +2 -11
- package/packages/core/release/binary/coordinates-action.js +0 -13
- package/packages/core/release/binary/coordinates.js +2 -19
- package/packages/core/release/commands/promotion-channel-router.mjs +12 -56
- package/packages/core/release/commands/resume-from-candidate-run.mjs +2 -3
- package/packages/core/release/dev-alpha-active-release-train.js +0 -5
- package/packages/core/release/line/action.js +2 -13
- package/packages/core/release/next-development/actions.js +2 -5
- package/packages/core/release/passport/consumer-validation.js +1 -28
- package/packages/core/release/promote-candidate/development-source.js +7 -8
- package/packages/core/release/promotion/actions.js +7 -38
- package/packages/core/release/promotion/admission.js +3 -50
- package/packages/core/release/promotion/candidate.js +2 -4
- package/packages/core/release/promotion/channel.js +13 -101
- package/packages/core/release/promotion/qualification-action.js +2 -13
- package/packages/core/release/promotion/routing.js +16 -81
- package/packages/core/release/promotion/selection.js +1 -9
- package/packages/core/release/promotion-request.js +1 -40
- package/packages/core/release/qualification/actions.js +0 -8
- package/packages/core/release/qualification/public-build.js +1 -1
- package/packages/core/release/recovery/candidate.js +15 -21
- package/packages/core/release/recovery/capsules.js +2 -10
- package/packages/core/release/recovery/lineage.js +305 -0
- package/packages/core/release/recovery/provenance.js +1 -2
- package/packages/core/release/recovery/publication.js +4 -14
- package/packages/core/release/recovery/readback.js +19 -32
- package/packages/core/release/recovery/runtime.js +4 -95
- package/packages/core/release/release-candidate-recovery.js +4 -9
- package/packages/core/release/release-candidate.js +2 -5
- package/packages/core/release/reseal/actions.js +3 -22
- package/packages/core/release/reseal/admission.js +0 -2
- package/packages/core/release/reseal/finalize-platform.js +0 -2
- package/packages/core/release/tail-reseal-github.js +1 -2
- package/packages/core/release/tail-reseal-receipt.js +0 -1
- package/packages/core/release/tail-reseal.js +2 -20
- package/packages/core/release/version-state.js +16 -13
- package/packages/core/runtime/buildchain-domain.wasm +0 -0
- package/packages/core/runtime/checkout-identity.js +0 -13
- package/packages/core/runtime/domain-wasm-artifact.js +2 -2
- package/packages/core/runtime/entry/actions.js +121 -0
- package/packages/core/runtime/entry/activation.js +86 -0
- package/packages/core/runtime/entry/github.js +55 -0
- package/packages/core/runtime/entry/recovery.js +37 -0
- package/packages/core/runtime/entry/selection.js +110 -0
- package/packages/core/web/controller.js +1 -1
- package/packages/core/web/publication-admission-action.js +1 -8
- package/packages/core/web/web-surface-publication-candidate.js +2 -5
- package/packages/core/workflow/admission/actions.js +6 -26
- package/packages/core/workflow/admission/recovery.js +3 -43
- package/packages/core/workflow/admission/transactions.js +8 -24
- package/packages/core/workflow/commands/buildchain-cli-help.mjs +1 -1
- package/packages/core/workflow/commands/universal-workflow-engine.mjs +2 -7
- package/packages/core/workflow/dogfood/actions.js +0 -17
- package/packages/core/workflow/engine/action.js +0 -5
- package/packages/core/workflow/engine/conformance.js +1 -1
- package/packages/core/workflow/engine/execution.js +2 -6
- package/packages/core/workflow/engine/identity.js +1 -6
- package/packages/core/workflow/engine/release-environment.js +11 -35
- package/packages/core/workflow/engine/release-promotion.js +2 -2
- package/packages/core/workflow/settlement/actions.js +0 -12
- package/packages/core/workflow/universal-self-dogfood.js +2 -16
- package/packages/core/workflow/universal-workflow-bootstrap.js +16 -241
- package/packages/core/workflow/workflow-taxonomy.mjs +2 -2
- package/scripts/check-dev-delivery-actions.mjs +17 -8
- package/scripts/check-floating-consumer-policy-contract.mjs +6 -6
- package/scripts/check-inventory.mjs +1 -10
- package/scripts/check-public-dogfood-contract.mjs +34 -21
- package/scripts/check-release-topology.mjs +2 -6
- package/scripts/check-runtime-entry.mjs +133 -0
- package/scripts/check-universal-workflow-bootstrap.mjs +45 -281
- package/scripts/check-workflows.sh +0 -7
- package/scripts/generate-bootstrap-admission.mjs +1 -1
- package/scripts/generate-channel-promotion-workflow.mjs +4 -4
- package/scripts/inventory/binary.mjs +4 -4
- package/scripts/inventory/promotion.mjs +5 -3
- package/scripts/runtime-source-boundaries.mjs +70 -0
- package/scripts/site-capability-metadata.mjs +2 -2
- package/scripts/workflow-action-graph.mjs +5 -18
- package/scripts/workflow-self-reference.mjs +20 -0
- package/templates/native-dev-delivery.yml +4 -4
- package/templates/universal-buildchain-bootstrap.yml +12 -2
- package/architecture/runtime-ref-resume-authority.json +0 -64
- package/architecture/universal-workflow-train-admission.json +0 -76
- package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +0 -235
- package/docs/v4-runtime-ref-resume-authority.md +0 -69
- package/packages/core/consumer/channel-selection.js +0 -211
- package/packages/core/consumer/commands/buildchain-channel-router.mjs +0 -81
- package/packages/core/consumer/invocation-selector.js +0 -4
- package/packages/core/consumer/runtime-ref-resume-authority.js +0 -621
- package/packages/core/consumer/workflow-definition-authority.js +0 -64
- package/packages/core/contracts/runtime-contract-action.js +0 -48
- package/packages/core/release/commands/promotion-identity-resolver.mjs +0 -77
- package/packages/core/release/commands/verify-promotion-router-binding.sh +0 -36
- package/packages/core/release/promotion/identities.js +0 -56
- package/packages/core/release/runtime-override-authorization.js +0 -242
- package/packages/core/runtime/commands/runtime-ref-core.mjs +0 -171
- package/packages/core/runtime/provider-closure.js +0 -60
- package/packages/core/runtime/runtime-selection-action.js +0 -34
- package/packages/core/runtime/runtime-selection.js +0 -136
- package/packages/core/runtime/workflow-runtime.js +0 -11
- package/packages/core/workflow/admission/review.js +0 -188
- package/packages/core/workflow/commands/universal-workflow-backflow.mjs +0 -26
- package/packages/core/workflow/installation.js +0 -33
- package/packages/core/workflow/settlement/backflow.js +0 -187
- package/scripts/generate-bootstrap-recovery.mjs +0 -94
- package/templates/bootstrap-recovery/actions/build/source/admit/action.yml +0 -17
- package/templates/bootstrap-recovery/actions/build/source/admit/dist/index.js +0 -63
- package/templates/bootstrap-recovery/actions/runtime/dependencies/install/action.yml +0 -18
- package/templates/bootstrap-recovery/actions/runtime/dependencies/install/dist/index.js +0 -63
- package/templates/bootstrap-recovery/actions/runtime/environment/prepare/action.yml +0 -21
- package/templates/bootstrap-recovery/actions/workflow/admission/inspect/action.yml +0 -27
- package/templates/bootstrap-recovery/actions/workflow/admission/inspect/dist/index.js +0 -64
- package/templates/bootstrap-recovery/actions/workflow/admission/review/action.yml +0 -15
- package/templates/bootstrap-recovery/actions/workflow/admission/review/dist/index.js +0 -65
- package/templates/bootstrap-recovery/actions/workflow/recovery/admit/action.yml +0 -47
- package/templates/bootstrap-recovery/actions/workflow/recovery/execute/action.yml +0 -48
- package/templates/bootstrap-recovery/actions/workflow/recovery/settle/action.yml +0 -54
- package/templates/bootstrap-recovery/actions/workflow/settlement/seal/action.yml +0 -17
- package/templates/bootstrap-recovery/actions/workflow/settlement/seal/dist/index.js +0 -65
- package/templates/bootstrap-recovery/manifest.json +0 -68
- package/templates/bootstrap-recovery/package.json +0 -9
- package/templates/universal-buildchain-bootstrap-recovery.yml +0 -115
|
@@ -17,10 +17,7 @@ function coordinates(env) {
|
|
|
17
17
|
)
|
|
18
18
|
throw new Error("exact repository and verification run required");
|
|
19
19
|
const workspace = path.resolve(env.GITHUB_WORKSPACE);
|
|
20
|
-
|
|
21
|
-
throw new Error(
|
|
22
|
-
"Next-development review must execute the protected source checkout",
|
|
23
|
-
);
|
|
20
|
+
|
|
24
21
|
return {
|
|
25
22
|
repository: env.GITHUB_REPOSITORY,
|
|
26
23
|
runId: env.VERIFY_RUN_ID,
|
|
@@ -47,7 +44,7 @@ export async function qualifyNextDevelopmentAction(core, env) {
|
|
|
47
44
|
}).trim();
|
|
48
45
|
if (git("rev-parse", "HEAD") !== env.GITHUB_SHA)
|
|
49
46
|
throw new Error(
|
|
50
|
-
"Review
|
|
47
|
+
"Review source differs from the protected verification source",
|
|
51
48
|
);
|
|
52
49
|
const plan = await verifyNextDevelopmentReview({
|
|
53
50
|
client,
|
|
@@ -5,9 +5,8 @@ import {
|
|
|
5
5
|
import { verifyFloatingConsumerPolicyCertification } from "../../consumer/floating-consumer-evidence.js";
|
|
6
6
|
import { issue } from "./issues.js";
|
|
7
7
|
import {
|
|
8
|
-
verifyRuntimeAuthorizationReceipt,
|
|
9
8
|
verifyRuntimeResumeLineage,
|
|
10
|
-
} from "
|
|
9
|
+
} from "../recovery/lineage.js";
|
|
11
10
|
import { runtimeResumeSourceSha } from "./consumer-input.js";
|
|
12
11
|
export function validateConsumerPolicyPassportSection({ passport, issues }) {
|
|
13
12
|
const routing = passport?.promotionRouting;
|
|
@@ -41,22 +40,6 @@ export function validateRuntimeResumePassportSection({ passport, issues }) {
|
|
|
41
40
|
if (!evidence) return;
|
|
42
41
|
const consumerPolicyReceiptRoot =
|
|
43
42
|
passport?.v4ConsumerPolicy?.certification?.receiptRoot || "";
|
|
44
|
-
const authorization = verifyRuntimeAuthorizationReceipt({
|
|
45
|
-
receipt: evidence.authorization,
|
|
46
|
-
receiptRoot: evidence.authorizationRoot,
|
|
47
|
-
repository: passport?.product?.repository || "",
|
|
48
|
-
sourceSha: runtimeResumeSourceSha(
|
|
49
|
-
passport?.release,
|
|
50
|
-
passport?.release?.sourceSha || "",
|
|
51
|
-
),
|
|
52
|
-
runtimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
|
|
53
|
-
consumerPolicyReceiptRoot,
|
|
54
|
-
});
|
|
55
|
-
for (const failure of authorization.failures) {
|
|
56
|
-
issues.push(
|
|
57
|
-
issue("error", `v4RuntimeResume.authorization.${failure}`, failure),
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
43
|
const lineage = verifyRuntimeResumeLineage({
|
|
61
44
|
lineage: evidence.lineage,
|
|
62
45
|
lineageRoot: evidence.lineageRoot,
|
|
@@ -65,19 +48,9 @@ export function validateRuntimeResumePassportSection({ passport, issues }) {
|
|
|
65
48
|
passport?.release,
|
|
66
49
|
passport?.release?.sourceSha || "",
|
|
67
50
|
),
|
|
68
|
-
resumeRuntimeSha: passport?.promotionRouting?.runtime?.resolvedSha || "",
|
|
69
51
|
consumerPolicyReceiptRoot,
|
|
70
52
|
});
|
|
71
53
|
for (const failure of lineage.failures) {
|
|
72
54
|
issues.push(issue("error", `v4RuntimeResume.lineage.${failure}`, failure));
|
|
73
55
|
}
|
|
74
|
-
if (evidence.lineage?.authorizationRoot !== evidence.authorizationRoot) {
|
|
75
|
-
issues.push(
|
|
76
|
-
issue(
|
|
77
|
-
"error",
|
|
78
|
-
"v4RuntimeResume.authorization-root-mismatch",
|
|
79
|
-
"runtime resume lineage must bind the embedded authorization receipt root",
|
|
80
|
-
),
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
56
|
}
|
|
@@ -23,14 +23,13 @@ export function prepareDevelopmentSource({ cwd, sourceSha }) {
|
|
|
23
23
|
// Shallow local clones omit commits reachable only through FETCH_HEAD.
|
|
24
24
|
execFileSync("git", ["fetch", "--no-tags", path.resolve(cwd), sourceSha], { cwd: source, stdio: "pipe" });
|
|
25
25
|
execFileSync("git", ["-c", "core.autocrlf=false", "-c", "core.eol=lf", "checkout", "--detach", sourceSha], { cwd: source, stdio: "pipe" });
|
|
26
|
-
const
|
|
27
|
-
fs.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
fs.symlinkSync(path.join(runtime, "node_modules"), path.join(source, "node_modules"), "junction");
|
|
26
|
+
const dependencies = path.resolve(cwd, "node_modules");
|
|
27
|
+
if (fs.existsSync(dependencies)) {
|
|
28
|
+
fs.cpSync(dependencies, path.join(source, "node_modules"), {
|
|
29
|
+
recursive: true,
|
|
30
|
+
verbatimSymlinks: true,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
34
33
|
return { cwd: source, dispose };
|
|
35
34
|
} catch (error) {
|
|
36
35
|
dispose();
|
|
@@ -2,7 +2,6 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { getOctokit } from "@actions/github";
|
|
4
4
|
import { installationRoot } from "../../runtime/installation-root.js";
|
|
5
|
-
import { verifyCheckoutIdentity } from "../../runtime/checkout-identity.js";
|
|
6
5
|
import { routePromotion } from "./routing.js";
|
|
7
6
|
import { bindPromotionSelection } from "./selection.js";
|
|
8
7
|
import { admitPromotionInvocation } from "./admission.js";
|
|
@@ -24,34 +23,16 @@ function context(env) {
|
|
|
24
23
|
payload: JSON.parse(fs.readFileSync(env.GITHUB_EVENT_PATH, "utf8")),
|
|
25
24
|
};
|
|
26
25
|
}
|
|
27
|
-
|
|
28
|
-
const runtimeRoot = installationRoot(import.meta.url);
|
|
29
|
-
if (
|
|
30
|
-
fs.realpathSync(runtimeRoot) !==
|
|
31
|
-
fs.realpathSync(path.join(workspace, relative))
|
|
32
|
-
)
|
|
33
|
-
throw new Error(
|
|
34
|
-
"Promotion action is outside its admitted runtime checkout",
|
|
35
|
-
);
|
|
36
|
-
verifyCheckoutIdentity({
|
|
37
|
-
directory: runtimeRoot,
|
|
38
|
-
sha,
|
|
39
|
-
label: "Promotion action runtime",
|
|
40
|
-
});
|
|
41
|
-
return runtimeRoot;
|
|
42
|
-
}
|
|
26
|
+
|
|
43
27
|
export async function routePromotionAction(core, env) {
|
|
44
28
|
const workflowSha = get(core, "workflow-sha"),
|
|
45
29
|
workspace = path.resolve(env.GITHUB_WORKSPACE);
|
|
46
|
-
const runtimeRoot =
|
|
47
|
-
workspace,
|
|
48
|
-
".buildchain/workflow-shell",
|
|
49
|
-
workflowSha,
|
|
50
|
-
);
|
|
30
|
+
const runtimeRoot = installationRoot(import.meta.url);
|
|
51
31
|
emit(
|
|
52
32
|
core,
|
|
53
33
|
await routePromotion({
|
|
54
34
|
request: get(core, "request-json"),
|
|
35
|
+
runtime: JSON.parse(env.BUILDCHAIN_RUNTIME_SELECTION),
|
|
55
36
|
workflowRepository: get(core, "workflow-repository"),
|
|
56
37
|
workflowSha,
|
|
57
38
|
workflowRef: get(core, "workflow-ref"),
|
|
@@ -67,11 +48,7 @@ export function bindPromotionSelectionAction(core, env) {
|
|
|
67
48
|
const selection = JSON.parse(get(core, "selection-json")),
|
|
68
49
|
request = JSON.parse(get(core, "request-json")),
|
|
69
50
|
workspace = path.resolve(env.GITHUB_WORKSPACE);
|
|
70
|
-
|
|
71
|
-
workspace,
|
|
72
|
-
".buildchain/workflow-shell",
|
|
73
|
-
selection["shell-sha"],
|
|
74
|
-
);
|
|
51
|
+
|
|
75
52
|
emit(
|
|
76
53
|
core,
|
|
77
54
|
bindPromotionSelection({
|
|
@@ -85,11 +62,7 @@ export function bindPromotionSelectionAction(core, env) {
|
|
|
85
62
|
export async function admitPromotionInvocationAction(core, env) {
|
|
86
63
|
const selection = JSON.parse(get(core, "selection-json")),
|
|
87
64
|
workspace = path.resolve(env.GITHUB_WORKSPACE);
|
|
88
|
-
|
|
89
|
-
workspace,
|
|
90
|
-
".buildchain/policy-runtime",
|
|
91
|
-
selection["router-sha"],
|
|
92
|
-
);
|
|
65
|
+
|
|
93
66
|
emit(
|
|
94
67
|
core,
|
|
95
68
|
await admitPromotionInvocation({
|
|
@@ -104,11 +77,7 @@ export async function admitPromotionInvocationAction(core, env) {
|
|
|
104
77
|
}
|
|
105
78
|
export function inspectPromotionInvocationAction(core, env) {
|
|
106
79
|
const workflowSha = get(core, "workflow-sha");
|
|
107
|
-
|
|
108
|
-
path.resolve(env.GITHUB_WORKSPACE),
|
|
109
|
-
".buildchain/workflow-shell",
|
|
110
|
-
workflowSha,
|
|
111
|
-
);
|
|
80
|
+
|
|
112
81
|
verifyPromotionInvocation(get(core, "request-json"), workflowSha);
|
|
113
82
|
}
|
|
114
83
|
export async function classifyPublicationHeadAction(core, env) {
|
|
@@ -117,7 +86,7 @@ export async function classifyPublicationHeadAction(core, env) {
|
|
|
117
86
|
throw new Error(
|
|
118
87
|
"Publication classification requires a workflow run with an exact source SHA",
|
|
119
88
|
);
|
|
120
|
-
|
|
89
|
+
|
|
121
90
|
const result = await classifyProductPublication(
|
|
122
91
|
{ requestedSha: event.head_sha, targetRef: event.head_branch },
|
|
123
92
|
productPublicationReader(
|
|
@@ -1,52 +1,5 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { authorizePromotionRuntimeOverride } from "../runtime-override-authorization.js";
|
|
3
1
|
import { bindPromotionInvocation } from "../promotion-request.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
selection
|
|
7
|
-
workspace,
|
|
8
|
-
consumerPolicyRoot,
|
|
9
|
-
github,
|
|
10
|
-
context,
|
|
11
|
-
}) {
|
|
12
|
-
let authorization = {};
|
|
13
|
-
if (selection["override-used"] === "true") {
|
|
14
|
-
const root = path.join(workspace, ".buildchain/consumer"),
|
|
15
|
-
mode = request["resume-candidate-run-id"] ? "resume" : "dispatch";
|
|
16
|
-
const result = await authorizePromotionRuntimeOverride({
|
|
17
|
-
github,
|
|
18
|
-
context,
|
|
19
|
-
request: {
|
|
20
|
-
consumerRoot: root,
|
|
21
|
-
runtimeRepository: request["buildchain-repository"],
|
|
22
|
-
consumerPolicyReceiptPath: path.join(
|
|
23
|
-
root,
|
|
24
|
-
".buildchain/evidence/consumer-policy-receipt.json",
|
|
25
|
-
),
|
|
26
|
-
consumerPolicyReceiptRoot: consumerPolicyRoot,
|
|
27
|
-
sourceSha: request["target-sha"] || context.sha,
|
|
28
|
-
requestedRef: selection["runtime-ref"],
|
|
29
|
-
resolvedRuntimeSha: selection["runtime-sha"],
|
|
30
|
-
reason: `trusted ${mode} runtime override ${selection["runtime-ref"]} for source ${request["target-sha"] || context.sha}`,
|
|
31
|
-
mode,
|
|
32
|
-
outputPath: path.join(
|
|
33
|
-
root,
|
|
34
|
-
".buildchain/evidence/runtime-authorization.json",
|
|
35
|
-
),
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
authorization = {
|
|
39
|
-
"runtime-authorization-json": JSON.stringify({
|
|
40
|
-
receipt: result.receipt,
|
|
41
|
-
receiptRoot: result.receiptRoot,
|
|
42
|
-
}),
|
|
43
|
-
"runtime-authorization-root": result.receiptRoot,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
...authorization,
|
|
48
|
-
"invocation-json": JSON.stringify(
|
|
49
|
-
bindPromotionInvocation(request, selection, authorization),
|
|
50
|
-
),
|
|
51
|
-
};
|
|
2
|
+
|
|
3
|
+
export async function admitPromotionInvocation({ request, selection }) {
|
|
4
|
+
return { "invocation-json": JSON.stringify(bindPromotionInvocation(request, selection)) };
|
|
52
5
|
}
|
|
@@ -46,16 +46,14 @@ export async function qualifyPromotionCandidate(
|
|
|
46
46
|
targetSha: intent["requested-sha"],
|
|
47
47
|
expectedSourceTree: request["resume-expected-source-tree"],
|
|
48
48
|
expectedCandidateRoot: request["resume-expected-candidate-root"],
|
|
49
|
-
candidateRuntimeSha: request["resume-expected-candidate-runtime-sha"],
|
|
50
|
-
runtimeSha: request["resume-buildchain-runtime-sha"],
|
|
51
49
|
transactionId: request["resume-transaction-id"],
|
|
52
50
|
rematerializeOnResume: request["publish-rematerialize-on-resume"],
|
|
53
51
|
releasePatterns: request["github-release-payload-patterns"],
|
|
54
52
|
runtimeRoot,
|
|
55
53
|
recoveryRunId,
|
|
56
54
|
recoveryRunAttempt,
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
|
|
56
|
+
|
|
59
57
|
});
|
|
60
58
|
return fresh({
|
|
61
59
|
...shared,
|
|
@@ -1,104 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
{
|
|
5
|
-
pattern: /^alpha\/v(\d+)\/v\d+\.\d+$/,
|
|
6
|
-
publicationChannel: "alpha",
|
|
7
|
-
shellChannel: "alpha",
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
pattern: /^release\/v(\d+)\/v\d+\.\d+$/,
|
|
11
|
-
publicationChannel: "release",
|
|
12
|
-
shellChannel: "stable",
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
pattern: /^publish-gate\/major$/,
|
|
16
|
-
publicationChannel: "major",
|
|
17
|
-
shellChannel: "stable",
|
|
18
|
-
},
|
|
1
|
+
const targets = [
|
|
2
|
+
{ pattern: /^alpha\/v\d+\/v\d+\.\d+$/, publicationChannel: "alpha", channel: "alpha" },
|
|
3
|
+
{ pattern: /^release\/v\d+\/v\d+\.\d+$/, publicationChannel: "release", channel: "stable" },
|
|
4
|
+
{ pattern: /^publish-gate\/major$/, publicationChannel: "major", channel: "stable" },
|
|
19
5
|
];
|
|
20
6
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function targetIntent(targetRef, requestedPublicationChannel = "") {
|
|
32
|
-
const ref = normalized(targetRef).replace(/^refs\/heads\//, "");
|
|
33
|
-
const target = TARGETS.find((entry) => entry.pattern.test(ref));
|
|
34
|
-
if (!target)
|
|
35
|
-
throw new Error(`unsupported promotion target ref: ${ref || "<empty>"}`);
|
|
36
|
-
const requested = normalized(requestedPublicationChannel).toLowerCase();
|
|
37
|
-
if (requested && requested !== target.publicationChannel) {
|
|
38
|
-
throw new Error(
|
|
39
|
-
`promotion channel ${requested} does not match target ref ${ref} (${target.publicationChannel})`,
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
targetRef: ref,
|
|
44
|
-
publicationChannel: target.publicationChannel,
|
|
45
|
-
shellChannel: target.shellChannel,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function resolvePromotionChannel({
|
|
50
|
-
requestedChannel = "auto",
|
|
51
|
-
requestedRef = "",
|
|
52
|
-
publicationChannel = "",
|
|
53
|
-
targetRef = "",
|
|
54
|
-
routerRef = "",
|
|
55
|
-
routerSha = "",
|
|
56
|
-
packageVersion = "",
|
|
57
|
-
} = {}) {
|
|
58
|
-
const intent = targetIntent(targetRef, publicationChannel);
|
|
59
|
-
const selected = resolveBuildchainChannel({
|
|
60
|
-
requestedChannel,
|
|
61
|
-
requestedRef,
|
|
62
|
-
publishChannel: intent.publicationChannel,
|
|
63
|
-
eventName: "workflow_call",
|
|
64
|
-
routerRef,
|
|
65
|
-
packageVersion,
|
|
66
|
-
});
|
|
67
|
-
const runtimeIdentity = parseBuildchainRefIdentity(selected.buildchainRef);
|
|
68
|
-
const opaqueOverride = new Set(["train", "authority", "exact-sha"]).has(
|
|
69
|
-
runtimeIdentity.kind,
|
|
70
|
-
);
|
|
71
|
-
const trustedRouterPin =
|
|
72
|
-
opaqueOverride && sameExactSha(selected.buildchainRef, routerSha);
|
|
73
|
-
const overrideUsed = opaqueOverride && !trustedRouterPin;
|
|
74
|
-
if (
|
|
75
|
-
!overrideUsed &&
|
|
76
|
-
!trustedRouterPin &&
|
|
77
|
-
selected.channel !== intent.shellChannel
|
|
78
|
-
) {
|
|
79
|
-
throw new Error(
|
|
80
|
-
`promotion target ${intent.targetRef} requires ${intent.shellChannel} shell/runtime, got ${selected.channel}`,
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
const shellRef =
|
|
84
|
-
intent.shellChannel === "alpha"
|
|
85
|
-
? `v${selected.major}-alpha`
|
|
86
|
-
: `v${selected.major}`;
|
|
87
|
-
return {
|
|
88
|
-
targetRef: intent.targetRef,
|
|
89
|
-
publicationChannel: intent.publicationChannel,
|
|
90
|
-
routerRef: normalized(routerRef),
|
|
91
|
-
routerSha: normalized(routerSha).toLowerCase(),
|
|
92
|
-
channel: intent.shellChannel,
|
|
93
|
-
major: selected.major,
|
|
94
|
-
shellRef,
|
|
95
|
-
runtimeRef: selected.buildchainRef,
|
|
96
|
-
overrideUsed,
|
|
97
|
-
selectionSource: trustedRouterPin
|
|
98
|
-
? "trusted-router-sha"
|
|
99
|
-
: selected.selectionSource,
|
|
100
|
-
reason: trustedRouterPin
|
|
101
|
-
? `explicit Buildchain runtime ref ${selected.buildchainRef} matches the reusable workflow SHA`
|
|
102
|
-
: selected.reason,
|
|
103
|
-
};
|
|
7
|
+
// Publication intent belongs to the product branch. Runtime selection belongs
|
|
8
|
+
// to the entry and cannot be inferred again from the publication channel.
|
|
9
|
+
export function resolvePromotionChannel({ targetRef = "", publicationChannel = "" } = {}) {
|
|
10
|
+
const ref = String(targetRef).replace(/^refs\/heads\//u, "");
|
|
11
|
+
const target = targets.find(({ pattern }) => pattern.test(ref));
|
|
12
|
+
if (!target) throw new Error(`unsupported promotion target ref: ${ref || "<empty>"}`);
|
|
13
|
+
if (publicationChannel && publicationChannel !== target.publicationChannel)
|
|
14
|
+
throw new Error(`promotion channel ${publicationChannel} does not match target ref ${ref}`);
|
|
15
|
+
return { targetRef: ref, publicationChannel: target.publicationChannel, channel: target.channel };
|
|
104
16
|
}
|
|
@@ -3,7 +3,6 @@ import path from "node:path";
|
|
|
3
3
|
import { getOctokit } from "@actions/github";
|
|
4
4
|
import { command } from "../../runtime/action-process.mjs";
|
|
5
5
|
import { installationRoot } from "../../runtime/installation-root.js";
|
|
6
|
-
import { verifyCheckoutIdentity } from "../../runtime/checkout-identity.js";
|
|
7
6
|
import { verifyPromotionInvocation } from "../promotion-request.js";
|
|
8
7
|
import { recoveryFailure } from "../release-candidate-recovery.js";
|
|
9
8
|
import { productPublicationReader } from "../../providers/github/product-publication.js";
|
|
@@ -17,18 +16,8 @@ export async function qualifyPromotionAction(core, env) {
|
|
|
17
16
|
const runtimeRoot = installationRoot(import.meta.url),
|
|
18
17
|
workspace = path.resolve(env.GITHUB_WORKSPACE),
|
|
19
18
|
runtimeSha = request["promotion-runtime-sha"];
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
fs.realpathSync(path.join(workspace, ".buildchain/runtime"))
|
|
23
|
-
)
|
|
24
|
-
throw new Error(
|
|
25
|
-
"Promotion qualification requires the selected runtime implementation",
|
|
26
|
-
);
|
|
27
|
-
verifyCheckoutIdentity({
|
|
28
|
-
directory: runtimeRoot,
|
|
29
|
-
sha: runtimeSha,
|
|
30
|
-
label: "Promotion qualification runtime",
|
|
31
|
-
});
|
|
19
|
+
|
|
20
|
+
|
|
32
21
|
const tree = command("git", ["-C", runtimeRoot, "rev-parse", "HEAD^{tree}"], {
|
|
33
22
|
stdio: "pipe",
|
|
34
23
|
}).trim();
|
|
@@ -1,94 +1,29 @@
|
|
|
1
1
|
import { resolvePromotionChannel } from "./channel.js";
|
|
2
|
-
import { resolvePromotionIdentities } from "./identities.js";
|
|
3
|
-
import * as override from "../runtime-override-authorization.js";
|
|
4
2
|
import { normalizePromotionRequest } from "../promotion-request.js";
|
|
5
3
|
|
|
6
|
-
export async function routePromotion({
|
|
7
|
-
github,
|
|
8
|
-
context,
|
|
9
|
-
request: requestValue,
|
|
10
|
-
workflowRepository,
|
|
11
|
-
workflowSha,
|
|
12
|
-
workflowRef,
|
|
13
|
-
packageVersion,
|
|
14
|
-
}) {
|
|
4
|
+
export async function routePromotion({ context, request: requestValue, workflowRepository, workflowSha, workflowRef, runtime }) {
|
|
15
5
|
const request = normalizePromotionRequest(requestValue);
|
|
16
|
-
const repository = workflowRepository;
|
|
17
|
-
const sha = String(workflowSha || "").toLowerCase();
|
|
18
|
-
const coordinate = workflowRef || "";
|
|
19
|
-
if (
|
|
20
|
-
!/^[\w.-]+\/[\w.-]+$/.test(repository) ||
|
|
21
|
-
!/^[0-9a-f]{40}$/.test(sha) ||
|
|
22
|
-
!coordinate.startsWith(`${repository}/.github/workflows/`)
|
|
23
|
-
)
|
|
24
|
-
throw Error("Promotion requires its exact defining workflow identity");
|
|
25
|
-
if (request["buildchain-repository"] !== repository)
|
|
26
|
-
throw Error(
|
|
27
|
-
"Promotion runtime repository must match its defining workflow repository",
|
|
28
|
-
);
|
|
29
|
-
const routerRef = coordinate
|
|
30
|
-
.split("@")
|
|
31
|
-
.at(-1)
|
|
32
|
-
.replace(/^refs\/(?:heads|tags)\//, "");
|
|
33
|
-
const requestedRef = String(request["buildchain-ref"] || sha).replace(
|
|
34
|
-
/^refs\/(?:heads|tags)\//,
|
|
35
|
-
"",
|
|
36
|
-
);
|
|
37
|
-
if (
|
|
38
|
-
!/^(?:v4(?:-alpha)?|[0-9a-f]{40}|(?:train|authority)\/v4\/v4\.\d+\/[\w./-]+)$/.test(
|
|
39
|
-
requestedRef,
|
|
40
|
-
) ||
|
|
41
|
-
requestedRef.includes("..")
|
|
42
|
-
)
|
|
43
|
-
throw Error(
|
|
44
|
-
"Promotion runtime selection is outside the current v4 authority",
|
|
45
|
-
);
|
|
46
6
|
const route = resolvePromotionChannel({
|
|
47
|
-
requestedChannel: request["buildchain-channel"],
|
|
48
|
-
requestedRef,
|
|
49
7
|
publicationChannel: request.channel,
|
|
50
|
-
targetRef:
|
|
51
|
-
request["target-ref"] || context.ref.replace(/^refs\/heads\//, ""),
|
|
52
|
-
routerRef,
|
|
53
|
-
routerSha: sha,
|
|
54
|
-
packageVersion,
|
|
8
|
+
targetRef: request["target-ref"] || context.ref.replace(/^refs\/heads\//u, ""),
|
|
55
9
|
});
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const [owner, repo] = repository.split("/");
|
|
59
|
-
const identities = await resolvePromotionIdentities({
|
|
60
|
-
routerRef,
|
|
61
|
-
routerSha: sha,
|
|
62
|
-
shellRef: route.shellRef,
|
|
63
|
-
shellCallRef: sha,
|
|
64
|
-
runtimeRef: route.runtimeRef,
|
|
65
|
-
resolveRef: async (ref) =>
|
|
66
|
-
(await github.rest.repos.getCommit({ owner, repo, ref })).data.sha,
|
|
67
|
-
});
|
|
68
|
-
if (
|
|
69
|
-
request["resume-candidate-run-id"] &&
|
|
70
|
-
identities.runtimeSha !==
|
|
71
|
-
String(request["resume-buildchain-runtime-sha"] || "").toLowerCase()
|
|
72
|
-
)
|
|
73
|
-
throw Error(
|
|
74
|
-
"Recovery runtime does not match resume-buildchain-runtime-sha",
|
|
75
|
-
);
|
|
76
|
-
const output = {
|
|
10
|
+
const entryRef = workflowRef.split("@").at(-1).replace(/^refs\/(?:heads|tags)\//u, "");
|
|
11
|
+
return {
|
|
77
12
|
"request-json": JSON.stringify(request),
|
|
78
|
-
repository,
|
|
13
|
+
repository: runtime.repository,
|
|
79
14
|
channel: route.channel,
|
|
80
15
|
"publication-channel": route.publicationChannel,
|
|
81
16
|
"target-ref": route.targetRef,
|
|
82
|
-
"router-ref":
|
|
83
|
-
"router-sha":
|
|
84
|
-
"shell-ref":
|
|
85
|
-
"shell-call-ref":
|
|
86
|
-
"shell-sha":
|
|
87
|
-
"
|
|
88
|
-
"runtime-
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
|
|
17
|
+
"router-ref": entryRef,
|
|
18
|
+
"router-sha": workflowSha,
|
|
19
|
+
"shell-ref": entryRef,
|
|
20
|
+
"shell-call-ref": workflowSha,
|
|
21
|
+
"shell-sha": workflowSha,
|
|
22
|
+
"contract-lock-path": runtime.contract?.path,
|
|
23
|
+
"runtime-ref": runtime.ref,
|
|
24
|
+
"runtime-sha": runtime.sha,
|
|
25
|
+
"override-used": String(runtime.origin === "runtime-parameter"),
|
|
26
|
+
"selection-source": runtime.origin,
|
|
27
|
+
reason: `Execute publication using the runtime selected by the entry (${runtime.origin})`,
|
|
92
28
|
};
|
|
93
|
-
return output;
|
|
94
29
|
}
|
|
@@ -9,8 +9,6 @@ export function bindPromotionSelection(
|
|
|
9
9
|
run = command,
|
|
10
10
|
) {
|
|
11
11
|
for (const [directory, expected] of [
|
|
12
|
-
["workflow-shell", selection["shell-sha"]],
|
|
13
|
-
["runtime", selection["runtime-sha"]],
|
|
14
12
|
["source", sourceSha],
|
|
15
13
|
]) {
|
|
16
14
|
verifyCheckoutIdentity(
|
|
@@ -23,13 +21,7 @@ export function bindPromotionSelection(
|
|
|
23
21
|
);
|
|
24
22
|
}
|
|
25
23
|
const source = path.join(workspace, ".buildchain/source");
|
|
26
|
-
const relative =
|
|
27
|
-
request["buildchain-contract-lock-path"] ||
|
|
28
|
-
request[
|
|
29
|
-
selection.channel === "alpha"
|
|
30
|
-
? "buildchain-alpha-contract-lock-path"
|
|
31
|
-
: "buildchain-stable-contract-lock-path"
|
|
32
|
-
];
|
|
24
|
+
const relative = selection["contract-lock-path"];
|
|
33
25
|
if (
|
|
34
26
|
!relative ||
|
|
35
27
|
path.isAbsolute(relative) ||
|
|
@@ -55,7 +55,6 @@ export function normalizePromotionRequest(value, kind = "request") {
|
|
|
55
55
|
export function bindPromotionInvocation(
|
|
56
56
|
requestValue,
|
|
57
57
|
selection,
|
|
58
|
-
authorization = {},
|
|
59
58
|
) {
|
|
60
59
|
const request = normalizePromotionRequest(requestValue);
|
|
61
60
|
const projected = Object.fromEntries(
|
|
@@ -64,8 +63,6 @@ export function bindPromotionInvocation(
|
|
|
64
63
|
),
|
|
65
64
|
);
|
|
66
65
|
const routing = {
|
|
67
|
-
"buildchain-ref": "runtime-sha",
|
|
68
|
-
"buildchain-contract-lock-path": "contract-lock-path",
|
|
69
66
|
"buildchain-expected-channel": "channel",
|
|
70
67
|
channel: "publication-channel",
|
|
71
68
|
"target-ref": "target-ref",
|
|
@@ -85,33 +82,11 @@ export function bindPromotionInvocation(
|
|
|
85
82
|
throw new Error(`Promotion selection requires ${source}`);
|
|
86
83
|
projected[key] = selection[source];
|
|
87
84
|
}
|
|
88
|
-
for (const key of ["runtime-sha", "shell-sha", "router-sha"])
|
|
89
|
-
if (!/^[0-9a-f]{40}$/.test(selection[key]))
|
|
90
|
-
throw new Error(`Promotion selection ${key} must be exact`);
|
|
91
|
-
if (
|
|
92
|
-
selection["router-sha"] !== selection["shell-sha"] ||
|
|
93
|
-
selection["shell-call-ref"] !== selection["shell-sha"]
|
|
94
|
-
)
|
|
95
|
-
throw new Error("Publisher must use the exact defining workflow");
|
|
96
85
|
if (!/^sha256:[0-9a-f]{64}$/.test(selection["contract-lock-digest"]))
|
|
97
86
|
throw new Error("Promotion contract lock must be rooted");
|
|
98
87
|
if (!["true", "false"].includes(selection["override-used"]))
|
|
99
88
|
throw new Error("Promotion override decision is missing");
|
|
100
89
|
projected["promotion-override-used"] = selection["override-used"] === "true";
|
|
101
|
-
projected["promotion-runtime-authorization-json"] =
|
|
102
|
-
authorization["runtime-authorization-json"] || "";
|
|
103
|
-
projected["promotion-runtime-authorization-root"] =
|
|
104
|
-
authorization["runtime-authorization-root"] || "";
|
|
105
|
-
if (
|
|
106
|
-
projected["promotion-override-used"] &&
|
|
107
|
-
(!projected["promotion-runtime-authorization-json"] ||
|
|
108
|
-
!/^sha256:[0-9a-f]{64}$/.test(
|
|
109
|
-
projected["promotion-runtime-authorization-root"],
|
|
110
|
-
))
|
|
111
|
-
)
|
|
112
|
-
throw new Error(
|
|
113
|
-
"Promotion override requires rooted consumer authorization",
|
|
114
|
-
);
|
|
115
90
|
projected["buildchain-expected-major"] = "4";
|
|
116
91
|
projected["publication-authority-workflow-path"] =
|
|
117
92
|
".github/workflows/.release-promote.yml";
|
|
@@ -119,25 +94,11 @@ export function bindPromotionInvocation(
|
|
|
119
94
|
return normalizePromotionRequest(projected, "invocation");
|
|
120
95
|
}
|
|
121
96
|
|
|
122
|
-
export function verifyPromotionInvocation(value
|
|
97
|
+
export function verifyPromotionInvocation(value) {
|
|
123
98
|
if (typeof value === "string") value = JSON.parse(value);
|
|
124
99
|
const normalized = normalizePromotionRequest(value, "invocation");
|
|
125
100
|
if (Object.keys(value).length !== Object.keys(normalized).length)
|
|
126
101
|
throw new Error("Promotion invocation must include all normalized fields");
|
|
127
|
-
if (
|
|
128
|
-
!/^[0-9a-f]{40}$/.test(workflowSha || "") ||
|
|
129
|
-
normalized["promotion-shell-sha"] !== workflowSha ||
|
|
130
|
-
normalized["promotion-router-sha"] !== workflowSha ||
|
|
131
|
-
normalized["promotion-shell-ref"] !== workflowSha
|
|
132
|
-
)
|
|
133
|
-
throw new Error(
|
|
134
|
-
"Promotion invocation is not bound to this defining workflow",
|
|
135
|
-
);
|
|
136
|
-
if (
|
|
137
|
-
!/^[0-9a-f]{40}$/.test(normalized["promotion-runtime-sha"]) ||
|
|
138
|
-
normalized["buildchain-ref"] !== normalized["promotion-runtime-sha"]
|
|
139
|
-
)
|
|
140
|
-
throw new Error("Promotion runtime must bind one exact admitted commit");
|
|
141
102
|
if (
|
|
142
103
|
!/^sha256:[0-9a-f]{64}$/.test(normalized["promotion-contract-lock-digest"])
|
|
143
104
|
)
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { installationRoot } from "../../runtime/installation-root.js";
|
|
4
3
|
import { createGitHubQualificationClient } from "../../providers/github/qualification.js";
|
|
5
4
|
import { qualifyPublicBuild } from "./public-build.js";
|
|
6
5
|
function inputs(core, env) {
|
|
7
6
|
const workspace = path.resolve(env.GITHUB_WORKSPACE);
|
|
8
|
-
if (
|
|
9
|
-
fs.realpathSync(installationRoot(import.meta.url)) !==
|
|
10
|
-
fs.realpathSync(workspace)
|
|
11
|
-
)
|
|
12
|
-
throw new Error(
|
|
13
|
-
"Stable candidate qualification requires the checked-out source implementation",
|
|
14
|
-
);
|
|
15
7
|
return {
|
|
16
8
|
workspace,
|
|
17
9
|
repositoryName: env.GITHUB_REPOSITORY,
|
|
@@ -37,7 +37,7 @@ export function resolveStableCandidateQualificationCandidate({
|
|
|
37
37
|
runtime?.workflowShellRef !== "v4-alpha" ||
|
|
38
38
|
runtime?.class !== "alpha" ||
|
|
39
39
|
runtime?.override !== false ||
|
|
40
|
-
runtime?.trustDecision !== "
|
|
40
|
+
runtime?.trustDecision !== "entry-selection"
|
|
41
41
|
) {
|
|
42
42
|
throw new Error(
|
|
43
43
|
"public build summary does not bind the exact source run and alpha workflow identity",
|