@kungfu-tech/buildchain 4.1.3-alpha.0 → 4.1.3-alpha.10
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 +41 -75
- package/CONTRIBUTING.md +19 -26
- package/architecture/action-taxonomy.json +24 -0
- package/architecture/agent-change-map.md +272 -12
- package/architecture/capability-state-machine-manifest.json +1 -4
- package/architecture/ci-lane-change-budget.json +190 -807
- package/architecture/core-mechanisms.json +3 -6
- package/architecture/decisions/0005-minimal-consumer-contract.md +122 -0
- package/architecture/decisions/0006-business-attempt-journal.md +89 -0
- package/architecture/decisions/0007-hosted-pipeline-controller.md +106 -0
- package/architecture/decisions/0008-pipeline-product-publication.md +120 -0
- package/architecture/decisions/0009-pipeline-version-preparation.md +186 -0
- package/architecture/internal-capabilities.json +371 -9
- package/architecture/maintainability-debt.json +50 -34
- package/architecture/maintainability-policy.json +8 -8
- package/architecture/minimal-consumer-migration.json +5670 -0
- package/architecture/platform-stage-checkpoints.json +31 -7
- package/architecture/product-upstreams.json +20 -0
- package/architecture/release-topology.json +331 -74
- package/architecture/stage-capsule-qualification.json +3 -1
- package/architecture/universal-workflow-bootstrap.json +15 -1
- package/architecture/universal-workflow-capability-policy.json +9 -9
- package/architecture/universal-workflow-fault-campaign.json +3 -1
- package/architecture/workflow-taxonomy.json +77 -328
- package/contracts/release-discussion-v1.schema.json +3 -0
- package/dist/readers/business-attempt.cjs +809 -0
- package/dist/readers/release-discussion.cjs +4 -0
- package/dist/site/buildchain-contract.json +16 -68
- package/dist/site/buildchain-site.json +47 -27
- package/dist/site/capability-registry.json +4 -4
- package/dist/site/controller-registry.json +1 -47
- package/dist/site/kfd-claims.json +499 -494
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +3 -3
- package/dist/site/node-api-registry.json +56 -56
- package/dist/site/page-registry.json +40 -20
- package/dist/site/public-surface-audit.json +286 -349
- package/dist/site/publication-authority-registry.json +203 -523
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/site-manifest.json +7 -7
- package/dist/site/workflow-registry.json +590 -940
- package/docs/code-organization.md +9 -6
- package/docs/node-api-reference.md +103 -103
- package/docs/release-discussions.md +44 -5
- package/docs/release-governance.md +10 -12
- package/docs/runtime-entry.md +73 -5
- package/docs/runtime-train-validation.md +39 -11
- package/docs/stable-candidate-patrol.md +6 -5
- package/docs/workflow-catalog.md +9 -32
- package/package.json +4 -3
- package/packages/core/adoption/buildchain-kfd-claims.js +7 -7
- package/packages/core/build/standalone/build.js +7 -1
- package/packages/core/consumer/buildchain-config.js +2 -21
- package/packages/core/consumer/contract/entries.js +85 -0
- package/packages/core/consumer/contract/examples.js +96 -0
- package/packages/core/consumer/contract/identity.js +65 -0
- package/packages/core/consumer/contract/inspection.js +45 -0
- package/packages/core/consumer/contract/plan.js +149 -0
- package/packages/core/consumer/contract/products.js +119 -0
- package/packages/core/consumer/contract/reader.js +47 -0
- package/packages/core/consumer/contract/shape.js +46 -0
- package/packages/core/dev-delivery/candidate/admission.js +9 -5
- package/packages/core/dev-delivery/candidate/reservation.js +11 -0
- package/packages/core/dev-delivery/candidate/source-paths.js +12 -4
- package/packages/core/dev-delivery/commands/project-cut-merge-queue-admission.mjs +47 -20
- package/packages/core/dev-delivery/dev-delivery-provider-heartbeat.js +18 -15
- package/packages/core/dev-delivery/native/actions.js +9 -1
- package/packages/core/dev-delivery/native/heartbeat-action.js +16 -0
- package/packages/core/dev-delivery/native/heartbeat.js +6 -4
- package/packages/core/dev-delivery/native/process-entry.js +19 -0
- package/packages/core/dev-delivery/queue/landing-action.js +53 -0
- package/packages/core/dev-delivery/warrant/failure-settlement.js +8 -6
- package/packages/core/dev-delivery/warrant/service.js +7 -0
- package/packages/core/governance/buildchain-publication-authority.js +8 -23
- package/packages/core/governance/github-governance-authority.js +1 -0
- package/packages/core/observability/controller-evidence.js +0 -8
- package/packages/core/paper/operations/bootstrap.js +2 -0
- package/packages/core/paper/paper-npm-bootstrap.js +2 -2
- package/packages/core/providers/github/attempt-index.js +60 -0
- package/packages/core/providers/github/attempt-journal.js +154 -0
- package/packages/core/providers/github/discussions/materials.js +35 -11
- package/packages/core/providers/github/discussions/transport.js +16 -5
- package/packages/core/providers/github/pipeline-checkout.js +49 -0
- package/packages/core/providers/github/pipeline-entry-runs.js +210 -0
- package/packages/core/providers/github/pipeline-events.js +131 -0
- package/packages/core/providers/github/pipeline-integration.js +95 -0
- package/packages/core/providers/github/pipeline-policy.js +240 -0
- package/packages/core/providers/github/pipeline-product-payload.js +50 -0
- package/packages/core/providers/github/pipeline-product-release.js +198 -0
- package/packages/core/providers/github/pipeline-publication-artifacts.js +153 -0
- package/packages/core/providers/github/pipeline-release-evidence.js +30 -0
- package/packages/core/providers/github/pipeline-run-entry.js +86 -0
- package/packages/core/providers/github/pipeline-runs.js +132 -0
- package/packages/core/providers/github/pipeline-source.js +195 -0
- package/packages/core/providers/github/pipeline-stable-baseline.js +86 -0
- package/packages/core/providers/github/pipeline-stable-source.js +372 -0
- package/packages/core/providers/github/pipeline-version-artifacts.js +91 -0
- package/packages/core/providers/github/pipeline-version-readback.js +117 -0
- package/packages/core/providers/github/pipeline-version.js +199 -0
- package/packages/core/providers/github/pipeline-worker.js +108 -0
- package/packages/core/providers/github/release-evidence-assets.js +97 -0
- package/packages/core/publication/candidate/registry-hydration.js +2 -2
- package/packages/core/publication/npm/pack-preview.js +2 -2
- package/packages/core/publication/npm/pack-result.js +31 -0
- package/packages/core/publication/npm/package.js +3 -6
- package/packages/core/publication/npm/pipeline-channel.js +36 -0
- package/packages/core/publication/npm/pipeline-provider.js +137 -0
- package/packages/core/publication/npm/registry.js +12 -9
- package/packages/core/publication/pipeline/actions.js +116 -0
- package/packages/core/publication/pipeline/apply.js +189 -0
- package/packages/core/publication/pipeline/build-segments.js +107 -0
- package/packages/core/publication/pipeline/capsules.js +92 -0
- package/packages/core/publication/pipeline/context.js +39 -0
- package/packages/core/publication/pipeline/development-anchor.js +91 -0
- package/packages/core/publication/pipeline/development-current.js +63 -0
- package/packages/core/publication/pipeline/development-pr.js +112 -0
- package/packages/core/publication/pipeline/development-proof.js +76 -0
- package/packages/core/publication/pipeline/development-transition.js +112 -0
- package/packages/core/publication/pipeline/distribution.js +130 -0
- package/packages/core/publication/pipeline/documents.js +192 -0
- package/packages/core/publication/pipeline/effects.js +192 -0
- package/packages/core/publication/pipeline/files.js +66 -0
- package/packages/core/publication/pipeline/imported-materials.js +32 -0
- package/packages/core/publication/pipeline/journal.js +122 -0
- package/packages/core/publication/pipeline/next-development.js +117 -0
- package/packages/core/publication/pipeline/pack.js +180 -0
- package/packages/core/publication/pipeline/package-policy.js +22 -0
- package/packages/core/publication/pipeline/plan.js +136 -0
- package/packages/core/publication/pipeline/prepare.js +139 -0
- package/packages/core/publication/pipeline/qualification.js +175 -0
- package/packages/core/publication/pipeline/qualify.js +104 -0
- package/packages/core/publication/pipeline/recovery-admission.js +122 -0
- package/packages/core/publication/pipeline/recovery-build-download.js +80 -0
- package/packages/core/publication/pipeline/recovery-build-plan.js +122 -0
- package/packages/core/publication/pipeline/recovery-build-readback.js +68 -0
- package/packages/core/publication/pipeline/recovery-capsules.js +54 -0
- package/packages/core/publication/pipeline/recovery-import.js +80 -0
- package/packages/core/publication/pipeline/recovery-inspection.js +218 -0
- package/packages/core/publication/pipeline/recovery-materials.js +104 -0
- package/packages/core/publication/pipeline/recovery-plan.js +46 -0
- package/packages/core/publication/pipeline/recovery-prepare.js +73 -0
- package/packages/core/publication/pipeline/recovery-qualification.js +128 -0
- package/packages/core/publication/pipeline/recovery-readback.js +56 -0
- package/packages/core/publication/pipeline/recovery-signing.js +58 -0
- package/packages/core/publication/pipeline/sealed-products.js +79 -0
- package/packages/core/publication/pipeline/settle.js +42 -0
- package/packages/core/publication/pipeline/signing.js +140 -0
- package/packages/core/publication/pipeline/source-plan.js +83 -0
- package/packages/core/publication/pipeline/stable-entry.js +219 -0
- package/packages/core/publication/pipeline/stable-products.js +317 -0
- package/packages/core/publication/pipeline/stable-wait.js +170 -0
- package/packages/core/publication/pipeline/stable.js +82 -0
- package/packages/core/publication/pipeline/version-actions.js +93 -0
- package/packages/core/publication/pipeline/version-build.js +130 -0
- package/packages/core/publication/pipeline/version-context.js +143 -0
- package/packages/core/publication/pipeline/version-material.js +36 -0
- package/packages/core/publication/pipeline/version-preparation.js +69 -0
- package/packages/core/publication/pipeline/version-regeneration.js +162 -0
- package/packages/core/publication/pipeline/version-source-guard.js +69 -0
- package/packages/core/publication/pipeline/version.js +81 -0
- package/packages/core/publication/pipeline/worker.js +72 -0
- package/packages/core/publication/publication-reproducibility.js +2 -2
- package/packages/core/release/discussion/binary.js +11 -0
- package/packages/core/release/discussion/checkpoints.js +45 -4
- package/packages/core/release/discussion/envelope.js +1 -0
- package/packages/core/release/discussion/evidence.js +51 -0
- package/packages/core/release/discussion/presentation.js +92 -0
- package/packages/core/release/discussion/publication.js +3 -1
- package/packages/core/release/discussion/qualification.js +1 -0
- package/packages/core/release/discussion/reader.js +9 -0
- package/packages/core/release/discussion/session.js +2 -0
- package/packages/core/release/discussion/store.js +28 -31
- package/packages/core/release/discussion/threads.js +83 -0
- package/packages/core/release/next-development-transition.js +15 -15
- package/packages/core/release/promote-candidate/product-provider-adapters.js +4 -3
- package/packages/core/release/promote-ref/internal/npm-existing-evidence.js +2 -1
- package/packages/core/release/promote-ref/internal/publish-command.js +16 -5
- package/packages/core/release/stable-release-gate.js +11 -0
- package/packages/core/runtime/buildchain-domain.wasm +0 -0
- package/packages/core/runtime/domain-wasm-artifact.js +2 -2
- package/packages/core/runtime/entry/actions.js +27 -25
- package/packages/core/runtime/entry/attempt.js +25 -0
- package/packages/core/runtime/entry/selection.js +14 -0
- package/packages/core/runtime/entry/source.js +62 -0
- package/packages/core/workflow/attempt/identity.js +170 -0
- package/packages/core/workflow/attempt/journal.js +89 -0
- package/packages/core/workflow/attempt/materials.js +72 -0
- package/packages/core/workflow/attempt/reader-entry.js +12 -0
- package/packages/core/workflow/attempt/reader.js +149 -0
- package/packages/core/workflow/attempt/records.js +153 -0
- package/packages/core/workflow/attempt/store.js +75 -0
- package/packages/core/workflow/commands/pipeline-build.mjs +23 -0
- package/packages/core/workflow/pipeline/action-output.js +11 -0
- package/packages/core/workflow/pipeline/actions.js +52 -0
- package/packages/core/workflow/pipeline/build-control.js +140 -0
- package/packages/core/workflow/pipeline/build-evidence.js +210 -0
- package/packages/core/workflow/pipeline/build-qualification.js +145 -0
- package/packages/core/workflow/pipeline/build-result.js +78 -0
- package/packages/core/workflow/pipeline/build.js +142 -0
- package/packages/core/workflow/pipeline/cancellation.js +169 -0
- package/packages/core/workflow/pipeline/channel-control.js +157 -0
- package/packages/core/workflow/pipeline/channel-source.js +53 -0
- package/packages/core/workflow/pipeline/controller.js +141 -0
- package/packages/core/workflow/pipeline/delivery-control.js +249 -0
- package/packages/core/workflow/pipeline/delivery-observation.js +124 -0
- package/packages/core/workflow/pipeline/delivery-request.js +198 -0
- package/packages/core/workflow/pipeline/events.js +84 -0
- package/packages/core/workflow/pipeline/fence.js +42 -0
- package/packages/core/workflow/pipeline/group-control.js +59 -0
- package/packages/core/workflow/pipeline/guard-build.js +74 -0
- package/packages/core/workflow/pipeline/guard.js +158 -0
- package/packages/core/workflow/pipeline/host.js +144 -0
- package/packages/core/workflow/pipeline/integration-status.js +113 -0
- package/packages/core/workflow/pipeline/materials.js +58 -0
- package/packages/core/workflow/pipeline/notifications.js +36 -0
- package/packages/core/workflow/pipeline/parent-notification.js +27 -0
- package/packages/core/workflow/pipeline/platforms.js +21 -0
- package/packages/core/workflow/pipeline/progress.js +108 -0
- package/packages/core/workflow/pipeline/projection.js +20 -0
- package/packages/core/workflow/pipeline/reconcile.js +194 -0
- package/packages/core/workflow/pipeline/record-action.js +27 -0
- package/packages/core/workflow/pipeline/recorder-status.js +69 -0
- package/packages/core/workflow/pipeline/recovery-action.js +30 -0
- package/packages/core/workflow/pipeline/recovery-admission.js +122 -0
- package/packages/core/workflow/pipeline/recovery-build-control.js +95 -0
- package/packages/core/workflow/pipeline/recovery-build-evidence.js +71 -0
- package/packages/core/workflow/pipeline/recovery-build.js +121 -0
- package/packages/core/workflow/pipeline/recovery-controller.js +91 -0
- package/packages/core/workflow/pipeline/recovery-integration.js +79 -0
- package/packages/core/workflow/pipeline/recovery-merge-proof.js +90 -0
- package/packages/core/workflow/pipeline/recovery-ownership-settlement.js +150 -0
- package/packages/core/workflow/pipeline/recovery-ownership.js +91 -0
- package/packages/core/workflow/pipeline/recovery-plan.js +126 -0
- package/packages/core/workflow/pipeline/recovery-runtime.js +68 -0
- package/packages/core/workflow/pipeline/recovery-session.js +129 -0
- package/packages/core/workflow/pipeline/recovery-transition.js +135 -0
- package/packages/core/workflow/pipeline/recovery-unrecorded-build.js +74 -0
- package/packages/core/workflow/pipeline/runtime-source.js +111 -0
- package/packages/core/workflow/pipeline/selection.js +111 -0
- package/packages/core/workflow/pipeline/session.js +72 -0
- package/packages/core/workflow/pipeline/settlement.js +137 -0
- package/packages/core/workflow/pipeline/wake.js +38 -0
- package/packages/core/workflow/pipeline/web-status.js +108 -0
- package/packages/core/workflow/workflow-taxonomy.mjs +67 -47
- package/scripts/build-release-discussion-reader.mjs +11 -7
- package/scripts/check-inventory.mjs +7 -70
- package/scripts/check-pipeline-publication-topology.mjs +50 -0
- package/scripts/check-public-dogfood-contract.mjs +38 -51
- package/scripts/check-release-topology.mjs +15 -8
- package/scripts/check-self-consumer-contract.mjs +133 -0
- package/scripts/check-universal-workflow-bootstrap.mjs +4 -6
- package/scripts/generate-minimal-consumer-contract.mjs +155 -0
- package/scripts/generate-site-bundle.mjs +1 -1
- package/scripts/inventory/binary.mjs +9 -19
- package/scripts/inventory/promotion.mjs +2 -13
- package/scripts/prepare-product-toolchain.mjs +10 -0
- package/scripts/verify-golden-path.mjs +5 -1
- package/scripts/verify-product-platform.mjs +65 -0
- package/scripts/verify-standalone-product.mjs +42 -0
- package/templates/minimal-consumer/binary/.buildchain/buildchain.toml +45 -0
- package/templates/minimal-consumer/binary/.github/workflows/buildchain-recover.yml +30 -0
- package/templates/minimal-consumer/binary/.github/workflows/buildchain.yml +28 -0
- package/templates/minimal-consumer/binary/package.json +6 -0
- package/templates/minimal-consumer/binary/src/build.mjs +5 -0
- package/templates/minimal-consumer/binary/src/hello.c +2 -0
- package/templates/minimal-consumer/binary/src/verify.mjs +3 -0
- package/templates/minimal-consumer/npm/.buildchain/buildchain.toml +46 -0
- package/templates/minimal-consumer/npm/.github/workflows/buildchain-recover.yml +30 -0
- package/templates/minimal-consumer/npm/.github/workflows/buildchain.yml +28 -0
- package/templates/minimal-consumer/npm/package.json +6 -0
- package/templates/minimal-consumer/npm/src/build.mjs +5 -0
- package/templates/minimal-consumer/npm/src/verify.mjs +3 -0
- package/templates/minimal-consumer/paper/.buildchain/buildchain.toml +45 -0
- package/templates/minimal-consumer/paper/.github/workflows/buildchain-recover.yml +30 -0
- package/templates/minimal-consumer/paper/.github/workflows/buildchain.yml +28 -0
- package/templates/minimal-consumer/paper/package.json +6 -0
- package/templates/minimal-consumer/paper/src/build.mjs +12 -0
- package/templates/minimal-consumer/paper/src/verify.mjs +3 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { checkSelfConsumerContract } from "./check-self-consumer-contract.mjs";
|
|
1
2
|
import { assertBinaryInventory } from "./inventory/binary.mjs";
|
|
2
3
|
import YAML from "yaml";
|
|
3
4
|
import { actionInventory } from "../packages/core/contracts/action-inventory.js";
|
|
@@ -145,41 +146,29 @@ const requiredPaths = [
|
|
|
145
146
|
".buildchain/alpha-contract-lock.json",
|
|
146
147
|
".buildchain/release-impact.json",
|
|
147
148
|
".github/actionlint.yaml",
|
|
148
|
-
".github/workflows/self-ops-runner-smoke.yml",
|
|
149
|
-
".github/workflows/self-release-promote.yml",
|
|
150
|
-
".github/workflows/self-release-line-open.yml",
|
|
151
149
|
".github/workflows/public-ops-release-governance.yml",
|
|
152
150
|
".github/workflows/public-ops-dev-auto-merge.yml",
|
|
153
|
-
".github/workflows/self-ops-dev-delivery.yml",
|
|
154
151
|
".github/workflows/public-ops-patrol.yml",
|
|
155
152
|
".github/workflows/public-ops-patrol-daily.yml",
|
|
156
153
|
".github/workflows/public-ops-patrol-weekly.yml",
|
|
157
154
|
".github/workflows/public-ops-patrol-monthly.yml",
|
|
158
155
|
".github/workflows/public-ops-observed-evidence.yml",
|
|
159
|
-
".github/workflows/self-ops-patrol-daily.yml",
|
|
160
|
-
".github/workflows/self-ops-patrol-weekly.yml",
|
|
161
|
-
".github/workflows/self-ops-patrol-monthly.yml",
|
|
162
|
-
".github/workflows/self-build-alpha-dogfood.yml",
|
|
163
|
-
".github/workflows/self-build-stable-dogfood.yml",
|
|
164
156
|
".github/workflows/public-release-promote.yml",
|
|
165
157
|
".github/workflows/.release-promote.yml",
|
|
166
158
|
".github/workflows/public-release-propagation.yml",
|
|
167
|
-
".github/workflows/self-release-npm-dry-run.yml",
|
|
168
159
|
".github/workflows/public-release-paper.yml",
|
|
169
|
-
".github/workflows/self-build-binary-distribution.yml",
|
|
170
160
|
".github/workflows/.release-binary-assets.yml",
|
|
171
|
-
".github/workflows/self-release-binary-assets.yml",
|
|
172
|
-
".github/workflows/self-build-verify.yml",
|
|
173
161
|
".github/workflows/.build.yml",
|
|
174
162
|
".github/workflows/.build-gate-profile.yml",
|
|
175
163
|
".github/workflows/.build-demo-adapter.yml",
|
|
176
164
|
".github/workflows/public-build-demo.yml",
|
|
177
|
-
".github/workflows/self-build-demo-dogfood.yml",
|
|
178
165
|
".github/workflows/build.yml",
|
|
179
|
-
".github/workflows/self-build-fixture.yml",
|
|
180
166
|
"fixtures/libnode-shaped/buildchain.toml",
|
|
181
167
|
"fixtures/libnode-shaped/.github/workflows/build.yml",
|
|
182
|
-
"fixtures/libnode-shaped/package.json"
|
|
168
|
+
"fixtures/libnode-shaped/package.json",
|
|
169
|
+
".github/workflows/buildchain.yml",
|
|
170
|
+
".github/workflows/buildchain-recover.yml",
|
|
171
|
+
"scripts/check-self-consumer-contract.mjs",
|
|
183
172
|
];
|
|
184
173
|
|
|
185
174
|
for (const rel of requiredPaths) {
|
|
@@ -277,14 +266,7 @@ for (const channel of ["alpha-contract-lock.json", "contract-lock.json"]) {
|
|
|
277
266
|
if (lock.buildchain.ref !== ref)
|
|
278
267
|
throw new Error(`${channel}: invalid accepted runtime selector`);
|
|
279
268
|
}
|
|
280
|
-
|
|
281
|
-
const workflow = fs.readFileSync(path.join(root, `.github/workflows/self-build-${channel}-dogfood.yml`), "utf8");
|
|
282
|
-
if (!workflow.includes(`/.github/workflows/build.yml@${ref}`) || /steps:|buildchain-channel:|runner-preset:|working-directory:/u.test(workflow)) throw new Error(`${channel} self-dogfood must remain a thin public TOML build caller`);
|
|
283
|
-
if (!workflow.includes(`group: buildchain-${channel}-self-dogfood-`) || !workflow.includes("cancel-in-progress: false")) throw new Error(`${channel} self-dogfood must serialize its own runs`);
|
|
284
|
-
const expectedInputs = [];
|
|
285
|
-
const call = parseWorkflowCallJobs(workflow).find((job) => job.id === `${channel}-consumer`);
|
|
286
|
-
if (JSON.stringify(Object.keys(call.with || {})) !== JSON.stringify(expectedInputs)) throw new Error(`${channel} self-dogfood input contract drift`);
|
|
287
|
-
}
|
|
269
|
+
checkSelfConsumerContract(root);
|
|
288
270
|
const reusableBuildWorkflow = fs.readFileSync(
|
|
289
271
|
path.join(root, ".github/workflows/.build.yml"),
|
|
290
272
|
"utf8",
|
|
@@ -310,10 +292,6 @@ const channelPromotionWorkflow = fs.readFileSync(
|
|
|
310
292
|
path.join(root, ".github/workflows/public-release-promote.yml"),
|
|
311
293
|
"utf8",
|
|
312
294
|
);
|
|
313
|
-
const boundedAlphaRecoveryWorkflow = fs.readFileSync(
|
|
314
|
-
path.join(root, ".github/workflows/self-ops-promotion-recovery.yml"),
|
|
315
|
-
"utf8",
|
|
316
|
-
);
|
|
317
295
|
assertPromotionInventory(root);
|
|
318
296
|
for (const workflow of [channelBuildWorkflow, reusableBuildWorkflow]) {
|
|
319
297
|
const block = workflow.split(" inputs:\n")[1].split(" secrets:\n")[0];
|
|
@@ -957,11 +935,6 @@ for (const requiredSnippet of [
|
|
|
957
935
|
if (commonJsSourcePattern.test(standaloneBinaryScript)) {
|
|
958
936
|
throw new Error("scripts/build-standalone-binary.mjs must use ESM syntax");
|
|
959
937
|
}
|
|
960
|
-
const npmPublishWorkflow = fs.readFileSync(path.join(root, ".github/workflows/self-release-npm-dry-run.yml"), "utf8");
|
|
961
|
-
const buildchainRefPromotionWorkflow = fs.readFileSync(path.join(root, ".github/workflows/self-release-promote.yml"), "utf8");
|
|
962
|
-
const binaryDistributionWorkflow = fs.readFileSync(path.join(root, ".github/workflows/self-build-binary-distribution.yml"), "utf8");
|
|
963
|
-
const binaryReleaseAssetsWorkflow = fs.readFileSync(path.join(root, ".github/workflows/.release-binary-assets.yml"), "utf8");
|
|
964
|
-
const selfHostedRunnerSmokeWorkflow = fs.readFileSync(path.join(root, ".github/workflows/self-ops-runner-smoke.yml"), "utf8");
|
|
965
938
|
const npmDryRunScript = fs.readFileSync(path.join(root, "packages/core/publication/npm/preview.js"), "utf8").replace(/\s+/gu, " ");
|
|
966
939
|
const npmPublishTransactionScript = ["transaction", "environment"].map(name => fs.readFileSync(path.join(root, `packages/core/publication/npm/${name}.js`), "utf8")).join("\n");
|
|
967
940
|
const rootPackageJson = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
|
|
@@ -977,29 +950,6 @@ if (!["patch", "minor", "major"].includes(selfReleaseImpact.classification)) {
|
|
|
977
950
|
if (!Array.isArray(selfReleaseImpact.surfaceImpacts) || selfReleaseImpact.surfaceImpacts.length === 0) {
|
|
978
951
|
throw new Error("Buildchain self release impact requires a summary and surfaceImpacts[]");
|
|
979
952
|
}
|
|
980
|
-
for (const requiredSnippet of [
|
|
981
|
-
"runs-on: ubuntu-24.04",
|
|
982
|
-
"workflow_dispatch:",
|
|
983
|
-
"Dry-run npm publish",
|
|
984
|
-
]) {
|
|
985
|
-
if (!npmPublishWorkflow.includes(requiredSnippet)) {
|
|
986
|
-
throw new Error(`npm publish workflow missing required snippet: ${requiredSnippet}`);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
for (const forbiddenSnippet of [
|
|
990
|
-
"tags:",
|
|
991
|
-
"Publish exact release tag",
|
|
992
|
-
"npm publish --access public --tag",
|
|
993
|
-
]) {
|
|
994
|
-
if (npmPublishWorkflow.includes(forbiddenSnippet)) {
|
|
995
|
-
throw new Error(`npm publish dry-run workflow must not contain real publish snippet: ${forbiddenSnippet}`);
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
const selfPromotion = inspectWorkflowJob(".github/workflows/self-release-promote.yml", "classify-workflow-run", root);
|
|
999
|
-
if (![...selfPromotion.modules.values()].some(source => source.includes("selectFinalizedProductPublicationVersion")))
|
|
1000
|
-
throw new Error("self promotion must classify finalization from rooted product state");
|
|
1001
|
-
if (buildchainRefPromotionWorkflow.includes("workflow_run.display_title"))
|
|
1002
|
-
throw new Error("self promotion must not classify finalization from a display title");
|
|
1003
953
|
const workflowDir = path.join(root, ".github/workflows");
|
|
1004
954
|
for (const workflowFile of fs.readdirSync(workflowDir).filter((entry) => entry.endsWith(".yml"))) {
|
|
1005
955
|
const workflowPath = path.join(workflowDir, workflowFile);
|
|
@@ -1054,14 +1004,6 @@ for (const requiredSnippet of [
|
|
|
1054
1004
|
throw new Error(`promote-buildchain-ref index missing semver GitHub Release implementation: ${requiredSnippet}`);
|
|
1055
1005
|
}
|
|
1056
1006
|
}
|
|
1057
|
-
for (const forbiddenSnippet of [
|
|
1058
|
-
"run: node packages/core/release/commands/release-candidate-resolver.mjs",
|
|
1059
|
-
"uses: ./actions/release/promotion/ref",
|
|
1060
|
-
]) {
|
|
1061
|
-
if (buildchainRefPromotionWorkflow.includes(forbiddenSnippet)) {
|
|
1062
|
-
throw new Error(`buildchain ref promotion workflow must use the declarative wrapper, found manual snippet: ${forbiddenSnippet}`);
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
1007
|
for (const requiredSnippet of [
|
|
1066
1008
|
"distTag || (pkg.version.includes(\"-\") ? \"alpha\" : \"latest\")",
|
|
1067
1009
|
"\"publish\", \"--dry-run\", \"--access\", \"public\"",
|
|
@@ -1089,13 +1031,8 @@ for (const requiredSnippet of [
|
|
|
1089
1031
|
if (commonJsSourcePattern.test(npmPublishTransactionScript)) {
|
|
1090
1032
|
throw new Error("packages/core/publication/commands/npm-publish-transaction.mjs must use ESM syntax");
|
|
1091
1033
|
}
|
|
1092
|
-
if (/runs-on:\s*self-hosted/.test(npmPublishWorkflow)) {
|
|
1093
|
-
throw new Error("npm publish workflow must use GitHub-hosted runners for trusted publishing");
|
|
1094
|
-
}
|
|
1095
1034
|
assertBinaryInventory(root);
|
|
1096
|
-
|
|
1097
|
-
throw new Error("self-hosted smoke must identify its actual runner kind");
|
|
1098
|
-
}
|
|
1035
|
+
|
|
1099
1036
|
|
|
1100
1037
|
const inventory = JSON.parse(
|
|
1101
1038
|
fs.readFileSync(path.join(root, "tests/buildchain-inventory.json"), "utf8")
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { inspectWorkflowJob } from "./workflow-action-graph.mjs";
|
|
3
|
+
|
|
4
|
+
export function assertPipelinePublicationTopology(
|
|
5
|
+
ledger,
|
|
6
|
+
discoverReleaseTopology,
|
|
7
|
+
root,
|
|
8
|
+
) {
|
|
9
|
+
const pipeline = ledger.pipelinePublicationScope;
|
|
10
|
+
assert.deepEqual(pipeline.workflowPaths, [
|
|
11
|
+
".github/workflows/.release-pipeline-products.yml",
|
|
12
|
+
".github/workflows/public-ops-pipeline.yml",
|
|
13
|
+
".github/workflows/public-ops-recover.yml",
|
|
14
|
+
".github/workflows/.ops-pipeline-execute.yml",
|
|
15
|
+
".github/workflows/.release-pipeline-version.yml",
|
|
16
|
+
".github/workflows/buildchain.yml",
|
|
17
|
+
".github/workflows/buildchain-recover.yml",
|
|
18
|
+
]);
|
|
19
|
+
const pipelineTopology = discoverReleaseTopology(
|
|
20
|
+
pipeline.workflowPaths,
|
|
21
|
+
pipeline.workflowPaths,
|
|
22
|
+
);
|
|
23
|
+
assert.deepEqual(pipeline.observedTopology, pipelineTopology);
|
|
24
|
+
for (const [name, ceiling] of Object.entries(pipeline.maximumMetrics))
|
|
25
|
+
assert.ok(
|
|
26
|
+
pipelineTopology.metrics[name] <= ceiling,
|
|
27
|
+
`pipeline publication exceeds ${name}`,
|
|
28
|
+
);
|
|
29
|
+
for (const [job, module] of [
|
|
30
|
+
["qualify", "packages/core/publication/pipeline/qualify.js"],
|
|
31
|
+
["apply", "packages/core/publication/pipeline/apply.js"],
|
|
32
|
+
["settle", "packages/core/publication/pipeline/settle.js"],
|
|
33
|
+
])
|
|
34
|
+
assert.ok(
|
|
35
|
+
inspectWorkflowJob(pipeline.workflowPaths[0], job, root).modules.has(
|
|
36
|
+
module,
|
|
37
|
+
),
|
|
38
|
+
);
|
|
39
|
+
const version = ".github/workflows/.release-pipeline-version.yml";
|
|
40
|
+
assert.ok(
|
|
41
|
+
inspectWorkflowJob(version, "build", root).modules.has(
|
|
42
|
+
"packages/core/publication/pipeline/version-build.js",
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
assert.ok(
|
|
46
|
+
inspectWorkflowJob(version, "materialize", root).modules.has(
|
|
47
|
+
"packages/core/publication/pipeline/version-context.js",
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -4,6 +4,7 @@ import fs from "node:fs";
|
|
|
4
4
|
import YAML from "yaml";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { checkSelfConsumerContract } from "./check-self-consumer-contract.mjs";
|
|
7
8
|
|
|
8
9
|
const DEFAULT_ROOT = path.resolve(
|
|
9
10
|
path.dirname(fileURLToPath(import.meta.url)),
|
|
@@ -15,35 +16,6 @@ export const PUBLIC_DOGFOOD_ENTRY_REF = "v4";
|
|
|
15
16
|
const PRIVATE_CONSUMER = ["buildchain", "self", "dogfood"].join("-");
|
|
16
17
|
const PRIVATE_SHADOW = ["kungfu", "shadow"].join("-");
|
|
17
18
|
|
|
18
|
-
export function expectedPublicDogfoodWorkflow(validationRef) {
|
|
19
|
-
return `name: V4 Public Consumer Dogfood
|
|
20
|
-
|
|
21
|
-
on:
|
|
22
|
-
pull_request:
|
|
23
|
-
workflow_dispatch:
|
|
24
|
-
inputs:
|
|
25
|
-
runtime-ref:
|
|
26
|
-
description: Transient runtime selected by the public entry.
|
|
27
|
-
type: string
|
|
28
|
-
default: ""
|
|
29
|
-
|
|
30
|
-
permissions:
|
|
31
|
-
contents: read
|
|
32
|
-
|
|
33
|
-
jobs:
|
|
34
|
-
dogfood:
|
|
35
|
-
uses: kungfu-systems/buildchain/.github/workflows/public-build-stage-capsule-canary.yml@${validationRef}
|
|
36
|
-
with:
|
|
37
|
-
runtime-ref: \${{ inputs.runtime-ref }}
|
|
38
|
-
consumer: buildchain
|
|
39
|
-
node-version: "24"
|
|
40
|
-
go-version: "1.25.x"
|
|
41
|
-
install-artifact-path: node_modules/.modules.yaml
|
|
42
|
-
build-artifact-path: actions/build/lifecycle/run/dist/index.js
|
|
43
|
-
verify-artifact-path: dist/site
|
|
44
|
-
`;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
19
|
function fail(message) {
|
|
48
20
|
throw new Error(`v4-public-dogfood-contract: ${message}`);
|
|
49
21
|
}
|
|
@@ -238,17 +210,22 @@ function assertWorkflowInventory(root) {
|
|
|
238
210
|
}
|
|
239
211
|
|
|
240
212
|
function assertProtectedVerify(root) {
|
|
241
|
-
|
|
242
|
-
const
|
|
243
|
-
const nodePath = "actions/build/verification/repository/action.yml";
|
|
213
|
+
checkSelfConsumerContract(root);
|
|
214
|
+
const verify = read(root, "scripts/verify-product-platform.mjs");
|
|
244
215
|
if (
|
|
245
|
-
!
|
|
246
|
-
|
|
247
|
-
|
|
216
|
+
!verify.includes("verifyStageCapsuleCheckpoints({") ||
|
|
217
|
+
!verify.includes('"--network=none"') ||
|
|
218
|
+
!verify.includes(
|
|
219
|
+
"sha256:11f0ba64267ce88174a4f73a9bf833ff4e9c59cd16ec3d08a6432a06c2be6fb1",
|
|
220
|
+
) ||
|
|
221
|
+
!verify.includes("tests/build-orchestration.test.mjs") ||
|
|
222
|
+
!verify.includes("tests/build-artifact-pipeline.test.mjs") ||
|
|
223
|
+
!verify.includes("tests/dev-delivery-minimal-request.test.mjs")
|
|
248
224
|
)
|
|
249
225
|
fail(
|
|
250
|
-
"
|
|
226
|
+
"Product verification must retain checkpoint recovery and the isolated container backbone lane",
|
|
251
227
|
);
|
|
228
|
+
const nodePath = "actions/build/verification/repository/action.yml";
|
|
252
229
|
const implementation = read(root, nodePath);
|
|
253
230
|
const steps = YAML.parse(implementation).runs.steps;
|
|
254
231
|
const qualify = steps.find((step) => step.id === "source-verification");
|
|
@@ -283,12 +260,13 @@ function assertArchitecture(root) {
|
|
|
283
260
|
const validationRef = dogfood?.validationRef;
|
|
284
261
|
if (validationRef !== PUBLIC_DOGFOOD_ENTRY_REF)
|
|
285
262
|
fail("architecture validationRef must use the public v4 entry");
|
|
286
|
-
const caller = read(root, CALLER_PATH);
|
|
287
263
|
if (
|
|
288
|
-
|
|
289
|
-
|
|
264
|
+
dogfood?.active !== false ||
|
|
265
|
+
dogfood.supersededBy !== ".github/workflows/buildchain.yml"
|
|
290
266
|
)
|
|
291
|
-
fail(
|
|
267
|
+
fail(
|
|
268
|
+
"Historical Canary caller must be explicitly superseded by the minimal pipeline",
|
|
269
|
+
);
|
|
292
270
|
if (JSON.stringify(architecture.campaign?.consumers) !== '["buildchain"]')
|
|
293
271
|
fail(
|
|
294
272
|
"architecture must qualify only the public Buildchain consumer identity",
|
|
@@ -335,17 +313,25 @@ function assertArchitecture(root) {
|
|
|
335
313
|
}
|
|
336
314
|
|
|
337
315
|
function assertConsumerLifecycle(root) {
|
|
338
|
-
const
|
|
339
|
-
for (const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
if (
|
|
316
|
+
const { plan } = checkSelfConsumerContract(root);
|
|
317
|
+
for (const platform of ["linux-x64", "macos-arm64", "windows-x64"]) {
|
|
318
|
+
const product = plan.products.find(
|
|
319
|
+
(product) =>
|
|
320
|
+
product.platforms.includes(platform) &&
|
|
321
|
+
product.verify.includes("corepack pnpm@11.7.0 run check"),
|
|
322
|
+
);
|
|
323
|
+
if (
|
|
324
|
+
!product?.install.includes("corepack enable pnpm") ||
|
|
325
|
+
!product.install.includes(
|
|
326
|
+
"corepack pnpm@11.7.0 install --frozen-lockfile",
|
|
327
|
+
) ||
|
|
328
|
+
!product.build.includes("corepack pnpm@11.7.0 run build") ||
|
|
329
|
+
!product.build.includes("corepack pnpm@11.7.0 run generate:site")
|
|
330
|
+
)
|
|
346
331
|
fail(
|
|
347
|
-
|
|
332
|
+
`${platform}: tracked consumer lifecycle is missing its pinned install or full generated build`,
|
|
348
333
|
);
|
|
334
|
+
}
|
|
349
335
|
const attributes = read(root, ".gitattributes");
|
|
350
336
|
if (!attributes.split("\n").includes("* text=auto eol=lf"))
|
|
351
337
|
fail("consumer checkout is missing the cross-platform LF contract");
|
|
@@ -394,8 +380,9 @@ export function checkPublicDogfoodContract(root = DEFAULT_ROOT) {
|
|
|
394
380
|
return {
|
|
395
381
|
schema: "buildchain-v4-public-dogfood-contract-check/v1",
|
|
396
382
|
ok: true,
|
|
397
|
-
caller:
|
|
398
|
-
reusable:
|
|
383
|
+
caller: ".github/workflows/buildchain.yml",
|
|
384
|
+
reusable: ".github/workflows/public-ops-pipeline.yml",
|
|
385
|
+
historicalCanary: REUSABLE_PATH,
|
|
399
386
|
validationRef,
|
|
400
387
|
productionAuthority: "v4-native",
|
|
401
388
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import assert from "node:assert/strict";
|
|
4
|
+
import { assertPipelinePublicationTopology } from "./check-pipeline-publication-topology.mjs";
|
|
4
5
|
import { inspectWorkflowJob, readWorkflow } from "./workflow-action-graph.mjs";
|
|
5
6
|
import crypto from "node:crypto";
|
|
6
7
|
import fs from "node:fs";
|
|
@@ -28,6 +29,8 @@ const PRIVILEGED_ENTRYPOINTS = [
|
|
|
28
29
|
"packages/core/release/next-development/actions.js",
|
|
29
30
|
"packages/core/publication/oci/preview-actions.js",
|
|
30
31
|
"packages/core/publication/settlement/actions.js",
|
|
32
|
+
"packages/core/publication/pipeline/actions.js",
|
|
33
|
+
"packages/core/publication/pipeline/version-actions.js",
|
|
31
34
|
];
|
|
32
35
|
|
|
33
36
|
export function localModuleSpecifiers(source) {
|
|
@@ -150,7 +153,9 @@ export function discoverReleaseAuthorityClosure() {
|
|
|
150
153
|
[".js", ".mjs", ".cjs"],
|
|
151
154
|
/(?:release-tail-provider-(?:adapters|plane)|create(?:GitHubReleaseAssets|SignedStaticChannel|SiteReleaseActivation|ReleasedEvidence)Adapter)/u,
|
|
152
155
|
);
|
|
153
|
-
const runtimeSelectors = productionFiles("packages/core/runtime/entry", [
|
|
156
|
+
const runtimeSelectors = productionFiles("packages/core/runtime/entry", [
|
|
157
|
+
".js",
|
|
158
|
+
]).sort();
|
|
154
159
|
const terminalProjections = matchingProductionFiles(
|
|
155
160
|
[".github/workflows", "actions", "packages/core", "scripts"],
|
|
156
161
|
[".yml", ".yaml", ".js", ".mjs", ".cjs"],
|
|
@@ -181,7 +186,10 @@ export function discoverReleaseAuthorityClosure() {
|
|
|
181
186
|
]),
|
|
182
187
|
].sort(),
|
|
183
188
|
runtimeSelectors,
|
|
184
|
-
runtimeEngines: [
|
|
189
|
+
runtimeEngines: [
|
|
190
|
+
"packages/core/release/promote-candidate/action.js",
|
|
191
|
+
"packages/core/publication/pipeline/apply.js",
|
|
192
|
+
],
|
|
185
193
|
terminalProjections,
|
|
186
194
|
privilegedExecutableClosure: {
|
|
187
195
|
entrypoints: PRIVILEGED_ENTRYPOINTS,
|
|
@@ -377,7 +385,7 @@ export function findUnknownReleaseTopology(
|
|
|
377
385
|
.filter((relative) => {
|
|
378
386
|
const source = readWorkflow(relative);
|
|
379
387
|
const usesReleaseAuthority = parseYamlUses(source).some(({ value }) =>
|
|
380
|
-
/(?:release-candidate-promote|promote-buildchain-ref|release-tail|actions\/release\/promotion\/(?:candidate|ref)|\.github\/workflows\/(?:public-release-promote|\.release-promote))/u.test(
|
|
388
|
+
/(?:release-candidate-promote|promote-buildchain-ref|release-tail|actions\/release\/promotion\/(?:candidate|ref)|\.github\/workflows\/(?:public-release-promote|\.release-promote|public-ops-pipeline|public-ops-recover|\.release-pipeline-products))/u.test(
|
|
381
389
|
value,
|
|
382
390
|
),
|
|
383
391
|
);
|
|
@@ -456,14 +464,12 @@ function assertAuthorityClosure(ledger) {
|
|
|
456
464
|
);
|
|
457
465
|
assert.deepEqual(closure.runtimeEngines, [
|
|
458
466
|
"packages/core/release/promote-candidate/action.js",
|
|
467
|
+
"packages/core/publication/pipeline/apply.js",
|
|
459
468
|
]);
|
|
460
|
-
assert.equal(
|
|
461
|
-
closure.freshEntry,
|
|
462
|
-
".github/workflows/public-release-promote.yml",
|
|
463
|
-
);
|
|
469
|
+
assert.equal(closure.freshEntry, ".github/workflows/public-ops-pipeline.yml");
|
|
464
470
|
assert.equal(
|
|
465
471
|
closure.recoveryEntry,
|
|
466
|
-
".github/workflows/
|
|
472
|
+
".github/workflows/public-ops-recover.yml",
|
|
467
473
|
);
|
|
468
474
|
const engineSurface = [
|
|
469
475
|
".github/workflows/.release-promote.yml",
|
|
@@ -523,6 +529,7 @@ export function checkReleaseTopology() {
|
|
|
523
529
|
assert.equal(ledger.contract, "kungfu-buildchain-v4-release-topology/v1");
|
|
524
530
|
assertClosedWorld(ledger.closedWorld.workflowPaths);
|
|
525
531
|
assertAuthorityClosure(ledger);
|
|
532
|
+
assertPipelinePublicationTopology(ledger, discoverReleaseTopology, root);
|
|
526
533
|
const preview = ledger.postPublicationScope;
|
|
527
534
|
assert.deepEqual(preview.workflowPaths, [
|
|
528
535
|
".github/workflows/public-release-oci-compose-preview.yml",
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { parse as yaml } from "yaml";
|
|
5
|
+
import { compileConsumerPlan } from "../packages/core/consumer/contract/plan.js";
|
|
6
|
+
import { consumerWorkflows } from "../packages/core/consumer/contract/entries.js";
|
|
7
|
+
import { workflowPath } from "../packages/core/workflow/workflow-taxonomy.mjs";
|
|
8
|
+
|
|
9
|
+
export const SELF_ENTRY_CHANNEL = "v4-alpha";
|
|
10
|
+
export const SELF_CONFIG_PATH = ".buildchain/minimal-consumer.toml";
|
|
11
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
12
|
+
const PLATFORMS = ["linux-x64", "macos-arm64", "windows-x64"];
|
|
13
|
+
|
|
14
|
+
// Repository policy checks the consumer-facing wiring. Product implementation
|
|
15
|
+
// libraries are separately registered and may not own repository event triggers.
|
|
16
|
+
// This policy supplies no repository identity exception to runtime admission.
|
|
17
|
+
export function checkSelfConsumerContract(root = ROOT) {
|
|
18
|
+
const read = (file) => fs.readFileSync(path.join(root, file), "utf8");
|
|
19
|
+
const fail = (message) => {
|
|
20
|
+
throw new Error(`self-consumer-contract: ${message}`);
|
|
21
|
+
};
|
|
22
|
+
const plan = compileConsumerPlan(read(SELF_CONFIG_PATH));
|
|
23
|
+
if (read(SELF_CONFIG_PATH) !== read(".buildchain/buildchain.toml"))
|
|
24
|
+
fail("transition config must match the canonical product plan");
|
|
25
|
+
const callers = consumerWorkflows(SELF_ENTRY_CHANNEL, SELF_CONFIG_PATH);
|
|
26
|
+
for (const [file, bytes] of Object.entries(callers))
|
|
27
|
+
if (read(file) !== bytes) fail(`${file}: generated caller drift`);
|
|
28
|
+
const taxonomy = JSON.parse(read("architecture/workflow-taxonomy.json"));
|
|
29
|
+
const registered = new Set(taxonomy.entries.map(workflowPath));
|
|
30
|
+
const observed = fs
|
|
31
|
+
.readdirSync(path.join(root, ".github/workflows"))
|
|
32
|
+
.filter((file) => /\.ya?ml$/u.test(file))
|
|
33
|
+
.map((file) => `.github/workflows/${file}`);
|
|
34
|
+
if (
|
|
35
|
+
observed.length !== registered.size ||
|
|
36
|
+
observed.some((file) => !registered.has(file))
|
|
37
|
+
)
|
|
38
|
+
fail("workflow inventory is not closed");
|
|
39
|
+
const self = taxonomy.entries
|
|
40
|
+
.filter((entry) => entry.role === "self")
|
|
41
|
+
.map(workflowPath)
|
|
42
|
+
.sort();
|
|
43
|
+
if (JSON.stringify(self) !== JSON.stringify(Object.keys(callers).sort()))
|
|
44
|
+
fail("self automation must contain exactly the generated caller pair");
|
|
45
|
+
for (const entry of taxonomy.entries.filter(
|
|
46
|
+
(entry) => entry.role !== "self",
|
|
47
|
+
)) {
|
|
48
|
+
const file = workflowPath(entry);
|
|
49
|
+
const document = yaml(read(file));
|
|
50
|
+
if (
|
|
51
|
+
Object.keys(document.on || {}).some(
|
|
52
|
+
(event) => !["workflow_call", "workflow_dispatch"].includes(event),
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
fail(`${file}: product library owns a repository event`);
|
|
56
|
+
}
|
|
57
|
+
for (const prefix of ["feature", "fix", "chore", "docs", "ci", "refactor"])
|
|
58
|
+
if (
|
|
59
|
+
!plan.channels.some(
|
|
60
|
+
(route) =>
|
|
61
|
+
route.from === `${prefix}/*` &&
|
|
62
|
+
route.to === "dev/v4/v4.1" &&
|
|
63
|
+
route.operation === "develop",
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
fail(`missing protected development route for ${prefix}`);
|
|
67
|
+
for (const platform of PLATFORMS) {
|
|
68
|
+
const verified = plan.products.some(
|
|
69
|
+
(product) =>
|
|
70
|
+
product.platforms.includes(platform) &&
|
|
71
|
+
product.verify.includes("corepack pnpm@11.7.0 run check") &&
|
|
72
|
+
product.verify.includes("node scripts/verify-product-platform.mjs"),
|
|
73
|
+
);
|
|
74
|
+
if (!verified)
|
|
75
|
+
fail(
|
|
76
|
+
`${platform}: full check and platform recovery verification are required`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
if (
|
|
80
|
+
!plan.products.some(
|
|
81
|
+
(product) =>
|
|
82
|
+
product.type === "npm" &&
|
|
83
|
+
product.targets.some((target) => target.provider === "npm"),
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
fail("npm publication is missing");
|
|
87
|
+
for (const platform of PLATFORMS)
|
|
88
|
+
if (
|
|
89
|
+
!plan.products.some(
|
|
90
|
+
(product) =>
|
|
91
|
+
product.type === "binary" &&
|
|
92
|
+
product.platforms.includes(platform) &&
|
|
93
|
+
product.targets.some(
|
|
94
|
+
(target) => target.provider === "github-release",
|
|
95
|
+
),
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
fail(`${platform}: binary release asset is missing`);
|
|
99
|
+
const commands = plan.products.flatMap((product) => [
|
|
100
|
+
...(product.install || []),
|
|
101
|
+
...product.build,
|
|
102
|
+
...product.verify,
|
|
103
|
+
]);
|
|
104
|
+
if (
|
|
105
|
+
commands.some((command) =>
|
|
106
|
+
/\b(?:npm publish|gh release|buildchain (?:dev warrant|release|promote|recover|publish))\b|request-json|fencingToken/u.test(
|
|
107
|
+
command,
|
|
108
|
+
),
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
fail("product lifecycle contains consumer-owned publication orchestration");
|
|
112
|
+
if (!read(".gitattributes").split("\n").includes("* text=auto eol=lf"))
|
|
113
|
+
fail("cross-platform LF checkout contract is missing");
|
|
114
|
+
return {
|
|
115
|
+
ok: true,
|
|
116
|
+
channel: SELF_ENTRY_CHANNEL,
|
|
117
|
+
callers: Object.keys(callers),
|
|
118
|
+
plan,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (
|
|
123
|
+
process.argv[1] &&
|
|
124
|
+
path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)
|
|
125
|
+
) {
|
|
126
|
+
const { plan, ...result } = checkSelfConsumerContract();
|
|
127
|
+
console.log(
|
|
128
|
+
JSON.stringify({
|
|
129
|
+
...result,
|
|
130
|
+
products: plan.products.map((product) => product.id),
|
|
131
|
+
}),
|
|
132
|
+
);
|
|
133
|
+
}
|
|
@@ -43,10 +43,8 @@ assert.doesNotMatch(read(contract.bootstrap.publicWorkflow), /admission-policy-j
|
|
|
43
43
|
const template = parse(contract.bootstrap.consumerTemplate);
|
|
44
44
|
assert.equal(template.jobs.bootstrap.uses, "kungfu-systems/buildchain/.github/workflows/public-ops-bootstrap.yml@v4");
|
|
45
45
|
assert.equal(template.jobs.bootstrap.with["runtime-ref"], "${{ inputs.runtime-ref }}");
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
assert.equal(job.with["runtime-ref"], mode === "primary" ? "${{ inputs.runtime-ref }}" : "${{ inputs.recovery-runtime-ref }}");
|
|
51
|
-
}
|
|
46
|
+
assert.equal(contract.bootstrap.selfDogfoodActive, false);
|
|
47
|
+
assert.equal(fs.existsSync(path.join(root, contract.bootstrap.selfDogfoodWorkflow)), false,
|
|
48
|
+
"The retired bootstrap self controller must not coexist with the minimal pipeline");
|
|
49
|
+
assert.equal(contract.bootstrap.selfDogfoodSupersededBy, ".github/workflows/buildchain.yml");
|
|
52
50
|
console.log(JSON.stringify({ ok: true, reusableWorkflowCount: reusable.length, runtimeAcquisitionOwners: 1 }));
|