@intentius/chant 0.124.27 → 0.124.29
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/build-params.d.ts +34 -1
- package/dist/build-params.d.ts.map +1 -1
- package/dist/build-params.js +31 -1
- package/dist/change-set-graph.d.ts +63 -0
- package/dist/change-set-graph.d.ts.map +1 -0
- package/dist/change-set-graph.js +130 -0
- package/dist/change-set.d.ts +62 -3
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +36 -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/build-params-cli.d.ts +7 -1
- package/dist/cli/build-params-cli.d.ts.map +1 -1
- package/dist/cli/build-params-cli.js +17 -8
- 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 +15 -11
- 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 +64 -4
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +43 -4
- 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 +10 -1
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +54 -6
- package/dist/cli/handlers/lifecycle-gc.d.ts +19 -0
- package/dist/cli/handlers/lifecycle-gc.d.ts.map +1 -0
- package/dist/cli/handlers/lifecycle-gc.js +143 -0
- package/dist/cli/handlers/pr.d.ts +16 -2
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +269 -37
- package/dist/cli/handlers/promote.d.ts +7 -0
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +440 -28
- package/dist/cli/handlers/release.d.ts +91 -0
- package/dist/cli/handlers/release.d.ts.map +1 -0
- package/dist/cli/handlers/release.js +589 -0
- package/dist/cli/handlers/run.d.ts +38 -2
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/run.js +234 -16
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +143 -17
- 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 +73 -5
- package/dist/cli/registry.d.ts +43 -5
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/run-events.d.ts +30 -0
- package/dist/cli/run-events.d.ts.map +1 -0
- package/dist/cli/run-events.js +49 -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 +6 -1
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/auto-release.js +3 -0
- package/dist/components/capability.d.ts +9 -0
- package/dist/components/capability.d.ts.map +1 -1
- 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 +50 -9
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +116 -54
- package/dist/components/fan-out-inputs.d.ts +69 -0
- package/dist/components/fan-out-inputs.d.ts.map +1 -0
- package/dist/components/fan-out-inputs.js +169 -0
- package/dist/components/fan-out-record.d.ts +13 -0
- package/dist/components/fan-out-record.d.ts.map +1 -1
- package/dist/components/fan-out-record.js +16 -0
- 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 +85 -26
- package/dist/components/fan-out.d.ts +4 -0
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/pr-pipeline.d.ts +25 -0
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +22 -4
- 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 +38 -2
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/promote.js +77 -2
- package/dist/components/release-compile.d.ts +142 -0
- package/dist/components/release-compile.d.ts.map +1 -0
- package/dist/components/release-compile.js +382 -0
- package/dist/components/release-gate.d.ts +135 -0
- package/dist/components/release-gate.d.ts.map +1 -0
- package/dist/components/release-gate.js +288 -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 +8 -1
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +11 -3
- package/dist/config.d.ts +45 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/flag-params.d.ts +54 -0
- package/dist/flag-params.d.ts.map +1 -0
- package/dist/flag-params.js +130 -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/__fixtures__/publish-fakes.d.ts +120 -0
- package/dist/lifecycle/__fixtures__/publish-fakes.d.ts.map +1 -0
- package/dist/lifecycle/__fixtures__/publish-fakes.js +304 -0
- package/dist/lifecycle/change-set-store.d.ts +68 -0
- package/dist/lifecycle/change-set-store.d.ts.map +1 -0
- package/dist/lifecycle/change-set-store.js +97 -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/delivery-metrics.d.ts +139 -0
- package/dist/lifecycle/delivery-metrics.d.ts.map +1 -0
- package/dist/lifecycle/delivery-metrics.js +145 -0
- package/dist/lifecycle/deploy-outcome.d.ts +81 -0
- package/dist/lifecycle/deploy-outcome.d.ts.map +1 -0
- package/dist/lifecycle/deploy-outcome.js +101 -0
- package/dist/lifecycle/gate-change-set.d.ts +78 -0
- package/dist/lifecycle/gate-change-set.d.ts.map +1 -0
- package/dist/lifecycle/gate-change-set.js +138 -0
- package/dist/lifecycle/gate-ledger.d.ts +51 -4
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.js +18 -0
- package/dist/lifecycle/git.d.ts +30 -1
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/git.js +31 -5
- package/dist/lifecycle/index.d.ts +4 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/index.js +4 -0
- package/dist/lifecycle/mixed-environment.d.ts +95 -0
- package/dist/lifecycle/mixed-environment.d.ts.map +1 -0
- package/dist/lifecycle/mixed-environment.js +154 -0
- package/dist/lifecycle/publish-attachments.d.ts +79 -0
- package/dist/lifecycle/publish-attachments.d.ts.map +1 -0
- package/dist/lifecycle/publish-attachments.js +179 -0
- package/dist/lifecycle/publish-credentials.d.ts +37 -0
- package/dist/lifecycle/publish-credentials.d.ts.map +1 -0
- package/dist/lifecycle/publish-credentials.js +69 -0
- package/dist/lifecycle/publish-declaration.d.ts +97 -0
- package/dist/lifecycle/publish-declaration.d.ts.map +1 -0
- package/dist/lifecycle/publish-declaration.js +83 -0
- package/dist/lifecycle/publish-forge.d.ts +53 -0
- package/dist/lifecycle/publish-forge.d.ts.map +1 -0
- package/dist/lifecycle/publish-forge.js +298 -0
- package/dist/lifecycle/publish-npm.d.ts +61 -0
- package/dist/lifecycle/publish-npm.d.ts.map +1 -0
- package/dist/lifecycle/publish-npm.js +242 -0
- package/dist/lifecycle/publish-oci.d.ts +64 -0
- package/dist/lifecycle/publish-oci.d.ts.map +1 -0
- package/dist/lifecycle/publish-oci.js +383 -0
- package/dist/lifecycle/publish-record.d.ts +66 -0
- package/dist/lifecycle/publish-record.d.ts.map +1 -0
- package/dist/lifecycle/publish-record.js +84 -0
- package/dist/lifecycle/publish-targets.d.ts +45 -0
- package/dist/lifecycle/publish-targets.d.ts.map +1 -0
- package/dist/lifecycle/publish-targets.js +85 -0
- package/dist/lifecycle/release-cut.d.ts +154 -0
- package/dist/lifecycle/release-cut.d.ts.map +1 -0
- package/dist/lifecycle/release-cut.js +366 -0
- package/dist/lifecycle/release-join.d.ts +95 -0
- package/dist/lifecycle/release-join.d.ts.map +1 -0
- package/dist/lifecycle/release-join.js +139 -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-publish.d.ts +312 -0
- package/dist/lifecycle/release-publish.d.ts.map +1 -0
- package/dist/lifecycle/release-publish.js +335 -0
- package/dist/lifecycle/release-revocation.d.ts +80 -0
- package/dist/lifecycle/release-revocation.d.ts.map +1 -0
- package/dist/lifecycle/release-revocation.js +123 -0
- package/dist/lifecycle/release-store.d.ts +200 -0
- package/dist/lifecycle/release-store.d.ts.map +1 -0
- package/dist/lifecycle/release-store.js +320 -0
- package/dist/lifecycle/release-verify.d.ts +61 -0
- package/dist/lifecycle/release-verify.d.ts.map +1 -0
- package/dist/lifecycle/release-verify.js +92 -0
- package/dist/lifecycle/release-workstation.d.ts +91 -0
- package/dist/lifecycle/release-workstation.d.ts.map +1 -0
- package/dist/lifecycle/release-workstation.js +180 -0
- package/dist/lifecycle/retention-policy.d.ts +45 -0
- package/dist/lifecycle/retention-policy.d.ts.map +1 -0
- package/dist/lifecycle/retention-policy.js +43 -0
- package/dist/lifecycle/retention.d.ts +185 -0
- package/dist/lifecycle/retention.d.ts.map +1 -0
- package/dist/lifecycle/retention.js +400 -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/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 +8 -0
- package/dist/plan-summary.d.ts.map +1 -1
- package/dist/plan-summary.js +8 -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/pr-loop.d.ts +7 -0
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +23 -4
- package/dist/pr-report-url.d.ts +82 -0
- package/dist/pr-report-url.d.ts.map +1 -0
- package/dist/pr-report-url.js +174 -0
- package/dist/provenance.d.ts +2 -2
- package/dist/provenance.d.ts.map +1 -1
- package/dist/run-event-store.d.ts +104 -0
- package/dist/run-event-store.d.ts.map +1 -0
- package/dist/run-event-store.js +251 -0
- package/dist/run-event-stream.d.ts +133 -0
- package/dist/run-event-stream.d.ts.map +1 -0
- package/dist/run-event-stream.js +242 -0
- package/dist/run-event.d.ts +285 -0
- package/dist/run-event.d.ts.map +1 -0
- package/dist/run-event.js +209 -0
- package/dist/wave-runtime.mjs +262 -226
- package/dist/workspace/__fixtures__/flag-workspace.d.ts +31 -0
- package/dist/workspace/__fixtures__/flag-workspace.d.ts.map +1 -0
- package/dist/workspace/__fixtures__/flag-workspace.js +114 -0
- 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 +32 -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/check.schema.json +4 -2
- package/dist/workspace/checks/records.d.ts +9 -1
- package/dist/workspace/checks/records.d.ts.map +1 -1
- package/dist/workspace/checks/records.js +35 -1
- package/dist/workspace/checks.d.ts +1 -0
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +2 -1
- 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 +281 -13
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +456 -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 +35 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +27 -1
- package/dist/workspace/declaration.schema.json +76 -0
- package/dist/workspace/declared-kinds.d.ts +16 -0
- package/dist/workspace/declared-kinds.d.ts.map +1 -1
- package/dist/workspace/declared-kinds.js +25 -0
- package/dist/workspace/delivery-metrics.d.ts +91 -0
- package/dist/workspace/delivery-metrics.d.ts.map +1 -0
- package/dist/workspace/delivery-metrics.js +217 -0
- package/dist/workspace/delivery-metrics.schema.json +519 -0
- package/dist/workspace/flags-read.d.ts +37 -0
- package/dist/workspace/flags-read.d.ts.map +1 -0
- package/dist/workspace/flags-read.js +103 -0
- package/dist/workspace/flags.d.ts +100 -0
- package/dist/workspace/flags.d.ts.map +1 -0
- package/dist/workspace/flags.js +98 -0
- package/dist/workspace/graph-cli.js +1 -1
- 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-cli.d.ts +11 -2
- package/dist/workspace/intent-cli.d.ts.map +1 -1
- package/dist/workspace/intent-cli.js +54 -5
- package/dist/workspace/intent-trace.d.ts +219 -0
- package/dist/workspace/intent-trace.d.ts.map +1 -0
- package/dist/workspace/intent-trace.js +314 -0
- package/dist/workspace/intent.d.ts +36 -7
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/intent.js +192 -22
- package/dist/workspace/intent.schema.json +702 -6
- 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/overlap.d.ts +146 -0
- package/dist/workspace/overlap.d.ts.map +1 -0
- package/dist/workspace/overlap.js +276 -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 +4 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +7 -1
- package/dist/workspace/records.d.ts +15 -2
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/records.js +32 -0
- package/dist/workspace/records.schema.json +21 -2
- package/dist/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
- package/dist/workspace/reference-kinds/flag/flag.schema.json +53 -0
- package/dist/workspace/releases.d.ts +81 -0
- package/dist/workspace/releases.d.ts.map +1 -0
- package/dist/workspace/releases.js +103 -0
- package/dist/workspace/releases.schema.json +513 -0
- package/dist/workspace/run-event.schema.json +295 -0
- package/dist/workspace/status-gates.d.ts +34 -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 +117 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/status.js +218 -4
- package/dist/workspace/status.schema.json +268 -2
- 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/dist/workspace/wip.d.ts.map +1 -1
- package/dist/workspace/wip.js +11 -3
- 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/build-params.test.ts +46 -0
- package/src/build-params.ts +55 -1
- package/src/change-set-graph.test.ts +72 -0
- package/src/change-set-graph.ts +141 -0
- package/src/change-set.ts +87 -6
- package/src/chant-version.ts +16 -0
- package/src/cli/build-params-cli.ts +22 -9
- package/src/cli/commands/build.ts +25 -11
- 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/handlers/approve-release.test.ts +84 -0
- package/src/cli/handlers/approve-revoked.test.ts +155 -0
- package/src/cli/handlers/approve.ts +65 -2
- package/src/cli/handlers/build.test.ts +67 -0
- package/src/cli/handlers/build.ts +46 -4
- package/src/cli/handlers/change-set.ts +49 -1
- package/src/cli/handlers/fan-out.test.ts +228 -1
- package/src/cli/handlers/fan-out.ts +53 -6
- package/src/cli/handlers/intent-trace.e2e.test.ts +201 -0
- package/src/cli/handlers/lifecycle-gc.test.ts +126 -0
- package/src/cli/handlers/lifecycle-gc.ts +146 -0
- package/src/cli/handlers/operator.test.ts +37 -0
- package/src/cli/handlers/pr.test.ts +341 -0
- package/src/cli/handlers/pr.ts +292 -47
- package/src/cli/handlers/promote.test.ts +669 -7
- package/src/cli/handlers/promote.ts +464 -29
- package/src/cli/handlers/release-implicit.e2e.test.ts +161 -0
- package/src/cli/handlers/release-join.e2e.test.ts +185 -0
- package/src/cli/handlers/release-publish-targets.e2e.test.ts +295 -0
- package/src/cli/handlers/release-verify.e2e.test.ts +117 -0
- package/src/cli/handlers/release-workstation-ci.e2e.test.ts +135 -0
- package/src/cli/handlers/release.e2e.test.ts +199 -0
- package/src/cli/handlers/release.ts +593 -0
- package/src/cli/handlers/run-auto-release.test.ts +80 -0
- package/src/cli/handlers/run-events-cmd.test.ts +92 -0
- package/src/cli/handlers/run-release.test.ts +55 -0
- package/src/cli/handlers/run.test.ts +30 -0
- package/src/cli/handlers/run.ts +243 -18
- package/src/cli/main.test.ts +8 -0
- package/src/cli/main.ts +143 -17
- 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 +56 -5
- package/src/cli/registry.ts +43 -5
- package/src/cli/run-events.ts +57 -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 +30 -0
- package/src/components/auto-release.ts +9 -1
- package/src/components/capability.ts +9 -0
- package/src/components/cli-support.test.ts +82 -0
- package/src/components/cli-support.ts +16 -9
- package/src/components/driver.test.ts +24 -0
- package/src/components/driver.ts +165 -56
- package/src/components/fan-out-inputs.test.ts +85 -0
- package/src/components/fan-out-inputs.ts +192 -0
- package/src/components/fan-out-record.test.ts +10 -0
- package/src/components/fan-out-record.ts +19 -0
- package/src/components/fan-out-run.ts +104 -35
- package/src/components/fan-out.ts +4 -0
- package/src/components/pr-pipeline.ts +35 -4
- 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 +94 -3
- package/src/components/release-compile.test.ts +147 -0
- package/src/components/release-compile.ts +459 -0
- package/src/components/release-gate.test.ts +215 -0
- package/src/components/release-gate.ts +355 -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 +16 -3
- package/src/config.ts +15 -1
- package/src/flag-params.test.ts +144 -0
- package/src/flag-params.ts +134 -0
- package/src/index.ts +2 -0
- package/src/lifecycle/__fixtures__/publish-fakes.ts +351 -0
- package/src/lifecycle/change-set-store.test.ts +217 -0
- package/src/lifecycle/change-set-store.ts +113 -0
- package/src/lifecycle/commit-sha.ts +23 -0
- package/src/lifecycle/delivery-metrics.ts +263 -0
- package/src/lifecycle/deploy-outcome.ts +147 -0
- package/src/lifecycle/gate-change-set.e2e.test.ts +122 -0
- package/src/lifecycle/gate-change-set.ts +164 -0
- package/src/lifecycle/gate-ledger.test.ts +33 -0
- package/src/lifecycle/gate-ledger.ts +68 -3
- package/src/lifecycle/git.ts +61 -8
- package/src/lifecycle/index.ts +4 -0
- package/src/lifecycle/mixed-environment.test.ts +97 -0
- package/src/lifecycle/mixed-environment.ts +204 -0
- package/src/lifecycle/publish-attachments.ts +196 -0
- package/src/lifecycle/publish-credentials.ts +84 -0
- package/src/lifecycle/publish-declaration.ts +95 -0
- package/src/lifecycle/publish-forge.ts +325 -0
- package/src/lifecycle/publish-npm.ts +259 -0
- package/src/lifecycle/publish-oci.ts +396 -0
- package/src/lifecycle/publish-record.ts +113 -0
- package/src/lifecycle/publish-resume.test.ts +168 -0
- package/src/lifecycle/publish-targets.test.ts +494 -0
- package/src/lifecycle/publish-targets.ts +100 -0
- package/src/lifecycle/release-cut-signed.test.ts +180 -0
- package/src/lifecycle/release-cut.test.ts +483 -0
- package/src/lifecycle/release-cut.ts +503 -0
- package/src/lifecycle/release-flag.test.ts +112 -0
- package/src/lifecycle/release-join.test.ts +68 -0
- package/src/lifecycle/release-join.ts +182 -0
- package/src/lifecycle/release-ledger.test.ts +14 -0
- package/src/lifecycle/release-ledger.ts +85 -17
- package/src/lifecycle/release-publish.test.ts +225 -0
- package/src/lifecycle/release-publish.ts +568 -0
- package/src/lifecycle/release-revocation.ts +147 -0
- package/src/lifecycle/release-store.ts +434 -0
- package/src/lifecycle/release-verify.test.ts +110 -0
- package/src/lifecycle/release-verify.ts +120 -0
- package/src/lifecycle/release-workstation.test.ts +204 -0
- package/src/lifecycle/release-workstation.ts +216 -0
- package/src/lifecycle/retention-growth.e2e.test.ts +279 -0
- package/src/lifecycle/retention-policy.ts +63 -0
- package/src/lifecycle/retention.test.ts +363 -0
- package/src/lifecycle/retention.ts +508 -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/commit-run-gate-deploy-join.test.ts +117 -0
- 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 +9 -0
- package/src/plan-summary.test.ts +20 -0
- package/src/plan-summary.ts +8 -1
- package/src/point-decision.ts +12 -2
- package/src/pr-loop.ts +25 -4
- package/src/pr-report-url.test.ts +131 -0
- package/src/pr-report-url.ts +209 -0
- package/src/provenance.ts +2 -2
- package/src/run-event-store.test.ts +144 -0
- package/src/run-event-store.ts +273 -0
- package/src/run-event-stream.test.ts +175 -0
- package/src/run-event-stream.ts +309 -0
- package/src/run-event.test.ts +277 -0
- package/src/run-event.ts +471 -0
- package/src/wave-loop-golden.test.ts +9 -0
- package/src/workspace/__fixtures__/flag-workspace.ts +132 -0
- package/src/workspace/__fixtures__/older-records/change-set-984534ea9.json +100 -0
- package/src/workspace/__fixtures__/older-records/older-records.json +326 -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 +32 -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/check.schema.json +4 -2
- package/src/workspace/checks/records.ts +35 -1
- package/src/workspace/checks.ts +2 -1
- 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 +635 -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 +76 -0
- package/src/workspace/declaration.test.ts +28 -0
- package/src/workspace/declaration.ts +60 -2
- package/src/workspace/declared-kinds.ts +40 -1
- package/src/workspace/delivery-metrics.schema.json +519 -0
- package/src/workspace/delivery-metrics.test.ts +236 -0
- package/src/workspace/delivery-metrics.ts +286 -0
- package/src/workspace/flags-read.ts +121 -0
- package/src/workspace/flags.test.ts +141 -0
- package/src/workspace/flags.ts +157 -0
- package/src/workspace/graph-cli.ts +1 -1
- package/src/workspace/identity-gate-rule.ts +91 -7
- package/src/workspace/identity.ts +14 -1
- package/src/workspace/intent-cli.ts +46 -5
- package/src/workspace/intent-trace.test.ts +173 -0
- package/src/workspace/intent-trace.ts +484 -0
- package/src/workspace/intent.schema.json +702 -6
- package/src/workspace/intent.ts +196 -26
- 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/older-records.test.ts +412 -0
- package/src/workspace/overlap.test.ts +165 -0
- package/src/workspace/overlap.ts +340 -0
- package/src/workspace/promotion-order.ts +97 -0
- package/src/workspace/read-contract.e2e.test.ts +5 -1
- package/src/workspace/reason-codes.test.ts +7 -1
- package/src/workspace/reason-codes.ts +7 -1
- package/src/workspace/record-assets.test.ts +2 -1
- package/src/workspace/records-contract.e2e.test.ts +2 -1
- package/src/workspace/records.schema.json +21 -2
- package/src/workspace/records.ts +36 -2
- package/src/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
- package/src/workspace/reference-kinds/flag/flag.schema.json +53 -0
- package/src/workspace/releases.schema.json +513 -0
- package/src/workspace/releases.test.ts +108 -0
- package/src/workspace/releases.ts +133 -0
- package/src/workspace/run-event.schema.json +295 -0
- package/src/workspace/status-contract.test.ts +81 -1
- package/src/workspace/status-gates.ts +64 -1
- package/src/workspace/status-mixed.test.ts +152 -0
- package/src/workspace/status-revoked.test.ts +153 -0
- package/src/workspace/status-stewards.ts +6 -0
- package/src/workspace/status.schema.json +268 -2
- package/src/workspace/status.ts +334 -4
- 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/workspace/wip.ts +11 -2
- 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
|
@@ -457,12 +457,24 @@ export async function checkLexicon(dir: string): Promise<CheckResult> {
|
|
|
457
457
|
pass: hasSerializerTest,
|
|
458
458
|
});
|
|
459
459
|
|
|
460
|
+
// A lexicon whose src/codegen/docs.ts runs docsPipeline always has a page:
|
|
461
|
+
// the pipeline writes the overview (index.mdx) from the manifest. Inside the
|
|
462
|
+
// chant repository that page is generated into the main docs site rather
|
|
463
|
+
// than committed under docs/ (chant #3993), so k3d, whose docs are all
|
|
464
|
+
// generated, has no .mdx of its own to count.
|
|
460
465
|
const mdxFiles = findFiles(join(dir, "docs"), (n) => n.endsWith(".mdx"));
|
|
466
|
+
const docsTs = join(dir, "src", "codegen", "docs.ts");
|
|
467
|
+
const pipelineOverview = existsSync(docsTs) && readFileSync(docsTs, "utf-8").includes("docsPipeline(");
|
|
461
468
|
items.push({
|
|
462
469
|
name: "At least 1 .mdx doc page",
|
|
463
470
|
tier: 1,
|
|
464
|
-
pass: mdxFiles.length > 0,
|
|
465
|
-
detail:
|
|
471
|
+
pass: mdxFiles.length > 0 || pipelineOverview,
|
|
472
|
+
detail:
|
|
473
|
+
mdxFiles.length > 0
|
|
474
|
+
? `${mdxFiles.length} page(s)`
|
|
475
|
+
: pipelineOverview
|
|
476
|
+
? "the docs pipeline's generated overview"
|
|
477
|
+
: undefined,
|
|
466
478
|
});
|
|
467
479
|
|
|
468
480
|
// Counting pages says nothing about whether a reader can find them.
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Docs site template generators for init-lexicon scaffold.
|
|
2
|
+
* Docs site template generators for init-lexicon scaffold. The app files
|
|
3
|
+
* (package.json, tsconfig, Astro config, content config) are written only for a
|
|
4
|
+
* lexicon outside the chant repository; inside it, the lexicon's docs are a
|
|
5
|
+
* section of the main site (chant #3993).
|
|
3
6
|
*/
|
|
4
7
|
|
|
8
|
+
import { DOCS_SITE_DEPENDENCIES } from "../../../../codegen/docs-in-site";
|
|
9
|
+
|
|
5
10
|
export function generateDocsPackageJson(name: string): string {
|
|
6
11
|
return JSON.stringify(
|
|
7
12
|
{
|
|
@@ -14,11 +19,7 @@ export function generateDocsPackageJson(name: string): string {
|
|
|
14
19
|
build: "astro build",
|
|
15
20
|
preview: "astro preview",
|
|
16
21
|
},
|
|
17
|
-
dependencies: {
|
|
18
|
-
"@astrojs/starlight": "^0.37.6",
|
|
19
|
-
astro: "^5.6.1",
|
|
20
|
-
sharp: "^0.34.2",
|
|
21
|
-
},
|
|
22
|
+
dependencies: { ...DOCS_SITE_DEPENDENCIES },
|
|
22
23
|
},
|
|
23
24
|
null,
|
|
24
25
|
2,
|
|
@@ -78,6 +78,31 @@ describe("initLexiconCommand", () => {
|
|
|
78
78
|
}
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
+
// chant #3993: inside the chant repository the lexicon's docs are a section
|
|
82
|
+
// of the main site, so only docs/pages/ is scaffolded.
|
|
83
|
+
test("inside the chant repository it scaffolds docs/pages/ and no docs app", async () => {
|
|
84
|
+
mkdirSync(join(tmpDir, "docs"), { recursive: true });
|
|
85
|
+
writeFileSync(join(tmpDir, "docs", "package.json"), JSON.stringify({ name: "@intentius/chant-docs" }));
|
|
86
|
+
writeFileSync(join(tmpDir, "docs", "astro.config.mjs"), "export default {};\n");
|
|
87
|
+
const targetDir = join(tmpDir, "lexicons", "in-repo");
|
|
88
|
+
const result = await initLexiconCommand({ name: "in-repo", path: targetDir });
|
|
89
|
+
|
|
90
|
+
expect(result.success).toBe(true);
|
|
91
|
+
expect(existsSync(join(targetDir, "docs/pages/getting-started.mdx"))).toBe(true);
|
|
92
|
+
for (const file of ["docs/package.json", "docs/tsconfig.json", "docs/astro.config.mjs", "docs/src"]) {
|
|
93
|
+
expect(existsSync(join(targetDir, file)), file).toBe(false);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("a standalone docs app pins the main site's Starlight and Astro", async () => {
|
|
98
|
+
const targetDir = join(tmpDir, "pins");
|
|
99
|
+
await initLexiconCommand({ name: "pins", path: targetDir });
|
|
100
|
+
const docsPkg = JSON.parse(readFileSync(join(targetDir, "docs/package.json"), "utf-8"));
|
|
101
|
+
const mainPkg = JSON.parse(readFileSync(join(__dirname, "..", "..", "..", "..", "..", "docs", "package.json"), "utf-8"));
|
|
102
|
+
expect(docsPkg.dependencies["@astrojs/starlight"]).toBe(mainPkg.dependencies["@astrojs/starlight"]);
|
|
103
|
+
expect(docsPkg.dependencies.astro).toBe(mainPkg.dependencies.astro);
|
|
104
|
+
});
|
|
105
|
+
|
|
81
106
|
test("plugin.ts contains all 5 required lifecycle methods", async () => {
|
|
82
107
|
const targetDir = join(tmpDir, "lifecycle");
|
|
83
108
|
await initLexiconCommand({ name: "k8s", path: targetDir });
|
|
@@ -12,6 +12,7 @@ import { generatePackageJson, generateTsConfig, generateTsConfigBuild, generateJ
|
|
|
12
12
|
import { generatePluginTestTs, generateSerializerTestTs, generateCompletionsTestTs, generateHoverTestTs } from "./init-lexicon/templates/tests";
|
|
13
13
|
import { generateDocsPackageJson, generateDocsTsConfig, generateDocsAstroConfig, generateDocsContentConfig, generateDocsIndexMdx, generateDocsGettingStartedMdx } from "./init-lexicon/templates/docs";
|
|
14
14
|
import { generateExamplePackageJson, generateExampleInfraTs } from "./init-lexicon/templates/examples";
|
|
15
|
+
import { findChantDocsSite } from "../../codegen/docs-in-site";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Init-lexicon command options
|
|
@@ -101,6 +102,13 @@ export async function initLexiconCommand(options: InitLexiconOptions): Promise<I
|
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
// Inside the chant repository a lexicon's docs are a section of the main
|
|
106
|
+
// site (chant #3993): the pipeline writes its pages into docs/, so the
|
|
107
|
+
// lexicon gets only docs/pages/. Anywhere else it gets a standalone
|
|
108
|
+
// Starlight app of its own, as before.
|
|
109
|
+
const standaloneDocs = findChantDocsSite(targetDir) === undefined;
|
|
110
|
+
const standaloneDocsDirs = ["docs/src", "docs/src/content", "docs/src/content/docs"];
|
|
111
|
+
|
|
104
112
|
// Create directory structure
|
|
105
113
|
const dirs = [
|
|
106
114
|
"",
|
|
@@ -112,9 +120,7 @@ export async function initLexiconCommand(options: InitLexiconOptions): Promise<I
|
|
|
112
120
|
"src/lsp",
|
|
113
121
|
"src/generated",
|
|
114
122
|
"docs",
|
|
115
|
-
|
|
116
|
-
"docs/src/content",
|
|
117
|
-
"docs/src/content/docs",
|
|
123
|
+
...(standaloneDocs ? standaloneDocsDirs : []),
|
|
118
124
|
"docs/pages",
|
|
119
125
|
"examples/getting-started",
|
|
120
126
|
"examples/getting-started/src",
|
|
@@ -157,11 +163,15 @@ export async function initLexiconCommand(options: InitLexiconOptions): Promise<I
|
|
|
157
163
|
"justfile": generateJustfile(name),
|
|
158
164
|
".gitignore": generateGitignore(),
|
|
159
165
|
"README.md": generateReadme(name, names),
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
166
|
+
...(standaloneDocs
|
|
167
|
+
? {
|
|
168
|
+
"docs/package.json": generateDocsPackageJson(name),
|
|
169
|
+
"docs/tsconfig.json": generateDocsTsConfig(),
|
|
170
|
+
"docs/astro.config.mjs": generateDocsAstroConfig(name),
|
|
171
|
+
"docs/src/content.config.ts": generateDocsContentConfig(),
|
|
172
|
+
"docs/src/content/docs/index.mdx": generateDocsIndexMdx(name),
|
|
173
|
+
}
|
|
174
|
+
: {}),
|
|
165
175
|
"docs/pages/getting-started.mdx": generateDocsGettingStartedMdx(name),
|
|
166
176
|
"examples/getting-started/package.json": generateExamplePackageJson(name),
|
|
167
177
|
"examples/getting-started/src/infra.ts": generateExampleInfraTs(name, names),
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant approve` on a release gate (#4045): the approval copies the release
|
|
3
|
+
* the pending fact names, with its plan and environment, so it counts for
|
|
4
|
+
* that release only. Against a temp repo; nothing is pushed.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { afterEach, describe, expect, test, vi } from "vitest";
|
|
8
|
+
import { withTestDir } from "@intentius/chant-test-utils";
|
|
9
|
+
import { spawnSync } from "node:child_process";
|
|
10
|
+
import { writeFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { appendPendingGate, readGateLedger } from "../../lifecycle/gate-ledger";
|
|
13
|
+
import { resetGateOrigin } from "../../lifecycle/gate-origin";
|
|
14
|
+
import { makeRelease, persistRelease } from "../../lifecycle/release-store";
|
|
15
|
+
|
|
16
|
+
vi.mock("../../op/discover", () => ({ discoverOps: async () => ({ errors: [], ops: new Map() }) }));
|
|
17
|
+
|
|
18
|
+
const { recordGateApproval } = await import("./approve");
|
|
19
|
+
|
|
20
|
+
function git(args: string[], cwd: string): void {
|
|
21
|
+
spawnSync("git", args, { cwd, encoding: "utf-8" });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The release the gate binds. #4033: approve reads it to check its commit isn't revoked, so it is stored. */
|
|
25
|
+
const STORED = makeRelease({ member: null, commit: "1".repeat(40), artifactDigests: [], targets: [{ env: "prod", templates: [], params: [] }] });
|
|
26
|
+
const RELEASE = STORED.releaseDigest;
|
|
27
|
+
const DOC = `jcs1-sha256:${"d".repeat(64)}`;
|
|
28
|
+
|
|
29
|
+
async function repoWithReleaseGate(dir: string): Promise<void> {
|
|
30
|
+
git(["init", "-q", "-b", "main"], dir);
|
|
31
|
+
git(["config", "user.email", "t@chant.dev"], dir);
|
|
32
|
+
git(["config", "user.name", "T"], dir);
|
|
33
|
+
writeFileSync(join(dir, "README.md"), "x\n");
|
|
34
|
+
git(["add", "."], dir);
|
|
35
|
+
git(["commit", "-q", "-m", "init"], dir);
|
|
36
|
+
await persistRelease(STORED, [], { cwd: dir });
|
|
37
|
+
await appendPendingGate(
|
|
38
|
+
{
|
|
39
|
+
op: "release",
|
|
40
|
+
gate: "prod-release",
|
|
41
|
+
timestamp: "2026-10-16T00:00:00.000Z",
|
|
42
|
+
expiresAt: "2999-01-01T00:00:00.000Z",
|
|
43
|
+
planDigest: DOC,
|
|
44
|
+
environment: "prod",
|
|
45
|
+
releaseDigest: RELEASE,
|
|
46
|
+
},
|
|
47
|
+
{ cwd: dir },
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
describe("chant approve on a release gate (#4045)", () => {
|
|
52
|
+
const cwd = process.cwd();
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
process.chdir(cwd);
|
|
55
|
+
resetGateOrigin();
|
|
56
|
+
vi.restoreAllMocks();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("the approval names the release, the environment and the change set the pending fact names", async () => {
|
|
60
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
61
|
+
await withTestDir(async (dir) => {
|
|
62
|
+
await repoWithReleaseGate(dir);
|
|
63
|
+
process.chdir(dir);
|
|
64
|
+
const outcome = await recordGateApproval("release", "prod-release", { origin: "cli", actor: "alice", cwd: dir, environment: "prod" });
|
|
65
|
+
expect(outcome.ok).toBe(true);
|
|
66
|
+
const { resolutions } = await readGateLedger("release", { cwd: dir });
|
|
67
|
+
expect(resolutions).toEqual([expect.objectContaining({ resolvedBy: "alice", planDigest: DOC, environment: "prod", releaseDigest: RELEASE })]);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("an approval of another plan names no release, so no release gate counts it", async () => {
|
|
72
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
73
|
+
await withTestDir(async (dir) => {
|
|
74
|
+
await repoWithReleaseGate(dir);
|
|
75
|
+
process.chdir(dir);
|
|
76
|
+
const other = `jcs1-sha256:${"e".repeat(64)}`;
|
|
77
|
+
const outcome = await recordGateApproval("release", "prod-release", { origin: "cli", actor: "alice", cwd: dir, environment: "prod", plan: other });
|
|
78
|
+
expect(outcome.ok).toBe(true);
|
|
79
|
+
const { resolutions } = await readGateLedger("release", { cwd: dir });
|
|
80
|
+
expect(resolutions[0].planDigest).toBe(other);
|
|
81
|
+
expect(resolutions[0].releaseDigest).toBeUndefined();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #4033 (ws-105): when a commit is revoked, the release cut from it is
|
|
3
|
+
* revoked, and its pending release gate refuses approval. Against temp repos;
|
|
4
|
+
* nothing is pushed.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { afterEach, describe, expect, test, vi } from "vitest";
|
|
8
|
+
import { withTestDir } from "@intentius/chant-test-utils";
|
|
9
|
+
import { spawnSync } from "node:child_process";
|
|
10
|
+
import { writeFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { appendPendingGate, readGateLedger } from "../../lifecycle/gate-ledger";
|
|
13
|
+
import { resetGateOrigin } from "../../lifecycle/gate-origin";
|
|
14
|
+
import { appendCut, makeRelease, persistRelease, type Release } from "../../lifecycle/release-store";
|
|
15
|
+
|
|
16
|
+
vi.mock("../../op/discover", () => ({ discoverOps: async () => ({ errors: [], ops: new Map() }) }));
|
|
17
|
+
|
|
18
|
+
const { recordGateApproval } = await import("./approve");
|
|
19
|
+
|
|
20
|
+
function git(cwd: string, ...args: string[]): string {
|
|
21
|
+
const r = spawnSync("git", args, { cwd, encoding: "utf-8" });
|
|
22
|
+
if (r.status !== 0) throw new Error(`git ${args.join(" ")}: ${r.stderr}`);
|
|
23
|
+
return r.stdout.trim();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const DOC = `jcs1-sha256:${"d".repeat(64)}`;
|
|
27
|
+
const GREEN = { branch: "main", phases: { test: ["test"] }, require: ["test"] };
|
|
28
|
+
|
|
29
|
+
function declaration(dir: string, green: Record<string, unknown>): void {
|
|
30
|
+
writeFileSync(
|
|
31
|
+
join(dir, "chant.workspace.json"),
|
|
32
|
+
JSON.stringify({ name: "acme", schema: 1, members: [{ name: "root", dir: ".", kind: "other", because: "the release fixture" }], ci: { green } }, null, 2),
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** A green commit, a release cut from it as v1.0.0, and a release gate pending for it in prod. */
|
|
37
|
+
async function releaseWaitingAtGate(dir: string): Promise<{ sha: string; release: Release }> {
|
|
38
|
+
git(dir, "init", "-q", "-b", "main");
|
|
39
|
+
git(dir, "config", "user.email", "t@chant.dev");
|
|
40
|
+
git(dir, "config", "user.name", "T");
|
|
41
|
+
declaration(dir, GREEN);
|
|
42
|
+
git(dir, "add", ".");
|
|
43
|
+
git(dir, "commit", "-q", "-m", "init");
|
|
44
|
+
const sha = git(dir, "rev-parse", "HEAD");
|
|
45
|
+
git(dir, "tag", "-a", "-m", "ci: green", `ci/green/${sha}`, sha);
|
|
46
|
+
const release = makeRelease({
|
|
47
|
+
member: null,
|
|
48
|
+
commit: sha,
|
|
49
|
+
artifactDigests: [],
|
|
50
|
+
targets: [{ env: "prod", templates: [{ component: "api", path: "t.json", digest: `sha256:${"c".repeat(64)}` }], params: [] }],
|
|
51
|
+
});
|
|
52
|
+
await persistRelease(release, [], { cwd: dir });
|
|
53
|
+
await appendCut({ releaseDigest: release.releaseDigest, label: "v1.0.0", actor: "alice", timestamp: "2026-10-16T10:00:00.000Z", runOrigin: null }, { cwd: dir });
|
|
54
|
+
await appendPendingGate(
|
|
55
|
+
{
|
|
56
|
+
op: "release",
|
|
57
|
+
gate: "prod-release",
|
|
58
|
+
timestamp: "2026-10-16T11:00:00.000Z",
|
|
59
|
+
expiresAt: "2999-01-01T00:00:00.000Z",
|
|
60
|
+
planDigest: DOC,
|
|
61
|
+
environment: "prod",
|
|
62
|
+
releaseDigest: release.releaseDigest,
|
|
63
|
+
gitSha: sha,
|
|
64
|
+
},
|
|
65
|
+
{ cwd: dir },
|
|
66
|
+
);
|
|
67
|
+
return { sha, release };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** ci tick's revoked tag for a run from chant runs (#4044): the run's id is null and the Op run is named in opRun. */
|
|
71
|
+
function revoke(dir: string, sha: string): void {
|
|
72
|
+
const record = {
|
|
73
|
+
schema: 1,
|
|
74
|
+
tag: "revoked",
|
|
75
|
+
commit: sha,
|
|
76
|
+
branch: "main",
|
|
77
|
+
at: "2026-10-16T12:00:00.000Z",
|
|
78
|
+
source: "runs",
|
|
79
|
+
phase: "test",
|
|
80
|
+
run: { name: "smoke", id: null, conclusion: "failure", url: null, opRun: { id: "r-12", env: "staging", signer: "runner:ci", statement: null } },
|
|
81
|
+
};
|
|
82
|
+
git(dir, "tag", "-a", "-m", `ci: phase test failed in smoke (failure)\n\n${JSON.stringify(record, null, 2)}\n`, `ci/revoked/${sha}`, sha);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
describe("chant approve on the gate of a revoked release (#4033)", () => {
|
|
86
|
+
const cwd = process.cwd();
|
|
87
|
+
afterEach(() => {
|
|
88
|
+
process.chdir(cwd);
|
|
89
|
+
resetGateOrigin();
|
|
90
|
+
vi.restoreAllMocks();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("revoke a commit, and its release's pending gate refuses approval with release-revoked and the fix line", async () => {
|
|
94
|
+
const errors: string[] = [];
|
|
95
|
+
vi.spyOn(console, "error").mockImplementation((...m: unknown[]) => { errors.push(m.join(" ")); });
|
|
96
|
+
await withTestDir(async (dir) => {
|
|
97
|
+
const { sha } = await releaseWaitingAtGate(dir);
|
|
98
|
+
process.chdir(dir);
|
|
99
|
+
revoke(dir, sha);
|
|
100
|
+
const outcome = await recordGateApproval("release", "prod-release", { origin: "cli", actor: "alice", cwd: dir, environment: "prod" });
|
|
101
|
+
expect(outcome.ok).toBe(false);
|
|
102
|
+
const said = errors.join("\n");
|
|
103
|
+
expect(said).toContain(`release v1.0.0 was cut from commit ${sha.slice(0, 12)}, which ci/revoked/${sha} revokes (phase test failed in smoke (Op run r-12 in staging))`);
|
|
104
|
+
expect(said).toContain("[release-revoked]");
|
|
105
|
+
expect(said).toContain("chant approve release prod-release --expire");
|
|
106
|
+
expect((await readGateLedger("release", { cwd: dir })).resolutions).toEqual([]);
|
|
107
|
+
|
|
108
|
+
// Naming the plan outright doesn't get round it.
|
|
109
|
+
const named = await recordGateApproval("release", "prod-release", { origin: "cli", actor: "alice", cwd: dir, environment: "prod", plan: DOC });
|
|
110
|
+
expect(named.ok).toBe(false);
|
|
111
|
+
expect((await readGateLedger("release", { cwd: dir })).resolutions).toEqual([]);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("before the commit is revoked, the same gate takes the approval", async () => {
|
|
116
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
117
|
+
await withTestDir(async (dir) => {
|
|
118
|
+
const { release } = await releaseWaitingAtGate(dir);
|
|
119
|
+
process.chdir(dir);
|
|
120
|
+
const outcome = await recordGateApproval("release", "prod-release", { origin: "cli", actor: "alice", cwd: dir, environment: "prod" });
|
|
121
|
+
expect(outcome.ok).toBe(true);
|
|
122
|
+
expect((await readGateLedger("release", { cwd: dir })).resolutions).toEqual([expect.objectContaining({ releaseDigest: release.releaseDigest })]);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("with ci.green.signedSince, a hand-pushed revoked tag is ignored and revokes nothing", async () => {
|
|
127
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
128
|
+
await withTestDir(async (dir) => {
|
|
129
|
+
const { sha } = await releaseWaitingAtGate(dir);
|
|
130
|
+
// The release's own commit is the pivot, so a tag on it needs a statement; this one has none.
|
|
131
|
+
declaration(dir, { ...GREEN, signedSince: sha });
|
|
132
|
+
git(dir, "commit", "-q", "-am", "require signed ci tags");
|
|
133
|
+
revoke(dir, sha);
|
|
134
|
+
process.chdir(dir);
|
|
135
|
+
const outcome = await recordGateApproval("release", "prod-release", { origin: "cli", actor: "alice", cwd: dir, environment: "prod" });
|
|
136
|
+
expect(outcome.ok).toBe(true);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("a gate whose release can't be read refuses, since whether it is revoked is unknown", async () => {
|
|
141
|
+
const errors: string[] = [];
|
|
142
|
+
vi.spyOn(console, "error").mockImplementation((...m: unknown[]) => { errors.push(m.join(" ")); });
|
|
143
|
+
await withTestDir(async (dir) => {
|
|
144
|
+
await releaseWaitingAtGate(dir);
|
|
145
|
+
await appendPendingGate(
|
|
146
|
+
{ op: "release", gate: "prod-release", timestamp: "2026-10-16T13:00:00.000Z", expiresAt: "2999-01-01T00:00:00.000Z", planDigest: DOC, environment: "prod", releaseDigest: `jcs1-sha256:${"e".repeat(64)}` },
|
|
147
|
+
{ cwd: dir },
|
|
148
|
+
);
|
|
149
|
+
process.chdir(dir);
|
|
150
|
+
const outcome = await recordGateApproval("release", "prod-release", { origin: "cli", actor: "alice", cwd: dir, environment: "prod" });
|
|
151
|
+
expect(outcome.ok).toBe(false);
|
|
152
|
+
expect(errors.join("\n")).toContain("[release-unreadable]");
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
});
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
type GateApprover, type GatePolicyDecision, type GatePolicyEvaluator, type ResolvedGateApproval,
|
|
22
22
|
} from "../../op/gate-approval";
|
|
23
23
|
import { approverOf, humanQuorumSince, tallyGateApprovals } from "../../op/gate";
|
|
24
|
-
import { FAN_OUT_GATE_OP, OVERRIDE_GATE_OP, WORKSPACE_UPGRADE_GATE_OP } from "../../op/gate-name";
|
|
24
|
+
import { FAN_OUT_GATE_OP, OVERRIDE_GATE_OP, RELEASE_GATE_OP, WORKSPACE_UPGRADE_GATE_OP } from "../../op/gate-name";
|
|
25
25
|
import { PR_GATE_OP } from "../../pr-loop";
|
|
26
26
|
import { pushLifecycleReport, requireLifecycleLedger } from "../../lifecycle/git";
|
|
27
27
|
import { LIFECYCLE_LOCAL_NOTE, isLifecycleLocalNote } from "../../lifecycle/local-note";
|
|
@@ -112,6 +112,8 @@ export async function runApprove(ctx: CommandContext): Promise<number> {
|
|
|
112
112
|
timestamp: now,
|
|
113
113
|
expiresAt: now,
|
|
114
114
|
...(standing.description ? { description: standing.description } : {}),
|
|
115
|
+
...(standing.runId ? { runId: standing.runId } : {}),
|
|
116
|
+
...(standing.gitSha ? { gitSha: standing.gitSha } : {}),
|
|
115
117
|
});
|
|
116
118
|
const push = await reportedPush(
|
|
117
119
|
`The expiry is recorded locally on ${LIFECYCLE_BRANCH}. Until it reaches the remote, ` +
|
|
@@ -127,6 +129,8 @@ export async function runApprove(ctx: CommandContext): Promise<number> {
|
|
|
127
129
|
? `The next \`chant components pr-apply\` decides this gate from scratch and records a fresh pending fact.`
|
|
128
130
|
: opName === WORKSPACE_UPGRADE_GATE_OP
|
|
129
131
|
? `The next \`chant workspace upgrade ${gate}\` decides this gate from scratch and records a fresh pending fact.`
|
|
132
|
+
: opName === RELEASE_GATE_OP
|
|
133
|
+
? `The next \`chant components promote --release\` decides this gate from scratch and records a fresh pending fact.`
|
|
130
134
|
: `The next \`chant run ${opName}\` decides this gate from scratch and records a fresh pending fact.`,
|
|
131
135
|
));
|
|
132
136
|
return 0;
|
|
@@ -177,6 +181,8 @@ export async function runApprove(ctx: CommandContext): Promise<number> {
|
|
|
177
181
|
? `The pull request's apply (\`chant components pr-apply\`) walks through gate "${gate}" when it plans this same digest.`
|
|
178
182
|
: opName === WORKSPACE_UPGRADE_GATE_OP
|
|
179
183
|
? `Repeat \`chant workspace upgrade ${gate}\` with the same target, and it applies the patch this approval names.`
|
|
184
|
+
: opName === RELEASE_GATE_OP
|
|
185
|
+
? `Repeat the same \`chant components promote --release\`, and it walks through gate "${gate}" when it plans this same change set for this release.`
|
|
180
186
|
: `Run \`chant run ${opName}\` and it walks through gate "${gate}".`),
|
|
181
187
|
));
|
|
182
188
|
return 0;
|
|
@@ -249,6 +255,46 @@ export type GateApprovalOutcome =
|
|
|
249
255
|
| { ok: true; record: GateResolutionRecord; pushed: boolean }
|
|
250
256
|
| { ok: false };
|
|
251
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Refuse the approval of a release gate whose release is revoked (#4033,
|
|
260
|
+
* ws-105): its commit carries a `ci/revoked/<sha>` tag that counts, read from
|
|
261
|
+
* local tags as `release cut` reads them. Prints the refusal and returns true
|
|
262
|
+
* when it refuses. A release file that can't be read, or tags that can't be
|
|
263
|
+
* judged, refuse too, since whether the release is revoked is then unknown.
|
|
264
|
+
*/
|
|
265
|
+
async function refuseRevokedRelease(opName: string, gate: string, releaseDigest: string, cwd: string): Promise<boolean> {
|
|
266
|
+
const { readRelease, readCuts, labelsByDigest } = await import("../../lifecycle/release-store");
|
|
267
|
+
const { readRevokedCommits, revocationOf, revokedRefusal } = await import("../../lifecycle/release-revocation");
|
|
268
|
+
const release = await readRelease(releaseDigest, { cwd }).catch(() => null);
|
|
269
|
+
if (!release) {
|
|
270
|
+
console.error(formatError({
|
|
271
|
+
message: `Gate "${gate}" on "${opName}" binds release ${releaseDigest}, which can't be read from ${LIFECYCLE_BRANCH}, so whether it is revoked is unknown [release-unreadable]`,
|
|
272
|
+
hint: `Fetch the ledger branch (git fetch origin ${LIFECYCLE_BRANCH}:${LIFECYCLE_BRANCH}) and approve again from the member's directory.`,
|
|
273
|
+
}));
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
let revoked: Awaited<ReturnType<typeof readRevokedCommits>>;
|
|
277
|
+
try {
|
|
278
|
+
revoked = await readRevokedCommits(cwd);
|
|
279
|
+
} catch (err) {
|
|
280
|
+
console.error(formatError({
|
|
281
|
+
message: `Gate "${gate}" on "${opName}" binds release ${releaseDigest}, and the ci tags can't be judged: ${err instanceof Error ? err.message : String(err)} [declaration-invalid]`,
|
|
282
|
+
hint: "Fix ci.green in chant.workspace.json at base; chant workspace check names the problem.",
|
|
283
|
+
}));
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
const r = revocationOf(release, revoked);
|
|
287
|
+
if (!r) return false;
|
|
288
|
+
const label = labelsByDigest((await readCuts({ cwd }).catch(() => ({ cuts: [] }))).cuts).get(releaseDigest) ?? null;
|
|
289
|
+
console.error(formatError(revokedRefusal(
|
|
290
|
+
{ releaseDigest, label },
|
|
291
|
+
r,
|
|
292
|
+
`Clear the pending gate with \`chant approve ${opName} ${gate} --expire\`, then promote a release cut from a green commit: ` +
|
|
293
|
+
"`chant ci last-green` names the newest, and `chant release list` marks the revoked releases.",
|
|
294
|
+
)));
|
|
295
|
+
return true;
|
|
296
|
+
}
|
|
297
|
+
|
|
252
298
|
/**
|
|
253
299
|
* The ledger write behind `chant approve` — extracted so `chant run approve`
|
|
254
300
|
* (#2121) records the identical fact before waking the runtime that hosts the
|
|
@@ -283,7 +329,7 @@ export async function recordGateApproval(
|
|
|
283
329
|
// so there is no `*.op.ts` to find and nothing is wrong when none is there.
|
|
284
330
|
// #3949: a gate that lists this one as an alias, after an Op was restructured.
|
|
285
331
|
const successor = aliasingGate([...ops.values()].map((o) => o.config), opName, gate);
|
|
286
|
-
if (!successor && !ops.has(opName) && opName !== FAN_OUT_GATE_OP && opName !== WORKSPACE_UPGRADE_GATE_OP && opName !== OVERRIDE_GATE_OP) {
|
|
332
|
+
if (!successor && !ops.has(opName) && opName !== FAN_OUT_GATE_OP && opName !== WORKSPACE_UPGRADE_GATE_OP && opName !== OVERRIDE_GATE_OP && opName !== RELEASE_GATE_OP) {
|
|
287
333
|
console.error(formatWarning({
|
|
288
334
|
message: `Op "${opName}" was not found among discovered *.op.ts declarations — recording the resolution anyway`,
|
|
289
335
|
}));
|
|
@@ -389,6 +435,18 @@ export async function recordGateApproval(
|
|
|
389
435
|
standing?.checkpointDigest !== undefined && samePlanDigest(planDigest, standing.planDigest)
|
|
390
436
|
? standing.checkpointDigest
|
|
391
437
|
: undefined;
|
|
438
|
+
// #4045: a release gate's fact names the release its change set was
|
|
439
|
+
// planned for. An approval of that fact's plan is for that release too; an
|
|
440
|
+
// approval of another plan names none, and no release gate counts it.
|
|
441
|
+
const releaseDigest =
|
|
442
|
+
standing?.releaseDigest !== undefined && samePlanDigest(planDigest, standing.planDigest) ? standing.releaseDigest : undefined;
|
|
443
|
+
// #4033 (ws-105): a release gate whose release was cut from a revoked
|
|
444
|
+
// commit is superseded. Its promote refuses the release, so an approval of
|
|
445
|
+
// it would count for nothing; refuse it here, whatever plan is named.
|
|
446
|
+
if (standing?.releaseDigest !== undefined) {
|
|
447
|
+
const refused = await refuseRevokedRelease(opName, gate, standing.releaseDigest, opts.cwd ?? process.cwd());
|
|
448
|
+
if (refused) return { ok: false };
|
|
449
|
+
}
|
|
392
450
|
|
|
393
451
|
// chant#2384 — the gate's whole value is that its two halves have different
|
|
394
452
|
// authors. At a shell they do: a person runs, reads the plan, and approves.
|
|
@@ -587,6 +645,10 @@ export async function recordGateApproval(
|
|
|
587
645
|
...(planDigest !== undefined ? { planDigest } : {}),
|
|
588
646
|
...(checkpointDigest !== undefined ? { checkpointDigest } : {}),
|
|
589
647
|
...(environment !== undefined ? { environment } : {}),
|
|
648
|
+
...(releaseDigest !== undefined ? { releaseDigest } : {}),
|
|
649
|
+
// #4020: the commit and run the gate waited on, off the fact this approves.
|
|
650
|
+
...(standing?.gitSha ? { gitSha: standing.gitSha } : {}),
|
|
651
|
+
...(standing?.runId ? { runId: standing.runId } : {}),
|
|
590
652
|
origin,
|
|
591
653
|
...(refusal && opts.allowSameOrigin ? { sameOriginOverride: true } : {}),
|
|
592
654
|
});
|
|
@@ -607,6 +669,7 @@ export async function recordGateApproval(
|
|
|
607
669
|
console.error(formatInfo(
|
|
608
670
|
`This approves the plan ${record.planDigest}` +
|
|
609
671
|
(record.environment !== undefined ? ` in environment "${record.environment}"` : "") +
|
|
672
|
+
(record.releaseDigest !== undefined ? ` for release ${record.releaseDigest}` : "") +
|
|
610
673
|
", and only that plan. A run whose fresh plan differs refuses rather than applying it.",
|
|
611
674
|
));
|
|
612
675
|
}
|
|
@@ -70,6 +70,37 @@ describe("runBuild --components --generate (chant #1108 build-time parameters)",
|
|
|
70
70
|
vi.restoreAllMocks();
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
+
test("--promote-to that skips a step of the declared promotion order is refused, and generates nothing (#4030)", async () => {
|
|
74
|
+
loadChantConfigUpwardMock.mockResolvedValue({ config: { environments: ["dev", "staging", "prod"] } });
|
|
75
|
+
const stderr = makeStderrSpy();
|
|
76
|
+
const exit = await runBuild({ args: makeArgs({ env: "dev", promoteTo: "prod" }), plugins: [], serializers: [] });
|
|
77
|
+
expect(exit).toBe(1);
|
|
78
|
+
expect(generateComponentsPipelineMock).not.toHaveBeenCalled();
|
|
79
|
+
const out = stderr.join("\n");
|
|
80
|
+
expect(out).toMatch(/\[promote-skips-environment\]/);
|
|
81
|
+
expect(out).toMatch(/--allow-skip/);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("--promote-to the next step of the order generates as before (#4030)", async () => {
|
|
85
|
+
loadChantConfigUpwardMock.mockResolvedValue({ config: { environments: ["dev", "staging", "prod"] } });
|
|
86
|
+
generateComponentsPipelineMock.mockResolvedValue({ success: true, yaml: "x", stages: [], jobs: [] });
|
|
87
|
+
vi.spyOn(console, "log").mockImplementation(() => {});
|
|
88
|
+
const exit = await runBuild({ args: makeArgs({ env: "staging", promoteTo: "prod" }), plugins: [], serializers: [] });
|
|
89
|
+
expect(exit).toBe(0);
|
|
90
|
+
expect(generateComponentsPipelineMock.mock.calls[0][2]).toEqual({ env: "staging", promoteTo: "prod" });
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("--allow-skip lets the skip through and the promote job passes it on (#4030)", async () => {
|
|
94
|
+
loadChantConfigUpwardMock.mockResolvedValue({ config: { environments: ["dev", "staging", "prod"] } });
|
|
95
|
+
generateComponentsPipelineMock.mockResolvedValue({ success: true, yaml: "x", stages: [], jobs: [] });
|
|
96
|
+
vi.spyOn(console, "log").mockImplementation(() => {});
|
|
97
|
+
const exit = await runBuild({ args: makeArgs({ env: "dev", promoteTo: "prod", allowSkip: true }), plugins: [], serializers: [] });
|
|
98
|
+
expect(exit).toBe(0);
|
|
99
|
+
expect(generateComponentsPipelineMock.mock.calls[0][2]).toMatchObject({
|
|
100
|
+
promoteCommand: ["chant", "components", "promote", "--from", "dev", "--to", "prod", "--allow-skip"],
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
73
104
|
test("--promote-to is forwarded to the generator as promoteTo (#2575)", async () => {
|
|
74
105
|
generateComponentsPipelineMock.mockResolvedValue({ success: true, yaml: "stages: []", stages: [], jobs: [] });
|
|
75
106
|
vi.spyOn(console, "log").mockImplementation(() => {});
|
|
@@ -81,6 +112,42 @@ describe("runBuild --components --generate (chant #1108 build-time parameters)",
|
|
|
81
112
|
vi.restoreAllMocks();
|
|
82
113
|
});
|
|
83
114
|
|
|
115
|
+
test("--image and each --before-script are forwarded to the generator, in order (#4002)", async () => {
|
|
116
|
+
generateComponentsPipelineMock.mockResolvedValue({ success: true, yaml: "stages: []", stages: [], jobs: [] });
|
|
117
|
+
vi.spyOn(console, "log").mockImplementation(() => {});
|
|
118
|
+
|
|
119
|
+
const exit = await runBuild({
|
|
120
|
+
args: makeArgs({ generate: "forgejo", prLoop: true, image: "node:22-bookworm", beforeScript: ["npm ci", "npm run setup"] }),
|
|
121
|
+
plugins: [],
|
|
122
|
+
serializers: [],
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
expect(exit).toBe(0);
|
|
126
|
+
expect(generateComponentsPipelineMock).toHaveBeenCalledWith(
|
|
127
|
+
".",
|
|
128
|
+
"forgejo",
|
|
129
|
+
{ env: undefined, prLoop: {}, image: "node:22-bookworm", beforeScript: ["npm ci", "npm run setup"] },
|
|
130
|
+
undefined,
|
|
131
|
+
[],
|
|
132
|
+
);
|
|
133
|
+
vi.restoreAllMocks();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("--pr-loop with --events-json and --report-url asks the generated jobs for both (#4007)", async () => {
|
|
137
|
+
generateComponentsPipelineMock.mockResolvedValue({ success: true, yaml: "stages: []", stages: [], jobs: [] });
|
|
138
|
+
vi.spyOn(console, "log").mockImplementation(() => {});
|
|
139
|
+
|
|
140
|
+
const exit = await runBuild({
|
|
141
|
+
args: makeArgs({ generate: "github", prLoop: true, eventsJson: true, reportUrl: "s3://reports/acme" }),
|
|
142
|
+
plugins: [],
|
|
143
|
+
serializers: [],
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(exit).toBe(0);
|
|
147
|
+
expect(generateComponentsPipelineMock).toHaveBeenCalledWith(".", "github", { env: undefined, prLoop: { events: true, reportUrl: "s3://reports/acme" } }, undefined, []);
|
|
148
|
+
vi.restoreAllMocks();
|
|
149
|
+
});
|
|
150
|
+
|
|
84
151
|
test("chant.config.ts's declared buildParams resolve, log, and are forwarded to generateComponentsPipeline", async () => {
|
|
85
152
|
loadChantConfigUpwardMock.mockResolvedValue({
|
|
86
153
|
config: { buildParams: { tier: { type: "string", default: "light" } } },
|