@intentius/chant 0.124.26 → 0.124.28
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/README.md +1 -1
- package/dist/__golden__/wave-loop/fan-out-gated.json +8 -0
- package/dist/__golden__/wave-loop/fan-out-no-members.json +4 -0
- package/dist/__golden__/wave-loop/fan-out-only.json +6 -0
- package/dist/__golden__/wave-loop/op-by-apply-hold.json +2 -0
- package/dist/__golden__/wave-loop/op-cost-member.json +3 -0
- package/dist/__golden__/wave-loop/op-held-on-before-apply.json +1 -0
- package/dist/__golden__/wave-loop/op-held-on.json +2 -0
- package/dist/__golden__/wave-loop/op-hooks-held.json +2 -0
- package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +2 -0
- package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +3 -0
- package/dist/__golden__/wave-loop/op-hooks-share.json +3 -0
- package/dist/__golden__/wave-loop/op-per-run.json +7 -0
- package/dist/__golden__/wave-loop/op-pr-review.json +7 -0
- package/dist/__golden__/wave-loop/op-sealed.json +3 -0
- package/dist/__golden__/wave-loop/op-spend.json +3 -0
- package/dist/__golden__/wave-loop/op-wave-commands.json +7 -0
- package/dist/__golden__/wave-loop/op-wide-waiting.json +4 -0
- package/dist/change-set-graph.d.ts +56 -0
- package/dist/change-set-graph.d.ts.map +1 -0
- package/dist/change-set-graph.js +128 -0
- package/dist/change-set.d.ts +52 -3
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +35 -4
- package/dist/chant-version.d.ts +9 -0
- package/dist/chant-version.d.ts.map +1 -0
- package/dist/chant-version.js +16 -0
- package/dist/cli/commands/build.d.ts +8 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +9 -8
- package/dist/cli/commands/check-lexicon-docs.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-docs.js +30 -2
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.js +13 -2
- package/dist/cli/commands/init-lexicon/templates/docs.d.ts +4 -1
- package/dist/cli/commands/init-lexicon/templates/docs.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/docs.js +6 -6
- package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon.js +17 -8
- package/dist/cli/handlers/approve.d.ts.map +1 -1
- package/dist/cli/handlers/approve.js +19 -4
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +28 -0
- package/dist/cli/handlers/change-set.d.ts +10 -0
- package/dist/cli/handlers/change-set.d.ts.map +1 -1
- package/dist/cli/handlers/change-set.js +51 -1
- package/dist/cli/handlers/fan-out.d.ts +1 -1
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +14 -3
- package/dist/cli/handlers/pr.d.ts +8 -2
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +148 -24
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +256 -21
- package/dist/cli/handlers/release.d.ts +34 -0
- package/dist/cli/handlers/release.d.ts.map +1 -0
- package/dist/cli/handlers/release.js +203 -0
- package/dist/cli/handlers/run.d.ts +28 -2
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/run.js +170 -13
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +88 -13
- package/dist/cli/mcp/workspace-tools.js +1 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +49 -3
- package/dist/cli/registry.d.ts +29 -3
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/run-events.d.ts +29 -0
- package/dist/cli/run-events.d.ts.map +1 -0
- package/dist/cli/run-events.js +47 -0
- package/dist/cli/version.d.ts +3 -5
- package/dist/cli/version.d.ts.map +1 -1
- package/dist/cli/version.js +3 -13
- package/dist/codegen/docs-in-site.d.ts +71 -0
- package/dist/codegen/docs-in-site.d.ts.map +1 -0
- package/dist/codegen/docs-in-site.js +177 -0
- package/dist/codegen/docs-types.d.ts +14 -1
- package/dist/codegen/docs-types.d.ts.map +1 -1
- package/dist/codegen/docs.d.ts +18 -1
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/codegen/docs.js +40 -7
- package/dist/codegen/rehype-base-url.mjs +15 -9
- package/dist/components/auto-release.d.ts +4 -1
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/auto-release.js +2 -0
- package/dist/components/cli-support.d.ts +6 -0
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/cli-support.js +10 -9
- package/dist/components/driver.d.ts +42 -9
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +81 -54
- package/dist/components/fan-out-run.d.ts +7 -0
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +35 -26
- package/dist/components/pr-run.d.ts +11 -0
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +20 -1
- package/dist/components/promote-order.d.ts +38 -0
- package/dist/components/promote-order.d.ts.map +1 -0
- package/dist/components/promote-order.js +62 -0
- package/dist/components/promote.d.ts +15 -2
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/promote.js +17 -0
- package/dist/components/release-compile.d.ts +133 -0
- package/dist/components/release-compile.d.ts.map +1 -0
- package/dist/components/release-compile.js +376 -0
- package/dist/components/release-gate.d.ts +125 -0
- package/dist/components/release-gate.d.ts.map +1 -0
- package/dist/components/release-gate.js +282 -0
- package/dist/components/release-promote.d.ts +96 -0
- package/dist/components/release-promote.d.ts.map +1 -0
- package/dist/components/release-promote.js +204 -0
- package/dist/components/run-progress.d.ts +7 -0
- package/dist/components/run-progress.d.ts.map +1 -1
- package/dist/components/wave-plan.d.ts +3 -1
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lifecycle/change-set-store.d.ts +67 -0
- package/dist/lifecycle/change-set-store.d.ts.map +1 -0
- package/dist/lifecycle/change-set-store.js +96 -0
- package/dist/lifecycle/commit-sha.d.ts +13 -0
- package/dist/lifecycle/commit-sha.d.ts.map +1 -0
- package/dist/lifecycle/commit-sha.js +21 -0
- package/dist/lifecycle/gate-change-set.d.ts +69 -0
- package/dist/lifecycle/gate-change-set.d.ts.map +1 -0
- package/dist/lifecycle/gate-change-set.js +106 -0
- package/dist/lifecycle/gate-ledger.d.ts +49 -1
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.js +18 -0
- package/dist/lifecycle/release-cut.d.ts +107 -0
- package/dist/lifecycle/release-cut.d.ts.map +1 -0
- package/dist/lifecycle/release-cut.js +273 -0
- package/dist/lifecycle/release-ledger.d.ts +54 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.js +53 -20
- package/dist/lifecycle/release-store.d.ts +190 -0
- package/dist/lifecycle/release-store.d.ts.map +1 -0
- package/dist/lifecycle/release-store.js +318 -0
- package/dist/lifecycle/run-ledger.d.ts +4 -0
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/run-ledger.js +2 -0
- package/dist/op/activities/change-coverage.d.ts.map +1 -1
- package/dist/op/activities/change-coverage.js +4 -2
- package/dist/op/activities/source-release.d.ts.map +1 -1
- package/dist/op/activities/source-release.js +7 -3
- package/dist/op/activities/source-rollback.d.ts.map +1 -1
- package/dist/op/activities/source-rollback.js +7 -3
- package/dist/op/activity-registry.d.ts +6 -3
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-registry.js +7 -5
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/discover.js +14 -7
- package/dist/op/gate-name.d.ts +11 -2
- package/dist/op/gate-name.d.ts.map +1 -1
- package/dist/op/gate-name.js +12 -3
- package/dist/op/gate-run-locator.d.ts +22 -0
- package/dist/op/gate-run-locator.d.ts.map +1 -1
- package/dist/op/gate-run-locator.js +31 -0
- package/dist/op/gate.d.ts +27 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +57 -3
- package/dist/op/local-executor.d.ts +36 -1
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +158 -52
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +4 -0
- package/dist/op/run-live.d.ts +2 -0
- package/dist/op/run-live.d.ts.map +1 -1
- package/dist/op/run-live.js +1 -1
- package/dist/op/runtime.d.ts +46 -0
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/runtimes/local.d.ts.map +1 -1
- package/dist/op/runtimes/local.js +12 -2
- package/dist/point-decision.d.ts +2 -0
- package/dist/point-decision.d.ts.map +1 -1
- package/dist/point-decision.js +9 -2
- package/dist/run-event-store.d.ts +77 -0
- package/dist/run-event-store.d.ts.map +1 -0
- package/dist/run-event-store.js +204 -0
- package/dist/run-event-stream.d.ts +132 -0
- package/dist/run-event-stream.d.ts.map +1 -0
- package/dist/run-event-stream.js +238 -0
- package/dist/run-event.d.ts +267 -0
- package/dist/run-event.d.ts.map +1 -0
- package/dist/run-event.js +207 -0
- package/dist/wave-runtime.mjs +225 -242
- package/dist/workspace/__fixtures__/run-event-check.d.ts +19 -0
- package/dist/workspace/__fixtures__/run-event-check.d.ts.map +1 -0
- package/dist/workspace/__fixtures__/run-event-check.js +59 -0
- package/dist/workspace/change-set-show.d.ts +56 -0
- package/dist/workspace/change-set-show.d.ts.map +1 -0
- package/dist/workspace/change-set-show.js +54 -0
- package/dist/workspace/change-set-show.schema.json +102 -0
- package/dist/workspace/change-set.schema.json +28 -1
- package/dist/workspace/changes-cli.d.ts.map +1 -1
- package/dist/workspace/changes-cli.js +10 -1
- package/dist/workspace/changes.d.ts +37 -0
- package/dist/workspace/changes.d.ts.map +1 -1
- package/dist/workspace/changes.js +49 -2
- package/dist/workspace/changes.schema.json +135 -0
- package/dist/workspace/ci-green-cli.d.ts +19 -4
- package/dist/workspace/ci-green-cli.d.ts.map +1 -1
- package/dist/workspace/ci-green-cli.js +75 -12
- package/dist/workspace/ci-green-forge.d.ts +20 -3
- package/dist/workspace/ci-green-forge.d.ts.map +1 -1
- package/dist/workspace/ci-green-forge.js +6 -4
- package/dist/workspace/ci-green-workflow.d.ts +11 -0
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +6 -0
- package/dist/workspace/ci-green.d.ts +273 -13
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +449 -38
- package/dist/workspace/ci-last-green.schema.json +32 -2
- package/dist/workspace/ci-list.schema.json +525 -0
- package/dist/workspace/commit-links.d.ts +85 -0
- package/dist/workspace/commit-links.d.ts.map +1 -0
- package/dist/workspace/commit-links.js +163 -0
- package/dist/workspace/declaration.d.ts +19 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +1 -1
- package/dist/workspace/declaration.schema.json +12 -0
- package/dist/workspace/identity-gate-rule.d.ts +37 -0
- package/dist/workspace/identity-gate-rule.d.ts.map +1 -1
- package/dist/workspace/identity-gate-rule.js +72 -7
- package/dist/workspace/identity.d.ts +12 -0
- package/dist/workspace/identity.d.ts.map +1 -1
- package/dist/workspace/identity.js +13 -1
- package/dist/workspace/intent.d.ts +6 -1
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/intent.js +51 -1
- package/dist/workspace/ls.d.ts +4 -0
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +2 -0
- package/dist/workspace/ls.schema.json +3 -1
- package/dist/workspace/member-pipeline.d.ts +6 -0
- package/dist/workspace/member-pipeline.d.ts.map +1 -1
- package/dist/workspace/member-pipeline.js +6 -0
- package/dist/workspace/promotion-order.d.ts +41 -0
- package/dist/workspace/promotion-order.d.ts.map +1 -0
- package/dist/workspace/promotion-order.js +95 -0
- package/dist/workspace/reason-codes.d.ts +2 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +4 -1
- package/dist/workspace/releases.d.ts +72 -0
- package/dist/workspace/releases.d.ts.map +1 -0
- package/dist/workspace/releases.js +94 -0
- package/dist/workspace/releases.schema.json +391 -0
- package/dist/workspace/run-event.schema.json +288 -0
- package/dist/workspace/status-gates.d.ts +26 -1
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status-gates.js +31 -2
- package/dist/workspace/status-stewards.d.ts +4 -0
- package/dist/workspace/status-stewards.d.ts.map +1 -1
- package/dist/workspace/status-stewards.js +2 -0
- package/dist/workspace/status.d.ts +39 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/status.js +48 -1
- package/dist/workspace/status.schema.json +70 -1
- package/dist/workspace/trust/ci-tag-statement.d.ts +102 -0
- package/dist/workspace/trust/ci-tag-statement.d.ts.map +1 -0
- package/dist/workspace/trust/ci-tag-statement.js +123 -0
- package/dist/workspace/trust/op-run-statement.d.ts +91 -0
- package/dist/workspace/trust/op-run-statement.d.ts.map +1 -0
- package/dist/workspace/trust/op-run-statement.js +143 -0
- package/dist/workspace/trust/rotation.d.ts +18 -2
- package/dist/workspace/trust/rotation.d.ts.map +1 -1
- package/dist/workspace/trust/rotation.js +65 -16
- package/dist/workspace/trust/seal.d.ts +11 -0
- package/dist/workspace/trust/seal.d.ts.map +1 -1
- package/dist/workspace/trust/seal.js +9 -0
- package/dist/workspace/trust/ssh-commit.d.ts.map +1 -1
- package/dist/workspace/trust/ssh-commit.js +10 -10
- package/package.json +1 -1
- package/src/__golden__/wave-loop/fan-out-gated.json +8 -0
- package/src/__golden__/wave-loop/fan-out-no-members.json +4 -0
- package/src/__golden__/wave-loop/fan-out-only.json +6 -0
- package/src/__golden__/wave-loop/op-by-apply-hold.json +2 -0
- package/src/__golden__/wave-loop/op-cost-member.json +3 -0
- package/src/__golden__/wave-loop/op-held-on-before-apply.json +1 -0
- package/src/__golden__/wave-loop/op-held-on.json +2 -0
- package/src/__golden__/wave-loop/op-hooks-held.json +2 -0
- package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +2 -0
- package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +3 -0
- package/src/__golden__/wave-loop/op-hooks-share.json +3 -0
- package/src/__golden__/wave-loop/op-per-run.json +7 -0
- package/src/__golden__/wave-loop/op-pr-review.json +7 -0
- package/src/__golden__/wave-loop/op-sealed.json +3 -0
- package/src/__golden__/wave-loop/op-spend.json +3 -0
- package/src/__golden__/wave-loop/op-wave-commands.json +7 -0
- package/src/__golden__/wave-loop/op-wide-waiting.json +4 -0
- package/src/change-set-graph.test.ts +72 -0
- package/src/change-set-graph.ts +133 -0
- package/src/change-set.ts +76 -6
- package/src/chant-version.ts +16 -0
- package/src/cli/commands/build.ts +19 -8
- package/src/cli/commands/check-lexicon-docs.test.ts +51 -0
- package/src/cli/commands/check-lexicon-docs.ts +39 -2
- package/src/cli/commands/check-lexicon.ts +14 -2
- package/src/cli/commands/init-lexicon/templates/docs.ts +7 -6
- package/src/cli/commands/init-lexicon.test.ts +25 -0
- package/src/cli/commands/init-lexicon.ts +18 -8
- package/src/cli/compiled-cli.e2e.test.ts +31 -6
- package/src/cli/handlers/approve-release.test.ts +80 -0
- package/src/cli/handlers/approve.ts +18 -2
- package/src/cli/handlers/build.test.ts +52 -0
- package/src/cli/handlers/build.ts +29 -0
- package/src/cli/handlers/change-set.ts +49 -1
- package/src/cli/handlers/fan-out.test.ts +48 -0
- package/src/cli/handlers/fan-out.ts +15 -3
- package/src/cli/handlers/operator.test.ts +37 -0
- package/src/cli/handlers/pr.test.ts +194 -0
- package/src/cli/handlers/pr.ts +168 -34
- package/src/cli/handlers/promote.test.ts +389 -5
- package/src/cli/handlers/promote.ts +279 -20
- package/src/cli/handlers/release-implicit.e2e.test.ts +153 -0
- package/src/cli/handlers/release.e2e.test.ts +85 -0
- package/src/cli/handlers/release.ts +206 -0
- package/src/cli/handlers/run-auto-release.test.ts +71 -0
- package/src/cli/handlers/run-events-cmd.test.ts +92 -0
- package/src/cli/handlers/run.test.ts +30 -0
- package/src/cli/handlers/run.ts +176 -15
- package/src/cli/main.test.ts +7 -0
- package/src/cli/main.ts +88 -13
- package/src/cli/mcp/never-over-mcp.test.ts +2 -0
- package/src/cli/mcp/workspace-tools.ts +1 -1
- package/src/cli/parse-args.ts +37 -3
- package/src/cli/registry.ts +29 -3
- package/src/cli/run-events.ts +54 -0
- package/src/cli/version.ts +3 -13
- package/src/codegen/docs-in-site.test.ts +166 -0
- package/src/codegen/docs-in-site.ts +182 -0
- package/src/codegen/docs-site/AgentPrompt.astro +26 -1
- package/src/codegen/docs-types.ts +14 -1
- package/src/codegen/docs.ts +60 -7
- package/src/codegen/rehype-base-url.d.mts +3 -1
- package/src/codegen/rehype-base-url.mjs +15 -9
- package/src/codegen/rehype-base-url.test.ts +34 -0
- package/src/components/auto-release.test.ts +21 -0
- package/src/components/auto-release.ts +6 -1
- package/src/components/cli-support.test.ts +82 -0
- package/src/components/cli-support.ts +16 -9
- package/src/components/driver.ts +129 -56
- package/src/components/fan-out-run.ts +56 -35
- package/src/components/pr-run.ts +30 -1
- package/src/components/promote-order.test.ts +90 -0
- package/src/components/promote-order.ts +75 -0
- package/src/components/promote.test.ts +10 -1
- package/src/components/promote.ts +26 -1
- package/src/components/release-compile.test.ts +147 -0
- package/src/components/release-compile.ts +445 -0
- package/src/components/release-gate.test.ts +215 -0
- package/src/components/release-gate.ts +341 -0
- package/src/components/release-promote.test.ts +159 -0
- package/src/components/release-promote.ts +232 -0
- package/src/components/run-progress.ts +7 -0
- package/src/components/wave-plan.ts +1 -1
- package/src/config.ts +7 -1
- package/src/index.ts +2 -0
- package/src/lifecycle/change-set-store.test.ts +217 -0
- package/src/lifecycle/change-set-store.ts +112 -0
- package/src/lifecycle/commit-sha.ts +23 -0
- package/src/lifecycle/gate-change-set.e2e.test.ts +122 -0
- package/src/lifecycle/gate-change-set.ts +133 -0
- package/src/lifecycle/gate-ledger.test.ts +33 -0
- package/src/lifecycle/gate-ledger.ts +66 -1
- package/src/lifecycle/release-cut-signed.test.ts +180 -0
- package/src/lifecycle/release-cut.test.ts +411 -0
- package/src/lifecycle/release-cut.ts +367 -0
- package/src/lifecycle/release-ledger.test.ts +14 -0
- package/src/lifecycle/release-ledger.ts +85 -17
- package/src/lifecycle/release-store.ts +423 -0
- package/src/lifecycle/run-ledger.test.ts +10 -0
- package/src/lifecycle/run-ledger.ts +6 -0
- package/src/op/activities/change-coverage.ts +4 -1
- package/src/op/activities/source-release.ts +8 -3
- package/src/op/activities/source-rollback.ts +8 -4
- package/src/op/activity-registry.ts +7 -5
- package/src/op/commit-run-gate-deploy-join.test.ts +117 -0
- package/src/op/discover-root.test.ts +39 -0
- package/src/op/discover.ts +15 -8
- package/src/op/gate-name.ts +13 -3
- package/src/op/gate-release.test.ts +126 -0
- package/src/op/gate-run-locator.test.ts +110 -0
- package/src/op/gate-run-locator.ts +35 -0
- package/src/op/gate.ts +88 -6
- package/src/op/local-executor.ts +207 -52
- package/src/op/op-waves-run.ts +4 -0
- package/src/op/run-events.test.ts +166 -0
- package/src/op/run-live.ts +1 -1
- package/src/op/runtime.ts +39 -0
- package/src/op/runtimes/local.test.ts +16 -0
- package/src/op/runtimes/local.ts +13 -2
- package/src/point-decision.ts +12 -2
- package/src/run-event-store.test.ts +144 -0
- package/src/run-event-store.ts +213 -0
- package/src/run-event-stream.test.ts +175 -0
- package/src/run-event-stream.ts +306 -0
- package/src/run-event.test.ts +277 -0
- package/src/run-event.ts +451 -0
- package/src/wave-loop-golden.test.ts +9 -0
- package/src/workspace/__fixtures__/run-event-check.ts +58 -0
- package/src/workspace/ancestry-index.test.ts +93 -0
- package/src/workspace/change-set-show.schema.json +102 -0
- package/src/workspace/change-set-show.ts +72 -0
- package/src/workspace/change-set.schema.json +28 -1
- package/src/workspace/changes-cli.ts +10 -1
- package/src/workspace/changes.schema.json +135 -0
- package/src/workspace/changes.test.ts +1 -1
- package/src/workspace/changes.ts +84 -2
- package/src/workspace/ci-green-cli.ts +75 -13
- package/src/workspace/ci-green-forge.ts +24 -4
- package/src/workspace/ci-green-runs.test.ts +242 -0
- package/src/workspace/ci-green-signed.test.ts +302 -0
- package/src/workspace/ci-green-workflow.test.ts +16 -0
- package/src/workspace/ci-green-workflow.ts +12 -0
- package/src/workspace/ci-green.test.ts +131 -2
- package/src/workspace/ci-green.ts +624 -42
- package/src/workspace/ci-last-green.schema.json +32 -2
- package/src/workspace/ci-list.schema.json +525 -0
- package/src/workspace/commit-links.test.ts +279 -0
- package/src/workspace/commit-links.ts +183 -0
- package/src/workspace/declaration.schema.json +12 -0
- package/src/workspace/declaration.ts +22 -2
- package/src/workspace/identity-gate-rule.ts +91 -7
- package/src/workspace/identity.ts +14 -1
- package/src/workspace/intent.ts +48 -1
- package/src/workspace/ls.schema.json +3 -1
- package/src/workspace/ls.ts +6 -0
- package/src/workspace/member-pipeline.test.ts +17 -0
- package/src/workspace/member-pipeline.ts +9 -0
- package/src/workspace/promotion-order.ts +97 -0
- package/src/workspace/read-contract.e2e.test.ts +4 -1
- package/src/workspace/reason-codes.test.ts +2 -1
- package/src/workspace/reason-codes.ts +4 -1
- package/src/workspace/releases.schema.json +391 -0
- package/src/workspace/releases.test.ts +108 -0
- package/src/workspace/releases.ts +122 -0
- package/src/workspace/run-event.schema.json +288 -0
- package/src/workspace/status-contract.test.ts +52 -1
- package/src/workspace/status-gates.ts +56 -1
- package/src/workspace/status-stewards.ts +6 -0
- package/src/workspace/status.schema.json +70 -1
- package/src/workspace/status.ts +80 -1
- package/src/workspace/trust/ci-tag-statement.ts +151 -0
- package/src/workspace/trust/op-run-statement.ts +148 -0
- package/src/workspace/trust/rotation.ts +61 -14
- package/src/workspace/trust/seal.ts +10 -0
- package/src/workspace/trust/ssh-commit.ts +10 -9
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/astro.config.mjs +0 -14
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/package.json +0 -16
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content/docs/index.mdx +0 -8
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content.config.ts +0 -15
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/tsconfig.json +0 -10
package/src/codegen/docs.ts
CHANGED
|
@@ -8,10 +8,19 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { copyFileSync, existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
|
|
11
|
-
import { join } from "path";
|
|
11
|
+
import { dirname, join } from "path";
|
|
12
12
|
import { fileURLToPath } from "url";
|
|
13
13
|
|
|
14
14
|
import { expandFileMarkers } from "./docs-file-markers";
|
|
15
|
+
import {
|
|
16
|
+
DOCS_SITE_DEPENDENCIES,
|
|
17
|
+
buildSectionGroup,
|
|
18
|
+
hiddenSectionSlugs,
|
|
19
|
+
rebaseImports,
|
|
20
|
+
resolveDocsMode,
|
|
21
|
+
sectionContentDir,
|
|
22
|
+
withQuadrant,
|
|
23
|
+
} from "./docs-in-site";
|
|
15
24
|
import { readAuthoredPages } from "./docs-pages";
|
|
16
25
|
import { scanRules, generateRules } from "./docs-rule-scanning";
|
|
17
26
|
import { buildSidebar } from "./docs-sidebar";
|
|
@@ -22,6 +31,14 @@ import type { DocsConfig, DocsResult, ManifestJSON, MetaEntry, SidebarPage } fro
|
|
|
22
31
|
export { expandFileMarkers } from "./docs-file-markers";
|
|
23
32
|
export type { DocsConfig, DocsResult, Quadrant, SidebarPage } from "./docs-types";
|
|
24
33
|
export { QUADRANTS, QUADRANT_LABELS, readAuthoredPages } from "./docs-pages";
|
|
34
|
+
export {
|
|
35
|
+
DOCS_SITE_DEPENDENCIES,
|
|
36
|
+
buildSectionGroup,
|
|
37
|
+
findChantDocsSite,
|
|
38
|
+
resolveDocsMode,
|
|
39
|
+
sectionContentDir,
|
|
40
|
+
type DocsSiteMode,
|
|
41
|
+
} from "./docs-in-site";
|
|
25
42
|
|
|
26
43
|
// ── Pipeline ───────────────────────────────────────────────────────
|
|
27
44
|
|
|
@@ -279,6 +296,46 @@ export function writeDocsPages(result: DocsResult, outDir: string): void {
|
|
|
279
296
|
}
|
|
280
297
|
}
|
|
281
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Write a lexicon's docs from pipeline results, in the mode
|
|
301
|
+
* {@link resolveDocsMode} picks: inside the chant repository, a section of the
|
|
302
|
+
* main site ({@link writeDocsSection}); anywhere else, a standalone Starlight
|
|
303
|
+
* app ({@link writeStandaloneDocsSite}). Every lexicon's `docs.ts` calls this,
|
|
304
|
+
* so neither they nor the `chant init-lexicon` scaffold choose a mode.
|
|
305
|
+
*/
|
|
306
|
+
export function writeDocsSite(config: DocsConfig, result: DocsResult): void {
|
|
307
|
+
const { mode, siteDir } = resolveDocsMode(config);
|
|
308
|
+
if (mode === "in-site" && siteDir) writeDocsSection(config, result, siteDir);
|
|
309
|
+
else writeStandaloneDocsSite(config, result);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Write a lexicon's pages into the main docs site (chant #3993): every page
|
|
314
|
+
* under `docs/src/content/docs/lexicons/<name>/`, and `_sidebar.json` beside
|
|
315
|
+
* them with the lexicon's sidebar group and its hidden pages. The section is
|
|
316
|
+
* build output, so the directory is replaced whole on every run; a page the
|
|
317
|
+
* pipeline stopped emitting cannot linger. No app files are written.
|
|
318
|
+
*/
|
|
319
|
+
export function writeDocsSection(config: DocsConfig, result: DocsResult, siteDir: string): void {
|
|
320
|
+
const sectionDir = sectionContentDir(siteDir, config.name);
|
|
321
|
+
rmSync(sectionDir, { recursive: true, force: true });
|
|
322
|
+
mkdirSync(sectionDir, { recursive: true });
|
|
323
|
+
|
|
324
|
+
const quadrantOf = new Map(result.sidebarPages.map((p) => [`${p.slug}.mdx`, p.quadrant]));
|
|
325
|
+
for (const [filename, content] of result.pages) {
|
|
326
|
+
const filePath = join(sectionDir, filename);
|
|
327
|
+
const pageDir = dirname(filePath);
|
|
328
|
+
mkdirSync(pageDir, { recursive: true });
|
|
329
|
+
const page = rebaseImports(withQuadrant(content, quadrantOf.get(filename)), { outDir: config.outDir, siteDir, pageDir });
|
|
330
|
+
writeFileSync(filePath, page);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
writeFileSync(
|
|
334
|
+
join(sectionDir, "_sidebar.json"),
|
|
335
|
+
JSON.stringify({ group: buildSectionGroup(config, result), hidden: hiddenSectionSlugs(config, result) }, null, 2) + "\n",
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
282
339
|
/**
|
|
283
340
|
* Scaffold a standalone Starlight docs site from pipeline results.
|
|
284
341
|
*
|
|
@@ -286,7 +343,7 @@ export function writeDocsPages(result: DocsResult, outDir: string): void {
|
|
|
286
343
|
* pages under src/content/docs/. The resulting directory can be built with
|
|
287
344
|
* `npm install && npm run build`.
|
|
288
345
|
*/
|
|
289
|
-
export function
|
|
346
|
+
export function writeStandaloneDocsSite(config: DocsConfig, result: DocsResult): void {
|
|
290
347
|
const outDir = config.outDir;
|
|
291
348
|
const contentDir = join(outDir, "src", "content", "docs");
|
|
292
349
|
|
|
@@ -350,11 +407,7 @@ export function writeDocsSite(config: DocsConfig, result: DocsResult): void {
|
|
|
350
407
|
build: "astro build",
|
|
351
408
|
preview: "astro preview",
|
|
352
409
|
},
|
|
353
|
-
dependencies: {
|
|
354
|
-
"@astrojs/starlight": "^0.37.6",
|
|
355
|
-
astro: "^5.6.1",
|
|
356
|
-
sharp: "^0.34.2",
|
|
357
|
-
},
|
|
410
|
+
dependencies: { ...DOCS_SITE_DEPENDENCIES },
|
|
358
411
|
},
|
|
359
412
|
null,
|
|
360
413
|
2,
|
|
@@ -3,6 +3,8 @@ export interface RehypeBaseUrlOptions {
|
|
|
3
3
|
base: string;
|
|
4
4
|
/** Project-wide base used to detect already-correctly-prefixed cross-site links. */
|
|
5
5
|
projectBase?: string;
|
|
6
|
+
/** Per-page base, by the page's source path; undefined falls back to `base`. */
|
|
7
|
+
baseFor?: (path: string) => string | undefined;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
type HastNode = {
|
|
@@ -14,4 +16,4 @@ type HastNode = {
|
|
|
14
16
|
|
|
15
17
|
export default function rehypeBaseUrl(
|
|
16
18
|
opts: RehypeBaseUrlOptions,
|
|
17
|
-
): (tree: HastNode) => void;
|
|
19
|
+
): (tree: HastNode, file?: { path?: string }) => void;
|
|
@@ -11,9 +11,16 @@
|
|
|
11
11
|
* idempotently skips hrefs that already start with the site's own base or the
|
|
12
12
|
* project-wide base.
|
|
13
13
|
*
|
|
14
|
+
* `baseFor` lets one site hold sections with their own root (chant #3993): the
|
|
15
|
+
* main docs site builds every lexicon's pages under /chant/lexicons/<name>/,
|
|
16
|
+
* and a lexicon page's `/foo/` has always meant its own lexicon's root, as it
|
|
17
|
+
* did when each lexicon was a separate site. `baseFor(file.path)` returns the
|
|
18
|
+
* base for that page, or undefined to use `base`.
|
|
19
|
+
*
|
|
14
20
|
* @typedef {Object} RehypeBaseUrlOptions
|
|
15
21
|
* @property {string} base - Site base, e.g. "/chant" or "/chant/lexicons/aws". Trailing/leading slashes optional.
|
|
16
22
|
* @property {string} [projectBase] - Project-wide base used to detect already-correctly-prefixed cross-site links.
|
|
23
|
+
* @property {(path: string) => string | undefined} [baseFor] - Per-page base, by the page's source path.
|
|
17
24
|
*/
|
|
18
25
|
|
|
19
26
|
const PROTOCOL_RE = /^[a-z][a-z0-9+.-]*:/i;
|
|
@@ -26,16 +33,12 @@ function normalizeBase(value) {
|
|
|
26
33
|
* @param {RehypeBaseUrlOptions} opts
|
|
27
34
|
*/
|
|
28
35
|
export default function rehypeBaseUrl(opts) {
|
|
29
|
-
const
|
|
30
|
-
if (base === "/") {
|
|
31
|
-
return () => {};
|
|
32
|
-
}
|
|
33
|
-
const ownPrefix = base + "/";
|
|
36
|
+
const siteBase = normalizeBase(opts.base);
|
|
34
37
|
const projectPrefix = opts.projectBase
|
|
35
38
|
? normalizeBase(opts.projectBase) + "/"
|
|
36
39
|
: null;
|
|
37
40
|
|
|
38
|
-
function rewrite(node) {
|
|
41
|
+
function rewrite(node, base, ownPrefix) {
|
|
39
42
|
if (
|
|
40
43
|
node &&
|
|
41
44
|
node.type === "element" &&
|
|
@@ -58,11 +61,14 @@ export default function rehypeBaseUrl(opts) {
|
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
if (node && node.children) {
|
|
61
|
-
for (const child of node.children) rewrite(child);
|
|
64
|
+
for (const child of node.children) rewrite(child, base, ownPrefix);
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
return (tree) => {
|
|
66
|
-
|
|
68
|
+
return (tree, file) => {
|
|
69
|
+
const own = opts.baseFor && file && typeof file.path === "string" ? opts.baseFor(file.path) : undefined;
|
|
70
|
+
const base = own ? normalizeBase(own) : siteBase;
|
|
71
|
+
if (base === "/") return;
|
|
72
|
+
rewrite(tree, base, base + "/");
|
|
67
73
|
};
|
|
68
74
|
}
|
|
@@ -159,3 +159,37 @@ describe("rehypeBaseUrl — tree traversal", () => {
|
|
|
159
159
|
expect(root.children[0].properties.src).toBe("/foo.png");
|
|
160
160
|
});
|
|
161
161
|
});
|
|
162
|
+
|
|
163
|
+
// chant #3993: the main site builds every lexicon's pages under
|
|
164
|
+
// /chant/lexicons/<name>/, and a lexicon page's root-relative link keeps
|
|
165
|
+
// meaning its own lexicon's root, as it did on the lexicon's own site.
|
|
166
|
+
describe("rehypeBaseUrl — per-page base (baseFor)", () => {
|
|
167
|
+
const baseFor = (path: string): string | undefined => {
|
|
168
|
+
const name = path.match(/\/content\/docs\/lexicons\/([^/]+)\//)?.[1];
|
|
169
|
+
return name ? `/chant/lexicons/${name}` : undefined;
|
|
170
|
+
};
|
|
171
|
+
const opts = { base: "/chant", projectBase: "/chant", baseFor };
|
|
172
|
+
|
|
173
|
+
function runAt(path: string | undefined, href: string): string {
|
|
174
|
+
const plugin = rehypeBaseUrl(opts);
|
|
175
|
+
const root = tree(a(href));
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
177
|
+
(plugin as any)(root, path === undefined ? undefined : { path });
|
|
178
|
+
return root.children[0].properties.href as string;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
it("prefixes a lexicon page's root-relative link with its lexicon's base", () => {
|
|
182
|
+
expect(runAt("/repo/docs/src/content/docs/lexicons/aws/composites.mdx", "/intrinsics/")).toBe(
|
|
183
|
+
"/chant/lexicons/aws/intrinsics/",
|
|
184
|
+
);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("leaves a lexicon page's /chant/ link alone", () => {
|
|
188
|
+
expect(runAt("/repo/docs/src/content/docs/lexicons/aws/composites.mdx", "/chant/guide/ops/")).toBe("/chant/guide/ops/");
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("uses the site base for every other page", () => {
|
|
192
|
+
expect(runAt("/repo/docs/src/content/docs/guide/ops.mdx", "/lexicons/aws/")).toBe("/chant/lexicons/aws/");
|
|
193
|
+
expect(runAt(undefined, "/lexicons/aws/")).toBe("/chant/lexicons/aws/");
|
|
194
|
+
});
|
|
195
|
+
});
|
|
@@ -95,6 +95,27 @@ describe("maybeRecordAutoRelease", () => {
|
|
|
95
95
|
expect(pushLifecycleMock).toHaveBeenCalledTimes(1);
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
+
test("a deploy that passed a gate records the approver and the admission (#4020)", async () => {
|
|
99
|
+
appendReleaseRecordMock.mockResolvedValue({ commit: "c".repeat(40), record: { version: 1 } });
|
|
100
|
+
const admission = { op: "svc", gate: "approve-prod", resolvedAt: "2026-01-01T00:05:00.000Z" };
|
|
101
|
+
|
|
102
|
+
await maybeRecordAutoRelease(
|
|
103
|
+
{ component: "svc", env: "prod", success: true, records: [publishRecord("sha256:abc")], runId: "9001", runOrigin: { forge: "github", repo: "acme/app" }, approver: "alice", admission },
|
|
104
|
+
{ actor: "alice" },
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const [input] = appendReleaseRecordMock.mock.calls[0];
|
|
108
|
+
expect(input).toMatchObject({ runId: "9001", runOrigin: { forge: "github", repo: "acme/app" }, approver: "alice", admission });
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("an ungated deploy records neither", async () => {
|
|
112
|
+
appendReleaseRecordMock.mockResolvedValue({ commit: "c".repeat(40), record: { version: 1 } });
|
|
113
|
+
await maybeRecordAutoRelease({ component: "svc", env: "prod", success: true, records: [publishRecord("sha256:abc")], runId: "r" }, { actor: "alice" });
|
|
114
|
+
const [input] = appendReleaseRecordMock.mock.calls[0];
|
|
115
|
+
expect(input).not.toHaveProperty("approver");
|
|
116
|
+
expect(input).not.toHaveProperty("admission");
|
|
117
|
+
});
|
|
118
|
+
|
|
98
119
|
test("a pre-resolved digest takes precedence and is used directly", async () => {
|
|
99
120
|
appendReleaseRecordMock.mockResolvedValue({
|
|
100
121
|
commit: "b".repeat(40),
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* env vars, timestamp is a real `new Date()` taken at record time).
|
|
27
27
|
*/
|
|
28
28
|
import { getHeadCommit, pushLifecycle, StaleLifecycleBranchError } from "../lifecycle/git";
|
|
29
|
-
import { appendReleaseRecord, InvalidReleaseRecordError, type ReleaseRecord, type RunOrigin } from "../lifecycle/release-ledger";
|
|
29
|
+
import { appendReleaseRecord, InvalidReleaseRecordError, type ReleaseAdmission, type ReleaseRecord, type RunOrigin } from "../lifecycle/release-ledger";
|
|
30
30
|
import type { DriverStepRecord } from "./driver";
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -94,6 +94,9 @@ export interface AutoReleaseRunInfo {
|
|
|
94
94
|
runId: string;
|
|
95
95
|
/** The id space `runId` lives in (#2045) — `{ forge: "op" }` for a hosted run, `{ forge: "local" }` for a local-executor mint. Recorded verbatim as the release record's `runOrigin`. */
|
|
96
96
|
runOrigin?: RunOrigin;
|
|
97
|
+
/** Who approved the deploy at its gate (#1035) and the gate resolution that admitted it (#4020), when it passed one. `recordAutoReleasesForRun` reads both off the component's gate step records. */
|
|
98
|
+
approver?: string;
|
|
99
|
+
admission?: ReleaseAdmission;
|
|
97
100
|
/** The bypassed capability-profile divergences, when the caller deliberately overrode a deploy-time profile assertion (chant #1244) — recorded verbatim as the release record's `profileOverride`. */
|
|
98
101
|
profileOverride?: string;
|
|
99
102
|
/** The deploy's input-side digest, when `digest` is a rendered-content identity (a pinned helm deploy, chant #1242) — recorded as the release record's `inputDigest` so ledger queries can still join on inputs across clusters whose bytes legitimately differ. */
|
|
@@ -184,6 +187,8 @@ export async function maybeRecordAutoRelease(
|
|
|
184
187
|
...(run.runOrigin ? { runOrigin: run.runOrigin } : {}),
|
|
185
188
|
timestamp,
|
|
186
189
|
actor,
|
|
190
|
+
...(run.approver ? { approver: run.approver } : {}),
|
|
191
|
+
...(run.admission ? { admission: run.admission } : {}),
|
|
187
192
|
...(run.profileOverride ? { profileOverride: run.profileOverride } : {}),
|
|
188
193
|
...(run.inputDigest ? { inputDigest: run.inputDigest } : {}),
|
|
189
194
|
},
|
|
@@ -27,6 +27,8 @@ import {
|
|
|
27
27
|
import { CapabilityRegistry, type DeployContext } from "./capability";
|
|
28
28
|
import { memoryGateLedgerPort } from "../op/gate";
|
|
29
29
|
import type { DriverComponent, RunProgressEvent } from "./driver";
|
|
30
|
+
import { openRunEventStream } from "../run-event-stream";
|
|
31
|
+
import { checkRunEventLines, stepTrail } from "../workspace/__fixtures__/run-event-check";
|
|
30
32
|
|
|
31
33
|
// A minimal stand-in for the real gitlab lexicon plugin, satisfying
|
|
32
34
|
// `isLexiconPlugin` (../lexicon.ts) — used only by the `generateComponentsPipeline`
|
|
@@ -1106,3 +1108,83 @@ describe("runComponents — onProgress (--progress-json wiring, M3)", () => {
|
|
|
1106
1108
|
expect(result.run?.ok).toBe(true);
|
|
1107
1109
|
});
|
|
1108
1110
|
});
|
|
1111
|
+
|
|
1112
|
+
describe("runComponents — onRunEvent (`chant run --components --events-json`, #4041)", () => {
|
|
1113
|
+
let testDir: string;
|
|
1114
|
+
|
|
1115
|
+
beforeEach(async () => {
|
|
1116
|
+
testDir = join(tmpdir(), `chant-run-components-events-test-${Date.now()}-${Math.random()}`);
|
|
1117
|
+
await mkdir(testDir, { recursive: true });
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
afterEach(async () => {
|
|
1121
|
+
await rm(testDir, { recursive: true, force: true });
|
|
1122
|
+
});
|
|
1123
|
+
|
|
1124
|
+
/** The run's stream, as `--events-json` opens it. */
|
|
1125
|
+
function stream() {
|
|
1126
|
+
const lines: string[] = [];
|
|
1127
|
+
const s = openRunEventStream(
|
|
1128
|
+
{ runId: "local-1", kind: "component", name: "all", gitSha: null, runtime: "local", runOrigin: { forge: "local" } },
|
|
1129
|
+
(l) => lines.push(l),
|
|
1130
|
+
);
|
|
1131
|
+
return { s, lines };
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
test("a two-wave run: schema-valid, waves and components framed, each step started before it settles", async () => {
|
|
1135
|
+
await writeFile(
|
|
1136
|
+
join(testDir, "alb.component.ts"),
|
|
1137
|
+
`export const alb = { name: "shared-alb", dependsOn: [], deploy: [{ phase: "Apply", steps: [{ kind: "deploy-thing" }] }] };`,
|
|
1138
|
+
);
|
|
1139
|
+
await writeFile(
|
|
1140
|
+
join(testDir, "svc.component.ts"),
|
|
1141
|
+
`export const svc = { name: "search-service", dependsOn: ["shared-alb"], deploy: [{ phase: "Apply", steps: [{ kind: "deploy-thing" }] }] };`,
|
|
1142
|
+
);
|
|
1143
|
+
const { s, lines } = stream();
|
|
1144
|
+
const result = await runComponents(testDir, "all", { registry: fakeRegistry(), onRunEvent: s.emit });
|
|
1145
|
+
|
|
1146
|
+
expect(result.success).toBe(true);
|
|
1147
|
+
const events = checkRunEventLines(lines);
|
|
1148
|
+
expect(events[0]).toMatchObject({ type: "run-start", waves: [["shared-alb"], ["search-service"]] });
|
|
1149
|
+
expect(events.filter((e) => e.type === "step-start")).toEqual([
|
|
1150
|
+
expect.objectContaining({ component: "shared-alb", phase: "Apply", step: "deploy-thing", index: 0 }),
|
|
1151
|
+
expect.objectContaining({ component: "search-service", phase: "Apply", step: "deploy-thing", index: 0 }),
|
|
1152
|
+
]);
|
|
1153
|
+
expect(events.at(-1)).toMatchObject({ type: "run-settle", status: "ok" });
|
|
1154
|
+
});
|
|
1155
|
+
|
|
1156
|
+
test("a gate nobody approved: gate-waiting and a gated settle, the step after it not-run, the run gated", async () => {
|
|
1157
|
+
await writeFile(
|
|
1158
|
+
join(testDir, "svc.component.ts"),
|
|
1159
|
+
`export const svc = { name: "svc", dependsOn: [], deploy: [{ phase: "Apply", steps: [{ kind: "gate", gate: "prod-ok" }, { kind: "deploy-thing" }] }] };`,
|
|
1160
|
+
);
|
|
1161
|
+
const { s, lines } = stream();
|
|
1162
|
+
const result = await runComponents(testDir, "svc", { registry: fakeRegistry(), gates: memoryGateLedgerPort(), onRunEvent: s.emit });
|
|
1163
|
+
|
|
1164
|
+
expect(result.gated).toBeDefined();
|
|
1165
|
+
const events = checkRunEventLines(lines);
|
|
1166
|
+
expect(stepTrail(events)).toEqual([
|
|
1167
|
+
["step-start", "gate:prod-ok"],
|
|
1168
|
+
["gate-waiting", "gate:prod-ok"],
|
|
1169
|
+
["step-settle", "gate:prod-ok", "gated"],
|
|
1170
|
+
["step-settle", "deploy-thing", "skipped:not-run"],
|
|
1171
|
+
]);
|
|
1172
|
+
expect(events.find((e) => e.type === "gate-waiting")).toMatchObject({ component: "svc", op: "svc", gate: "prod-ok", point: null });
|
|
1173
|
+
expect(events.at(-1)).toMatchObject({ type: "run-settle", status: "gated" });
|
|
1174
|
+
});
|
|
1175
|
+
|
|
1176
|
+
test("onProgress beside onRunEvent prints what it printed alone: the older stream is unchanged", async () => {
|
|
1177
|
+
await writeFile(
|
|
1178
|
+
join(testDir, "svc.component.ts"),
|
|
1179
|
+
`export const svc = { name: "svc", dependsOn: [], deploy: [{ phase: "Apply", steps: [{ kind: "gate", gate: "prod-ok" }, { kind: "deploy-thing" }] }] };`,
|
|
1180
|
+
);
|
|
1181
|
+
const alone: RunProgressEvent[] = [];
|
|
1182
|
+
await runComponents(testDir, "svc", { registry: fakeRegistry({ failRun: true }), gates: memoryGateLedgerPort(), onProgress: (e) => alone.push(e) });
|
|
1183
|
+
const beside: RunProgressEvent[] = [];
|
|
1184
|
+
const { s } = stream();
|
|
1185
|
+
await runComponents(testDir, "svc", { registry: fakeRegistry({ failRun: true }), gates: memoryGateLedgerPort(), onProgress: (e) => beside.push(e), onRunEvent: s.emit });
|
|
1186
|
+
expect(beside).toEqual(alone);
|
|
1187
|
+
// The gate step, its decision and the not-run step after it are not in the older stream.
|
|
1188
|
+
expect(alone.map((e) => e.type)).toEqual(["run-start", "wave-start", "component-start", "phase-start", "phase-done", "component-done", "wave-done", "run-done"]);
|
|
1189
|
+
});
|
|
1190
|
+
});
|
|
@@ -45,6 +45,7 @@ import type { GateDigestMismatch, GateLedgerPort } from "../op/gate";
|
|
|
45
45
|
import { gateName } from "../op/gate-name";
|
|
46
46
|
import { isLexiconPlugin, type LexiconPlugin, type ComponentPipelineOptions } from "../lexicon";
|
|
47
47
|
import type { RunProgressEvent } from "./run-progress";
|
|
48
|
+
import { joinRunEventSinks, progressSinkOf, type RunEventSink } from "../run-event-stream";
|
|
48
49
|
import { dirname, relative } from "node:path";
|
|
49
50
|
import { existsSync, statSync } from "node:fs";
|
|
50
51
|
import { getHeadCommit } from "../lifecycle/git";
|
|
@@ -437,6 +438,11 @@ export interface RunComponentsOptions {
|
|
|
437
438
|
* `--progress-json`, in which case nothing changes.
|
|
438
439
|
*/
|
|
439
440
|
onProgress?: (event: RunProgressEvent) => void;
|
|
441
|
+
/**
|
|
442
|
+
* Where the run's events go (#4041, `--events-json`): run-event bodies,
|
|
443
|
+
* with the same single-wave framing for a single component as `onProgress`.
|
|
444
|
+
*/
|
|
445
|
+
onRunEvent?: RunEventSink;
|
|
440
446
|
/**
|
|
441
447
|
* chant #1108 — this run's resolved build-time parameter values, resolved
|
|
442
448
|
* the exact same way `chant build` resolves them
|
|
@@ -681,7 +687,7 @@ export async function runComponents(
|
|
|
681
687
|
// from a caller (a downstream CI job passing an upstream job's dumped
|
|
682
688
|
// outputs via `--seed-outputs`); grows as this run's components complete.
|
|
683
689
|
const seedOutputs = options.componentOutputs ?? {};
|
|
684
|
-
const
|
|
690
|
+
const emit = joinRunEventSinks(options.onRunEvent, progressSinkOf(options.onProgress));
|
|
685
691
|
|
|
686
692
|
const gates = options.gates;
|
|
687
693
|
// #3061: the commit this run deploys, for the workloads' vcs.ref.head.revision. The digest comes
|
|
@@ -705,7 +711,7 @@ export async function runComponents(
|
|
|
705
711
|
env,
|
|
706
712
|
releaseIdentity,
|
|
707
713
|
componentOutputs: seedOutputs,
|
|
708
|
-
|
|
714
|
+
...(emit ? { onRunEvent: emit } : {}),
|
|
709
715
|
...(gates ? { gates } : {}),
|
|
710
716
|
});
|
|
711
717
|
return {
|
|
@@ -741,21 +747,22 @@ export async function runComponents(
|
|
|
741
747
|
// `run.waves`/`run.order` below already give it.
|
|
742
748
|
const componentOutputs = { ...seedOutputs };
|
|
743
749
|
const componentName = resolvedTargets[0].name;
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
750
|
+
emit?.({ type: "run-start", waves: [selected] });
|
|
751
|
+
emit?.({ type: "wave-start", wave: 1, components: selected });
|
|
752
|
+
emit?.({ type: "component-start", wave: 1, component: componentName });
|
|
747
753
|
const componentResult = await runComponentDeploy(
|
|
748
754
|
resolvedTargets[0],
|
|
749
755
|
deployContext({ env, releaseIdentity }, componentName),
|
|
750
756
|
registry,
|
|
751
757
|
componentOutputs,
|
|
752
|
-
|
|
758
|
+
undefined,
|
|
753
759
|
gates ? { port: gates } : undefined,
|
|
760
|
+
emit,
|
|
754
761
|
);
|
|
755
762
|
const status = componentResult.status === "fail" ? "failed" : componentResult.status;
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
763
|
+
emit?.({ type: "component-settle", wave: 1, component: componentName, status });
|
|
764
|
+
emit?.({ type: "wave-settle", wave: 1, status });
|
|
765
|
+
emit?.({ type: "run-settle", status, durationMs: null });
|
|
759
766
|
const run: DriverRunResult = {
|
|
760
767
|
order: selected,
|
|
761
768
|
waves: [selected],
|