@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,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mapping a change set's entries onto graph node ids (#4022). The real-estate
|
|
3
|
+
* tests read the graph from `chant graph --format ir`: the five tofu roots in
|
|
4
|
+
* `lexicons/terraform/src/components/pr-loop.tofu.test.ts` and the aws
|
|
5
|
+
* workspace member in `lifecycle/gate-change-set.e2e.test.ts`. This holds the
|
|
6
|
+
* address rules and the digest.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { readFileSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { describe, expect, test } from "vitest";
|
|
12
|
+
import { composeChangeSet, lifecyclePlanPart, verifyChangeSetDigest, type ChangeSetEntry } from "./change-set";
|
|
13
|
+
import { changeSetNodeCandidates, mapChangeSetToGraph, terraformBlockKey } from "./change-set-graph";
|
|
14
|
+
import type { ChangeSet as LifecycleChangeSet } from "./lifecycle/change-set";
|
|
15
|
+
|
|
16
|
+
const plan = JSON.parse(readFileSync(join(import.meta.dirname, "__fixtures__", "change-set", "lifecycle-plan.floci.json"), "utf8")) as LifecycleChangeSet;
|
|
17
|
+
|
|
18
|
+
describe("terraformBlockKey", () => {
|
|
19
|
+
test("names the block the terraform lexicon keys, without the instance index", () => {
|
|
20
|
+
expect(terraformBlockKey("terraform_data.keep")).toBe("terraform_data.keep");
|
|
21
|
+
expect(terraformBlockKey("module.app.terraform_data.instance[0]")).toBe("module.app/terraform_data.instance");
|
|
22
|
+
expect(terraformBlockKey('module.cdn["eu"].module.bucket[1].aws_s3_bucket.this["a.b]"]')).toBe("module.cdn/module.bucket/aws_s3_bucket.this");
|
|
23
|
+
expect(terraformBlockKey("data.aws_iam_policy.boundary")).toBe("data.aws_iam_policy.boundary");
|
|
24
|
+
expect(terraformBlockKey("module.app.data.aws_ami.ubuntu")).toBe("module.app/data.aws_ami.ubuntu");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("a terraform entry tries <root>/<block key>, then its address", () => {
|
|
28
|
+
expect(changeSetNodeCandidates({ member: "estate", planner: "tofu", address: "module.app.terraform_data.instance[1]" })).toEqual([
|
|
29
|
+
"estate/module.app/terraform_data.instance",
|
|
30
|
+
"module.app.terraform_data.instance[1]",
|
|
31
|
+
]);
|
|
32
|
+
expect(changeSetNodeCandidates({ member: "delivery", planner: "chant", address: "jobs" })).toEqual(["jobs"]);
|
|
33
|
+
expect(changeSetNodeCandidates({ member: "org", planner: "warden", address: "team.platform" })).toEqual(["team.platform"]);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("mapChangeSetToGraph", () => {
|
|
38
|
+
const doc = composeChangeSet([lifecyclePlanPart({ member: "delivery", plan })]);
|
|
39
|
+
|
|
40
|
+
test("keeps the ids the graph holds, puts the member in front, and leaves the digest alone", () => {
|
|
41
|
+
const mapped = mapChangeSetToGraph(doc, { member: "delivery", at: "a".repeat(40), ids: ["jobs", "events", "dlq"] });
|
|
42
|
+
expect(mapped.entries.map((e) => [e.address, e.node])).toEqual([
|
|
43
|
+
["alerts", null],
|
|
44
|
+
["dlq", "delivery/dlq"],
|
|
45
|
+
["events", "delivery/events"],
|
|
46
|
+
["jobs", "delivery/jobs"],
|
|
47
|
+
]);
|
|
48
|
+
expect(mapped.graph).toEqual({ member: "delivery", at: "a".repeat(40) });
|
|
49
|
+
expect(mapped.digest).toBe(doc.digest);
|
|
50
|
+
expect(verifyChangeSetDigest(mapped)).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("outside a workspace the id is the member's own", () => {
|
|
54
|
+
const mapped = mapChangeSetToGraph(doc, { member: null, at: null, ids: ["jobs"] });
|
|
55
|
+
expect(mapped.entries.find((e) => e.address === "jobs")!.node).toBe("jobs");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("no graph gives every entry a null node", () => {
|
|
59
|
+
const mapped = mapChangeSetToGraph(doc, null);
|
|
60
|
+
expect(mapped.graph).toBeNull();
|
|
61
|
+
expect(mapped.entries.every((e: ChangeSetEntry) => e.node === null)).toBe(true);
|
|
62
|
+
expect(verifyChangeSetDigest(mapped)).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("a node is not hashed, and every other part of an entry still is", () => {
|
|
66
|
+
const mapped = mapChangeSetToGraph(doc, { member: null, at: null, ids: ["jobs"] });
|
|
67
|
+
const moved = { ...mapped, entries: mapped.entries.map((e) => ({ ...e, node: "elsewhere" })) };
|
|
68
|
+
expect(verifyChangeSetDigest(moved)).toBe(true);
|
|
69
|
+
const changed = { ...mapped, entries: mapped.entries.map((e, i) => (i === 0 ? { ...e, address: "other" } : e)) };
|
|
70
|
+
expect(verifyChangeSetDigest(changed)).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Place a change set's entries on the graph (#4022).
|
|
3
|
+
*
|
|
4
|
+
* A reader such as behold draws the graph `chant graph --format ir` and
|
|
5
|
+
* `chant workspace graph` print, and wants each change of a change set on the
|
|
6
|
+
* node it changes. The planner's address is not that node's id: a terraform
|
|
7
|
+
* plan names an instance, `module.app.terraform_data.instance[0]`, where the
|
|
8
|
+
* graph has one node per block, `<root>/module.app/terraform_data.instance`
|
|
9
|
+
* (the terraform lexicon's entity key, `hcl/parse.ts`). So chant maps the
|
|
10
|
+
* address itself, against the node ids of the graph it read, and a reader
|
|
11
|
+
* never derives an id.
|
|
12
|
+
*
|
|
13
|
+
* {@link changeSetNodeCandidates} lists the ids an entry's address can have,
|
|
14
|
+
* by planner. {@link mapChangeSetToGraph} keeps the first that the graph
|
|
15
|
+
* holds and puts the member's name in front, as `chant workspace graph`
|
|
16
|
+
* does, with the node's source file as `source` when the graph gives one
|
|
17
|
+
* (#4025). An entry whose address the graph does not hold gets `node: null`:
|
|
18
|
+
* a delete of a block the source no longer declares, or a warden or sql
|
|
19
|
+
* change outside the graph.
|
|
20
|
+
*
|
|
21
|
+
* Like `./change-set.ts`, this imports nothing at run time, so it bundles
|
|
22
|
+
* into one file with the change-set code.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type { ChangeSetDocument, ChangeSetEntry } from "./change-set";
|
|
26
|
+
|
|
27
|
+
/** The graph a document is mapped onto: the node ids of one member's own IR. */
|
|
28
|
+
export interface ChangeSetGraphNodes {
|
|
29
|
+
/** The workspace member whose graph it is, its path of names joined with `/` when nested, or null outside a workspace. */
|
|
30
|
+
member: string | null;
|
|
31
|
+
/** The commit the graph was read at, or null when unknown. */
|
|
32
|
+
at: string | null;
|
|
33
|
+
/** Every node id of the member's `chant graph --format ir`, without the member in front. */
|
|
34
|
+
ids: Iterable<string>;
|
|
35
|
+
/**
|
|
36
|
+
* The source file of each node that has one (#4025), by the same ids, as a
|
|
37
|
+
* path from the repository root. An entry mapped onto such a node gets it
|
|
38
|
+
* as `source`.
|
|
39
|
+
*/
|
|
40
|
+
sources?: ReadonlyMap<string, string>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Split a terraform address into its dot-separated parts, dropping every
|
|
45
|
+
* `[...]` index. A quoted key may hold `.` or `]`, so quotes are honoured.
|
|
46
|
+
*/
|
|
47
|
+
function terraformParts(address: string): string[] {
|
|
48
|
+
const parts: string[] = [];
|
|
49
|
+
let current = "";
|
|
50
|
+
let depth = 0;
|
|
51
|
+
let quoted = false;
|
|
52
|
+
for (let i = 0; i < address.length; i++) {
|
|
53
|
+
const c = address[i];
|
|
54
|
+
if (depth > 0) {
|
|
55
|
+
if (quoted) {
|
|
56
|
+
if (c === "\\") i++;
|
|
57
|
+
else if (c === '"') quoted = false;
|
|
58
|
+
} else if (c === '"') quoted = true;
|
|
59
|
+
else if (c === "]") depth--;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (c === "[") depth++;
|
|
63
|
+
else if (c === ".") {
|
|
64
|
+
parts.push(current);
|
|
65
|
+
current = "";
|
|
66
|
+
} else current += c;
|
|
67
|
+
}
|
|
68
|
+
parts.push(current);
|
|
69
|
+
return parts.filter((p) => p.length > 0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The block key the terraform lexicon gives an address in its root:
|
|
74
|
+
* `module.<call>/` for each module call, then the block's own address with
|
|
75
|
+
* no index. `module.app.terraform_data.instance[0]` is
|
|
76
|
+
* `module.app/terraform_data.instance`.
|
|
77
|
+
*/
|
|
78
|
+
export function terraformBlockKey(address: string): string | undefined {
|
|
79
|
+
const parts = terraformParts(address);
|
|
80
|
+
const scope: string[] = [];
|
|
81
|
+
let i = 0;
|
|
82
|
+
while (parts[i] === "module" && i + 1 < parts.length) {
|
|
83
|
+
scope.push(`module.${parts[i + 1]}`);
|
|
84
|
+
i += 2;
|
|
85
|
+
}
|
|
86
|
+
const rest = parts.slice(i);
|
|
87
|
+
let block: string | undefined;
|
|
88
|
+
if (rest[0] === "data" && rest.length >= 3) block = `data.${rest[1]}.${rest[2]}`;
|
|
89
|
+
else if (rest.length >= 2) block = `${rest[0]}.${rest[1]}`;
|
|
90
|
+
else if (rest.length === 0 && scope.length > 0) {
|
|
91
|
+
// The module call itself is a block of its caller.
|
|
92
|
+
const call = scope.pop()!;
|
|
93
|
+
block = call;
|
|
94
|
+
}
|
|
95
|
+
if (block === undefined) return undefined;
|
|
96
|
+
return [...scope, block].join("/");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The ids, in the order tried, that an entry's address can have in its
|
|
101
|
+
* member's graph IR:
|
|
102
|
+
*
|
|
103
|
+
* - `chant`: the address, which is the entity name the IR uses as its id.
|
|
104
|
+
* - `terraform`, `tofu`, `choudoufu`: `<root>/<block key>`, the root being
|
|
105
|
+
* the change-set member (`terraformBlockKey`), then the address.
|
|
106
|
+
* - `warden`, `sql`: the address.
|
|
107
|
+
*/
|
|
108
|
+
export function changeSetNodeCandidates(entry: Pick<ChangeSetEntry, "member" | "planner" | "address">): string[] {
|
|
109
|
+
switch (entry.planner) {
|
|
110
|
+
case "terraform":
|
|
111
|
+
case "tofu":
|
|
112
|
+
case "choudoufu": {
|
|
113
|
+
const key = terraformBlockKey(entry.address);
|
|
114
|
+
return key === undefined ? [entry.address] : [`${entry.member}/${key}`, entry.address];
|
|
115
|
+
}
|
|
116
|
+
default:
|
|
117
|
+
return [entry.address];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The document with each entry's `node` set from `graph`, and `graph`
|
|
123
|
+
* recording which graph it was. A null `graph` (none could be read) gives
|
|
124
|
+
* every entry `node: null`. The digest is unchanged: `node` is not hashed.
|
|
125
|
+
*/
|
|
126
|
+
export function mapChangeSetToGraph(doc: ChangeSetDocument, graph: ChangeSetGraphNodes | null): ChangeSetDocument {
|
|
127
|
+
if (graph === null) {
|
|
128
|
+
return { ...doc, entries: doc.entries.map((e) => ({ ...e, node: null })), graph: null };
|
|
129
|
+
}
|
|
130
|
+
const ids = new Set(graph.ids);
|
|
131
|
+
const prefix = graph.member ? `${graph.member}/` : "";
|
|
132
|
+
return {
|
|
133
|
+
...doc,
|
|
134
|
+
entries: doc.entries.map((e) => {
|
|
135
|
+
const id = changeSetNodeCandidates(e).find((c) => ids.has(c));
|
|
136
|
+
const source = id === undefined ? undefined : graph.sources?.get(id);
|
|
137
|
+
return { ...e, node: id === undefined ? null : `${prefix}${id}`, ...(source !== undefined ? { source } : {}) };
|
|
138
|
+
}),
|
|
139
|
+
graph: { member: graph.member, at: graph.at },
|
|
140
|
+
};
|
|
141
|
+
}
|
package/src/change-set.ts
CHANGED
|
@@ -113,6 +113,25 @@ export interface ChangeSetEntry {
|
|
|
113
113
|
/** The estate, environment or org the change lands in. */
|
|
114
114
|
scope?: string;
|
|
115
115
|
attributes: ChangeSetAttribute[];
|
|
116
|
+
/**
|
|
117
|
+
* The graph node the entry changes, as `chant graph --format ir` and
|
|
118
|
+
* `chant workspace graph` name it (#4022): `<member>/<id>` inside a
|
|
119
|
+
* workspace. Null when the graph holds no node for the address, such as
|
|
120
|
+
* a delete of a block the source no longer declares. Absent until the
|
|
121
|
+
* document is mapped onto a graph (`./change-set-graph.ts`), and never
|
|
122
|
+
* part of the digest.
|
|
123
|
+
*/
|
|
124
|
+
node?: string | null;
|
|
125
|
+
/**
|
|
126
|
+
* The source file that declares the entry's node, from the repository
|
|
127
|
+
* root (#4025): the node's `sourceLoc.file` in the member's graph IR, with
|
|
128
|
+
* the member's directory in front. Set beside `node` when a stored change
|
|
129
|
+
* set is mapped onto a graph whose node has a source location, absent
|
|
130
|
+
* otherwise. Like `node`, never part of the digest. The overlap report
|
|
131
|
+
* attributes the entry to a work item through the commits that changed
|
|
132
|
+
* this file.
|
|
133
|
+
*/
|
|
134
|
+
source?: string;
|
|
116
135
|
}
|
|
117
136
|
|
|
118
137
|
/** Something a planner could not read, so the plan says nothing about it. */
|
|
@@ -201,6 +220,30 @@ export interface ChangeSetDocument {
|
|
|
201
220
|
/** Triggered actions, sorted by member and address. Absent when no member runs one. */
|
|
202
221
|
sideEffects?: ChangeSetSideEffect[];
|
|
203
222
|
summary: ChangeSetSummary;
|
|
223
|
+
/**
|
|
224
|
+
* The graph the entries' `node` ids come from (#4022): the workspace member
|
|
225
|
+
* whose graph it is, or null outside a workspace, and the commit it was
|
|
226
|
+
* read at, or null when that is unknown. Null when no graph could be read,
|
|
227
|
+
* so every `node` is null. Absent on a document never mapped. Not hashed.
|
|
228
|
+
*/
|
|
229
|
+
graph?: ChangeSetGraph | null;
|
|
230
|
+
/**
|
|
231
|
+
* The release this change set was planned for (#4045): the `releaseDigest`
|
|
232
|
+
* of the release a `components promote --release` deploys. Set with
|
|
233
|
+
* `environment` on a release gate's document, absent on every other. Part
|
|
234
|
+
* of the digest when present, so a stored document names the one release
|
|
235
|
+
* and environment its gate bound, and two releases whose plans read the
|
|
236
|
+
* same never share a document or an approval.
|
|
237
|
+
*/
|
|
238
|
+
releaseDigest?: string;
|
|
239
|
+
/** The environment this change set was planned for (#4045), set with `releaseDigest`. Part of the digest when present. */
|
|
240
|
+
environment?: string;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** Where a document's node ids come from. */
|
|
244
|
+
export interface ChangeSetGraph {
|
|
245
|
+
member: string | null;
|
|
246
|
+
at: string | null;
|
|
204
247
|
}
|
|
205
248
|
|
|
206
249
|
const byString = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0);
|
|
@@ -235,22 +278,40 @@ export function changeSetDigest(members: ReadonlyArray<Pick<ChangeSetMember, "me
|
|
|
235
278
|
/**
|
|
236
279
|
* The document's digest: `computePlanDigest("change-set-document", …)` over
|
|
237
280
|
* the set digest ({@link changeSetDigest}), each member's name, status and
|
|
238
|
-
* holes, the entries and the side effects.
|
|
281
|
+
* holes, the entries (without their graph `node`) and the side effects.
|
|
282
|
+
* Members are sorted by name and
|
|
239
283
|
* entries and side effects by the keys {@link composeChangeSet} sorts them by,
|
|
240
284
|
* so order makes no difference.
|
|
241
285
|
*
|
|
242
286
|
* A provisional member is left out, with its entries and side effects, as
|
|
243
287
|
* the set digest leaves it out: no approval of the document covers it.
|
|
288
|
+
*
|
|
289
|
+
* A release gate's document (#4045) also hashes the `releaseDigest` and
|
|
290
|
+
* `environment` it was planned for. A document without them hashes as it
|
|
291
|
+
* always has, so no earlier digest moves.
|
|
244
292
|
*/
|
|
245
|
-
export function changeSetDocumentDigest(
|
|
293
|
+
export function changeSetDocumentDigest(
|
|
294
|
+
doc: Pick<ChangeSetDocument, "members" | "entries" | "sideEffects" | "releaseDigest" | "environment">,
|
|
295
|
+
): string {
|
|
246
296
|
const provisional = new Set(doc.members.filter((m) => m.provisional === true).map((m) => m.member));
|
|
247
297
|
const members = doc.members
|
|
248
298
|
.filter((m) => !provisional.has(m.member))
|
|
249
299
|
.map((m) => ({ member: m.member, status: m.status, holes: m.holes }))
|
|
250
300
|
.sort((a, b) => byString(a.member, b.member));
|
|
251
|
-
|
|
301
|
+
// An entry's graph node (#4022) and its source file (#4025) say where on
|
|
302
|
+
// the graph the change is, not what the plan does, so they stay outside
|
|
303
|
+
// the digest: mapping a stored
|
|
304
|
+
// document onto a graph never moves the value its gate bound.
|
|
305
|
+
const entries = doc.entries
|
|
306
|
+
.filter((e) => !provisional.has(e.member))
|
|
307
|
+
.map(({ node: _node, source: _source, ...e }) => e)
|
|
308
|
+
.sort((a, b) => byString(entryKey(a), entryKey(b)));
|
|
252
309
|
const sideEffects = (doc.sideEffects ?? []).filter((s) => !provisional.has(s.member)).sort(bySideEffect);
|
|
253
|
-
|
|
310
|
+
const planned =
|
|
311
|
+
doc.releaseDigest !== undefined || doc.environment !== undefined
|
|
312
|
+
? { planned: { releaseDigest: doc.releaseDigest ?? null, environment: doc.environment ?? null } }
|
|
313
|
+
: {};
|
|
314
|
+
return computePlanDigest("change-set-document", { set: changeSetDigest(doc.members), members, entries, sideEffects, ...planned });
|
|
254
315
|
}
|
|
255
316
|
|
|
256
317
|
/** The summary of a set of members and entries. */
|
|
@@ -296,6 +357,8 @@ function sortKeys<T>(o: Record<string, T>): Record<string, T> {
|
|
|
296
357
|
export interface ComposeChangeSetOptions {
|
|
297
358
|
/** The chant version to record in `chant`. */
|
|
298
359
|
chant?: string;
|
|
360
|
+
/** The release and environment a release gate's change set was planned for (#4045), recorded and hashed. */
|
|
361
|
+
planned?: { releaseDigest: string; environment: string };
|
|
299
362
|
}
|
|
300
363
|
|
|
301
364
|
/**
|
|
@@ -317,12 +380,14 @@ export function composeChangeSet(parts: ReadonlyArray<ChangeSetPart>, options: C
|
|
|
317
380
|
const sideEffects: ChangeSetSideEffect[] = parts
|
|
318
381
|
.flatMap((p) => (p.sideEffects ?? []).map((s) => ({ member: p.member.member, ...s })))
|
|
319
382
|
.sort(bySideEffect);
|
|
320
|
-
const
|
|
383
|
+
const planned = options.planned ? { releaseDigest: options.planned.releaseDigest, environment: options.planned.environment } : {};
|
|
384
|
+
const digest = changeSetDocumentDigest({ members, entries, sideEffects, ...planned });
|
|
321
385
|
return {
|
|
322
386
|
$schema: CHANGE_SET_SCHEMA_ID,
|
|
323
387
|
contract: CHANGE_SET_CONTRACT,
|
|
324
388
|
...(options.chant !== undefined ? { chant: options.chant } : {}),
|
|
325
389
|
digest,
|
|
390
|
+
...planned,
|
|
326
391
|
members,
|
|
327
392
|
entries,
|
|
328
393
|
...(sideEffects.length > 0 ? { sideEffects } : {}),
|
|
@@ -335,7 +400,9 @@ export function composeChangeSet(parts: ReadonlyArray<ChangeSetPart>, options: C
|
|
|
335
400
|
* effects give ({@link changeSetDocumentDigest}). A document that names a
|
|
336
401
|
* member twice has no digest and is not verified.
|
|
337
402
|
*/
|
|
338
|
-
export function verifyChangeSetDigest(
|
|
403
|
+
export function verifyChangeSetDigest(
|
|
404
|
+
doc: Pick<ChangeSetDocument, "digest" | "members" | "entries" | "sideEffects" | "releaseDigest" | "environment">,
|
|
405
|
+
): boolean {
|
|
339
406
|
try {
|
|
340
407
|
return changeSetDocumentDigest(doc) === doc.digest;
|
|
341
408
|
} catch {
|
|
@@ -343,6 +410,20 @@ export function verifyChangeSetDigest(doc: Pick<ChangeSetDocument, "digest" | "m
|
|
|
343
410
|
}
|
|
344
411
|
}
|
|
345
412
|
|
|
413
|
+
/**
|
|
414
|
+
* Whether a change set changes nothing (ws-104 question 6, #4045): it has at
|
|
415
|
+
* least one member, every member planned, none failed or provisional, no
|
|
416
|
+
* member has a hole, and every entry is a `no-op` or a `read`. A release
|
|
417
|
+
* gate over such a document passes without an approval.
|
|
418
|
+
*/
|
|
419
|
+
export function isEmptyChangeSet(doc: Pick<ChangeSetDocument, "members" | "entries">): boolean {
|
|
420
|
+
if (doc.members.length === 0) return false;
|
|
421
|
+
for (const m of doc.members) {
|
|
422
|
+
if (m.status !== "planned" || m.provisional === true || m.holes.length > 0) return false;
|
|
423
|
+
}
|
|
424
|
+
return doc.entries.every((e) => e.action === "no-op" || e.action === "read");
|
|
425
|
+
}
|
|
426
|
+
|
|
346
427
|
// ── chant lifecycle plan ───────────────────────────────────────────────────────
|
|
347
428
|
|
|
348
429
|
export interface LifecyclePlanPartInput {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The installed chant's version, read from `@intentius/chant`'s own
|
|
5
|
+
* package.json, or "0.0.0" when it can't be read. The path is the same from
|
|
6
|
+
* `src/` and `dist/`, so it holds whether chant runs from source or from its
|
|
7
|
+
* build. Kept outside `cli/` so that a module the Op entry loads, such as the
|
|
8
|
+
* run-event writer (#4041), can name the version without loading the CLI.
|
|
9
|
+
*/
|
|
10
|
+
export const CHANT_VERSION: string = (() => {
|
|
11
|
+
try {
|
|
12
|
+
return (createRequire(import.meta.url)("../package.json") as { version?: string }).version ?? "0.0.0";
|
|
13
|
+
} catch {
|
|
14
|
+
return "0.0.0";
|
|
15
|
+
}
|
|
16
|
+
})();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from "fs";
|
|
2
2
|
import { resolve } from "path";
|
|
3
|
-
import { resolveBuildParams, type BuildParamsConfig } from "../build-params";
|
|
3
|
+
import { resolveBuildParams, type BuildParamFlags, type BuildParamsConfig } from "../build-params";
|
|
4
4
|
import type { BuildParamProvenance } from "../provenance";
|
|
5
5
|
import { formatError, formatInfo } from "./format";
|
|
6
6
|
|
|
@@ -40,6 +40,10 @@ export interface CliBuildParamsArgs {
|
|
|
40
40
|
paramsFile?: string;
|
|
41
41
|
/** `--verbose` — list every resolved parameter one per line instead of the one-line count (#1424). */
|
|
42
42
|
verbose?: boolean;
|
|
43
|
+
/** The workspace flags backing parameters in this build's environment (#4024), from `../flag-params.ts`. */
|
|
44
|
+
flags?: BuildParamFlags;
|
|
45
|
+
/** `false` to resolve without printing the summary line, for a caller that checks more before it prints ({@link echoBuildParams}). */
|
|
46
|
+
echo?: boolean;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
export interface CliBuildParamsResolution {
|
|
@@ -94,6 +98,7 @@ export function resolveCliBuildParams(
|
|
|
94
98
|
cli: args.cli,
|
|
95
99
|
fromFile,
|
|
96
100
|
env: process.env,
|
|
101
|
+
...(args.flags ? { flags: args.flags } : {}),
|
|
97
102
|
});
|
|
98
103
|
for (const message of resolution.errors) {
|
|
99
104
|
errors.push(formatError({ message }));
|
|
@@ -103,21 +108,25 @@ export function resolveCliBuildParams(
|
|
|
103
108
|
return { success: false, provenance: [], errors };
|
|
104
109
|
}
|
|
105
110
|
|
|
111
|
+
if (args.echo !== false) echoBuildParams(resolution.provenance, args.verbose);
|
|
112
|
+
return { success: true, provenance: resolution.provenance, errors: [] };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Print a successful resolution: the one-line summary, or every value under `--verbose` or `CHANT_PARAM_ECHO=all` (#1424). */
|
|
116
|
+
export function echoBuildParams(provenance: readonly BuildParamProvenance[], verboseFlag?: boolean): void {
|
|
106
117
|
// #1424 — one line by default. A project with two dozen declared
|
|
107
118
|
// parameters printed two dozen grey lines on every build, ahead of the
|
|
108
119
|
// warnings the reader actually needed. The count by source still answers
|
|
109
120
|
// "did my override reach the build" (the failure mode
|
|
110
121
|
// warnIfParamsCannotReachProject exists for); --verbose names every value.
|
|
111
|
-
const verbose =
|
|
122
|
+
const verbose = verboseFlag === true || process.env.CHANT_PARAM_ECHO === "all";
|
|
112
123
|
if (verbose) {
|
|
113
|
-
for (const p of
|
|
124
|
+
for (const p of provenance) {
|
|
114
125
|
console.error(formatInfo(`[param] ${p.name} = ${JSON.stringify(p.value)} (${p.source})`));
|
|
115
126
|
}
|
|
116
|
-
} else if (
|
|
117
|
-
console.error(formatInfo(summarizeBuildParams(
|
|
127
|
+
} else if (provenance.length > 0) {
|
|
128
|
+
console.error(formatInfo(summarizeBuildParams(provenance)));
|
|
118
129
|
}
|
|
119
|
-
|
|
120
|
-
return { success: true, provenance: resolution.provenance, errors: [] };
|
|
121
130
|
}
|
|
122
131
|
|
|
123
132
|
/**
|
|
@@ -127,8 +136,12 @@ export function resolveCliBuildParams(
|
|
|
127
136
|
*/
|
|
128
137
|
export function summarizeBuildParams(provenance: readonly { source: string }[]): string {
|
|
129
138
|
const counts = new Map<string, number>();
|
|
130
|
-
|
|
131
|
-
const
|
|
139
|
+
// Every flag source (`flag:<name>`, #4024) counts as one, "from flags".
|
|
140
|
+
for (const p of provenance) {
|
|
141
|
+
const source = p.source.startsWith("flag:") ? "flags" : p.source;
|
|
142
|
+
counts.set(source, (counts.get(source) ?? 0) + 1);
|
|
143
|
+
}
|
|
144
|
+
const order = ["cli", "params-file", "env", "flags", "default"];
|
|
132
145
|
const rank = (s: string) => (order.includes(s) ? order.indexOf(s) : order.length);
|
|
133
146
|
const parts = [...counts.keys()]
|
|
134
147
|
.sort((a, b) => rank(a) - rank(b))
|
|
@@ -12,7 +12,7 @@ import { resolveTelemetryAttribution } from "../../telemetry-attribution";
|
|
|
12
12
|
import { loadOkfBundle } from "../../okf-read";
|
|
13
13
|
import { unknownEnvError } from "../../env";
|
|
14
14
|
import type { OwnershipMarker } from "../../ownership";
|
|
15
|
-
import {
|
|
15
|
+
import { resolveFlaggedBuildParams } from "../../flag-params";
|
|
16
16
|
import type { Serializer, SerializerResult } from "../../serializer";
|
|
17
17
|
import type { LexiconPlugin } from "../../lexicon";
|
|
18
18
|
import { runPostSynthChecks, type PostSynthDiagnostic } from "../../lint/post-synth";
|
|
@@ -118,6 +118,20 @@ export interface BuildOptions {
|
|
|
118
118
|
* outputs of its own `serializers`, so the sources are evaluated once.
|
|
119
119
|
*/
|
|
120
120
|
sharedBuild?: { serializers: Serializer[]; result?: ReturnType<typeof build> };
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Where each output file goes: called with its absolute path and its
|
|
124
|
+
* content in place of creating the directory and writing the file. A
|
|
125
|
+
* release cut (#4046) passes one that keeps the files in memory, so it
|
|
126
|
+
* records exactly what this build writes and nothing left on disk by an
|
|
127
|
+
* earlier one.
|
|
128
|
+
*/
|
|
129
|
+
writeFile?: (path: string, content: string) => void;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function writeFileCreatingDir(path: string, content: string): void {
|
|
133
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
134
|
+
writeFileSync(path, content);
|
|
121
135
|
}
|
|
122
136
|
|
|
123
137
|
/**
|
|
@@ -283,11 +297,14 @@ export async function buildCommand(options: BuildOptions): Promise<BuildResult>
|
|
|
283
297
|
// project's own `params.ts` does before migrating to this mechanism). Also
|
|
284
298
|
// logs a one-line count on success, or every resolved value (`[param] name =
|
|
285
299
|
// value (source)`) under --verbose (#1424).
|
|
286
|
-
|
|
300
|
+
// #4024: in a workspace member, a build for an environment also reads the
|
|
301
|
+
// flag records that back its parameters, and refuses an override of one
|
|
302
|
+
// where the environment has a gate (../../flag-params.ts).
|
|
303
|
+
const paramsResolution = await resolveFlaggedBuildParams(configDir, config.buildParams, {
|
|
287
304
|
cli: options.params,
|
|
288
305
|
paramsFile: options.paramsFile,
|
|
289
306
|
verbose: options.verbose,
|
|
290
|
-
});
|
|
307
|
+
}, options.env);
|
|
291
308
|
if (!paramsResolution.success) {
|
|
292
309
|
errors.push(...paramsResolution.errors);
|
|
293
310
|
return { success: false, resourceCount: 0, fileCount: 0, errors, warnings };
|
|
@@ -735,6 +752,7 @@ export async function buildCommand(options: BuildOptions): Promise<BuildResult>
|
|
|
735
752
|
}
|
|
736
753
|
|
|
737
754
|
// Handle output
|
|
755
|
+
const writeOutput = options.writeFile ?? writeFileCreatingDir;
|
|
738
756
|
if (result.errors.length === 0 && errors.length === 0) {
|
|
739
757
|
// Extract primary content and collect additional files from SerializerResult.
|
|
740
758
|
// Each entry remembers which lexicon produced it, so a same-basename
|
|
@@ -866,8 +884,7 @@ export async function buildCommand(options: BuildOptions): Promise<BuildResult>
|
|
|
866
884
|
additionalFiles.delete(filename);
|
|
867
885
|
try {
|
|
868
886
|
const targetPath = join(projectDist, filename);
|
|
869
|
-
|
|
870
|
-
writeFileSync(targetPath, entry.content);
|
|
887
|
+
writeOutput(targetPath, entry.content);
|
|
871
888
|
opsWritten += 1;
|
|
872
889
|
} catch (err) {
|
|
873
890
|
errors.push(
|
|
@@ -893,8 +910,7 @@ export async function buildCommand(options: BuildOptions): Promise<BuildResult>
|
|
|
893
910
|
if (!config?.name) continue;
|
|
894
911
|
try {
|
|
895
912
|
const targetPath = join(projectDist, "ops", config.name, "op.json");
|
|
896
|
-
|
|
897
|
-
writeFileSync(targetPath, serializeOpIR(config));
|
|
913
|
+
writeOutput(targetPath, serializeOpIR(config));
|
|
898
914
|
irWritten += 1;
|
|
899
915
|
} catch (err) {
|
|
900
916
|
errors.push(
|
|
@@ -913,8 +929,7 @@ export async function buildCommand(options: BuildOptions): Promise<BuildResult>
|
|
|
913
929
|
// output path and any nested additional-file paths (e.g. ops/<name>/...).
|
|
914
930
|
try {
|
|
915
931
|
const outputPath = resolve(options.output);
|
|
916
|
-
|
|
917
|
-
writeFileSync(outputPath, output);
|
|
932
|
+
writeOutput(outputPath, output);
|
|
918
933
|
|
|
919
934
|
// Write additional files (e.g. nested stack templates) alongside the primary output
|
|
920
935
|
if (additionalFiles.size > 0) {
|
|
@@ -935,8 +950,7 @@ export async function buildCommand(options: BuildOptions): Promise<BuildResult>
|
|
|
935
950
|
}
|
|
936
951
|
}
|
|
937
952
|
const targetPath = join(outputDir, filename);
|
|
938
|
-
|
|
939
|
-
writeFileSync(targetPath, fileContent);
|
|
953
|
+
writeOutput(targetPath, fileContent);
|
|
940
954
|
}
|
|
941
955
|
}
|
|
942
956
|
} catch (err) {
|
|
@@ -88,3 +88,54 @@ describe("auditDocsReachability", () => {
|
|
|
88
88
|
expect(auditDocsReachability(d).unreachable).toEqual(["a", "c"]);
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* chant #3993: inside the chant repository a lexicon's pages are generated
|
|
94
|
+
* into the main docs site with a _sidebar.json beside them, and the audit
|
|
95
|
+
* reads those instead of a docs app the lexicon no longer has.
|
|
96
|
+
*/
|
|
97
|
+
describe("auditDocsReachability for a section of the main site", () => {
|
|
98
|
+
function mainSite(): void {
|
|
99
|
+
mkdirSync(join(dir, "docs"), { recursive: true });
|
|
100
|
+
writeFileSync(join(dir, "docs", "package.json"), JSON.stringify({ name: "@intentius/chant-docs" }));
|
|
101
|
+
writeFileSync(join(dir, "docs", "astro.config.mjs"), "export default {};\n");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function repoWithSection(pages: string[], group: unknown, hidden: string[] = []): string {
|
|
105
|
+
mainSite();
|
|
106
|
+
const section = join(dir, "docs", "src", "content", "docs", "lexicons", "fixture");
|
|
107
|
+
mkdirSync(section, { recursive: true });
|
|
108
|
+
for (const page of pages) writeFileSync(join(section, `${page}.mdx`), "body\n");
|
|
109
|
+
writeFileSync(join(section, "_sidebar.json"), JSON.stringify({ group, hidden }));
|
|
110
|
+
const lex = join(dir, "lexicons", "fixture");
|
|
111
|
+
mkdirSync(join(lex, "docs", "pages"), { recursive: true });
|
|
112
|
+
return lex;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
test("every page in the fragment, or hidden by it, is reachable", () => {
|
|
116
|
+
const lex = repoWithSection(
|
|
117
|
+
["index", "start", "secret"],
|
|
118
|
+
{
|
|
119
|
+
label: "Fixture",
|
|
120
|
+
items: [
|
|
121
|
+
{ label: "Overview", slug: "lexicons/fixture" },
|
|
122
|
+
{ label: "Tutorials", items: [{ label: "Start", slug: "lexicons/fixture/start" }] },
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
["lexicons/fixture/secret"],
|
|
126
|
+
);
|
|
127
|
+
expect(auditDocsReachability(lex)).toEqual({ hasSite: true, pages: ["index", "secret", "start"], unreachable: [] });
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("a page the fragment does not name is unreachable", () => {
|
|
131
|
+
const lex = repoWithSection(["index", "orphan"], { label: "Fixture", items: [{ label: "Overview", slug: "lexicons/fixture" }] });
|
|
132
|
+
expect(auditDocsReachability(lex).unreachable).toEqual(["orphan"]);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("before the section is generated there is nothing to audit", () => {
|
|
136
|
+
mainSite();
|
|
137
|
+
const lex = join(dir, "lexicons", "fixture");
|
|
138
|
+
mkdirSync(lex, { recursive: true });
|
|
139
|
+
expect(auditDocsReachability(lex).hasSite).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
18
|
-
import { join } from "path";
|
|
18
|
+
import { basename, join, resolve } from "path";
|
|
19
|
+
|
|
20
|
+
import { collectSidebarSlugs } from "../../codegen/docs";
|
|
21
|
+
import { findChantDocsSite, sectionContentDir } from "../../codegen/docs-in-site";
|
|
19
22
|
|
|
20
23
|
export interface DocsReachability {
|
|
21
24
|
/** Whether this lexicon ships a Starlight site at all. */
|
|
@@ -55,7 +58,7 @@ export function auditDocsReachability(lexiconDir: string): DocsReachability {
|
|
|
55
58
|
const configPath = join(lexiconDir, "docs", "astro.config.mjs");
|
|
56
59
|
|
|
57
60
|
if (!existsSync(contentDir) || !existsSync(configPath)) {
|
|
58
|
-
return
|
|
61
|
+
return auditSectionReachability(lexiconDir);
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
const slugs = sidebarSlugs(readFileSync(configPath, "utf-8"));
|
|
@@ -99,3 +102,37 @@ export function auditDocsClassification(lexiconDir: string): DocsClassification
|
|
|
99
102
|
}
|
|
100
103
|
return { hasPages: true, unclassified };
|
|
101
104
|
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Reachability for a lexicon whose docs are a section of the chant main site
|
|
108
|
+
* (chant #3993): its generated pages under
|
|
109
|
+
* `docs/src/content/docs/lexicons/<name>/` against the `_sidebar.json` the
|
|
110
|
+
* pipeline wrote beside them. A page the fragment lists as hidden is
|
|
111
|
+
* deliberately URL-only and does not count. Before the section has been
|
|
112
|
+
* generated there is nothing to audit, which reads as no site, like a
|
|
113
|
+
* lexicon with no docs.
|
|
114
|
+
*/
|
|
115
|
+
function auditSectionReachability(lexiconDir: string): DocsReachability {
|
|
116
|
+
const site = findChantDocsSite(lexiconDir);
|
|
117
|
+
const name = basename(resolve(lexiconDir));
|
|
118
|
+
const dir = site ? sectionContentDir(site, name) : undefined;
|
|
119
|
+
const fragmentPath = dir ? join(dir, "_sidebar.json") : undefined;
|
|
120
|
+
if (!dir || !fragmentPath || !existsSync(fragmentPath)) return { hasSite: false, pages: [], unreachable: [] };
|
|
121
|
+
|
|
122
|
+
const fragment = JSON.parse(readFileSync(fragmentPath, "utf-8")) as {
|
|
123
|
+
group: Record<string, unknown>;
|
|
124
|
+
hidden?: string[];
|
|
125
|
+
};
|
|
126
|
+
const prefix = `lexicons/${name}/`;
|
|
127
|
+
const reached = new Set(
|
|
128
|
+
[...collectSidebarSlugs([fragment.group]), ...(fragment.hidden ?? [])].map((slug) =>
|
|
129
|
+
slug.startsWith(prefix) ? slug.slice(prefix.length) : slug,
|
|
130
|
+
),
|
|
131
|
+
);
|
|
132
|
+
const pages = readdirSync(dir)
|
|
133
|
+
.filter((f) => f.endsWith(".mdx") || f.endsWith(".md"))
|
|
134
|
+
.map((f) => f.replace(/\.mdx?$/, ""))
|
|
135
|
+
.sort();
|
|
136
|
+
const unreachable = pages.filter((slug) => slug !== "index" && !reached.has(slug));
|
|
137
|
+
return { hasSite: true, pages, unreachable };
|
|
138
|
+
}
|