@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.
Files changed (295) hide show
  1. package/AGENTS.md +30 -41
  2. package/CONTRIBUTING.md +6 -7
  3. package/architecture/action-taxonomy.json +5 -21
  4. package/architecture/agent-change-map.md +74 -56
  5. package/architecture/build-orchestration.json +8 -1
  6. package/architecture/ci-lane-change-budget.json +179 -69
  7. package/architecture/floating-consumer-policy.json +7 -17
  8. package/architecture/internal-capabilities.json +58 -72
  9. package/architecture/maintainability-debt.json +138 -52
  10. package/architecture/maintainability-policy.json +6 -15
  11. package/architecture/promotion-job-topology.json +39 -20
  12. package/architecture/release-topology.json +26 -37
  13. package/architecture/runtime-entry.json +26 -0
  14. package/architecture/runtime-resume-lineage.json +23 -0
  15. package/architecture/stage-capsule-qualification.json +2 -2
  16. package/architecture/universal-workflow-bootstrap.json +10 -25
  17. package/architecture/universal-workflow-capability-policy.json +61 -0
  18. package/architecture/universal-workflow-fault-campaign.json +18 -24
  19. package/architecture/workflow-taxonomy.json +0 -11
  20. package/contracts/fixtures/{v4-runtime-ref-resume-authority-v1 → runtime-resume-lineage-v2}/scenario.json +2 -3
  21. package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +2 -2
  22. package/contracts/fixtures/v4-tail-reseal-v1/valid.json +1 -1
  23. package/contracts/promotion-invocation-v1.schema.json +0 -44
  24. package/contracts/promotion-request-v1.schema.json +0 -39
  25. package/contracts/runtime-resume-lineage-v2.schema.json +182 -0
  26. package/dist/site/buildchain-contract.json +472 -361
  27. package/dist/site/buildchain-site.json +99 -99
  28. package/dist/site/capability-registry.json +3 -3
  29. package/dist/site/cli-registry.json +4 -4
  30. package/dist/site/controller-registry.json +94 -78
  31. package/dist/site/kfd-claims.json +224 -343
  32. package/dist/site/kfd-upstream-aggregate.json +1 -1
  33. package/dist/site/manual-registry.json +15 -15
  34. package/dist/site/node-api-registry.json +239 -354
  35. package/dist/site/page-registry.json +80 -80
  36. package/dist/site/public-surface-audit.json +203 -254
  37. package/dist/site/publication-authority-registry.json +1 -24
  38. package/dist/site/publication-registry.json +4 -4
  39. package/dist/site/release-provenance.json +1 -1
  40. package/dist/site/site-manifest.json +19 -19
  41. package/dist/site/workflow-registry.json +197 -357
  42. package/docs/MAP.md +3 -3
  43. package/docs/auditable-demo.md +4 -4
  44. package/docs/cli-reference.md +2 -2
  45. package/docs/code-organization.md +5 -4
  46. package/docs/controller-evidence.md +2 -2
  47. package/docs/dev-alpha-candidate-patrol.md +5 -5
  48. package/docs/dev-delivery-warrant.md +14 -24
  49. package/docs/engineering-housekeeper.md +3 -3
  50. package/docs/github-artifact-attestation.md +9 -12
  51. package/docs/github-governance-authority.md +4 -4
  52. package/docs/node-api-reference.md +153 -167
  53. package/docs/publication-artifacts.md +3 -4
  54. package/docs/publication-authority.md +2 -2
  55. package/docs/release-candidate.md +21 -27
  56. package/docs/release-governance.md +10 -10
  57. package/docs/release-promotion-request.md +11 -18
  58. package/docs/release-propagation.md +5 -6
  59. package/docs/release-tail-provider-plane.md +2 -3
  60. package/docs/reusable-build-surface.md +13 -7
  61. package/docs/runtime-entry.md +122 -0
  62. package/docs/runtime-train-validation.md +30 -41
  63. package/docs/v4-publication-rehearsal.md +5 -5
  64. package/docs/v4-stage-capsule.md +9 -10
  65. package/docs/web-surface-deployments.md +16 -20
  66. package/docs/workflow-catalog.md +0 -1
  67. package/package.json +6 -6
  68. package/packages/core/adoption/commands/init-repo.mjs +2 -2
  69. package/packages/core/adoption/cross-platform-adopter-qualification.js +2 -13
  70. package/packages/core/adoption/qualification/actions.js +3 -5
  71. package/packages/core/adoption/qualification/admission.js +2 -3
  72. package/packages/core/build/artifact/attestation.js +0 -1
  73. package/packages/core/build/artifact/contracts.js +1 -4
  74. package/packages/core/build/artifact/store.js +6 -5
  75. package/packages/core/build/artifact-signing.js +4 -10
  76. package/packages/core/build/binary/actions.js +15 -9
  77. package/packages/core/build/binary-publication-dispatch.js +2 -6
  78. package/packages/core/build/demo/action-context.js +2 -11
  79. package/packages/core/build/demo/binary-action.js +8 -10
  80. package/packages/core/build/gate/controller.js +0 -2
  81. package/packages/core/build/github-attestation/action.js +2 -7
  82. package/packages/core/build/github-attestation/admission.js +0 -8
  83. package/packages/core/build/github-attestation/transaction.js +1 -2
  84. package/packages/core/build/lifecycle/stage-action.js +2 -0
  85. package/packages/core/build/lifecycle/stage.js +6 -3
  86. package/packages/core/build/macos-credential-island/dmg-assembly.js +0 -2
  87. package/packages/core/build/macos-credential-island/lib.js +2 -6
  88. package/packages/core/build/plan/action-context.js +0 -7
  89. package/packages/core/build/plan/action.js +7 -11
  90. package/packages/core/build/plan/admission.js +6 -73
  91. package/packages/core/build/plan/configuration.js +1 -1
  92. package/packages/core/build/plan/environment.js +1 -1
  93. package/packages/core/build/plan/identity.js +1 -5
  94. package/packages/core/build/plan/resolve.js +7 -1
  95. package/packages/core/build/recovery/checkpoint.js +158 -0
  96. package/packages/core/build/recovery/transaction.js +51 -0
  97. package/packages/core/build/signing/authority-actions.js +2 -11
  98. package/packages/core/build/signing/control.js +0 -5
  99. package/packages/core/build/signing/controller-transaction.js +0 -1
  100. package/packages/core/build/signing/delegation.js +2 -4
  101. package/packages/core/build/signing/dispatch.js +10 -56
  102. package/packages/core/build/signing/intake.js +0 -4
  103. package/packages/core/build/signing/prepare.js +1 -1
  104. package/packages/core/build/signing/request.js +3 -8
  105. package/packages/core/build/source/checkout-action.js +6 -10
  106. package/packages/core/build/source/controller.js +1 -4
  107. package/packages/core/build/source/lifecycle.js +3 -13
  108. package/packages/core/build/stage-capsule/actions.js +3 -13
  109. package/packages/core/build/stage-capsule/campaign/resume.js +10 -5
  110. package/packages/core/build/stage-capsule/rehearsal/verify.js +3 -4
  111. package/packages/core/build/stage-capsule-resume-planner.js +0 -1
  112. package/packages/core/build/summary/aggregation.js +5 -5
  113. package/packages/core/build/summary/finalization.js +1 -1
  114. package/packages/core/build/verification/actions.js +3 -12
  115. package/packages/core/build/verification/runner.js +22 -20
  116. package/packages/core/consumer/floating-consumer-evidence.js +3 -21
  117. package/packages/core/consumer/floating-consumer-policy.js +2 -93
  118. package/packages/core/consumer/floating-consumer-release-passport.js +1 -34
  119. package/packages/core/consumer/policy-admission.js +1 -3
  120. package/packages/core/contracts/buildchain-contract.js +12 -146
  121. package/packages/core/contracts/workflow-yaml-contract.js +11 -1
  122. package/packages/core/dev-delivery/candidate/admission.js +3 -4
  123. package/packages/core/dev-delivery/candidate/coordinates.js +0 -8
  124. package/packages/core/dev-delivery/commands/dev-delivery-request.sh +5 -13
  125. package/packages/core/dev-delivery/commands/dev-delivery-source-proof-reuse.mjs +0 -3
  126. package/packages/core/dev-delivery/dev-delivery-contract-surface.js +4 -52
  127. package/packages/core/dev-delivery/dev-delivery-execution-transfer.js +2 -15
  128. package/packages/core/dev-delivery/native/action-context.js +4 -32
  129. package/packages/core/dev-delivery/native/provider-boundary.js +0 -2
  130. package/packages/core/dev-delivery/native/transactions.js +1 -2
  131. package/packages/core/dev-delivery/queue/reconciliation-action.js +6 -10
  132. package/packages/core/dev-delivery/source-proof/predicates.js +0 -6
  133. package/packages/core/dev-delivery/source-proof/reuse.js +0 -2
  134. package/packages/core/dev-delivery/source-proof/seal.js +0 -2
  135. package/packages/core/governance/alpha-candidate/action.js +1 -10
  136. package/packages/core/governance/audit/actions.js +1 -3
  137. package/packages/core/governance/audit/collection.js +1 -3
  138. package/packages/core/governance/audit/identity.js +3 -31
  139. package/packages/core/governance/audit/transactions.js +2 -4
  140. package/packages/core/governance/buildchain-publication-authority.js +0 -1
  141. package/packages/core/governance/commands/audit-github-governance.mjs +3 -2
  142. package/packages/core/governance/github-governance-authority.js +0 -5
  143. package/packages/core/governance/receipt-admission.js +0 -15
  144. package/packages/core/index.js +1 -1
  145. package/packages/core/observability/controller/identity.js +4 -5
  146. package/packages/core/observability/controller-evidence.js +5 -10
  147. package/packages/core/paper/commands/paper.mjs +6 -6
  148. package/packages/core/paper/operations/plans.js +2 -2
  149. package/packages/core/paper/operations/provisioning-validation.js +1 -1
  150. package/packages/core/paper/operations/scaffold-workflows.js +29 -12
  151. package/packages/core/paper/operations/scaffold.js +97 -69
  152. package/packages/core/paper/paper-agent-entry.js +0 -11
  153. package/packages/core/paper/paper-runtime-channels.js +21 -66
  154. package/packages/core/paper/paper-scaffold-content.js +1 -1
  155. package/packages/core/paper/paper.js +9 -5
  156. package/packages/core/paper/publication/candidate.js +0 -9
  157. package/packages/core/paper/publication-controller.js +2 -4
  158. package/packages/core/providers/github/artifact-attestation.js +1 -1
  159. package/packages/core/publication/authority/actions.js +9 -8
  160. package/packages/core/publication/authority/admission.js +0 -11
  161. package/packages/core/publication/authority/assembly.js +2 -7
  162. package/packages/core/publication/authority/control-plane.js +2 -2
  163. package/packages/core/publication/authority/governance.js +2 -9
  164. package/packages/core/publication/authority/request.js +7 -2
  165. package/packages/core/publication/authority/verification.js +3 -18
  166. package/packages/core/publication/binary/action.js +5 -7
  167. package/packages/core/publication/candidate/qualification-action.js +1 -6
  168. package/packages/core/publication/candidate/stage-capsules.js +1 -1
  169. package/packages/core/publication/npm/preview-action.js +9 -15
  170. package/packages/core/publication/oci/preview-actions.js +1 -10
  171. package/packages/core/publication/publication-artifact-candidate.js +2 -2
  172. package/packages/core/publication/publication-authority.js +2 -2
  173. package/packages/core/publication/publication-rehearsal-projection.js +3 -3
  174. package/packages/core/publication/settlement/actions.js +2 -11
  175. package/packages/core/release/binary/coordinates-action.js +0 -13
  176. package/packages/core/release/binary/coordinates.js +2 -19
  177. package/packages/core/release/commands/promotion-channel-router.mjs +12 -56
  178. package/packages/core/release/commands/resume-from-candidate-run.mjs +2 -3
  179. package/packages/core/release/dev-alpha-active-release-train.js +0 -5
  180. package/packages/core/release/line/action.js +2 -13
  181. package/packages/core/release/next-development/actions.js +2 -5
  182. package/packages/core/release/passport/consumer-validation.js +1 -28
  183. package/packages/core/release/promote-candidate/development-source.js +7 -8
  184. package/packages/core/release/promotion/actions.js +7 -38
  185. package/packages/core/release/promotion/admission.js +3 -50
  186. package/packages/core/release/promotion/candidate.js +2 -4
  187. package/packages/core/release/promotion/channel.js +13 -101
  188. package/packages/core/release/promotion/qualification-action.js +2 -13
  189. package/packages/core/release/promotion/routing.js +16 -81
  190. package/packages/core/release/promotion/selection.js +1 -9
  191. package/packages/core/release/promotion-request.js +1 -40
  192. package/packages/core/release/qualification/actions.js +0 -8
  193. package/packages/core/release/qualification/public-build.js +1 -1
  194. package/packages/core/release/recovery/candidate.js +15 -21
  195. package/packages/core/release/recovery/capsules.js +2 -10
  196. package/packages/core/release/recovery/lineage.js +305 -0
  197. package/packages/core/release/recovery/provenance.js +1 -2
  198. package/packages/core/release/recovery/publication.js +4 -14
  199. package/packages/core/release/recovery/readback.js +19 -32
  200. package/packages/core/release/recovery/runtime.js +4 -95
  201. package/packages/core/release/release-candidate-recovery.js +4 -9
  202. package/packages/core/release/release-candidate.js +2 -5
  203. package/packages/core/release/reseal/actions.js +3 -22
  204. package/packages/core/release/reseal/admission.js +0 -2
  205. package/packages/core/release/reseal/finalize-platform.js +0 -2
  206. package/packages/core/release/tail-reseal-github.js +1 -2
  207. package/packages/core/release/tail-reseal-receipt.js +0 -1
  208. package/packages/core/release/tail-reseal.js +2 -20
  209. package/packages/core/release/version-state.js +16 -13
  210. package/packages/core/runtime/buildchain-domain.wasm +0 -0
  211. package/packages/core/runtime/checkout-identity.js +0 -13
  212. package/packages/core/runtime/domain-wasm-artifact.js +2 -2
  213. package/packages/core/runtime/entry/actions.js +121 -0
  214. package/packages/core/runtime/entry/activation.js +86 -0
  215. package/packages/core/runtime/entry/github.js +55 -0
  216. package/packages/core/runtime/entry/recovery.js +37 -0
  217. package/packages/core/runtime/entry/selection.js +110 -0
  218. package/packages/core/web/controller.js +1 -1
  219. package/packages/core/web/publication-admission-action.js +1 -8
  220. package/packages/core/web/web-surface-publication-candidate.js +2 -5
  221. package/packages/core/workflow/admission/actions.js +6 -26
  222. package/packages/core/workflow/admission/recovery.js +3 -43
  223. package/packages/core/workflow/admission/transactions.js +8 -24
  224. package/packages/core/workflow/commands/buildchain-cli-help.mjs +1 -1
  225. package/packages/core/workflow/commands/universal-workflow-engine.mjs +2 -7
  226. package/packages/core/workflow/dogfood/actions.js +0 -17
  227. package/packages/core/workflow/engine/action.js +0 -5
  228. package/packages/core/workflow/engine/conformance.js +1 -1
  229. package/packages/core/workflow/engine/execution.js +2 -6
  230. package/packages/core/workflow/engine/identity.js +1 -6
  231. package/packages/core/workflow/engine/release-environment.js +11 -35
  232. package/packages/core/workflow/engine/release-promotion.js +2 -2
  233. package/packages/core/workflow/settlement/actions.js +0 -12
  234. package/packages/core/workflow/universal-self-dogfood.js +2 -16
  235. package/packages/core/workflow/universal-workflow-bootstrap.js +16 -241
  236. package/packages/core/workflow/workflow-taxonomy.mjs +2 -2
  237. package/scripts/check-dev-delivery-actions.mjs +17 -8
  238. package/scripts/check-floating-consumer-policy-contract.mjs +6 -6
  239. package/scripts/check-inventory.mjs +1 -10
  240. package/scripts/check-public-dogfood-contract.mjs +34 -21
  241. package/scripts/check-release-topology.mjs +2 -6
  242. package/scripts/check-runtime-entry.mjs +133 -0
  243. package/scripts/check-universal-workflow-bootstrap.mjs +45 -281
  244. package/scripts/check-workflows.sh +0 -7
  245. package/scripts/generate-bootstrap-admission.mjs +1 -1
  246. package/scripts/generate-channel-promotion-workflow.mjs +4 -4
  247. package/scripts/inventory/binary.mjs +4 -4
  248. package/scripts/inventory/promotion.mjs +5 -3
  249. package/scripts/runtime-source-boundaries.mjs +70 -0
  250. package/scripts/site-capability-metadata.mjs +2 -2
  251. package/scripts/workflow-action-graph.mjs +5 -18
  252. package/scripts/workflow-self-reference.mjs +20 -0
  253. package/templates/native-dev-delivery.yml +4 -4
  254. package/templates/universal-buildchain-bootstrap.yml +12 -2
  255. package/architecture/runtime-ref-resume-authority.json +0 -64
  256. package/architecture/universal-workflow-train-admission.json +0 -76
  257. package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +0 -235
  258. package/docs/v4-runtime-ref-resume-authority.md +0 -69
  259. package/packages/core/consumer/channel-selection.js +0 -211
  260. package/packages/core/consumer/commands/buildchain-channel-router.mjs +0 -81
  261. package/packages/core/consumer/invocation-selector.js +0 -4
  262. package/packages/core/consumer/runtime-ref-resume-authority.js +0 -621
  263. package/packages/core/consumer/workflow-definition-authority.js +0 -64
  264. package/packages/core/contracts/runtime-contract-action.js +0 -48
  265. package/packages/core/release/commands/promotion-identity-resolver.mjs +0 -77
  266. package/packages/core/release/commands/verify-promotion-router-binding.sh +0 -36
  267. package/packages/core/release/promotion/identities.js +0 -56
  268. package/packages/core/release/runtime-override-authorization.js +0 -242
  269. package/packages/core/runtime/commands/runtime-ref-core.mjs +0 -171
  270. package/packages/core/runtime/provider-closure.js +0 -60
  271. package/packages/core/runtime/runtime-selection-action.js +0 -34
  272. package/packages/core/runtime/runtime-selection.js +0 -136
  273. package/packages/core/runtime/workflow-runtime.js +0 -11
  274. package/packages/core/workflow/admission/review.js +0 -188
  275. package/packages/core/workflow/commands/universal-workflow-backflow.mjs +0 -26
  276. package/packages/core/workflow/installation.js +0 -33
  277. package/packages/core/workflow/settlement/backflow.js +0 -187
  278. package/scripts/generate-bootstrap-recovery.mjs +0 -94
  279. package/templates/bootstrap-recovery/actions/build/source/admit/action.yml +0 -17
  280. package/templates/bootstrap-recovery/actions/build/source/admit/dist/index.js +0 -63
  281. package/templates/bootstrap-recovery/actions/runtime/dependencies/install/action.yml +0 -18
  282. package/templates/bootstrap-recovery/actions/runtime/dependencies/install/dist/index.js +0 -63
  283. package/templates/bootstrap-recovery/actions/runtime/environment/prepare/action.yml +0 -21
  284. package/templates/bootstrap-recovery/actions/workflow/admission/inspect/action.yml +0 -27
  285. package/templates/bootstrap-recovery/actions/workflow/admission/inspect/dist/index.js +0 -64
  286. package/templates/bootstrap-recovery/actions/workflow/admission/review/action.yml +0 -15
  287. package/templates/bootstrap-recovery/actions/workflow/admission/review/dist/index.js +0 -65
  288. package/templates/bootstrap-recovery/actions/workflow/recovery/admit/action.yml +0 -47
  289. package/templates/bootstrap-recovery/actions/workflow/recovery/execute/action.yml +0 -48
  290. package/templates/bootstrap-recovery/actions/workflow/recovery/settle/action.yml +0 -54
  291. package/templates/bootstrap-recovery/actions/workflow/settlement/seal/action.yml +0 -17
  292. package/templates/bootstrap-recovery/actions/workflow/settlement/seal/dist/index.js +0 -65
  293. package/templates/bootstrap-recovery/manifest.json +0 -68
  294. package/templates/bootstrap-recovery/package.json +0 -9
  295. package/templates/universal-buildchain-bootstrap-recovery.yml +0 -115
