@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
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The release gate (#4045, ws-104 questions 2 and 6): the gate `chant
|
|
3
|
+
* components promote --release` passes for an environment.
|
|
4
|
+
*
|
|
5
|
+
* ## What it binds
|
|
6
|
+
*
|
|
7
|
+
* A promote under a release plans the release's change set for the
|
|
8
|
+
* environment it deploys to ({@link planReleaseChangeSet}), stores it on
|
|
9
|
+
* `chant/lifecycle` under its digest (`../lifecycle/gate-change-set.ts`), and
|
|
10
|
+
* decides every gate its components reach against three values:
|
|
11
|
+
*
|
|
12
|
+
* - the change-set document's `digest`, in `planDigest`;
|
|
13
|
+
* - the release, in `releaseDigest`;
|
|
14
|
+
* - the environment, in `environment`.
|
|
15
|
+
*
|
|
16
|
+
* An approval counts only when all three match (`evaluateGate` in
|
|
17
|
+
* `../op/gate.ts`). The document itself names the release and the environment
|
|
18
|
+
* it was planned for, and both are part of its digest, so a stored document
|
|
19
|
+
* names the one release its gate bound and two releases never share a digest.
|
|
20
|
+
*
|
|
21
|
+
* Every gate a promote under a release reaches is recorded in one ledger,
|
|
22
|
+
* {@link RELEASE_GATE_OP}, rather than in each component's. The gate name a
|
|
23
|
+
* composition authors is kept, so components that share a gate name share one
|
|
24
|
+
* gate per environment, and one approval of the release's change set passes
|
|
25
|
+
* each of them. A promote of one component (`--component`) plans that
|
|
26
|
+
* component's subset, which has its own digest and needs its own approval.
|
|
27
|
+
*
|
|
28
|
+
* ## Empty change sets
|
|
29
|
+
*
|
|
30
|
+
* When the change set changes nothing ({@link isEmptyChangeSet}), the
|
|
31
|
+
* promote writes an `empty: true` resolution for each gate, with the actor
|
|
32
|
+
* running it in `resolvedBy` ({@link emptyResolution}). A gate counts it only
|
|
33
|
+
* after it reads the stored document back and finds it empty
|
|
34
|
+
* ({@link emptyVerifier}). Quorum and signing rules don't apply to it.
|
|
35
|
+
*
|
|
36
|
+
* ## The members
|
|
37
|
+
*
|
|
38
|
+
* A component with a step whose capability can plan (`terraform-apply`) is
|
|
39
|
+
* planned by that capability, as a pull request's plan is. A plan that
|
|
40
|
+
* returns no change-set part is a hole, since nothing says what it changes.
|
|
41
|
+
*
|
|
42
|
+
* Any other component is a `chant` member compared with what the
|
|
43
|
+
* environment runs now: its latest deploy record and the release that record
|
|
44
|
+
* names. The artifact digest, each template the release's target records for
|
|
45
|
+
* the component, and the target's parameters are compared, and each one that
|
|
46
|
+
* differs is an attribute of one `update` entry (a `create` when the
|
|
47
|
+
* environment has no deploy of the component). When they are all equal the
|
|
48
|
+
* member has no entries. When the environment's deploy names no release, or
|
|
49
|
+
* the release it names can't be read, the member has a hole: nothing says
|
|
50
|
+
* what the environment runs, so the change can't be shown empty. So does a
|
|
51
|
+
* component a promote, rollback or redeploy left failed or gated with nothing
|
|
52
|
+
* recorded since (#4035): its record names what ran before that run.
|
|
53
|
+
*/
|
|
54
|
+
import { deployContext, resolveComponentGraph, resolveStepInput } from "./driver.js";
|
|
55
|
+
import { componentPlanDigest } from "./gate-plan.js";
|
|
56
|
+
import { gateName, RELEASE_GATE_OP } from "../op/gate-name.js";
|
|
57
|
+
import { capabilitySteps, planContext, readComponentOutputs } from "./wave-plan.js";
|
|
58
|
+
import { composeChangeSet, isEmptyChangeSet, } from "../change-set.js";
|
|
59
|
+
/** The gate ledger every release gate is recorded in: `_gates/release.jsonl`, under the member's prefix. */
|
|
60
|
+
export { RELEASE_GATE_OP };
|
|
61
|
+
/** The address and type a `chant` member's one entry has. */
|
|
62
|
+
export const RELEASE_COMPONENT_ENTRY_TYPE = "chant:component";
|
|
63
|
+
function isGate(step) {
|
|
64
|
+
return step.kind === "gate";
|
|
65
|
+
}
|
|
66
|
+
function isPhase(step) {
|
|
67
|
+
return typeof step.phase === "string" && Array.isArray(step.steps);
|
|
68
|
+
}
|
|
69
|
+
/** The name of every gate the compositions declare, nested phases included, sorted and distinct. */
|
|
70
|
+
export function gateNamesOf(components) {
|
|
71
|
+
const names = new Set();
|
|
72
|
+
const walk = (steps) => {
|
|
73
|
+
for (const step of steps) {
|
|
74
|
+
if (isPhase(step))
|
|
75
|
+
walk(step.steps);
|
|
76
|
+
else if (isGate(step))
|
|
77
|
+
names.add(gateName(step));
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
for (const c of components)
|
|
81
|
+
for (const phase of c.deploy)
|
|
82
|
+
walk(phase.steps);
|
|
83
|
+
return [...names].sort();
|
|
84
|
+
}
|
|
85
|
+
const byString = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
86
|
+
/** One attribute per key whose value differs between `before` and `after`, sorted by path. */
|
|
87
|
+
function differing(before, after, prefix) {
|
|
88
|
+
const out = [];
|
|
89
|
+
for (const key of [...new Set([...before.keys(), ...after.keys()])].sort(byString)) {
|
|
90
|
+
const was = before.get(key);
|
|
91
|
+
const now = after.get(key);
|
|
92
|
+
if (was === now)
|
|
93
|
+
continue;
|
|
94
|
+
out.push({ path: `${prefix}${key}`, ...(was !== undefined ? { before: was } : {}), ...(now !== undefined ? { after: now } : {}) });
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
/** What one target says a component deploys: its templates by path, and the target's parameters by name. */
|
|
99
|
+
function deployedInputs(release, env, component) {
|
|
100
|
+
const target = release.targets.find((t) => t.env === env);
|
|
101
|
+
if (!target)
|
|
102
|
+
return null;
|
|
103
|
+
return {
|
|
104
|
+
templates: new Map(target.templates.filter((t) => t.component === component).map((t) => [t.path, t.digest])),
|
|
105
|
+
params: new Map(target.params.map((p) => [p.name, JSON.stringify(p.value)])),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* A component no capability plans, as a `chant` member: what the release
|
|
110
|
+
* deploys compared with what the environment runs now. See the module doc.
|
|
111
|
+
*/
|
|
112
|
+
export function chantComponentPart(input) {
|
|
113
|
+
const { component, release, env, digest, current } = input;
|
|
114
|
+
const name = component.name;
|
|
115
|
+
const member = {
|
|
116
|
+
member: name,
|
|
117
|
+
lexicon: "chant",
|
|
118
|
+
planner: "chant",
|
|
119
|
+
status: "planned",
|
|
120
|
+
planDigest: componentPlanDigest({ environment: env, component, release: digest }),
|
|
121
|
+
holes: [],
|
|
122
|
+
};
|
|
123
|
+
const want = deployedInputs(release, env, name);
|
|
124
|
+
if (!want) {
|
|
125
|
+
member.holes.push({ address: name, type: RELEASE_COMPONENT_ENTRY_TYPE, reason: `release ${release.releaseDigest} has no target for "${env}"` });
|
|
126
|
+
return { member, entries: [] };
|
|
127
|
+
}
|
|
128
|
+
const entry = (action, attributes) => ({
|
|
129
|
+
member,
|
|
130
|
+
entries: [
|
|
131
|
+
{
|
|
132
|
+
member: name,
|
|
133
|
+
lexicon: "chant",
|
|
134
|
+
planner: "chant",
|
|
135
|
+
address: name,
|
|
136
|
+
type: RELEASE_COMPONENT_ENTRY_TYPE,
|
|
137
|
+
name,
|
|
138
|
+
action,
|
|
139
|
+
...(action === "update" ? { disruption: "unknown" } : {}),
|
|
140
|
+
scope: env,
|
|
141
|
+
attributes,
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
});
|
|
145
|
+
if (input.unsettled !== undefined) {
|
|
146
|
+
member.holes.push({ address: name, type: RELEASE_COMPONENT_ENTRY_TYPE, reason: input.unsettled });
|
|
147
|
+
return { member, entries: [] };
|
|
148
|
+
}
|
|
149
|
+
if (!current) {
|
|
150
|
+
return entry("create", [
|
|
151
|
+
{ path: "artifact", after: digest },
|
|
152
|
+
...differing(new Map(), want.templates, "template:"),
|
|
153
|
+
...differing(new Map(), want.params, "param:"),
|
|
154
|
+
]);
|
|
155
|
+
}
|
|
156
|
+
const named = current.record.releaseDigest;
|
|
157
|
+
if (named === undefined) {
|
|
158
|
+
member.holes.push({
|
|
159
|
+
address: name,
|
|
160
|
+
type: RELEASE_COMPONENT_ENTRY_TYPE,
|
|
161
|
+
reason: `the "${env}" deploy of ${name} (run ${current.record.runId}) names no release, so what it runs can't be compared with this release`,
|
|
162
|
+
});
|
|
163
|
+
return { member, entries: [] };
|
|
164
|
+
}
|
|
165
|
+
const have = current.release ? deployedInputs(current.release, env, name) : null;
|
|
166
|
+
if (!have) {
|
|
167
|
+
member.holes.push({
|
|
168
|
+
address: name,
|
|
169
|
+
type: RELEASE_COMPONENT_ENTRY_TYPE,
|
|
170
|
+
reason: current.release
|
|
171
|
+
? `release ${named}, which the "${env}" deploy of ${name} names, has no target for "${env}"`
|
|
172
|
+
: `release ${named}, which the "${env}" deploy of ${name} names, can't be read from chant/lifecycle`,
|
|
173
|
+
});
|
|
174
|
+
return { member, entries: [] };
|
|
175
|
+
}
|
|
176
|
+
const attributes = [
|
|
177
|
+
...differing(new Map([["", current.record.digest]]), new Map([["", digest]]), "artifact"),
|
|
178
|
+
...differing(have.templates, want.templates, "template:"),
|
|
179
|
+
...differing(have.params, want.params, "param:"),
|
|
180
|
+
];
|
|
181
|
+
return attributes.length === 0 ? { member, entries: [] } : entry("update", attributes);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Plan the release's change set for `env`: one part per promoted component
|
|
185
|
+
* (or per member its planning capability names), composed into a document
|
|
186
|
+
* that names the release and the environment. Never throws for a component
|
|
187
|
+
* that fails to plan: it becomes a failed member.
|
|
188
|
+
*/
|
|
189
|
+
export async function planReleaseChangeSet(input) {
|
|
190
|
+
const { release, env, registry } = input;
|
|
191
|
+
const components = [...input.components];
|
|
192
|
+
const byName = new Map(components.map((c) => [c.name, c]));
|
|
193
|
+
const outputs = { ...(input.seededOutputs ?? {}) };
|
|
194
|
+
const read = new Set(Object.keys(outputs));
|
|
195
|
+
const parts = [];
|
|
196
|
+
const { order } = resolveComponentGraph(components.map((c) => ({ ...c, dependsOn: (c.dependsOn ?? []).filter((d) => byName.has(d)) })));
|
|
197
|
+
for (const name of order) {
|
|
198
|
+
const component = byName.get(name);
|
|
199
|
+
const digest = input.digests.get(name) ?? "";
|
|
200
|
+
const plannable = capabilitySteps(component.deploy).filter((s) => registry.has(s.kind) && registry.resolve(s.kind).plan !== undefined);
|
|
201
|
+
if (plannable.length === 0) {
|
|
202
|
+
parts.push(chantComponentPart({ component, release, env, digest, current: input.current.get(name), unsettled: input.unsettled?.get(name) }));
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const ctx = deployContext({ env }, name);
|
|
206
|
+
try {
|
|
207
|
+
for (const dep of component.dependsOn ?? []) {
|
|
208
|
+
if (read.has(dep) || !byName.has(dep))
|
|
209
|
+
continue;
|
|
210
|
+
read.add(dep);
|
|
211
|
+
const found = await readComponentOutputs(byName.get(dep), registry, deployContext({ env }, dep), outputs);
|
|
212
|
+
if (found)
|
|
213
|
+
outputs[dep] = found;
|
|
214
|
+
}
|
|
215
|
+
for (const step of plannable) {
|
|
216
|
+
const { kind, ...rest } = step;
|
|
217
|
+
const planned = await registry.resolve(kind).plan(planContext(ctx, rest, outputs), resolveStepInput(rest, {}, outputs));
|
|
218
|
+
parts.push(planned.changeSet ?? {
|
|
219
|
+
member: {
|
|
220
|
+
member: planned.member,
|
|
221
|
+
lexicon: "chant",
|
|
222
|
+
planner: "chant",
|
|
223
|
+
status: "planned",
|
|
224
|
+
planDigest: planned.planDigest,
|
|
225
|
+
holes: [{ address: planned.member, reason: `its ${kind} plan describes no changes, so what it changes is unknown` }],
|
|
226
|
+
},
|
|
227
|
+
entries: [],
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
parts.push({
|
|
233
|
+
member: {
|
|
234
|
+
member: name,
|
|
235
|
+
lexicon: "chant",
|
|
236
|
+
planner: "chant",
|
|
237
|
+
status: "failed",
|
|
238
|
+
error: err instanceof Error ? err.message : String(err),
|
|
239
|
+
planDigest: null,
|
|
240
|
+
holes: [],
|
|
241
|
+
},
|
|
242
|
+
entries: [],
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return composeChangeSet(parts, {
|
|
247
|
+
...(input.chant !== undefined ? { chant: input.chant } : {}),
|
|
248
|
+
planned: { releaseDigest: release.releaseDigest, environment: env },
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
/** The members a release gate refuses: provisional ones, which no approval of the document covers (`change-set.mdx`). */
|
|
252
|
+
export function provisionalMembers(doc) {
|
|
253
|
+
return doc.members.filter((m) => m.provisional === true).map((m) => m.member);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* The `verifyEmpty` a release gate decides with: the document stored under
|
|
257
|
+
* the digest, read back and checked against its digest by `read`, is the
|
|
258
|
+
* one planned for this release and environment, and it is empty.
|
|
259
|
+
*/
|
|
260
|
+
export function emptyVerifier(read, planned) {
|
|
261
|
+
return async (digest) => {
|
|
262
|
+
const stored = await read(digest);
|
|
263
|
+
return (stored.status === "found" &&
|
|
264
|
+
stored.document.releaseDigest === planned.releaseDigest &&
|
|
265
|
+
stored.document.environment === planned.environment &&
|
|
266
|
+
isEmptyChangeSet(stored.document));
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/** The `empty: true` resolution a promote writes for one release gate over an empty change set. */
|
|
270
|
+
export function emptyResolution(input) {
|
|
271
|
+
const { doc } = input;
|
|
272
|
+
if (doc.releaseDigest === undefined || doc.environment === undefined) {
|
|
273
|
+
throw new Error(`change set ${doc.digest} names no release and environment, so no release gate can pass on it`);
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
op: RELEASE_GATE_OP,
|
|
277
|
+
gate: input.gate,
|
|
278
|
+
resolvedBy: input.actor,
|
|
279
|
+
timestamp: input.timestamp,
|
|
280
|
+
note: `the change set of release ${doc.releaseDigest} for "${doc.environment}" is empty`,
|
|
281
|
+
planDigest: doc.digest,
|
|
282
|
+
environment: doc.environment,
|
|
283
|
+
releaseDigest: doc.releaseDigest,
|
|
284
|
+
empty: true,
|
|
285
|
+
...(input.gitSha ? { gitSha: input.gitSha } : {}),
|
|
286
|
+
...(input.runId ? { runId: input.runId } : {}),
|
|
287
|
+
};
|
|
288
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A promote under a release (#4026, ws-104 question 5): the deploy reads the
|
|
3
|
+
* templates the release recorded for the target environment, not the ones in
|
|
4
|
+
* the promoting checkout.
|
|
5
|
+
*
|
|
6
|
+
* Each template a promoted component's deploy names ({@link templateRefs}) has
|
|
7
|
+
* to be one the release's target records for that component. Its bytes are
|
|
8
|
+
* read from `_releases/templates/` on `chant/lifecycle` and checked against
|
|
9
|
+
* the target's digest, the way a promote checks the publish digest, and a
|
|
10
|
+
* mismatch refuses the promote before anything runs. The bytes are written
|
|
11
|
+
* under `.chant/release-templates/<digest>/` in the member's directory and the
|
|
12
|
+
* step reads them from there. The path is relative and fixed by the digest,
|
|
13
|
+
* so a gate approval bound to the promote's plan still matches on a re-run.
|
|
14
|
+
*/
|
|
15
|
+
import type { DriverComponent } from "./driver.js";
|
|
16
|
+
import type { Release, ReleaseTarget } from "../lifecycle/release-store.js";
|
|
17
|
+
import type { ReleaseRecord } from "../lifecycle/release-ledger.js";
|
|
18
|
+
import type { BuildArchiveManifest } from "./verbs/build-archive.js";
|
|
19
|
+
/** Where a promote under a release writes the recorded templates, relative to the member's directory. */
|
|
20
|
+
export declare const RELEASE_TEMPLATES_DIR = ".chant/release-templates";
|
|
21
|
+
/** A template ready to write: where, and its bytes. */
|
|
22
|
+
export interface PinnedTemplate {
|
|
23
|
+
/** Relative to the member's directory. */
|
|
24
|
+
path: string;
|
|
25
|
+
content: string;
|
|
26
|
+
}
|
|
27
|
+
/** The release's target for `env`, or an error naming the environments it has. */
|
|
28
|
+
export declare function targetFor(release: Release, env: string): {
|
|
29
|
+
target: ReleaseTarget;
|
|
30
|
+
} | {
|
|
31
|
+
error: string;
|
|
32
|
+
};
|
|
33
|
+
/** Whether a release is of a project with no components (#4046): no artifact, and every template it records has `component: null`. */
|
|
34
|
+
export declare function isImplicitRelease(release: Release): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Point every template `components` read at the target's recorded bytes.
|
|
37
|
+
* Returns the rewritten compositions and the files to write, or the reasons
|
|
38
|
+
* the promote is refused: a template the target does not record, one whose
|
|
39
|
+
* bytes are missing, or one whose bytes do not hash to the target's digest.
|
|
40
|
+
*/
|
|
41
|
+
export declare function pinReleaseTemplates(components: readonly DriverComponent[], release: Release, target: ReleaseTarget, readTemplate: (digest: string) => Promise<string | null>): Promise<{
|
|
42
|
+
components: DriverComponent[];
|
|
43
|
+
files: PinnedTemplate[];
|
|
44
|
+
} | {
|
|
45
|
+
errors: string[];
|
|
46
|
+
}>;
|
|
47
|
+
/**
|
|
48
|
+
* The files a release's target records, read back by digest and checked, for
|
|
49
|
+
* `chant release export` (#4046). A project with no components has no deploy
|
|
50
|
+
* step for a promote to point at the recorded bytes, so its deploy (an Op such
|
|
51
|
+
* as `chant run deploy`, or a CI job) reads the files this writes instead of
|
|
52
|
+
* building them again. Each path is the one the build wrote, relative to the
|
|
53
|
+
* member's directory; a template whose bytes are missing or don't hash to the
|
|
54
|
+
* target's digest is refused, as {@link pinReleaseTemplates} refuses one.
|
|
55
|
+
*/
|
|
56
|
+
export declare function targetFiles(release: Release, target: ReleaseTarget, readTemplate: (digest: string) => Promise<string | null>): Promise<{
|
|
57
|
+
files: PinnedTemplate[];
|
|
58
|
+
} | {
|
|
59
|
+
errors: string[];
|
|
60
|
+
}>;
|
|
61
|
+
/** Write the pinned templates under `dir`, the member's directory. */
|
|
62
|
+
export declare function writePinnedTemplates(dir: string, files: readonly PinnedTemplate[]): void;
|
|
63
|
+
/**
|
|
64
|
+
* Remove the templates {@link writePinnedTemplates} wrote once the promote is
|
|
65
|
+
* done, and {@link RELEASE_TEMPLATES_DIR} with them when nothing else is in
|
|
66
|
+
* it, so a promote leaves the checkout as it found it. A re-run writes them
|
|
67
|
+
* again from the release.
|
|
68
|
+
*/
|
|
69
|
+
export declare function removePinnedTemplates(dir: string, files: readonly PinnedTemplate[]): void;
|
|
70
|
+
/**
|
|
71
|
+
* Whether the artifact a promote deploys under a release is one the release
|
|
72
|
+
* built (#4045, the rule #4026 left open). The release records build digests
|
|
73
|
+
* (`artifactDigests`, the digest the archive step returned), and a deploy
|
|
74
|
+
* record carries the publish digest, which is another value for an image, so
|
|
75
|
+
* the two are compared through the build manifest the source deploy record
|
|
76
|
+
* names (`manifestDigest`), whose entries carry build digests at the same
|
|
77
|
+
* archive paths:
|
|
78
|
+
*
|
|
79
|
+
* - a source record that names this release in `releaseDigest` matches;
|
|
80
|
+
* - else, each of the release's artifacts for the component must be in that
|
|
81
|
+
* manifest at its path with the release's digest, and one that differs is
|
|
82
|
+
* a mismatch;
|
|
83
|
+
* - a record with no `manifestDigest`, a manifest that isn't stored, or an
|
|
84
|
+
* artifact path the manifest doesn't hold can't be compared.
|
|
85
|
+
*
|
|
86
|
+
* A mismatch is a warning, not a refusal. The environment promoted from was
|
|
87
|
+
* deployed by its own `run --components`, which builds again, and an image
|
|
88
|
+
* build is not reproducible, so its digest differs from the cut's for the
|
|
89
|
+
* same commit. Refusing would refuse every image promote until a deploy can
|
|
90
|
+
* run the release's own artifacts (#4043).
|
|
91
|
+
*/
|
|
92
|
+
export declare function releaseArtifactMismatches(release: Release, sources: ReadonlyArray<{
|
|
93
|
+
component: string;
|
|
94
|
+
source: ReleaseRecord;
|
|
95
|
+
}>, readManifest: (manifestDigest: string) => Promise<BuildArchiveManifest | null>): Promise<string[]>;
|
|
96
|
+
//# sourceMappingURL=release-promote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-promote.d.ts","sourceRoot":"","sources":["../../src/components/release-promote.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAuC,MAAM,UAAU,CAAC;AAErF,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,yGAAyG;AACzG,eAAO,MAAM,qBAAqB,6BAA6B,CAAC;AAEhE,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAMtG;AAED,sIAAsI;AACtI,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAG3D;AAUD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,SAAS,eAAe,EAAE,EACtC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GACvD,OAAO,CAAC;IAAE,UAAU,EAAE,eAAe,EAAE,CAAC;IAAC,KAAK,EAAE,cAAc,EAAE,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAiD5F;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GACvD,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA2B7D;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAMxF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAQzF;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,aAAa,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC,EACpE,YAAY,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,GAC7E,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBnB"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A promote under a release (#4026, ws-104 question 5): the deploy reads the
|
|
3
|
+
* templates the release recorded for the target environment, not the ones in
|
|
4
|
+
* the promoting checkout.
|
|
5
|
+
*
|
|
6
|
+
* Each template a promoted component's deploy names ({@link templateRefs}) has
|
|
7
|
+
* to be one the release's target records for that component. Its bytes are
|
|
8
|
+
* read from `_releases/templates/` on `chant/lifecycle` and checked against
|
|
9
|
+
* the target's digest, the way a promote checks the publish digest, and a
|
|
10
|
+
* mismatch refuses the promote before anything runs. The bytes are written
|
|
11
|
+
* under `.chant/release-templates/<digest>/` in the member's directory and the
|
|
12
|
+
* step reads them from there. The path is relative and fixed by the digest,
|
|
13
|
+
* so a gate approval bound to the promote's plan still matches on a re-run.
|
|
14
|
+
*/
|
|
15
|
+
import { mkdirSync, readdirSync, rmSync, rmdirSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { basename, dirname, join } from "node:path";
|
|
17
|
+
import { contentDigest } from "../content-digest.js";
|
|
18
|
+
import { TEMPLATE_FIELDS, templateRefs } from "./release-compile.js";
|
|
19
|
+
/** Where a promote under a release writes the recorded templates, relative to the member's directory. */
|
|
20
|
+
export const RELEASE_TEMPLATES_DIR = ".chant/release-templates";
|
|
21
|
+
/** The release's target for `env`, or an error naming the environments it has. */
|
|
22
|
+
export function targetFor(release, env) {
|
|
23
|
+
const target = release.targets.find((t) => t.env === env);
|
|
24
|
+
if (target)
|
|
25
|
+
return { target };
|
|
26
|
+
return {
|
|
27
|
+
error: `release ${release.releaseDigest} has no target for "${env}"; it was compiled for ${release.targets.map((t) => t.env).join(", ") || "no environment"}`,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Whether a release is of a project with no components (#4046): no artifact, and every template it records has `component: null`. */
|
|
31
|
+
export function isImplicitRelease(release) {
|
|
32
|
+
const templates = release.targets.flatMap((t) => t.templates);
|
|
33
|
+
return release.artifactDigests.length === 0 && templates.length > 0 && templates.every((t) => t.component === null);
|
|
34
|
+
}
|
|
35
|
+
function isGate(step) {
|
|
36
|
+
return step.kind === "gate";
|
|
37
|
+
}
|
|
38
|
+
function isPhase(step) {
|
|
39
|
+
return typeof step.phase === "string" && Array.isArray(step.steps);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Point every template `components` read at the target's recorded bytes.
|
|
43
|
+
* Returns the rewritten compositions and the files to write, or the reasons
|
|
44
|
+
* the promote is refused: a template the target does not record, one whose
|
|
45
|
+
* bytes are missing, or one whose bytes do not hash to the target's digest.
|
|
46
|
+
*/
|
|
47
|
+
export async function pinReleaseTemplates(components, release, target, readTemplate) {
|
|
48
|
+
const errors = [];
|
|
49
|
+
const files = [];
|
|
50
|
+
const out = [];
|
|
51
|
+
for (const component of components) {
|
|
52
|
+
const replace = new Map();
|
|
53
|
+
for (const ref of templateRefs(component)) {
|
|
54
|
+
if (replace.has(ref.value))
|
|
55
|
+
continue;
|
|
56
|
+
const recorded = target.templates.find((t) => t.component === component.name && t.path === ref.path);
|
|
57
|
+
if (!recorded) {
|
|
58
|
+
errors.push(`component "${component.name}" reads ${ref.field} "${ref.value}", which release ${release.releaseDigest} does not record for "${target.env}"; ` +
|
|
59
|
+
`this checkout's deploy is not the one the release was compiled from (commit ${release.commit.slice(0, 12)})`);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const content = await readTemplate(recorded.digest);
|
|
63
|
+
if (content === null) {
|
|
64
|
+
errors.push(`component "${component.name}": the bytes of template "${ref.path}" (${recorded.digest}) are not on the chant/lifecycle branch; fetch it and try again`);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const got = contentDigest(content);
|
|
68
|
+
if (got !== recorded.digest) {
|
|
69
|
+
errors.push(`component "${component.name}": template "${ref.path}" hashes to ${got}, but the release's target for "${target.env}" records ${recorded.digest}; refusing to deploy it`);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const path = join(RELEASE_TEMPLATES_DIR, recorded.digest.replace(/:/g, "_"), basename(ref.path));
|
|
73
|
+
files.push({ path, content });
|
|
74
|
+
replace.set(ref.value, path);
|
|
75
|
+
}
|
|
76
|
+
const rewrite = (phase) => ({
|
|
77
|
+
...phase,
|
|
78
|
+
steps: phase.steps.map((step) => {
|
|
79
|
+
if (isPhase(step))
|
|
80
|
+
return rewrite(step);
|
|
81
|
+
if (isGate(step))
|
|
82
|
+
return step;
|
|
83
|
+
const next = { ...step };
|
|
84
|
+
for (const field of TEMPLATE_FIELDS) {
|
|
85
|
+
const v = next[field];
|
|
86
|
+
if (typeof v === "string" && replace.has(v))
|
|
87
|
+
next[field] = replace.get(v);
|
|
88
|
+
else if (Array.isArray(v))
|
|
89
|
+
next[field] = v.map((x) => (typeof x === "string" && replace.has(x) ? replace.get(x) : x));
|
|
90
|
+
}
|
|
91
|
+
return next;
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
94
|
+
out.push({ ...component, deploy: component.deploy.map(rewrite) });
|
|
95
|
+
}
|
|
96
|
+
return errors.length > 0 ? { errors } : { components: out, files };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The files a release's target records, read back by digest and checked, for
|
|
100
|
+
* `chant release export` (#4046). A project with no components has no deploy
|
|
101
|
+
* step for a promote to point at the recorded bytes, so its deploy (an Op such
|
|
102
|
+
* as `chant run deploy`, or a CI job) reads the files this writes instead of
|
|
103
|
+
* building them again. Each path is the one the build wrote, relative to the
|
|
104
|
+
* member's directory; a template whose bytes are missing or don't hash to the
|
|
105
|
+
* target's digest is refused, as {@link pinReleaseTemplates} refuses one.
|
|
106
|
+
*/
|
|
107
|
+
export async function targetFiles(release, target, readTemplate) {
|
|
108
|
+
const errors = [];
|
|
109
|
+
const files = [];
|
|
110
|
+
for (const t of target.templates) {
|
|
111
|
+
const who = t.component === null ? "" : `component "${t.component}": `;
|
|
112
|
+
if (t.path.startsWith("/") || t.path.split("/").includes("..")) {
|
|
113
|
+
errors.push(`${who}template "${t.path}" is not a path inside the member's directory; refusing to write it`);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const content = await readTemplate(t.digest);
|
|
117
|
+
if (content === null) {
|
|
118
|
+
errors.push(`${who}the bytes of template "${t.path}" (${t.digest}) are not on the chant/lifecycle branch; fetch it and try again`);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const got = contentDigest(content);
|
|
122
|
+
if (got !== t.digest) {
|
|
123
|
+
errors.push(`${who}template "${t.path}" hashes to ${got}, but release ${release.releaseDigest} records ${t.digest} for "${target.env}"; refusing to write it`);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const same = files.find((f) => f.path === t.path);
|
|
127
|
+
if (same) {
|
|
128
|
+
if (same.content !== content)
|
|
129
|
+
errors.push(`two components record different bytes at "${t.path}" for "${target.env}", so they can't both be written there`);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
files.push({ path: t.path, content });
|
|
133
|
+
}
|
|
134
|
+
return errors.length > 0 ? { errors } : { files };
|
|
135
|
+
}
|
|
136
|
+
/** Write the pinned templates under `dir`, the member's directory. */
|
|
137
|
+
export function writePinnedTemplates(dir, files) {
|
|
138
|
+
for (const f of files) {
|
|
139
|
+
const full = join(dir, f.path);
|
|
140
|
+
mkdirSync(dirname(full), { recursive: true });
|
|
141
|
+
writeFileSync(full, f.content);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Remove the templates {@link writePinnedTemplates} wrote once the promote is
|
|
146
|
+
* done, and {@link RELEASE_TEMPLATES_DIR} with them when nothing else is in
|
|
147
|
+
* it, so a promote leaves the checkout as it found it. A re-run writes them
|
|
148
|
+
* again from the release.
|
|
149
|
+
*/
|
|
150
|
+
export function removePinnedTemplates(dir, files) {
|
|
151
|
+
for (const f of files)
|
|
152
|
+
rmSync(dirname(join(dir, f.path)), { recursive: true, force: true });
|
|
153
|
+
const root = join(dir, RELEASE_TEMPLATES_DIR);
|
|
154
|
+
try {
|
|
155
|
+
if (readdirSync(root).length === 0)
|
|
156
|
+
rmdirSync(root);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// Already gone, or not ours to remove.
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Whether the artifact a promote deploys under a release is one the release
|
|
164
|
+
* built (#4045, the rule #4026 left open). The release records build digests
|
|
165
|
+
* (`artifactDigests`, the digest the archive step returned), and a deploy
|
|
166
|
+
* record carries the publish digest, which is another value for an image, so
|
|
167
|
+
* the two are compared through the build manifest the source deploy record
|
|
168
|
+
* names (`manifestDigest`), whose entries carry build digests at the same
|
|
169
|
+
* archive paths:
|
|
170
|
+
*
|
|
171
|
+
* - a source record that names this release in `releaseDigest` matches;
|
|
172
|
+
* - else, each of the release's artifacts for the component must be in that
|
|
173
|
+
* manifest at its path with the release's digest, and one that differs is
|
|
174
|
+
* a mismatch;
|
|
175
|
+
* - a record with no `manifestDigest`, a manifest that isn't stored, or an
|
|
176
|
+
* artifact path the manifest doesn't hold can't be compared.
|
|
177
|
+
*
|
|
178
|
+
* A mismatch is a warning, not a refusal. The environment promoted from was
|
|
179
|
+
* deployed by its own `run --components`, which builds again, and an image
|
|
180
|
+
* build is not reproducible, so its digest differs from the cut's for the
|
|
181
|
+
* same commit. Refusing would refuse every image promote until a deploy can
|
|
182
|
+
* run the release's own artifacts (#4043).
|
|
183
|
+
*/
|
|
184
|
+
export async function releaseArtifactMismatches(release, sources, readManifest) {
|
|
185
|
+
const out = [];
|
|
186
|
+
for (const { component, source } of sources) {
|
|
187
|
+
if (source.releaseDigest === release.releaseDigest)
|
|
188
|
+
continue;
|
|
189
|
+
const artifacts = release.artifactDigests.filter((a) => a.component === component);
|
|
190
|
+
if (artifacts.length === 0 || source.manifestDigest === undefined)
|
|
191
|
+
continue;
|
|
192
|
+
const manifest = await readManifest(source.manifestDigest);
|
|
193
|
+
if (!manifest)
|
|
194
|
+
continue;
|
|
195
|
+
for (const a of artifacts) {
|
|
196
|
+
const entry = manifest.contents.find((e) => e.path === a.path && e.kind === a.kind);
|
|
197
|
+
if (entry && entry.digest !== a.digest) {
|
|
198
|
+
out.push(`${component}: the ${source.env} deploy being promoted was built with ${a.path} at ${entry.digest}, ` +
|
|
199
|
+
`but release ${release.releaseDigest} built it at ${a.digest}, so the artifact deployed is not the release's own`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return out;
|
|
204
|
+
}
|
|
@@ -79,6 +79,13 @@ export interface RunDoneEvent {
|
|
|
79
79
|
type: "run-done";
|
|
80
80
|
status: RunProgressStatus;
|
|
81
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* @deprecated Read `RunEvent` (`../run-event.ts`, exported from
|
|
84
|
+
* `@intentius/chant`) instead: one contract for Op, component and pipeline
|
|
85
|
+
* runs, with the run id, commit and runtime on every event (#4019).
|
|
86
|
+
* `runEventOfProgress` maps each of these onto it. `--progress-json` keeps
|
|
87
|
+
* printing this shape until #4041 moves it to the run-event stream.
|
|
88
|
+
*/
|
|
82
89
|
export type RunProgressEvent = RunStartEvent | WaveStartEvent | ComponentStartEvent | PhaseStartEvent | StepEvent | PhaseDoneEvent | ComponentDoneEvent | WaveDoneEvent | RunDoneEvent;
|
|
83
90
|
/** A sink that receives progress events as they occur. The driver only ever calls this — it never writes to a stream directly, so it stays testable without stdout. */
|
|
84
91
|
export type RunProgressSink = (event: RunProgressEvent) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-progress.d.ts","sourceRoot":"","sources":["../../src/components/run-progress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mPAAmP;AACnP,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1D,mMAAmM;AACnM,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;CACnB;AAED,2GAA2G;AAC3G,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,2JAA2J;AAC3J,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,+FAA+F;AAC/F,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,IAAI,GAAG,QAAQ,CAAC;IACpC,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,0LAA0L;AAC1L,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,2IAA2I;AAC3I,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,uHAAuH;AACvH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,4FAA4F;AAC5F,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,cAAc,GACd,mBAAmB,GACnB,eAAe,GACf,SAAS,GACT,cAAc,GACd,kBAAkB,GAClB,aAAa,GACb,YAAY,CAAC;AAEjB,uKAAuK;AACvK,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAEhE;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,gBAAgB,EACrD,KAAK,GAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAA0C,GACnE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAEpB"}
|
|
1
|
+
{"version":3,"file":"run-progress.d.ts","sourceRoot":"","sources":["../../src/components/run-progress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mPAAmP;AACnP,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1D,mMAAmM;AACnM,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;CACnB;AAED,2GAA2G;AAC3G,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,2JAA2J;AAC3J,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,+FAA+F;AAC/F,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,IAAI,GAAG,QAAQ,CAAC;IACpC,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,0LAA0L;AAC1L,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,2IAA2I;AAC3I,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,uHAAuH;AACvH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,4FAA4F;AAC5F,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,cAAc,GACd,mBAAmB,GACnB,eAAe,GACf,SAAS,GACT,cAAc,GACd,kBAAkB,GAClB,aAAa,GACb,YAAY,CAAC;AAEjB,uKAAuK;AACvK,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAEhE;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,gBAAgB,EACrD,KAAK,GAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAA0C,GACnE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAEpB"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* plans as `undefined`. Cross-component wiring (`stackOutput()`,
|
|
19
19
|
* `@<component>.publish.*`) resolves.
|
|
20
20
|
*/
|
|
21
|
-
import { type DriverComponent } from "./driver.js";
|
|
21
|
+
import { type DriverComponent, type DriverPhase, type DriverStep } from "./driver.js";
|
|
22
22
|
import type { CapabilityRegistry, DeployContext } from "./capability.js";
|
|
23
23
|
import type { WaveMember } from "../gated-waves.js";
|
|
24
24
|
import type { ChangeSetPart } from "../change-set.js";
|
|
@@ -37,6 +37,13 @@ export type WaveComponentPlan = {
|
|
|
37
37
|
component: string;
|
|
38
38
|
error: string;
|
|
39
39
|
};
|
|
40
|
+
/** Every capability step in a composition, nested phases included, gates left out. */
|
|
41
|
+
export declare function capabilitySteps(phases: readonly DriverPhase[]): DriverStep[];
|
|
42
|
+
/**
|
|
43
|
+
* The context a step is planned with: `ctx`, plus the components whose
|
|
44
|
+
* outputs the step reads and could not read yet (`unresolvedInputs`, #4084).
|
|
45
|
+
*/
|
|
46
|
+
export declare function planContext(ctx: DeployContext, stepInput: Record<string, unknown>, componentOutputs: Record<string, Record<string, unknown>>): DeployContext;
|
|
40
47
|
/** Plan one component against the outputs earlier waves produced. Never throws: a failure comes back as `error`. */
|
|
41
48
|
export declare function planWaveComponent(component: DriverComponent, registry: CapabilityRegistry, ctx: DeployContext, componentOutputs: Record<string, Record<string, unknown>>): Promise<WaveComponentPlan>;
|
|
42
49
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wave-plan.d.ts","sourceRoot":"","sources":["../../src/components/wave-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"wave-plan.d.ts","sourceRoot":"","sources":["../../src/components/wave-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAA6C,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAE9H,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,aAAa,EAAE,CAAA;CAAE,GACpG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAUzC,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,UAAU,EAAE,CAc5E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,aAAa,EAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxD,aAAa,CAGf;AAED,oHAAoH;AACpH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,kBAAkB,EAC5B,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxD,OAAO,CAAC,iBAAiB,CAAC,CAgC5B;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,kBAAkB,EAC5B,GAAG,EAAE,aAAa,EAClB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAU9C"}
|