@@ -1,48 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import {
4
- inspectRuntimeContract,
5
- assertRuntimeContractAccepted,
6
- } from "./runtime-contract-inspection.js";
7
- import { resolveBuildchainContractLockPath } from "./buildchain-layout.js";
8
-
9
- export function runtimeContractAction(core, env) {
10
- const workspace = env.GITHUB_WORKSPACE;
11
- if (!path.isAbsolute(workspace || ""))
12
- throw new Error("Runtime contract check requires the runner workspace");
13
- const input = JSON.parse(core.getInput("request-json", { required: true }));
14
- const runtimeRoot = path.join(workspace, ".buildchain/runtime");
15
- const result = inspectRuntimeContract({
16
- lockPath: path.resolve(
17
- workspace,
18
- input["buildchain-contract-lock-path"] ||
19
- resolveBuildchainContractLockPath(workspace),
20
- ),
21
- currentContractPath: path.join(
22
- runtimeRoot,
23
- "dist/site/buildchain-contract.json",
24
- ),
25
- runtimeRoot,
26
- runtimeRef: core.getInput("runtime-ref"),
27
- runtimeSha: core.getInput("runtime-sha"),
28
- runtimeClass: core.getInput("runtime-class"),
29
- workflowShellRef: core.getInput("workflow-ref"),
30
- allowOpaqueRuntime: core.getBooleanInput("runtime-override"),
31
- compatibilityPolicy: input["buildchain-contract-compatibility-policy"],
32
- expectedChannel: input["buildchain-contract-expected-channel"],
33
- expectedMajor: input["buildchain-contract-expected-major"],
34
- issueMode: input["buildchain-contract-drift-issue-mode"],
35
- issueBodyPath: path.join(
36
- workspace,
37
- ".buildchain/contract-drift/issue-body.md",
38
- ),
39
- repository: env.GITHUB_REPOSITORY,
40
- workflow: env.GITHUB_WORKFLOW,
41
- runUrl: `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}/actions/runs/${env.GITHUB_RUN_ID}`,
42
- });
43
- if (env.GITHUB_STEP_SUMMARY)
44
- fs.appendFileSync(env.GITHUB_STEP_SUMMARY, result.summary + "\n\n");
45
- for (const [key, value] of Object.entries(result.outputs))
46
- core.setOutput(key, value);
47
- assertRuntimeContractAccepted(result);
48
- }
@@ -1,77 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from "node:fs";
3
- import path from "node:path";
4
- import { fileURLToPath } from "node:url";
5
- import { resolvePromotionIdentities } from "../promotion/identities.js";
6
- const normalized = value => String(value ?? "").trim();
7
- function parseArgs(argv) {
8
- const values = {};
9
- for (let index = 0; index < argv.length; index += 1) {
10
- const token = argv[index];
11
- if (!token.startsWith("--")) throw new Error(`unexpected argument: ${token}`);
12
- const value = argv[index + 1];
13
- if (value === undefined || value.startsWith("--")) throw new Error(`missing value for ${token}`);
14
- values[token.slice(2)] = value;
15
- index += 1;
16
- }
17
- return values;
18
- }
19
-
20
- function repositoryParts(value) {
21
- const match = normalized(value).match(/^([^/]+)\/([^/]+)$/);
22
- if (!match) throw new Error("repository must use owner/name form");
23
- return { owner: match[1], repo: match[2] };
24
- }
25
-
26
- async function githubCommitResolver({ repository, token }) {
27
- const { owner, repo } = repositoryParts(repository);
28
- return async (ref) => {
29
- const response = await fetch(
30
- `https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/commits/${encodeURIComponent(ref)}`,
31
- {
32
- headers: {
33
- Accept: "application/vnd.github+json",
34
- Authorization: `Bearer ${token}`,
35
- "X-GitHub-Api-Version": "2022-11-28",
36
- "User-Agent": "kungfu-buildchain-promotion-router",
37
- },
38
- },
39
- );
40
- if (!response.ok) throw new Error(`unable to resolve ${ref}: GitHub API returned ${response.status}`);
41
- return (await response.json()).sha;
42
- };
43
- }
44
-
45
- function writeOutputs(file, identities) {
46
- const outputs = {
47
- "router-sha": identities.routerSha,
48
- "shell-call-ref": identities.shellCallRef,
49
- "shell-sha": identities.shellSha,
50
- "runtime-sha": identities.runtimeSha,
51
- };
52
- fs.appendFileSync(file, Object.entries(outputs).map(([key, value]) => `${key}=${value}\n`).join(""));
53
- }
54
-
55
- async function main() {
56
- const args = parseArgs(process.argv.slice(2));
57
- const token = normalized(process.env.GITHUB_TOKEN);
58
- if (!token) throw new Error("GITHUB_TOKEN is required to resolve floating promotion refs");
59
- const identities = await resolvePromotionIdentities({
60
- routerRef: args["router-ref"],
61
- routerSha: args["router-sha"],
62
- shellRef: args["shell-ref"],
63
- shellCallRef: args["shell-call-ref"],
64
- runtimeRef: args["runtime-ref"],
65
- resolveRef: await githubCommitResolver({ repository: args.repository, token }),
66
- });
67
- if (process.env.GITHUB_OUTPUT) writeOutputs(process.env.GITHUB_OUTPUT, identities);
68
- process.stdout.write(`${JSON.stringify(identities, null, 2)}\n`);
69
- }
70
-
71
- const isMain = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
72
- if (isMain) {
73
- main().catch((error) => {
74
- console.error(`promotion-identity-resolver: ${error.message}`);
75
- process.exitCode = 1;
76
- });
77
- }
@@ -1,36 +0,0 @@
1
- #!/bin/bash
2
- set -euo pipefail
3
-
4
- for name in ROUTER_REF ROUTER_SHA SHELL_REF SHELL_SHA RUNTIME_REF RUNTIME_SHA LOCK_PATH LOCK_DIGEST PUBLICATION_CHANNEL ROUTED_TARGET_REF; do
5
- if [[ -z "${!name}" ]]; then
6
- echo "::error::Incomplete promotion router binding: ${name} is empty"
7
- exit 1
8
- fi
9
- done
10
-
11
- router_sha="$(git -C .buildchain/promotion-router rev-parse HEAD)"
12
- shell_sha="$(git -C .buildchain/runtime/promotion-shell rev-parse HEAD)"
13
- runtime_sha="$(git -C .buildchain/runtime rev-parse HEAD)"
14
- expected_router_sha="${ROUTER_SHA:-}"
15
- expected_shell_sha="${SHELL_SHA:-}"
16
- expected_runtime_sha="${RUNTIME_SHA:-}"
17
- expected_lock_digest="${LOCK_DIGEST:-}"
18
- lock_file=".buildchain/promotion-source/${LOCK_PATH}"
19
- if [[ ! -f "${lock_file}" ]]; then
20
- echo "::error::Selected promotion contract lock is missing: ${LOCK_PATH}"
21
- exit 1
22
- fi
23
- lock_digest="sha256:$(shasum -a 256 "${lock_file}" | awk '{print $1}')"
24
- [[ "${router_sha}" = "${expected_router_sha}" ]] || { echo "::error::Promotion router SHA mismatch"; exit 1; }
25
- [[ "${shell_sha}" = "${expected_shell_sha}" ]] || { echo "::error::Promotion shell SHA mismatch"; exit 1; }
26
- [[ "${runtime_sha}" = "${expected_runtime_sha}" ]] || { echo "::error::Promotion runtime SHA mismatch"; exit 1; }
27
- [[ "${lock_digest}" = "${expected_lock_digest}" ]] || { echo "::error::Promotion contract-lock digest mismatch"; exit 1; }
28
- [[ "${ACTUAL_RUNTIME_SHA}" = "${RUNTIME_SHA}" ]] || { echo "::error::Promotion runtime SHA mismatch"; exit 1; }
29
- [[ "${ACTUAL_LOCK_PATH}" = "${LOCK_PATH}" ]] || { echo "::error::Promotion contract-lock path mismatch"; exit 1; }
30
- [[ "${ACTUAL_CHANNEL}" = "${PUBLICATION_CHANNEL}" ]] || { echo "::error::Promotion publication channel mismatch"; exit 1; }
31
- [[ "${ACTUAL_TARGET_REF}" = "${ROUTED_TARGET_REF}" ]] || { echo "::error::Promotion target ref mismatch"; exit 1; }
32
- [[ "${CALLED_WORKFLOW_SHA}" = "${SHELL_SHA}" ]] || { echo "::error::Called promotion shell SHA mismatch"; exit 1; }
33
- called_ref="${CALLED_WORKFLOW_REF##*@}"
34
- called_ref="${called_ref#refs/heads/}"
35
- called_ref="${called_ref#refs/tags/}"
36
- [[ "${called_ref}" = "${SHELL_REF}" ]] || { echo "::error::Called promotion shell ref ${called_ref} does not match ${SHELL_REF}"; exit 1; }
@@ -1,56 +0,0 @@
1
- const SHA_PATTERN = /^[0-9a-f]{40}$/i;
2
-
3
- function normalized(value) {
4
- return String(value ?? "").trim();
5
- }
6
-
7
- function requireSha(value, label) {
8
- const sha = normalized(value).toLowerCase();
9
- if (!SHA_PATTERN.test(sha))
10
- throw new Error(`${label} must be an exact 40-character SHA`);
11
- return sha;
12
- }
13
-
14
- export async function resolvePromotionIdentities({
15
- routerRef,
16
- routerSha,
17
- shellRef,
18
- shellCallRef,
19
- runtimeRef,
20
- resolveRef,
21
- } = {}) {
22
- const requested = {
23
- router: normalized(routerRef),
24
- shell: normalized(shellRef),
25
- shellCall: normalized(shellCallRef),
26
- runtime: normalized(runtimeRef),
27
- };
28
- if (Object.values(requested).some((value) => !value)) {
29
- throw new Error("router, shell, shell call, and runtime refs are required");
30
- }
31
- if (typeof resolveRef !== "function")
32
- throw new Error("resolveRef must be a function");
33
-
34
- const immutableRouterSha = requireSha(routerSha, "router SHA");
35
- const resolved = new Map([[requested.router, immutableRouterSha]]);
36
- const resolveOnce = async (ref) => {
37
- if (SHA_PATTERN.test(ref)) return ref.toLowerCase();
38
- if (!resolved.has(ref)) {
39
- resolved.set(
40
- ref,
41
- requireSha(await resolveRef(ref), `resolved SHA for ${ref}`),
42
- );
43
- }
44
- return resolved.get(ref);
45
- };
46
-
47
- return {
48
- routerRef: requested.router,
49
- routerSha: immutableRouterSha,
50
- shellRef: requested.shell,
51
- shellCallRef: requested.shellCall,
52
- shellSha: await resolveOnce(requested.shellCall),
53
- runtimeRef: requested.runtime,
54
- runtimeSha: await resolveOnce(requested.runtime),
55
- };
56
- }
@@ -1,242 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { execFileSync } from "node:child_process";
4
- import * as runtime from "../consumer/runtime-ref-resume-authority.js";
5
-
6
- const EXACT_SHA = /^[0-9a-f]{40}$/u;
7
- const OFFICIAL_REF = /^v4(?:-alpha)?$/u;
8
- const GOVERNED_REF = /^(?:train|authority)\/v4\/v4\.\d+\/[A-Za-z0-9._/-]+$/u;
9
-
10
- function normalizeRef(value) {
11
- return String(value || "")
12
- .trim()
13
- .replace(/^refs\/(?:heads|tags)\//u, "");
14
- }
15
-
16
- async function readProviderRef({ github, owner, repo, ref }) {
17
- let response;
18
- for (const namespace of ["heads", "tags"]) {
19
- try {
20
- response = await github.rest.git.getRef({
21
- owner,
22
- repo,
23
- ref: `${namespace}/${ref}`,
24
- });
25
- break;
26
- } catch (error) {
27
- if (error?.status !== 404) throw error;
28
- }
29
- }
30
- if (!response) return undefined;
31
- return {
32
- ref,
33
- sha: String(response.data.object.sha || "").toLowerCase(),
34
- providerRef: response.data.ref || `refs/heads/${ref}`,
35
- };
36
- }
37
-
38
- async function containsCommit({ github, owner, repo, headSha, runtimeSha }) {
39
- if (headSha === runtimeSha) return true;
40
- const comparison = await github.rest.repos.compareCommitsWithBasehead({
41
- owner,
42
- repo,
43
- basehead: `${runtimeSha}...${headSha}`,
44
- });
45
- return ["ahead", "identical"].includes(comparison.data.status);
46
- }
47
-
48
- function permissionLevel(permission) {
49
- const declaredLevel = permission.data.permission;
50
- const userPermissions = permission.data.user?.permissions;
51
- return (
52
- (typeof declaredLevel === "string" && declaredLevel) ||
53
- (typeof userPermissions === "string" && userPermissions) ||
54
- (userPermissions?.admin && "admin") ||
55
- (userPermissions?.maintain && "maintain") ||
56
- (userPermissions?.push && "write") ||
57
- (userPermissions?.triage && "triage") ||
58
- (userPermissions?.pull && "read") ||
59
- "none"
60
- );
61
- }
62
-
63
- async function requireTrustedActor({ github, context }) {
64
- if (context.eventName !== "workflow_dispatch") {
65
- throw new Error(
66
- "promotion runtime override is only allowed for trusted workflow_dispatch runs",
67
- );
68
- }
69
- const permission = await github.rest.repos.getCollaboratorPermissionLevel({
70
- owner: context.repo.owner,
71
- repo: context.repo.repo,
72
- username: context.actor,
73
- });
74
- const level = permissionLevel(permission);
75
- if (!["write", "maintain", "admin"].includes(level)) {
76
- throw new Error(
77
- `promotion runtime override requires write, maintain, or admin permission; actor has ${level}`,
78
- );
79
- }
80
- return { actor: context.actor, permission: level };
81
- }
82
-
83
- function normalizeRequestedSelection(request) {
84
- const requestedRef = normalizeRef(request.requestedRef);
85
- const runtimeSha = String(request.resolvedRuntimeSha || "")
86
- .trim()
87
- .toLowerCase();
88
- if (!EXACT_SHA.test(runtimeSha)) {
89
- throw new Error("resolved runtime must be an exact 40-character Git SHA");
90
- }
91
- if (
92
- !EXACT_SHA.test(requestedRef.toLowerCase()) &&
93
- !OFFICIAL_REF.test(requestedRef) &&
94
- !GOVERNED_REF.test(requestedRef)
95
- ) {
96
- throw new Error(
97
- "requested runtime ref is outside the v4 authority boundary",
98
- );
99
- }
100
- return { requestedRef, runtimeSha };
101
- }
102
-
103
- function normalizeRuntimeRepository(request, context) {
104
- const repository = String(
105
- request.runtimeRepository || `${context.repo.owner}/${context.repo.repo}`,
106
- ).split("/");
107
- if (
108
- repository.length !== 2 ||
109
- repository.some((part) => !/^[A-Za-z0-9_.-]+$/u.test(part))
110
- ) {
111
- throw new Error("runtimeRepository must be owner/repository");
112
- }
113
- return { owner: repository[0], repo: repository[1] };
114
- }
115
-
116
- async function approvedRuntimeRefReadbacks({
117
- github,
118
- runtime,
119
- runtimeRepository,
120
- requestedRef,
121
- runtimeSha,
122
- }) {
123
- const refs = new Set(["v4", "v4-alpha"]);
124
- if (GOVERNED_REF.test(requestedRef)) refs.add(requestedRef);
125
- const approvedRefReadbacks = [];
126
- for (const ref of [...refs].sort()) {
127
- const readback = await readProviderRef({
128
- github,
129
- ...runtimeRepository,
130
- ref,
131
- });
132
- if (!readback) continue;
133
- const containsRuntimeSha = await containsCommit({
134
- github,
135
- ...runtimeRepository,
136
- headSha: readback.sha,
137
- runtimeSha,
138
- });
139
- approvedRefReadbacks.push({
140
- ref,
141
- sha: readback.sha,
142
- containsRuntimeSha,
143
- readbackRoot: runtime.runtimeResumeDocumentRoot({
144
- provider: "github",
145
- repository: `${runtimeRepository.owner}/${runtimeRepository.repo}`,
146
- providerRef: readback.providerRef,
147
- sha: readback.sha,
148
- runtimeSha,
149
- containsRuntimeSha,
150
- }),
151
- });
152
- }
153
- return approvedRefReadbacks;
154
- }
155
-
156
- function writeAuthorization(outputPath, authorization) {
157
- if (!outputPath) return;
158
- const output = path.resolve(outputPath);
159
- fs.mkdirSync(path.dirname(output), { recursive: true });
160
- fs.writeFileSync(output, `${JSON.stringify(authorization, null, 2)}\n`);
161
- }
162
-
163
- function trackedRuntimePersistencePaths(consumerRoot) {
164
- return execFileSync(
165
- "git",
166
- [
167
- "-C",
168
- consumerRoot,
169
- "ls-files",
170
- "--",
171
- ".github/workflows",
172
- "actions",
173
- ".buildchain",
174
- ],
175
- { encoding: "utf8" },
176
- )
177
- .split(/\r?\n/u)
178
- .filter((entry) => /\.(?:json|toml|ya?ml)$/u.test(entry));
179
- }
180
-
181
- export async function authorizePromotionRuntimeOverride({
182
- github,
183
- context,
184
- request = undefined,
185
- }) {
186
- const actor = await requireTrustedActor({ github, context });
187
- if (!request) return actor;
188
-
189
- const { requestedRef, runtimeSha } = normalizeRequestedSelection(request);
190
- const consumerRoot = path.resolve(request.consumerRoot || process.cwd());
191
- const policyDocument = JSON.parse(
192
- fs.readFileSync(path.resolve(request.consumerPolicyReceiptPath), "utf8"),
193
- );
194
- const policyReceipt = policyDocument.receipt || policyDocument;
195
- const persistenceScan = runtime.scanRuntimeSelectorPersistence({
196
- root: consumerRoot,
197
- paths: trackedRuntimePersistencePaths(consumerRoot),
198
- });
199
- if (persistenceScan.status !== "passed") {
200
- throw new Error(
201
- "runtime selector persistence scan rejected the consumer source",
202
- );
203
- }
204
-
205
- const runtimeRepository = normalizeRuntimeRepository(request, context);
206
- const approvedRefReadbacks = await approvedRuntimeRefReadbacks({
207
- github,
208
- runtime,
209
- runtimeRepository,
210
- requestedRef,
211
- runtimeSha,
212
- });
213
- const sourceTreeSha = String(
214
- request.sourceTreeSha ||
215
- execFileSync("git", ["-C", consumerRoot, "rev-parse", "HEAD^{tree}"], {
216
- encoding: "utf8",
217
- }),
218
- )
219
- .trim()
220
- .toLowerCase();
221
- const authorization = runtime.authorizeRuntimeSelection({
222
- repository: `${context.repo.owner}/${context.repo.repo}`,
223
- eventName: context.eventName,
224
- mode: request.mode || "dispatch",
225
- actor: context.actor,
226
- actorPermission: actor.permission,
227
- reason: request.reason,
228
- authorizedAt: request.authorizedAt || new Date().toISOString(),
229
- sourceSha: request.sourceSha || context.sha,
230
- sourceTreeSha,
231
- requestedRef,
232
- resolvedRuntimeSha: runtimeSha,
233
- approvedRefReadbacks,
234
- stableContractLockRoot: policyReceipt.contractLocks?.stable?.root,
235
- alphaContractLockRoot: policyReceipt.contractLocks?.alpha?.root,
236
- consumerPolicyReceiptRoot:
237
- request.consumerPolicyReceiptRoot || policyDocument.receiptRoot,
238
- persistenceScan,
239
- });
240
- writeAuthorization(request.outputPath, authorization);
241
- return { ...actor, ...authorization, persistenceScan };
242
- }
@@ -1,171 +0,0 @@
1
- import { parseBuildchainRefIdentity } from "../../consumer/buildchain-channel-identity.js";
2
-
3
- const EXACT_SHA_RE = /^[0-9a-f]{40}$/i;
4
- const TRAIN_REF_RE = /^train\/v\d+\/v\d+\.\d+\/[A-Za-z0-9._/-]+$/;
5
- const AUTHORITY_REF_RE = /^authority\/v\d+\/v\d+\.\d+\/[A-Za-z0-9._/-]+$/;
6
- const OFFICIAL_CHANNEL_REF_RE = /^v\d+(?:\.\d+)?(?:-alpha)?$/;
7
-
8
- export function parseWorkflowShellRef(workflowRef = "", fallback = "v3", buildchainRepository = "kungfu-systems/buildchain") {
9
- const value = String(workflowRef || "");
10
- const expectedPrefix = `${buildchainRepository}/.github/workflows/`;
11
- if (!value.startsWith(expectedPrefix)) {
12
- return fallback;
13
- }
14
- const ref = value.split("@").pop()?.trim();
15
- return (ref || fallback).replace(/^refs\/(?:heads|tags)\//, "");
16
- }
17
-
18
- export function classifyBuildchainRuntimeRef(ref = "") {
19
- const identity = parseBuildchainRefIdentity(ref);
20
- return identity.channel || (identity.kind === "missing" ? "development" : identity.kind);
21
- }
22
-
23
- export function isOfficialBuildchainChannelRef(ref = "") {
24
- const value = String(ref || "").trim().replace(/^refs\/tags\//, "");
25
- return OFFICIAL_CHANNEL_REF_RE.test(value);
26
- }
27
-
28
- export function normalizeRequestedRuntimeRef(requestedRef = "") {
29
- const requested = String(requestedRef || "").trim();
30
- if (!requested) {
31
- return { ref: "", fullRef: "", class: "", exactSha: false, officialChannel: false };
32
- }
33
- if (isOfficialBuildchainChannelRef(requested)) {
34
- const channelRef = requested.replace(/^refs\/tags\//, "");
35
- return {
36
- ref: channelRef,
37
- fullRef: channelRef,
38
- class: classifyBuildchainRuntimeRef(channelRef),
39
- exactSha: false,
40
- officialChannel: true,
41
- };
42
- }
43
- if (EXACT_SHA_RE.test(requested)) {
44
- return {
45
- ref: requested,
46
- fullRef: requested,
47
- class: "exact-sha",
48
- exactSha: true,
49
- officialChannel: false,
50
- };
51
- }
52
- const protectedRef = requested.replace(/^refs\/heads\//, "");
53
- if (!TRAIN_REF_RE.test(protectedRef) && !AUTHORITY_REF_RE.test(protectedRef)) {
54
- throw new Error(
55
- "buildchain-ref override must be train/vN/vN.M/<capability>, refs/heads/train/vN/vN.M/<capability>, authority/vN/vN.M/<capability>, refs/heads/authority/vN/vN.M/<capability>, or an exact 40-character SHA",
56
- );
57
- }
58
- return {
59
- ref: protectedRef,
60
- fullRef: `refs/heads/${protectedRef}`,
61
- class: AUTHORITY_REF_RE.test(protectedRef) ? "authority" : "train",
62
- exactSha: false,
63
- officialChannel: false,
64
- };
65
- }
66
-
67
- export function resolveRuntimeSelection({
68
- requestedRef = "",
69
- workflowRef = "",
70
- defaultStableRef = "v3",
71
- buildchainRepository = "kungfu-systems/buildchain",
72
- } = {}) {
73
- const requested = String(requestedRef || "").trim();
74
- const workflowShellRef = parseWorkflowShellRef(workflowRef, defaultStableRef, buildchainRepository);
75
- if (!requested) {
76
- return {
77
- requestedRef: "",
78
- runtimeRef: workflowShellRef || defaultStableRef,
79
- runtimeFullRef: workflowShellRef || defaultStableRef,
80
- runtimeClass: classifyBuildchainRuntimeRef(workflowShellRef || defaultStableRef),
81
- runtimeOverride: false,
82
- workflowShellRef: workflowShellRef || defaultStableRef,
83
- rollbackRef: workflowShellRef || defaultStableRef,
84
- trustDecision: "stable-default",
85
- };
86
- }
87
- const normalized = normalizeRequestedRuntimeRef(requested);
88
- const sameRepositoryWorkflow = String(workflowRef || "").startsWith(
89
- `${buildchainRepository}/.github/workflows/`,
90
- );
91
- const pinnedSelfRuntime =
92
- sameRepositoryWorkflow &&
93
- normalized.exactSha &&
94
- EXACT_SHA_RE.test(workflowShellRef) &&
95
- normalized.ref.toLowerCase() === workflowShellRef.toLowerCase();
96
- const runtimeOverride = !normalized.officialChannel && !pinnedSelfRuntime;
97
- return {
98
- requestedRef: requested,
99
- runtimeRef: normalized.ref,
100
- runtimeFullRef: normalized.fullRef,
101
- runtimeClass: normalized.class,
102
- runtimeOverride,
103
- workflowShellRef: workflowShellRef || defaultStableRef,
104
- rollbackRef: workflowShellRef || defaultStableRef,
105
- trustDecision: normalized.officialChannel
106
- ? "official-channel"
107
- : pinnedSelfRuntime
108
- ? "pinned-self"
109
- : "override-requested",
110
- };
111
- }
112
-
113
- export function validateRuntimeOverrideTrust({
114
- requestedRef = "",
115
- eventName = "",
116
- eventAction = "",
117
- actorPermission = "",
118
- sameRepositoryPullRequest = false,
119
- sameRepositoryWorkflow = false,
120
- pullRequestHeadSha = "",
121
- workflowShellSha = "",
122
- } = {}) {
123
- if (!String(requestedRef || "").trim()) {
124
- return { ok: true, decision: "stable-default" };
125
- }
126
- if (isOfficialBuildchainChannelRef(requestedRef)) {
127
- return { ok: true, decision: "official-channel" };
128
- }
129
- const normalizedRequested = String(requestedRef || "").trim().toLowerCase();
130
- const normalizedHeadSha = String(pullRequestHeadSha || "").trim().toLowerCase();
131
- const normalizedWorkflowShellSha = String(workflowShellSha || "").trim().toLowerCase();
132
- if (
133
- sameRepositoryWorkflow === true &&
134
- EXACT_SHA_RE.test(normalizedRequested) &&
135
- EXACT_SHA_RE.test(normalizedWorkflowShellSha) &&
136
- normalizedRequested === normalizedWorkflowShellSha
137
- ) {
138
- return { ok: true, decision: "pinned-self" };
139
- }
140
- if (
141
- eventName === "pull_request" &&
142
- eventAction === "closed" &&
143
- EXACT_SHA_RE.test(normalizedRequested) &&
144
- normalizedRequested === normalizedWorkflowShellSha
145
- ) {
146
- return { ok: true, decision: "closed-release-pr-shell-runtime" };
147
- }
148
- if (
149
- eventName === "pull_request" &&
150
- sameRepositoryPullRequest === true &&
151
- EXACT_SHA_RE.test(normalizedRequested) &&
152
- normalizedRequested === normalizedHeadSha
153
- ) {
154
- return { ok: true, decision: "same-repository-pr-head" };
155
- }
156
- if (eventName !== "workflow_dispatch") {
157
- return {
158
- ok: false,
159
- decision: "rejected-untrusted-event",
160
- reason: "buildchain-ref override is only allowed for trusted workflow_dispatch runs",
161
- };
162
- }
163
- if (!new Set(["admin", "maintain", "write"]).has(String(actorPermission || ""))) {
164
- return {
165
- ok: false,
166
- decision: "rejected-insufficient-permission",
167
- reason: "buildchain-ref override requires actor write, maintain, or admin permission",
168
- };
169
- }
170
- return { ok: true, decision: "override-accepted" };
171
- }
@@ -1,60 +0,0 @@
1
- import { command, requireValue } from "./action-process.mjs";
2
- import fs from "node:fs";
3
- import path from "node:path";
4
- import { installLockedDependencies } from "./locked-dependencies.js";
5
- export function verify(env, execute = command) {
6
- for (const name of ["RUNTIME_SHA", "RUNTIME_TREE"])
7
- requireValue(
8
- /^[0-9a-f]{40}$/u.test(env[name] || ""),
9
- `${name} must be an immutable 40-hex identity`,
10
- );
11
- for (const [revision, expected] of [
12
- ["HEAD", env.RUNTIME_SHA],
13
- ["HEAD^{tree}", env.RUNTIME_TREE],
14
- ]) {
15
- const actual = execute(
16
- "git",
17
- ["-C", ".buildchain/runtime", "rev-parse", revision],
18
- { stdio: ["ignore", "pipe", "inherit"] },
19
- ).trim();
20
- requireValue(
21
- actual === expected,
22
- `Admitted runtime ${revision} does not match the checked-out closure`,
23
- );
24
- }
25
- }
26
-
27
- export function exposeProviderDependencies(workspace = process.cwd()) {
28
- const target = path.resolve(workspace, ".buildchain/runtime/node_modules");
29
- const link = path.resolve(workspace, "node_modules");
30
- requireValue(
31
- fs.statSync(target).isDirectory(),
32
- "Verified provider dependencies are missing",
33
- );
34
- // Existing source-owned dependencies must never be replaced by this boundary.
35
- fs.symlinkSync(
36
- target,
37
- link,
38
- process.platform === "win32" ? "junction" : "dir",
39
- );
40
- }
41
-
42
- export function activateProviderClosure(identity, ports = {}) {
43
- (ports.verify || verify)({
44
- RUNTIME_SHA: identity.sha,
45
- RUNTIME_TREE: identity.tree,
46
- });
47
- (ports.install || installLockedDependencies)({
48
- directory: ".buildchain/runtime",
49
- production: false,
50
- ignoreScripts: true,
51
- });
52
- (ports.expose || exposeProviderDependencies)();
53
- }
54
-
55
- export function providerClosureAction(core) {
56
- activateProviderClosure({
57
- sha: core.getInput("sha", { required: true }),
58
- tree: core.getInput("tree", { required: true }),
59
- });
60
- }