@intentius/chant 0.124.46 → 0.124.49
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/dist/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-hold.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-pass.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-skip.json +10 -0
- package/dist/__golden__/wave-loop/op-cost-member-clash.json +6 -0
- package/dist/__golden__/wave-loop/op-cost-member.json +13 -0
- package/dist/__golden__/wave-loop/op-denied-source.json +16 -0
- package/dist/__golden__/wave-loop/op-denied.json +16 -0
- package/dist/__golden__/wave-loop/op-discover-rest-short.json +6 -0
- package/dist/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
- package/dist/__golden__/wave-loop/op-discover-rest.json +26 -0
- package/dist/__golden__/wave-loop/op-discover-wide.json +26 -0
- package/dist/__golden__/wave-loop/op-held-on-again.json +16 -0
- package/dist/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
- package/dist/__golden__/wave-loop/op-held-on.json +16 -0
- package/dist/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-held.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-pass.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-share.json +33 -0
- package/dist/__golden__/wave-loop/op-outcome-held.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
- package/dist/__golden__/wave-loop/op-overridden.json +16 -0
- package/dist/__golden__/wave-loop/op-per-run.json +20 -0
- package/dist/__golden__/wave-loop/op-point.json +13 -0
- package/dist/__golden__/wave-loop/op-pr-review.json +10 -0
- package/dist/__golden__/wave-loop/op-sealed.json +10 -0
- package/dist/__golden__/wave-loop/op-spend-change-only.json +10 -0
- package/dist/__golden__/wave-loop/op-spend.json +10 -0
- package/dist/__golden__/wave-loop/op-wave-commands.json +55 -0
- package/dist/__golden__/wave-loop/op-wide-refused.json +26 -0
- package/dist/__golden__/wave-loop/op-wide-waiting.json +29 -0
- package/dist/__golden__/wave-loop/op-wide.json +39 -0
- package/dist/action-pins.d.ts +61 -0
- package/dist/action-pins.d.ts.map +1 -0
- package/dist/action-pins.js +77 -0
- package/dist/cli/commands/carve.d.ts +3 -0
- package/dist/cli/commands/carve.d.ts.map +1 -1
- package/dist/cli/commands/carve.js +36 -7
- package/dist/cli/commands/import-report.d.ts +26 -0
- package/dist/cli/commands/import-report.d.ts.map +1 -0
- package/dist/cli/commands/import-report.js +65 -0
- package/dist/cli/commands/import.d.ts +11 -1
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/import.js +22 -3
- package/dist/cli/commands/migrate.d.ts +13 -1
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +134 -10
- package/dist/cli/handlers/approve.d.ts.map +1 -1
- package/dist/cli/handlers/approve.js +41 -14
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +6 -1
- package/dist/cli/handlers/graph-reader.d.ts +26 -0
- package/dist/cli/handlers/graph-reader.d.ts.map +1 -0
- package/dist/cli/handlers/graph-reader.js +41 -0
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +14 -0
- package/dist/cli/handlers/ledger.d.ts +3 -0
- package/dist/cli/handlers/ledger.d.ts.map +1 -0
- package/dist/cli/handlers/ledger.js +55 -0
- package/dist/cli/handlers/migrate.d.ts.map +1 -1
- package/dist/cli/handlers/migrate.js +18 -11
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/misc.js +12 -1
- package/dist/cli/handlers/pr-env.js +2 -2
- package/dist/cli/handlers/pr.d.ts +15 -1
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +183 -40
- package/dist/cli/handlers/query.d.ts +7 -2
- package/dist/cli/handlers/query.d.ts.map +1 -1
- package/dist/cli/handlers/query.js +16 -4
- package/dist/cli/handlers/release.d.ts.map +1 -1
- package/dist/cli/handlers/release.js +6 -3
- package/dist/cli/handlers/search.d.ts +2 -4
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +13 -39
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +87 -14
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +47 -2
- package/dist/cli/registry.d.ts +22 -4
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/builders.d.ts +5 -1
- package/dist/components/builders.d.ts.map +1 -1
- package/dist/components/builders.js +5 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.js +16 -1
- package/dist/components/capability-plugin.d.ts +14 -0
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/pr-hooks.d.ts +21 -1
- package/dist/components/pr-hooks.d.ts.map +1 -1
- package/dist/components/pr-hooks.js +72 -4
- package/dist/components/pr-pipeline.d.ts +45 -10
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +47 -14
- package/dist/components/pr-policy.d.ts +36 -0
- package/dist/components/pr-policy.d.ts.map +1 -1
- package/dist/components/pr-policy.js +36 -0
- package/dist/components/pr-run.d.ts +3 -0
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +1 -0
- package/dist/components/starter-plugin.d.ts +1 -0
- package/dist/components/starter-plugin.d.ts.map +1 -1
- package/dist/components/starter-plugin.js +5 -1
- package/dist/components/verbs/index.d.ts +2 -0
- package/dist/components/verbs/index.d.ts.map +1 -1
- package/dist/components/verbs/index.js +2 -0
- package/dist/components/verbs/publish-artifact.d.ts +65 -0
- package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
- package/dist/components/verbs/publish-artifact.js +74 -0
- package/dist/components/verbs/publish-image.d.ts +129 -0
- package/dist/components/verbs/publish-image.d.ts.map +1 -0
- package/dist/components/verbs/publish-image.js +145 -0
- package/dist/config-environments.d.ts +20 -0
- package/dist/config-environments.d.ts.map +1 -1
- package/dist/config-environments.js +12 -0
- package/dist/config.d.ts +25 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -2
- package/dist/gate-decision.d.ts +20 -2
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +30 -3
- package/dist/graph-ir.d.ts +25 -0
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-walk.d.ts +66 -0
- package/dist/graph-walk.d.ts.map +1 -0
- package/dist/graph-walk.js +70 -0
- package/dist/import/parser.d.ts +19 -0
- package/dist/import/parser.d.ts.map +1 -1
- package/dist/lexicon.d.ts +94 -6
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +11 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +2 -5
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/ledger-read.d.ts +65 -0
- package/dist/lifecycle/ledger-read.d.ts.map +1 -0
- package/dist/lifecycle/ledger-read.js +160 -0
- package/dist/lifecycle/release-workstation.d.ts +7 -0
- package/dist/lifecycle/release-workstation.d.ts.map +1 -1
- package/dist/lifecycle/release-workstation.js +25 -0
- package/dist/lifecycle/run-ledger.d.ts +4 -3
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/run-ledger.js +1 -0
- package/dist/lint/discover.js +3 -1
- package/dist/lint/post-synth.d.ts +127 -1
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lint/post-synth.js +84 -2
- package/dist/lint/rules/op/index.d.ts +1 -0
- package/dist/lint/rules/op/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.js +2 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
- package/dist/op/activities/activity-contracts.d.ts +9 -6
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.js +5 -2
- package/dist/op/activities/index.d.ts +2 -2
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/index.js +1 -1
- package/dist/op/activities/review-agent.d.ts +90 -4
- package/dist/op/activities/review-agent.d.ts.map +1 -1
- package/dist/op/activities/review-agent.js +217 -19
- package/dist/op/activities/work-evidence.d.ts +8 -1
- package/dist/op/activities/work-evidence.d.ts.map +1 -1
- package/dist/op/activities/work-evidence.js +1 -0
- package/dist/op/builders.d.ts +9 -5
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +9 -5
- package/dist/op/composites/apply-op.d.ts +29 -2
- package/dist/op/composites/apply-op.d.ts.map +1 -1
- package/dist/op/composites/apply-op.js +20 -1
- package/dist/op/gate-approval-base.d.ts +25 -0
- package/dist/op/gate-approval-base.d.ts.map +1 -0
- package/dist/op/gate-approval-base.js +71 -0
- package/dist/op/gate-approval.d.ts +18 -9
- package/dist/op/gate-approval.d.ts.map +1 -1
- package/dist/op/gate-approval.js +13 -31
- package/dist/op/gate-name.d.ts +13 -0
- package/dist/op/gate-name.d.ts.map +1 -1
- package/dist/op/gate-name.js +14 -1
- package/dist/op/gate-quorum.d.ts +100 -3
- package/dist/op/gate-quorum.d.ts.map +1 -1
- package/dist/op/gate-quorum.js +108 -6
- package/dist/op/gate-review.d.ts +9 -0
- package/dist/op/gate-review.d.ts.map +1 -1
- package/dist/op/gate-review.js +13 -0
- package/dist/op/gate.d.ts +47 -5
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +25 -4
- package/dist/op/index.d.ts +3 -3
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/index.js +1 -1
- package/dist/op/local-executor.d.ts +45 -3
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +68 -7
- package/dist/op/op-waves-run.d.ts +26 -1
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +259 -13
- package/dist/op/op-waves.d.ts +72 -5
- package/dist/op/op-waves.d.ts.map +1 -1
- package/dist/op/op-waves.js +110 -15
- package/dist/op/runtime.d.ts +11 -0
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/schedule-overdue.d.ts +16 -0
- package/dist/op/schedule-overdue.d.ts.map +1 -1
- package/dist/op/schedule-overdue.js +36 -0
- package/dist/op/stage-hooks.d.ts +9 -2
- package/dist/op/stage-hooks.d.ts.map +1 -1
- package/dist/op/stage-hooks.js +7 -5
- package/dist/op/workspace-run-env.d.ts +22 -0
- package/dist/op/workspace-run-env.d.ts.map +1 -0
- package/dist/op/workspace-run-env.js +21 -0
- package/dist/pr-forge.d.ts +24 -0
- package/dist/pr-forge.d.ts.map +1 -1
- package/dist/pr-forge.js +47 -0
- package/dist/pr-loop.d.ts +10 -0
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +4 -0
- package/dist/pr-migrations.d.ts +62 -0
- package/dist/pr-migrations.d.ts.map +1 -0
- package/dist/pr-migrations.js +50 -0
- package/dist/pr-post.d.ts +42 -0
- package/dist/pr-post.d.ts.map +1 -1
- package/dist/pr-post.js +68 -2
- package/dist/read-filter.d.ts +65 -0
- package/dist/read-filter.d.ts.map +1 -0
- package/dist/read-filter.js +179 -0
- package/dist/run-event.d.ts +1 -1
- package/dist/run-event.d.ts.map +1 -1
- package/dist/terraform/carve.d.ts +24 -3
- package/dist/terraform/carve.d.ts.map +1 -1
- package/dist/terraform/carve.js +32 -14
- package/dist/terraform/cuts.d.ts +97 -0
- package/dist/terraform/cuts.d.ts.map +1 -0
- package/dist/terraform/cuts.js +138 -0
- package/dist/terraform/folds.d.ts +26 -0
- package/dist/terraform/folds.d.ts.map +1 -0
- package/dist/terraform/folds.js +38 -0
- package/dist/terraform/graph.d.ts.map +1 -1
- package/dist/terraform/graph.js +10 -0
- package/dist/terraform/reach.d.ts +140 -0
- package/dist/terraform/reach.d.ts.map +1 -0
- package/dist/terraform/reach.js +170 -0
- package/dist/terraform/score.d.ts +14 -0
- package/dist/terraform/score.d.ts.map +1 -1
- package/dist/terraform/score.js +14 -31
- package/dist/terraform/state.d.ts.map +1 -1
- package/dist/terraform/state.js +4 -2
- package/dist/terraform/types.d.ts +8 -0
- package/dist/terraform/types.d.ts.map +1 -1
- package/dist/wave-blocked.d.ts +10 -1
- package/dist/wave-blocked.d.ts.map +1 -1
- package/dist/wave-blocked.js +31 -3
- package/dist/wave-runtime.mjs +264 -254
- package/dist/workspace/check.schema.json +13 -2
- package/dist/workspace/checks/ci-branch.d.ts +44 -0
- package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
- package/dist/workspace/checks/ci-branch.js +133 -0
- package/dist/workspace/checks/gate-approval.d.ts +58 -0
- package/dist/workspace/checks/gate-approval.d.ts.map +1 -0
- package/dist/workspace/checks/gate-approval.js +103 -0
- package/dist/workspace/checks/links.d.ts +3 -0
- package/dist/workspace/checks/links.d.ts.map +1 -1
- package/dist/workspace/checks/links.js +12 -1
- package/dist/workspace/checks/org.d.ts +48 -0
- package/dist/workspace/checks/org.d.ts.map +1 -0
- package/dist/workspace/checks/org.js +156 -0
- package/dist/workspace/checks.d.ts +12 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +63 -7
- package/dist/workspace/ci-branches.d.ts +16 -0
- package/dist/workspace/ci-branches.d.ts.map +1 -1
- package/dist/workspace/ci-branches.js +27 -0
- package/dist/workspace/ci-green-cli.js +7 -7
- package/dist/workspace/ci-green-workflow.d.ts +1 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +13 -8
- package/dist/workspace/ci-green.d.ts +14 -0
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +44 -11
- package/dist/workspace/ci-run.d.ts +9 -1
- package/dist/workspace/ci-run.d.ts.map +1 -1
- package/dist/workspace/ci-run.js +67 -6
- package/dist/workspace/ci-serve.d.ts +9 -0
- package/dist/workspace/ci-serve.d.ts.map +1 -1
- package/dist/workspace/ci-serve.js +114 -76
- package/dist/workspace/compose-graph.d.ts +14 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/composites.d.ts +4 -1
- package/dist/workspace/composites.d.ts.map +1 -1
- package/dist/workspace/composites.js +5 -2
- package/dist/workspace/composites.schema.json +22 -0
- package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
- package/dist/workspace/cross-root-lint.d.ts +56 -0
- package/dist/workspace/cross-root-lint.d.ts.map +1 -0
- package/dist/workspace/cross-root-lint.js +111 -0
- package/dist/workspace/dbt-models-reader.d.ts +44 -0
- package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
- package/dist/workspace/dbt-models-reader.js +356 -0
- package/dist/workspace/dbt-project-common.d.ts +40 -0
- package/dist/workspace/dbt-project-common.d.ts.map +1 -0
- package/dist/workspace/dbt-project-common.js +106 -0
- package/dist/workspace/dbt-project-reader.d.ts +4 -3
- package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
- package/dist/workspace/dbt-project-reader.js +14 -108
- package/dist/workspace/decision-rank.d.ts +26 -0
- package/dist/workspace/decision-rank.d.ts.map +1 -0
- package/dist/workspace/decision-rank.js +16 -0
- package/dist/workspace/declaration.d.ts +50 -2
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +57 -11
- package/dist/workspace/declaration.schema.json +166 -24
- package/dist/workspace/environments.d.ts +26 -2
- package/dist/workspace/environments.d.ts.map +1 -1
- package/dist/workspace/environments.js +26 -2
- package/dist/workspace/exit-cli.d.ts +44 -0
- package/dist/workspace/exit-cli.d.ts.map +1 -0
- package/dist/workspace/exit-cli.js +198 -0
- package/dist/workspace/exit.d.ts +159 -0
- package/dist/workspace/exit.d.ts.map +1 -0
- package/dist/workspace/exit.js +480 -0
- package/dist/workspace/exit.schema.json +257 -0
- package/dist/workspace/flyway-dir.d.ts +39 -0
- package/dist/workspace/flyway-dir.d.ts.map +1 -0
- package/dist/workspace/flyway-dir.js +104 -0
- package/dist/workspace/flyway-layout.d.ts +96 -0
- package/dist/workspace/flyway-layout.d.ts.map +1 -0
- package/dist/workspace/flyway-layout.js +308 -0
- package/dist/workspace/graph-cache.d.ts +3 -1
- package/dist/workspace/graph-cache.d.ts.map +1 -1
- package/dist/workspace/graph-cache.js +12 -1
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +26 -8
- package/dist/workspace/graph.schema.json +34 -0
- package/dist/workspace/import-fetch.d.ts +38 -0
- package/dist/workspace/import-fetch.d.ts.map +1 -0
- package/dist/workspace/import-fetch.js +99 -0
- package/dist/workspace/import-init.d.ts +26 -0
- package/dist/workspace/import-init.d.ts.map +1 -0
- package/dist/workspace/import-init.js +130 -0
- package/dist/workspace/import-source.d.ts +147 -0
- package/dist/workspace/import-source.d.ts.map +1 -0
- package/dist/workspace/import-source.js +370 -0
- package/dist/workspace/init.d.ts +4 -0
- package/dist/workspace/init.d.ts.map +1 -1
- package/dist/workspace/init.js +70 -3
- package/dist/workspace/intent.d.ts +2 -3
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/intent.js +5 -9
- package/dist/workspace/kind-link-readers.d.ts +59 -2
- package/dist/workspace/kind-link-readers.d.ts.map +1 -1
- package/dist/workspace/kind-link-readers.js +17 -1
- package/dist/workspace/kind-readers.d.ts +6 -0
- package/dist/workspace/kind-readers.d.ts.map +1 -1
- package/dist/workspace/kind-readers.js +18 -0
- package/dist/workspace/kinds.d.ts +90 -3
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +161 -7
- package/dist/workspace/ledger.schema.json +158 -0
- package/dist/workspace/lexicon-outputs.d.ts +20 -1
- package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
- package/dist/workspace/lexicon-outputs.js +102 -10
- package/dist/workspace/lineage-check.d.ts +3 -0
- package/dist/workspace/lineage-check.d.ts.map +1 -1
- package/dist/workspace/lineage-check.js +23 -4
- package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
- package/dist/workspace/lineage-upgrade.js +13 -4
- package/dist/workspace/links.d.ts +8 -1
- package/dist/workspace/links.d.ts.map +1 -1
- package/dist/workspace/links.js +25 -1
- package/dist/workspace/ls.d.ts +8 -0
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +7 -1
- package/dist/workspace/ls.schema.json +7 -0
- package/dist/workspace/member-commands.d.ts.map +1 -1
- package/dist/workspace/member-commands.js +54 -5
- package/dist/workspace/migrate-links.d.ts +45 -0
- package/dist/workspace/migrate-links.d.ts.map +1 -0
- package/dist/workspace/migrate-links.js +100 -0
- package/dist/workspace/migration-dirs.d.ts +74 -0
- package/dist/workspace/migration-dirs.d.ts.map +1 -0
- package/dist/workspace/migration-dirs.js +254 -0
- package/dist/workspace/new-migrations.d.ts +47 -0
- package/dist/workspace/new-migrations.d.ts.map +1 -0
- package/dist/workspace/new-migrations.js +91 -0
- package/dist/workspace/pr-report.schema.json +46 -0
- package/dist/workspace/promote.d.ts +96 -0
- package/dist/workspace/promote.d.ts.map +1 -0
- package/dist/workspace/promote.js +263 -0
- package/dist/workspace/reason-codes.d.ts +21 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +25 -0
- package/dist/workspace/records-cli.d.ts +11 -0
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-cli.js +57 -5
- package/dist/workspace/records.schema.json +5 -0
- package/dist/workspace/release-candidates.d.ts +2 -0
- package/dist/workspace/release-candidates.d.ts.map +1 -1
- package/dist/workspace/release-candidates.js +5 -2
- package/dist/workspace/release-train.d.ts +53 -0
- package/dist/workspace/release-train.d.ts.map +1 -0
- package/dist/workspace/release-train.js +134 -0
- package/dist/workspace/release-workflow.d.ts.map +1 -1
- package/dist/workspace/release-workflow.js +4 -3
- package/dist/workspace/repo-ref.d.ts +45 -0
- package/dist/workspace/repo-ref.d.ts.map +1 -0
- package/dist/workspace/repo-ref.js +114 -0
- package/dist/workspace/run-event.schema.json +2 -2
- package/dist/workspace/runs-cli.d.ts +9 -0
- package/dist/workspace/runs-cli.d.ts.map +1 -1
- package/dist/workspace/runs-cli.js +48 -3
- package/dist/workspace/runs.schema.json +7 -0
- package/dist/workspace/search-contract.d.ts +1 -1
- package/dist/workspace/search-contract.d.ts.map +1 -1
- package/dist/workspace/status-decisions.d.ts +37 -0
- package/dist/workspace/status-decisions.d.ts.map +1 -0
- package/dist/workspace/status-decisions.js +147 -0
- package/dist/workspace/status-gates.d.ts +9 -0
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +4 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/status.js +14 -2
- package/dist/workspace/status.schema.json +6 -0
- package/dist/workspace/work-cli.d.ts.map +1 -1
- package/dist/workspace/work-cli.js +5 -3
- package/dist/workspace/work-evidence-ops.d.ts +83 -0
- package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
- package/dist/workspace/work-evidence-ops.js +169 -0
- package/dist/workspace/work-evidence.d.ts +12 -2
- package/dist/workspace/work-evidence.d.ts.map +1 -1
- package/dist/workspace/work-evidence.js +21 -3
- package/dist/workspace/work-evidence.schema.json +49 -2
- package/dist/workspace/workspace-gates.d.ts +110 -0
- package/dist/workspace/workspace-gates.d.ts.map +1 -0
- package/dist/workspace/workspace-gates.js +140 -0
- package/dist/workspace/workspace-kinds.schema.json +108 -10
- package/dist/workspace/workspace-ledger.d.ts +76 -0
- package/dist/workspace/workspace-ledger.d.ts.map +1 -0
- package/dist/workspace/workspace-ledger.js +91 -0
- package/dist/workspace/workspace-run.d.ts +112 -0
- package/dist/workspace/workspace-run.d.ts.map +1 -0
- package/dist/workspace/workspace-run.js +432 -0
- package/package.json +1 -1
- package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
- package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
- package/src/__golden__/wave-loop/op-cost-member.json +13 -0
- package/src/__golden__/wave-loop/op-denied-source.json +16 -0
- package/src/__golden__/wave-loop/op-denied.json +16 -0
- package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
- package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
- package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
- package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
- package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
- package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
- package/src/__golden__/wave-loop/op-held-on.json +16 -0
- package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
- package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
- package/src/__golden__/wave-loop/op-overridden.json +16 -0
- package/src/__golden__/wave-loop/op-per-run.json +20 -0
- package/src/__golden__/wave-loop/op-point.json +13 -0
- package/src/__golden__/wave-loop/op-pr-review.json +10 -0
- package/src/__golden__/wave-loop/op-sealed.json +10 -0
- package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
- package/src/__golden__/wave-loop/op-spend.json +10 -0
- package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
- package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
- package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
- package/src/__golden__/wave-loop/op-wide.json +39 -0
- package/src/action-pins.test.ts +78 -0
- package/src/action-pins.ts +92 -0
- package/src/cli/commands/carve-score-once.test.ts +99 -0
- package/src/cli/commands/carve.ts +37 -6
- package/src/cli/commands/check-lexicon.test.ts +2 -2
- package/src/cli/commands/import-report.ts +71 -0
- package/src/cli/commands/import.ts +33 -3
- package/src/cli/commands/migrate-dialect.test.ts +145 -0
- package/src/cli/commands/migrate.ts +132 -11
- package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
- package/src/cli/handlers/approve.ts +33 -4
- package/src/cli/handlers/build.ts +7 -1
- package/src/cli/handlers/graph-reader.test.ts +31 -0
- package/src/cli/handlers/graph-reader.ts +51 -0
- package/src/cli/handlers/graph.ts +14 -0
- package/src/cli/handlers/ledger.ts +54 -0
- package/src/cli/handlers/migrate.ts +21 -12
- package/src/cli/handlers/misc.ts +10 -1
- package/src/cli/handlers/pr-env.ts +2 -2
- package/src/cli/handlers/pr.ts +176 -37
- package/src/cli/handlers/query.ts +16 -4
- package/src/cli/handlers/release.ts +6 -3
- package/src/cli/handlers/search.ts +13 -34
- package/src/cli/main.test.ts +17 -0
- package/src/cli/main.ts +87 -14
- package/src/cli/parse-args.ts +35 -2
- package/src/cli/registry.ts +22 -4
- package/src/components/builders.ts +8 -0
- package/src/components/capability-plugin-loader.ts +13 -1
- package/src/components/capability-plugin.ts +16 -0
- package/src/components/pr-env-run-bundle.test.ts +1 -0
- package/src/components/pr-hooks.test.ts +73 -5
- package/src/components/pr-hooks.ts +95 -5
- package/src/components/pr-pipeline.ts +64 -16
- package/src/components/pr-policy.test.ts +64 -1
- package/src/components/pr-policy.ts +53 -0
- package/src/components/pr-run.ts +4 -0
- package/src/components/registry.test.ts +1 -1
- package/src/components/starter-plugin.ts +6 -0
- package/src/components/verbs/index.ts +2 -0
- package/src/components/verbs/publish-artifact.test.ts +60 -0
- package/src/components/verbs/publish-artifact.ts +122 -0
- package/src/components/verbs/publish-image.test.ts +101 -0
- package/src/components/verbs/publish-image.ts +265 -0
- package/src/config-environments.ts +28 -1
- package/src/config.ts +24 -1
- package/src/gate-decision-bundle.test.ts +5 -2
- package/src/gate-decision-identity.test.ts +20 -0
- package/src/gate-decision.ts +46 -3
- package/src/graph-ir.ts +27 -0
- package/src/graph-walk.test.ts +44 -0
- package/src/graph-walk.ts +102 -0
- package/src/import/parser.ts +20 -0
- package/src/lexicon.ts +98 -6
- package/src/lifecycle/gate-ledger.ts +8 -0
- package/src/lifecycle/git.ts +2 -2
- package/src/lifecycle/ledger-read.test.ts +107 -0
- package/src/lifecycle/ledger-read.ts +195 -0
- package/src/lifecycle/release-workstation.ts +24 -0
- package/src/lifecycle/run-ledger.ts +5 -2
- package/src/lint/cross-root.test.ts +122 -0
- package/src/lint/discover.ts +3 -1
- package/src/lint/post-synth.ts +212 -2
- package/src/lint/rules/op/index.ts +2 -0
- package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
- package/src/op/activities/activity-contracts.ts +5 -2
- package/src/op/activities/index.ts +2 -2
- package/src/op/activities/review-agent.test.ts +221 -4
- package/src/op/activities/review-agent.ts +265 -22
- package/src/op/activities/work-evidence.ts +9 -1
- package/src/op/builders.ts +9 -5
- package/src/op/composites/apply-op.test.ts +108 -0
- package/src/op/composites/apply-op.ts +37 -2
- package/src/op/gate-approval-at-base.test.ts +97 -0
- package/src/op/gate-approval-base.ts +72 -0
- package/src/op/gate-approval.test.ts +6 -1
- package/src/op/gate-approval.ts +22 -27
- package/src/op/gate-name.ts +16 -1
- package/src/op/gate-quorum-at-base.test.ts +211 -0
- package/src/op/gate-quorum.ts +156 -8
- package/src/op/gate-review.ts +14 -0
- package/src/op/gate.ts +69 -9
- package/src/op/index.ts +3 -2
- package/src/op/local-executor.ts +91 -11
- package/src/op/op-waves-depends-on.test.ts +81 -0
- package/src/op/op-waves-hook-targets.test.ts +4 -2
- package/src/op/op-waves-quorum-product.test.ts +158 -0
- package/src/op/op-waves-run.ts +288 -14
- package/src/op/op-waves.ts +143 -14
- package/src/op/runtime.ts +8 -0
- package/src/op/schedule-overdue.ts +33 -0
- package/src/op/stage-hooks.ts +13 -5
- package/src/op/workspace-run-env.ts +29 -0
- package/src/pr-forge-bundle.test.ts +2 -2
- package/src/pr-forge.test.ts +47 -0
- package/src/pr-forge.ts +68 -0
- package/src/pr-loop-bundle.test.ts +3 -2
- package/src/pr-loop.test.ts +52 -0
- package/src/pr-loop.ts +12 -0
- package/src/pr-migrations.ts +97 -0
- package/src/pr-post-open.e2e.test.ts +36 -0
- package/src/pr-post.test.ts +102 -3
- package/src/pr-post.ts +90 -2
- package/src/read-filter.test.ts +54 -0
- package/src/read-filter.ts +193 -0
- package/src/run-event.ts +1 -1
- package/src/stage-hooks-bundle.test.ts +1 -0
- package/src/terraform/carve.ts +52 -15
- package/src/terraform/cuts.test.ts +173 -0
- package/src/terraform/cuts.ts +188 -0
- package/src/terraform/folds.ts +44 -0
- package/src/terraform/graph.ts +9 -0
- package/src/terraform/radius.test.ts +90 -0
- package/src/terraform/reach.test.ts +146 -0
- package/src/terraform/reach.ts +247 -0
- package/src/terraform/score.ts +27 -29
- package/src/terraform/state.ts +3 -1
- package/src/terraform/types.ts +8 -0
- package/src/wave-blocked.ts +28 -3
- package/src/wave-loop-golden.test.ts +4 -3
- package/src/workspace/__fixtures__/import/spacelift.json +9 -0
- package/src/workspace/__fixtures__/import/tfc.json +13 -0
- package/src/workspace/behold-kinds.test.ts +2 -1
- package/src/workspace/check-contract.test.ts +8 -6
- package/src/workspace/check.schema.json +13 -2
- package/src/workspace/checks/ci-branch.test.ts +128 -0
- package/src/workspace/checks/ci-branch.ts +141 -0
- package/src/workspace/checks/gate-approval.test.ts +77 -0
- package/src/workspace/checks/gate-approval.ts +121 -0
- package/src/workspace/checks/links.ts +12 -1
- package/src/workspace/checks/org.ts +169 -0
- package/src/workspace/checks.ts +68 -7
- package/src/workspace/ci-branches.ts +31 -0
- package/src/workspace/ci-green-branches.test.ts +153 -0
- package/src/workspace/ci-green-cli.ts +7 -7
- package/src/workspace/ci-green-workflow.test.ts +4 -3
- package/src/workspace/ci-green-workflow.ts +13 -9
- package/src/workspace/ci-green.ts +49 -12
- package/src/workspace/ci-run.test.ts +72 -1
- package/src/workspace/ci-run.ts +68 -8
- package/src/workspace/ci-serve.test.ts +95 -0
- package/src/workspace/ci-serve.ts +106 -65
- package/src/workspace/component-environments.test.ts +25 -2
- package/src/workspace/compose-graph.ts +9 -2
- package/src/workspace/composites.schema.json +22 -0
- package/src/workspace/composites.test.ts +39 -8
- package/src/workspace/composites.ts +6 -2
- package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
- package/src/workspace/cross-root-lint.test.ts +90 -0
- package/src/workspace/cross-root-lint.ts +126 -0
- package/src/workspace/dbt-kind.test.ts +3 -2
- package/src/workspace/dbt-models-reader.ts +362 -0
- package/src/workspace/dbt-models.test.ts +248 -0
- package/src/workspace/dbt-project-common.ts +113 -0
- package/src/workspace/dbt-project-reader.ts +29 -112
- package/src/workspace/decision-rank.ts +40 -0
- package/src/workspace/declaration.schema.json +166 -24
- package/src/workspace/declaration.ts +101 -15
- package/src/workspace/environments.ts +40 -4
- package/src/workspace/exit-cli.ts +219 -0
- package/src/workspace/exit.schema.json +257 -0
- package/src/workspace/exit.test.ts +185 -0
- package/src/workspace/exit.ts +560 -0
- package/src/workspace/flyway-dir.ts +113 -0
- package/src/workspace/flyway-layout.ts +337 -0
- package/src/workspace/graph-cache.ts +12 -2
- package/src/workspace/graph-cli.ts +25 -10
- package/src/workspace/graph-contract.test.ts +4 -2
- package/src/workspace/graph.schema.json +34 -0
- package/src/workspace/identity.test.ts +29 -2
- package/src/workspace/import-fetch.ts +151 -0
- package/src/workspace/import-init.ts +147 -0
- package/src/workspace/import-source.test.ts +183 -0
- package/src/workspace/import-source.ts +462 -0
- package/src/workspace/init.test.ts +55 -1
- package/src/workspace/init.ts +66 -4
- package/src/workspace/intent.ts +6 -14
- package/src/workspace/kind-link-readers.ts +68 -3
- package/src/workspace/kind-readers.test.ts +36 -0
- package/src/workspace/kind-readers.ts +18 -1
- package/src/workspace/kinds.test.ts +35 -7
- package/src/workspace/kinds.ts +212 -11
- package/src/workspace/ledger.schema.json +158 -0
- package/src/workspace/lexicon-outputs.ts +132 -13
- package/src/workspace/lineage-check.ts +30 -7
- package/src/workspace/lineage-upgrade.test.ts +20 -0
- package/src/workspace/lineage-upgrade.ts +16 -7
- package/src/workspace/links.ts +24 -1
- package/src/workspace/ls-contract.test.ts +1 -1
- package/src/workspace/ls.schema.json +7 -0
- package/src/workspace/ls.ts +10 -1
- package/src/workspace/member-commands.ts +60 -2
- package/src/workspace/member-file-schema.test.ts +124 -0
- package/src/workspace/migrate-links.test.ts +99 -0
- package/src/workspace/migrate-links.ts +108 -0
- package/src/workspace/migration-dirs.test.ts +272 -0
- package/src/workspace/migration-dirs.ts +267 -0
- package/src/workspace/new-migrations.test.ts +98 -0
- package/src/workspace/new-migrations.ts +109 -0
- package/src/workspace/org-scope.test.ts +238 -0
- package/src/workspace/pr-report.schema.json +46 -0
- package/src/workspace/promote.test.ts +114 -0
- package/src/workspace/promote.ts +302 -0
- package/src/workspace/reason-codes.test.ts +10 -1
- package/src/workspace/reason-codes.ts +25 -0
- package/src/workspace/records-cli.ts +58 -5
- package/src/workspace/records.schema.json +5 -0
- package/src/workspace/release-candidates.ts +7 -2
- package/src/workspace/release-train.ts +157 -0
- package/src/workspace/release-workflow.ts +4 -3
- package/src/workspace/repo-ref.ts +113 -0
- package/src/workspace/run-event.schema.json +2 -2
- package/src/workspace/runs-cli.ts +48 -4
- package/src/workspace/runs.schema.json +7 -0
- package/src/workspace/status-contract.test.ts +46 -1
- package/src/workspace/status-decisions.test.ts +100 -0
- package/src/workspace/status-decisions.ts +151 -0
- package/src/workspace/status-gates.ts +9 -0
- package/src/workspace/status.schema.json +6 -0
- package/src/workspace/status.ts +17 -3
- package/src/workspace/where-filters.test.ts +39 -0
- package/src/workspace/work-cli.ts +5 -3
- package/src/workspace/work-evidence-ops.test.ts +176 -0
- package/src/workspace/work-evidence-ops.ts +189 -0
- package/src/workspace/work-evidence.schema.json +49 -2
- package/src/workspace/work-evidence.ts +22 -3
- package/src/workspace/workspace-gates.ts +200 -0
- package/src/workspace/workspace-kinds.schema.json +108 -10
- package/src/workspace/workspace-ledger.ts +130 -0
- package/src/workspace/workspace-run.test.ts +322 -0
- package/src/workspace/workspace-run.ts +461 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterAll, describe, expect, test } from "vitest";
|
|
5
|
+
import { readGraphWithModule } from "./graph-reader";
|
|
6
|
+
|
|
7
|
+
const scratch = mkdtempSync(join(tmpdir(), "chant-graph-reader-"));
|
|
8
|
+
afterAll(() => rmSync(scratch, { recursive: true, force: true }));
|
|
9
|
+
|
|
10
|
+
function mod(name: string, text: string): string {
|
|
11
|
+
const file = join(scratch, name);
|
|
12
|
+
writeFileSync(file, text);
|
|
13
|
+
return file;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("readGraphWithModule (#4413)", () => {
|
|
17
|
+
test("calls the default export with dir and config, and fills in groups", async () => {
|
|
18
|
+
const file = mod("ok.mjs", "export default async ({ dir, config }) => ({ nodes: [{ id: 'a', kind: 'K', lexicon: 'x', attrs: { dir, n: config.n } }], edges: [] });\n");
|
|
19
|
+
const read = await readGraphWithModule(file, { dir: "/m", n: 2 }, "/p");
|
|
20
|
+
expect(read).toEqual({ ir: { nodes: [{ id: "a", kind: "K", lexicon: "x", attrs: { dir: "/m", n: 2 } }], edges: [], groups: {} } });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("says why when the module is missing, has no function, throws or returns no graph", async () => {
|
|
24
|
+
const msg = async (p: string) => ("error" in (await readGraphWithModule(p, {}, "/p")) ? ((await readGraphWithModule(p, {}, "/p")) as { error: string }).error : "");
|
|
25
|
+
expect(await msg(join(scratch, "nope.mjs"))).toMatch(/could not be loaded/);
|
|
26
|
+
expect(await msg(mod("nofn.mjs", "export default 3;\n"))).toMatch(/no default export function/);
|
|
27
|
+
expect(await msg(mod("throws.mjs", "export default () => { throw new Error('boom'); };\n"))).toMatch(/failed: boom/);
|
|
28
|
+
expect(await msg(mod("bad.mjs", "export default () => ({});\n"))).toMatch(/no nodes and edges/);
|
|
29
|
+
expect(await msg("rel.mjs")).toMatch(/absolute/);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant graph` over a graph reader module (#4413).
|
|
3
|
+
*
|
|
4
|
+
* A kind's `graph.reader` names a module in the package that supplies the
|
|
5
|
+
* kind; `chant workspace graph` writes a reader project whose
|
|
6
|
+
* `graph.reader.module` is that module, and the member's own `chant graph`
|
|
7
|
+
* runs here. Because the member's chant loads it, the reader runs under the
|
|
8
|
+
* member's toolchain, as a lexicon reader does. The module's default export
|
|
9
|
+
* is `(input: { dir, config }) => GraphIR`, sync or async. It reads files and
|
|
10
|
+
* returns data; chant gives it no write handle, and nothing it returns is
|
|
11
|
+
* run.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { pathToFileURL } from "node:url";
|
|
15
|
+
import { isAbsolute } from "node:path";
|
|
16
|
+
import type { GraphIR } from "../../graph-ir";
|
|
17
|
+
|
|
18
|
+
export interface GraphReaderInput {
|
|
19
|
+
/** The member's directory, absolute, as the kind's config placed it in `config.dir` (or the reader project when it didn't). */
|
|
20
|
+
dir: string;
|
|
21
|
+
/** The kind's `graph.config`, placeholders substituted. */
|
|
22
|
+
config: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Load the module and call it, or say why not. Never throws. */
|
|
26
|
+
export async function readGraphWithModule(
|
|
27
|
+
module: string,
|
|
28
|
+
config: Record<string, unknown>,
|
|
29
|
+
projectPath: string,
|
|
30
|
+
): Promise<{ ir: GraphIR } | { error: string }> {
|
|
31
|
+
if (!isAbsolute(module)) return { error: `graph.reader.module must be an absolute path, got ${module}` };
|
|
32
|
+
let read: unknown;
|
|
33
|
+
try {
|
|
34
|
+
read = ((await import(pathToFileURL(module).href)) as { default?: unknown }).default;
|
|
35
|
+
} catch (err) {
|
|
36
|
+
return { error: `graph reader ${module} could not be loaded: ${err instanceof Error ? err.message : String(err)}` };
|
|
37
|
+
}
|
|
38
|
+
if (typeof read !== "function") return { error: `graph reader ${module} has no default export function` };
|
|
39
|
+
let out: unknown;
|
|
40
|
+
try {
|
|
41
|
+
const dir = typeof config.dir === "string" ? config.dir : projectPath;
|
|
42
|
+
out = await (read as (input: GraphReaderInput) => unknown)({ dir, config });
|
|
43
|
+
} catch (err) {
|
|
44
|
+
return { error: `graph reader ${module} failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
45
|
+
}
|
|
46
|
+
const ir = out as Partial<GraphIR> | null;
|
|
47
|
+
if (ir === null || typeof ir !== "object" || !Array.isArray(ir.nodes) || !Array.isArray(ir.edges)) {
|
|
48
|
+
return { error: `graph reader ${module} returned something with no nodes and edges` };
|
|
49
|
+
}
|
|
50
|
+
return { ir: { ...ir, nodes: ir.nodes, edges: ir.edges, groups: ir.groups ?? {} } as GraphIR };
|
|
51
|
+
}
|
|
@@ -118,6 +118,20 @@ export function runGraph(ctx: CommandContext): Promise<number> {
|
|
|
118
118
|
async function runGraphCommand(ctx: CommandContext): Promise<number> {
|
|
119
119
|
const viewFormats = ["ir", "mermaid", "dot", "layout"] as const;
|
|
120
120
|
const isViewFormat = (viewFormats as readonly string[]).includes(ctx.args.format);
|
|
121
|
+
// A project whose config names a graph reader module is read by it (#4413): `chant workspace graph` writes such a project for a kind that supplies one.
|
|
122
|
+
if (isViewFormat && !ctx.args.live && !ctx.args.at && !ctx.args.components) {
|
|
123
|
+
const { config } = await loadChantConfigUpward(resolve(ctx.args.path === "." ? "." : ctx.args.path)).catch(() => ({ config: {} as ChantConfig }));
|
|
124
|
+
const reader = config.graph?.reader;
|
|
125
|
+
if (reader) {
|
|
126
|
+
const { readGraphWithModule } = await import("./graph-reader");
|
|
127
|
+
const read = await readGraphWithModule(reader.module, reader.config ?? {}, resolve(ctx.args.path === "." ? "." : ctx.args.path));
|
|
128
|
+
if ("error" in read) {
|
|
129
|
+
console.error(formatError({ message: read.error }));
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
return emitIr(read.ir, ctx, ctx.args.format as (typeof viewFormats)[number]);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
121
135
|
// `--projection <lexicon>` (#989) only means anything for the component
|
|
122
136
|
// graph's IR — it adds the CI/pipeline shape to `GraphIR.pipeline`, a field
|
|
123
137
|
// the other view formats' emitters (mermaid/dot/layout) don't read, and the
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant ledger <table> [dir] [--member <name>] [--where <field><op><value>]...
|
|
3
|
+
* [--since <time>] [--at <rev>] [--json]` (#4363): one ledger's rows from the
|
|
4
|
+
* local `chant/lifecycle` branch, filtered with typed filters. The read and
|
|
5
|
+
* its contract live in `../../lifecycle/ledger-read.ts`; the ledgers are read
|
|
6
|
+
* as `chant query` reads them (`./query.ts` {@link queryLedgers}).
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { resolve } from "node:path";
|
|
10
|
+
import { formatError, formatWarning } from "../format";
|
|
11
|
+
import type { CommandContext } from "../registry";
|
|
12
|
+
import { queryLedgers } from "./query";
|
|
13
|
+
|
|
14
|
+
const USAGE = "chant ledger <resources|snapshots|runs|gates|deploys|releases|cuts> [dir] [--member <name>] [--where <field><op><value>]... [--since <time>] [--at <rev>] [--json]";
|
|
15
|
+
|
|
16
|
+
const cell = (v: unknown): string => (v === null || v === undefined ? "" : typeof v === "object" ? JSON.stringify(v) : String(v));
|
|
17
|
+
|
|
18
|
+
export async function runLedgerCommand(ctx: CommandContext): Promise<number> {
|
|
19
|
+
const { args } = ctx;
|
|
20
|
+
const table = args.positionals?.[0];
|
|
21
|
+
if (table === undefined || table.trim() === "") {
|
|
22
|
+
console.error(formatError({ message: "chant ledger needs a table", hint: USAGE }));
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
const cwd = resolve(args.positionals?.[1] ?? ".");
|
|
26
|
+
if (!existsSync(cwd)) {
|
|
27
|
+
console.error(formatError({ message: `${cwd} does not exist`, hint: USAGE }));
|
|
28
|
+
return 1;
|
|
29
|
+
}
|
|
30
|
+
const { readLedgerTable, ledgerReadFailure, LedgerRevisionError } = await import("../../lifecycle/ledger-read");
|
|
31
|
+
const { QueryError } = await import("../../lifecycle/query");
|
|
32
|
+
let doc;
|
|
33
|
+
try {
|
|
34
|
+
doc = await readLedgerTable(table, () => queryLedgers(cwd, args.members, args.at), { where: args.where, since: args.since, at: args.at ?? null });
|
|
35
|
+
} catch (err) {
|
|
36
|
+
if (err instanceof LedgerRevisionError) doc = ledgerReadFailure("revision-unknown", err.message);
|
|
37
|
+
else if (err instanceof QueryError) doc = ledgerReadFailure("ledger-unreadable", err.message);
|
|
38
|
+
else throw err;
|
|
39
|
+
}
|
|
40
|
+
if (args.json) {
|
|
41
|
+
console.log(JSON.stringify(doc, null, 2));
|
|
42
|
+
return "error" in doc ? 1 : 0;
|
|
43
|
+
}
|
|
44
|
+
if ("error" in doc) {
|
|
45
|
+
console.error(formatError({ message: `${doc.error.code}: ${doc.error.message}`, hint: USAGE }));
|
|
46
|
+
return 1;
|
|
47
|
+
}
|
|
48
|
+
const widths = doc.columns.map((c) => Math.max(c.length, ...doc.rows.map((r) => cell(r[c]).length)));
|
|
49
|
+
const line = (vals: string[]): string => vals.map((v, i) => v.padEnd(widths[i])).join(" ").trimEnd();
|
|
50
|
+
console.log([line(doc.columns), line(widths.map((w) => "-".repeat(w))), ...doc.rows.map((r) => line(doc.columns.map((c) => cell(r[c]))))].join("\n"));
|
|
51
|
+
console.log(`(${doc.rows.length} of ${doc.total} ${doc.total === 1 ? "row" : "rows"})`);
|
|
52
|
+
if (doc.malformed > 0) console.error(formatWarning({ message: `left out ${doc.malformed} in ${doc.table} that could not be read` }));
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { migrateCommand, printMigrateResult } from "../commands/migrate";
|
|
1
|
+
import { lexiconOfSide, migrateCommand, printMigrateResult } from "../commands/migrate";
|
|
2
2
|
import { formatError } from "../format";
|
|
3
3
|
import { loadPlugins } from "../plugins";
|
|
4
4
|
import type { CommandContext } from "../registry";
|
|
@@ -16,30 +16,39 @@ export async function runMigrate(ctx: CommandContext): Promise<number> {
|
|
|
16
16
|
return 1;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
// A side is a lexicon, or a lexicon and a dialect: `sql/clickhouse` (#4399).
|
|
20
|
+
const toName = args.migrateTo ?? "gitlab";
|
|
21
|
+
const fromName = args.migrateFrom ?? "github";
|
|
22
|
+
|
|
23
|
+
// The sql pair writes declarations, so ts is its default; yaml is the gitlab pair's.
|
|
24
|
+
const emit = (args.emit as "yaml" | "ts" | "sql" | undefined) ?? (lexiconOfSide(toName) === "sql" ? "ts" : "yaml");
|
|
25
|
+
if (emit !== "yaml" && emit !== "ts" && emit !== "sql") {
|
|
26
|
+
console.error(formatError({ message: `Invalid --emit value: ${emit}. Expected 'yaml', 'ts' or 'sql'.` }));
|
|
27
|
+
return 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (emit === "sql" && lexiconOfSide(toName) !== "sql") {
|
|
31
|
+
console.error(formatError({ message: `--emit sql writes DDL, and ${toName} is not a sql target`, hint: "use --emit yaml or --emit ts" }));
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
19
35
|
// migrate does not require a chant project context. Load the target
|
|
20
36
|
// lexicon directly by name.
|
|
21
|
-
const toName = args.migrateTo ?? "gitlab";
|
|
22
37
|
let plugins;
|
|
23
38
|
try {
|
|
24
|
-
plugins = await loadPlugins([toName]);
|
|
39
|
+
plugins = await loadPlugins([lexiconOfSide(toName)]);
|
|
25
40
|
} catch (err) {
|
|
26
41
|
console.error(formatError({
|
|
27
42
|
message: `Cannot load target lexicon "${toName}": ${err instanceof Error ? err.message : String(err)}`,
|
|
28
|
-
hint: `Install @intentius/chant-lexicon-${toName} or pass --to <other-lexicon>`,
|
|
43
|
+
hint: `Install @intentius/chant-lexicon-${lexiconOfSide(toName)} or pass --to <other-lexicon>`,
|
|
29
44
|
}));
|
|
30
45
|
return 1;
|
|
31
46
|
}
|
|
32
47
|
|
|
33
|
-
const emit = (args.emit as "yaml" | "ts" | undefined) ?? "yaml";
|
|
34
|
-
if (emit !== "yaml" && emit !== "ts") {
|
|
35
|
-
console.error(formatError({ message: `Invalid --emit value: ${emit}. Expected 'yaml' or 'ts'.` }));
|
|
36
|
-
return 1;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
48
|
const result = await migrateCommand({
|
|
40
49
|
sourceFile: args.path,
|
|
41
|
-
from:
|
|
42
|
-
to:
|
|
50
|
+
from: fromName,
|
|
51
|
+
to: toName,
|
|
43
52
|
emit,
|
|
44
53
|
strict: args.strict ?? false,
|
|
45
54
|
validate: args.validate ?? false,
|
package/src/cli/handlers/misc.ts
CHANGED
|
@@ -384,10 +384,19 @@ export async function runImport(ctx: CommandContext): Promise<number> {
|
|
|
384
384
|
force: ctx.args.force,
|
|
385
385
|
lexicon: ctx.args.lexicon,
|
|
386
386
|
parserOptions: ctx.args.parserOption,
|
|
387
|
+
validate: ctx.args.validate,
|
|
387
388
|
});
|
|
388
389
|
|
|
389
390
|
printImportResult(result);
|
|
390
|
-
|
|
391
|
+
if (!result.success) return 1;
|
|
392
|
+
// The review report and `--strict` (#4398): the parser's diagnostics, as `chant migrate` reports its own.
|
|
393
|
+
if (ctx.args.reportFile) {
|
|
394
|
+
const { writeImportReport } = await import("../commands/import-report");
|
|
395
|
+
const failed = writeImportReport(ctx.args.reportFile, resolve(ctx.args.path), result.diagnostics ?? [], CHANT_VERSION);
|
|
396
|
+
if (failed) console.error(formatWarning({ message: failed }));
|
|
397
|
+
}
|
|
398
|
+
const { importExitCode } = await import("../commands/import-report");
|
|
399
|
+
return importExitCode(result.diagnostics, ctx.args.strict === true);
|
|
391
400
|
}
|
|
392
401
|
|
|
393
402
|
export async function runUpdate(ctx: CommandContext): Promise<number> {
|
|
@@ -241,10 +241,10 @@ function componentsPrEnvAdapter(p: Prepared, run: { planAll: typeof import("./pr
|
|
|
241
241
|
},
|
|
242
242
|
async apply(target) {
|
|
243
243
|
const planned = set!;
|
|
244
|
-
const hookStop = run.runStageHook(p, "before-apply", p.plan.order, planned);
|
|
244
|
+
const hookStop = await run.runStageHook(p, "before-apply", p.plan.order, planned);
|
|
245
245
|
if (hookStop) return { status: "stopped", rows: rows(target, () => "planned"), message: hookStop };
|
|
246
246
|
const applied = await applyPrSet({ components: p.components, plan: p.plan, registry: p.registry, env: target.env, set: planned, gate: PR_ENV_GATE });
|
|
247
|
-
const afterHook = run.runStageHook(p, "after-apply", p.plan.order, planned, "the environment stands as applied");
|
|
247
|
+
const afterHook = await run.runStageHook(p, "after-apply", p.plan.order, planned, "the environment stands as applied");
|
|
248
248
|
const status = (component: string) => applied.members.find((m) => m.component === component)?.status ?? "planned";
|
|
249
249
|
return {
|
|
250
250
|
status: applied.status === "applied" ? "applied" : applied.status === "waiting" ? "waiting" : "failed",
|
package/src/cli/handlers/pr.ts
CHANGED
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
*/
|
|
66
66
|
|
|
67
67
|
import { spawnSync } from "node:child_process";
|
|
68
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
69
|
-
import { join, resolve } from "node:path";
|
|
68
|
+
import { mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
69
|
+
import { join, relative, resolve, sep } from "node:path";
|
|
70
70
|
import { loadChantConfig, resolveAutoReleaseDisabled, type ChantConfig } from "../../config";
|
|
71
71
|
import { resolveCommit, resolveMergeBase } from "../../components/changed-files";
|
|
72
72
|
import { deriveFanOut, fanOutRegistry } from "../../components/fan-out-support";
|
|
@@ -90,7 +90,8 @@ import { blockedMembers, blockedWords, settleEarlierWaves, type WaveMemberOutcom
|
|
|
90
90
|
import { readFanOutAttempt, writeFanOutAttempt, type FanOutAttempt, type PrApplyRecord } from "../../components/fan-out-record";
|
|
91
91
|
import { componentInputDigests, progressThatCarries } from "../../components/fan-out-inputs";
|
|
92
92
|
import { samePlanDigest } from "../../lifecycle/plan-digest";
|
|
93
|
-
import { gateIsSealed, gitGateLedgerPort, type GateCheck } from "../../op/gate";
|
|
93
|
+
import { evaluateGate, gateIsSealed, gitGateLedgerPort, type GateCheck, type GateLedgerPort } from "../../op/gate";
|
|
94
|
+
import type { OtherGateHold } from "../../op/stage-hooks";
|
|
94
95
|
import { emitGateStep, gateEventsOf, GATE_PHASE, type RunEventSink, type RunEventStream } from "../../run-event-stream";
|
|
95
96
|
import type { RunEventBody, RunEventComponentSettle, RunEventSettleStatus } from "../../run-event";
|
|
96
97
|
import { openCliRunEvents, refusesEventsWithJson } from "../run-events";
|
|
@@ -130,10 +131,12 @@ import type { ComponentChangeSignal, FanOutPlan } from "../../components/fan-out
|
|
|
130
131
|
import { failedRunExitCode, type DriverComponent } from "../../components/driver";
|
|
131
132
|
import type { CapabilityRegistry } from "../../components/capability";
|
|
132
133
|
import type { ComponentEnvironmentDeclaration } from "../../components/component";
|
|
133
|
-
import { prLoopHooksAt, runPrHooks, type PrHookPlace, type PrLoopHooks } from "../../components/pr-hooks";
|
|
134
|
-
import { decidePrPolicyOverride, prLoopPolicyAt, prPolicyReport, runPrPolicy, spendPrPolicyOverride, type PrLoopPolicy } from "../../components/pr-policy";
|
|
134
|
+
import { prLoopHooksAt, runPrHooks, type PrHoldSettled, type PrHookPlace, type PrLoopHooks } from "../../components/pr-hooks";
|
|
135
|
+
import { decidePrPolicyOverride, policyReviewOf, prLoopPolicyAt, prPolicyReport, runPrPolicy, spendPrPolicyOverride, type PrLoopPolicy } from "../../components/pr-policy";
|
|
135
136
|
import type { OpWaveHookMoment } from "../../op/op-waves";
|
|
136
137
|
import type { PrHookOutcome } from "../../pr-loop";
|
|
138
|
+
import type { PrMigrationFile } from "../../pr-migrations";
|
|
139
|
+
import { lexiconNames } from "../../lexicon-module";
|
|
137
140
|
|
|
138
141
|
|
|
139
142
|
/** Where the reports land unless `--output` says. */
|
|
@@ -320,9 +323,19 @@ export function placeHooks(ctx: CommandContext, p: Prepared, stage: PrHookPlace[
|
|
|
320
323
|
* when no hook failed. A hold is logged: the pull request's gate already
|
|
321
324
|
* waits for a person's approval of the digest.
|
|
322
325
|
*/
|
|
323
|
-
export function runStageHook(
|
|
326
|
+
export async function runStageHook(
|
|
327
|
+
p: Prepared,
|
|
328
|
+
moment: OpWaveHookMoment,
|
|
329
|
+
components: readonly string[],
|
|
330
|
+
planned?: PrPlanSet,
|
|
331
|
+
what = "nothing was applied",
|
|
332
|
+
env?: Record<string, string>,
|
|
333
|
+
): Promise<string | undefined> {
|
|
324
334
|
if (!p.hookPlace || components.length === 0) return undefined;
|
|
325
|
-
const ran = runPrHooks(p.hooks, moment, p.hookPlace, components, planned ? { members: planned.members, plans: planned.plans } : undefined
|
|
335
|
+
const ran = await runPrHooks(p.hooks, moment, p.hookPlace, components, planned ? { members: planned.members, plans: planned.plans } : undefined, {
|
|
336
|
+
...(env ? { env } : {}),
|
|
337
|
+
settle: (hold) => settleHeldGate(p, hold),
|
|
338
|
+
});
|
|
326
339
|
p.hookOutcomes.push(...ran.outcomes);
|
|
327
340
|
for (const hold of ran.holds) console.error(formatInfo(`${hold} held, and the pull request's gate asks for an approval of the digest either way`));
|
|
328
341
|
if (!ran.failed) return undefined;
|
|
@@ -330,6 +343,46 @@ export function runStageHook(p: Prepared, moment: OpWaveHookMoment, components:
|
|
|
330
343
|
return p.hookFailed;
|
|
331
344
|
}
|
|
332
345
|
|
|
346
|
+
/**
|
|
347
|
+
* Settle a hook's hold on another gate (#4323), the way an Op waves job does:
|
|
348
|
+
* an approval of that gate and digest under its `identity.gates` rule read at
|
|
349
|
+
* base, else a pending fact for it. The plan stage writes nothing, so there
|
|
350
|
+
* it only reads.
|
|
351
|
+
*/
|
|
352
|
+
async function settleHeldGate(p: Prepared, hold: OtherGateHold): Promise<PrHoldSettled> {
|
|
353
|
+
const real = gitGateLedgerPort();
|
|
354
|
+
const ledger = p.hookPlace?.stage === "plan" ? readOnlyLedger(real) : real;
|
|
355
|
+
const port: GateLedgerPort = ledger.approvalRule ? { ...ledger, approvalRule: (g: string) => ledger.approvalRule!(g, { base: p.base }) } : ledger;
|
|
356
|
+
const op = hold.request.op ?? p.hookPlace?.op ?? "";
|
|
357
|
+
const check = await evaluateGate(port, {
|
|
358
|
+
op,
|
|
359
|
+
gate: hold.request.gate,
|
|
360
|
+
planDigest: hold.request.digest,
|
|
361
|
+
description: hold.request.description ?? `${hold.label} holds the pull request on it`,
|
|
362
|
+
fields: { ...hold.request.pending, approvalMode: "ledger", heldBy: { hook: hold.name, moment: hold.moment, ...(hold.target ? { target: hold.target } : {}) } },
|
|
363
|
+
});
|
|
364
|
+
if (check.satisfied) return { status: "approved", approvedBy: check.resolution.resolvedBy, approvedAt: check.resolution.timestamp };
|
|
365
|
+
for (const { resolution: r, reason } of check.refused ?? []) console.error(formatInfo(`${op} / ${hold.request.gate}: the approval by ${r.resolvedBy} at ${r.timestamp} does not count: ${reason}`));
|
|
366
|
+
return { status: "waiting" };
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Run the `after-gate` hooks once the pull request's gate decided (#4323),
|
|
371
|
+
* whatever it decided. `CHANT_GATE_STATUS` is `approved`, or `waiting` when no
|
|
372
|
+
* approval of the digest stands; `CHANT_GATE_OP`, `CHANT_GATE` and
|
|
373
|
+
* `CHANT_GATE_DIGEST` name the gate. Returns the failure message, as
|
|
374
|
+
* {@link runStageHook} does; the caller ignores it when the gate did not let
|
|
375
|
+
* the apply through, since the stage ends there anyway.
|
|
376
|
+
*/
|
|
377
|
+
export function runGateHook(p: Prepared, at: { op: string; digest: string; satisfied: boolean }, components: readonly string[]): Promise<string | undefined> {
|
|
378
|
+
return runStageHook(p, "after-gate", components, undefined, "nothing was applied", {
|
|
379
|
+
CHANT_GATE_STATUS: at.satisfied ? "approved" : "waiting",
|
|
380
|
+
CHANT_GATE_OP: at.op,
|
|
381
|
+
CHANT_GATE: p.gate,
|
|
382
|
+
CHANT_GATE_DIGEST: at.digest,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
333
386
|
const EMPTY_SET = (): PrPlanSet => ({ doc: composeChangeSet([]), members: [], plans: {}, outputs: {}, failed: true });
|
|
334
387
|
|
|
335
388
|
/**
|
|
@@ -338,11 +391,11 @@ const EMPTY_SET = (): PrPlanSet => ({ doc: composeChangeSet([]), members: [], pl
|
|
|
338
391
|
* set, so the stage reports `plan-failed` and nothing applies.
|
|
339
392
|
*/
|
|
340
393
|
async function hookedPlan(p: Prepared, components: readonly string[], plan: () => Promise<PrPlanSet>): Promise<PrPlanSet> {
|
|
341
|
-
if (runStageHook(p, "before-observe", components, undefined, "nothing was planned or applied")) return EMPTY_SET();
|
|
342
|
-
if (runStageHook(p, "before-plan", components, undefined, "nothing was planned or applied")) return EMPTY_SET();
|
|
394
|
+
if (await runStageHook(p, "before-observe", components, undefined, "nothing was planned or applied")) return EMPTY_SET();
|
|
395
|
+
if (await runStageHook(p, "before-plan", components, undefined, "nothing was planned or applied")) return EMPTY_SET();
|
|
343
396
|
const set = await plan();
|
|
344
397
|
if (set.failed) return set;
|
|
345
|
-
if (runStageHook(p, "after-plan", components, set)) return { ...set, failed: true };
|
|
398
|
+
if (await runStageHook(p, "after-plan", components, set)) return { ...set, failed: true };
|
|
346
399
|
return set;
|
|
347
400
|
}
|
|
348
401
|
|
|
@@ -474,7 +527,7 @@ async function publish(forge: PrForge | undefined, report: PrReport, note: strin
|
|
|
474
527
|
if (report.pr === null) return;
|
|
475
528
|
// A member the change does not reach has nothing to say: one note per
|
|
476
529
|
// member would put a line on every pull request for each member it skips.
|
|
477
|
-
if (report.member && report.status === "nothing" && !report.overdue?.length) return;
|
|
530
|
+
if (report.member && report.status === "nothing" && !report.overdue?.length && !report.migrations?.length) return;
|
|
478
531
|
try {
|
|
479
532
|
await forge.upsertNote(report.pr, prNoteMarker(report.env, report.member), note);
|
|
480
533
|
} catch (err) {
|
|
@@ -570,7 +623,9 @@ interface PolicyJudged {
|
|
|
570
623
|
* read only at the plan stage, and recorded for an override at the apply.
|
|
571
624
|
*/
|
|
572
625
|
async function judgePolicy(p: Prepared, at: { stage: "plan" | "apply"; op: string; pr: number | null; set: PrPlanSet }): Promise<PolicyJudged> {
|
|
573
|
-
|
|
626
|
+
// The review is read only when a policy will run: a workspace with no policy makes no forge call for it.
|
|
627
|
+
const review = p.policy.settings ? await policyReviewOf(p.forge, at.pr) : undefined;
|
|
628
|
+
const verdict = runPrPolicy(p.policy, { version: 1, stage: at.stage, op: at.op, gate: p.gate, env: p.env, pr: at.pr, base: p.base, head: p.head, changeSet: at.set.doc, ...(review ? { review } : {}) });
|
|
574
629
|
if (!verdict) return { held: false };
|
|
575
630
|
const report = prPolicyReport(verdict, p.policy.base);
|
|
576
631
|
p.policyReport = report;
|
|
@@ -673,8 +728,10 @@ async function prPlan(ctx: CommandContext, stage: StageEvents): Promise<number>
|
|
|
673
728
|
}
|
|
674
729
|
const status = p.plan.order.length === 0 ? "nothing" : set.failed ? "plan-failed" : "planned";
|
|
675
730
|
const overdue = await overdueOps(p.forge, p.member);
|
|
731
|
+
const migrations = await newMigrations(p);
|
|
676
732
|
const planned = prReport({
|
|
677
733
|
stage: "plan",
|
|
734
|
+
...(migrations.length > 0 ? { migrations } : {}),
|
|
678
735
|
pr: ctx.args.pr,
|
|
679
736
|
env: p.env,
|
|
680
737
|
...(p.member ? { member: p.member } : {}),
|
|
@@ -704,6 +761,39 @@ async function prPlan(ctx: CommandContext, stage: StageEvents): Promise<number>
|
|
|
704
761
|
return status === "plan-failed" || judged.stop ? 1 : 0;
|
|
705
762
|
}
|
|
706
763
|
|
|
764
|
+
/**
|
|
765
|
+
* The migration files the pull request adds in a migration-directory member
|
|
766
|
+
* (#4407), each statement classified offline by the sql lexicon. Nothing is
|
|
767
|
+
* applied and no server is contacted. A workspace without such a member, or
|
|
768
|
+
* a classifier that cannot load, leaves the note as it was.
|
|
769
|
+
*/
|
|
770
|
+
async function newMigrations(p: Prepared): Promise<PrMigrationFile[]> {
|
|
771
|
+
const { newMigrationFilesBetween } = await import("../../workspace/new-migrations");
|
|
772
|
+
try {
|
|
773
|
+
return await newMigrationFilesBetween(resolve("."), p.base, p.head, {
|
|
774
|
+
...(p.member ? { member: p.member } : {}),
|
|
775
|
+
plugins: async () => {
|
|
776
|
+
const { loadPlugin } = await import("../plugins");
|
|
777
|
+
const names = ["sql", ...lexiconNames(p.config.lexicons ?? []).filter((n) => n !== "sql")];
|
|
778
|
+
const loaded = [];
|
|
779
|
+
for (const name of names) {
|
|
780
|
+
try {
|
|
781
|
+
const plugin = await loadPlugin(name);
|
|
782
|
+
if (plugin.classifyMigrations) loaded.push(plugin);
|
|
783
|
+
if (loaded.length > 0) break;
|
|
784
|
+
} catch {
|
|
785
|
+
// not installed: the next name, or the note says no lexicon classifies the dialect
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
return loaded;
|
|
789
|
+
},
|
|
790
|
+
});
|
|
791
|
+
} catch (err) {
|
|
792
|
+
console.error(formatWarning({ message: `could not classify the new migration files: ${err instanceof Error ? err.message : String(err)}` }));
|
|
793
|
+
return [];
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
707
797
|
/**
|
|
708
798
|
* The scheduled watch and reconcile Ops that stopped running (#4289,
|
|
709
799
|
* `op/schedule-overdue.ts`), asked of the forge. Without a forge, or when
|
|
@@ -712,27 +802,8 @@ async function prPlan(ctx: CommandContext, stage: StageEvents): Promise<number>
|
|
|
712
802
|
* `pr-post` asks instead, reading the Ops at the target branch's commit.
|
|
713
803
|
*/
|
|
714
804
|
async function overdueOps(forge: PrForge | undefined, member: string | undefined): Promise<PrOverdue[]> {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
const { discoverOps } = await import("../../op/discover");
|
|
718
|
-
const { scheduledWatches, checkOverdueOps } = await import("../../op/schedule-overdue");
|
|
719
|
-
const discovered = await discoverOps({ cwd: resolve(".") });
|
|
720
|
-
const watches = scheduledWatches([...discovered.ops.values()].map((d) => d.config));
|
|
721
|
-
if (watches.length === 0) return [];
|
|
722
|
-
const top = spawnSync("git", ["rev-parse", "--show-toplevel"], { encoding: "utf-8" });
|
|
723
|
-
if (top.status !== 0) return [];
|
|
724
|
-
return await checkOverdueOps({
|
|
725
|
-
watches,
|
|
726
|
-
forge,
|
|
727
|
-
repoRoot: top.stdout.trim(),
|
|
728
|
-
...(member ? { member } : {}),
|
|
729
|
-
now: new Date(),
|
|
730
|
-
log: (line) => console.error(formatWarning({ message: line })),
|
|
731
|
-
});
|
|
732
|
-
} catch (err) {
|
|
733
|
-
console.error(formatWarning({ message: `could not check the scheduled Ops, so none is reported overdue: ${err instanceof Error ? err.message : String(err)}` }));
|
|
734
|
-
return [];
|
|
735
|
-
}
|
|
805
|
+
const { overdueOpsAt } = await import("../../op/schedule-overdue");
|
|
806
|
+
return overdueOpsAt({ forge, cwd: resolve("."), ...(member ? { member } : {}), log: (line) => console.error(formatWarning({ message: line })) });
|
|
736
807
|
}
|
|
737
808
|
|
|
738
809
|
/** chant components pr-apply --base <ref> [--pr <n>] [--env <env>] [--gate <name>] [--forge <kind>] [--require-review] [--output <dir>] [--json] [--events-json] [--report-url <url>] */
|
|
@@ -881,6 +952,9 @@ async function prApply(ctx: CommandContext, stage: StageEvents, beforeMerge?: Pr
|
|
|
881
952
|
if (judged.stop) return stop(prReport({ ...base, approval: { status: "pending" }, status: "refused", refusal: judged.stop.refusal, message: judged.stop.message }), judged.stop.code);
|
|
882
953
|
const decided = await decideApplyGate(p, { op, pr, set, events, held: judged.held, ...(green ? { green } : {}) });
|
|
883
954
|
approval = decided.approval;
|
|
955
|
+
// #4323: the after-gate hooks hear the decision, a refusal too; only a failure that would have applied changes the outcome.
|
|
956
|
+
const afterGate = await runGateHook(p, { op, digest: set.doc.digest, satisfied: decided.satisfied }, p.plan.order);
|
|
957
|
+
if (afterGate && decided.satisfied) return stop(prReport({ ...base, approval, status: "failed", message: afterGate }), 1);
|
|
884
958
|
if (!decided.satisfied) return stop(prReport({ ...base, approval, status: "refused", refusal: decided.refusal, message: decided.message }), GATED_EXIT_CODE);
|
|
885
959
|
via = decided.via;
|
|
886
960
|
}
|
|
@@ -935,7 +1009,7 @@ async function prApply(ctx: CommandContext, stage: StageEvents, beforeMerge?: Pr
|
|
|
935
1009
|
|
|
936
1010
|
// #4288: the before-apply hooks, once the gate and the review let the apply through.
|
|
937
1011
|
const toApply = (resumed?.plan ?? p.plan).order.filter((name) => !completedSoFar.has(name));
|
|
938
|
-
const beforeFailed = runStageHook(p, "before-apply", toApply);
|
|
1012
|
+
const beforeFailed = await runStageHook(p, "before-apply", toApply);
|
|
939
1013
|
if (beforeFailed) return stop(prReport({ ...base, approval, status: "failed", message: beforeFailed }), 1);
|
|
940
1014
|
|
|
941
1015
|
// #3999: a round planned after an upstream applied waits on a gate of its
|
|
@@ -994,7 +1068,7 @@ async function prApply(ctx: CommandContext, stage: StageEvents, beforeMerge?: Pr
|
|
|
994
1068
|
});
|
|
995
1069
|
recordAttempt();
|
|
996
1070
|
// #4288: the after-apply hooks, for the components that applied.
|
|
997
|
-
const afterFailed = runStageHook(p, "after-apply", toApply.filter((name) => applied.run.completed.includes(name)), undefined, "the apply counts as failed though its components applied");
|
|
1071
|
+
const afterFailed = await runStageHook(p, "after-apply", toApply.filter((name) => applied.run.completed.includes(name)), undefined, "the apply counts as failed though its components applied");
|
|
998
1072
|
await recordAutoReleasesForRun(applied.run.results, p.env, release.runId, resolveAutoReleaseDisabled(p.config, args.noReleaseRecord), release.runOrigin, undefined, undefined, prAppliedDigests(p, applied.members));
|
|
999
1073
|
const report = prReport({
|
|
1000
1074
|
...base,
|
|
@@ -1787,6 +1861,9 @@ async function prApplyWaves(
|
|
|
1787
1861
|
if (judged.stop) return stop(report({ status: "refused", refusal: judged.stop.refusal, message: judged.stop.message }), judged.stop.code);
|
|
1788
1862
|
const decided = await decideApplyGate(p, { op, pr, set, events, held: judged.held, ...(green ? { green } : {}) });
|
|
1789
1863
|
approval = decided.approval;
|
|
1864
|
+
// #4323: the after-gate hooks hear the decision, a refusal too.
|
|
1865
|
+
const afterGate = await runGateHook(p, { op, digest: set.doc.digest, satisfied: decided.satisfied }, p.plan.order);
|
|
1866
|
+
if (afterGate && decided.satisfied) return stop(report({ status: "failed", message: afterGate }), 1);
|
|
1790
1867
|
if (!decided.satisfied) return stop(report({ status: "refused", refusal: decided.refusal, message: decided.message }), GATED_EXIT_CODE);
|
|
1791
1868
|
via = decided.via;
|
|
1792
1869
|
planned = set;
|
|
@@ -1944,7 +2021,7 @@ async function prApplyWaves(
|
|
|
1944
2021
|
}
|
|
1945
2022
|
|
|
1946
2023
|
// #4288: the wave's apply-side hooks, around its apply.
|
|
1947
|
-
const waveBefore = runStageHook(p, "before-apply", wavePlan.order, undefined, `nothing in wave ${k} was applied`);
|
|
2024
|
+
const waveBefore = await runStageHook(p, "before-apply", wavePlan.order, undefined, `nothing in wave ${k} was applied`);
|
|
1948
2025
|
if (waveBefore) {
|
|
1949
2026
|
setWave({ ...entry, status: "failed" });
|
|
1950
2027
|
return stop(report({ status: "failed", message: waveBefore }), 1);
|
|
@@ -1979,7 +2056,7 @@ async function prApplyWaves(
|
|
|
1979
2056
|
const outputs = applied.run.componentOutputs[name];
|
|
1980
2057
|
if (outputs) outputsSoFar[name] = outputs;
|
|
1981
2058
|
}
|
|
1982
|
-
const waveAfter = runStageHook(p, "after-apply", wavePlan.order.filter((name) => applied.run.completed.includes(name)), undefined, `wave ${k} counts as failed though its components applied`);
|
|
2059
|
+
const waveAfter = await runStageHook(p, "after-apply", wavePlan.order.filter((name) => applied.run.completed.includes(name)), undefined, `wave ${k} counts as failed though its components applied`);
|
|
1983
2060
|
setWave({ ...entry, status: applied.status === "applied" && !waveAfter ? "applied" : "failed" });
|
|
1984
2061
|
await recordAutoReleasesForRun(applied.run.results, p.env, at.release.runId, resolveAutoReleaseDisabled(p.config, args.noReleaseRecord), at.release.runOrigin, undefined, undefined, prAppliedDigests(p, applied.members));
|
|
1985
2062
|
if (applied.status !== "applied") {
|
|
@@ -2023,6 +2100,7 @@ function writeWaveChangeSet(ctx: CommandContext, wave: number, doc: PrPlanSet["d
|
|
|
2023
2100
|
|
|
2024
2101
|
/**
|
|
2025
2102
|
* chant components pr-post --pr <n> --head <sha> --env <env> --forge <kind> [--member <name>] [--output <dir>] [--result <result>] (#4295)
|
|
2103
|
+
* chant components pr-post --open --env <env> --forge gitlab [--branch <branch>] [--member <name>] [--output <dir>] (#4328)
|
|
2026
2104
|
*
|
|
2027
2105
|
* Post the plan note and the `chant/plan` status from the report a plan job
|
|
2028
2106
|
* wrote with `pr-plan --no-status`, in a job that runs none of the change's
|
|
@@ -2033,6 +2111,7 @@ function writeWaveChangeSet(ctx: CommandContext, wave: number, doc: PrPlanSet["d
|
|
|
2033
2111
|
*/
|
|
2034
2112
|
export async function runComponentsPrPost(ctx: CommandContext): Promise<number> {
|
|
2035
2113
|
const { args } = ctx;
|
|
2114
|
+
if (args.open) return runComponentsPrPostOpen(ctx);
|
|
2036
2115
|
if (args.pr === undefined) return fail("pr-post needs the pull or merge request: --pr <n>");
|
|
2037
2116
|
if (!args.head || !/^[0-9a-f]{40}$/.test(args.head)) return fail("pr-post needs the full commit the plan job checked out: --head <sha>");
|
|
2038
2117
|
if (!args.env) return fail("pr-post needs the environment the plan was for: --env <env>");
|
|
@@ -2062,3 +2141,63 @@ export async function runComponentsPrPost(ctx: CommandContext): Promise<number>
|
|
|
2062
2141
|
console.error(formatInfo(`pr-post: ${prStatusContext("plan", member)} ${posted.state}: ${posted.description}${posted.noted ? "; note posted" : ""}`));
|
|
2063
2142
|
return 0;
|
|
2064
2143
|
}
|
|
2144
|
+
|
|
2145
|
+
/**
|
|
2146
|
+
* `pr-post --open` (#4328): in a pipeline of the target branch on GitLab,
|
|
2147
|
+
* post the plan note and status of every open merge request into it whose
|
|
2148
|
+
* plan job settled, reading each report from the plan job's artifacts
|
|
2149
|
+
* (`postOpenPlanReports`, ../../pr-post.ts). The branch is `--branch`, else
|
|
2150
|
+
* the pipeline's own (`CI_COMMIT_BRANCH`). The plan job is `plan`, or
|
|
2151
|
+
* `<member>-plan` with `--member`, as the gitlab lexicon names it, and the
|
|
2152
|
+
* artifact path is `--output` from the repository root. It exits 0 once it
|
|
2153
|
+
* has posted, as `pr-post` does.
|
|
2154
|
+
*/
|
|
2155
|
+
async function runComponentsPrPostOpen(ctx: CommandContext): Promise<number> {
|
|
2156
|
+
const { args } = ctx;
|
|
2157
|
+
if (args.pr !== undefined || args.head) return fail("pr-post --open finds each merge request and its head itself, so it takes no --pr or --head");
|
|
2158
|
+
if (!args.env) return fail("pr-post needs the environment the plan was for: --env <env>");
|
|
2159
|
+
if (args.forge !== "gitlab") return fail("pr-post --open is for a GitLab pipeline of the target branch: --forge gitlab");
|
|
2160
|
+
if (args.members && args.members.length > 1) return fail(`pr-post takes one --member, not ${args.members.join(", ")}`);
|
|
2161
|
+
const branch = args.branch ?? process.env.CI_COMMIT_BRANCH;
|
|
2162
|
+
if (!branch) return fail("pr-post --open posts for the merge requests into a branch: run it in a branch pipeline, or pass --branch <branch>");
|
|
2163
|
+
let forge: PrForge;
|
|
2164
|
+
try {
|
|
2165
|
+
forge = forgeFromEnv("gitlab");
|
|
2166
|
+
} catch (err) {
|
|
2167
|
+
return fail(err instanceof Error ? err.message : String(err));
|
|
2168
|
+
}
|
|
2169
|
+
const top = spawnSync("git", ["rev-parse", "--show-toplevel"], { encoding: "utf-8" });
|
|
2170
|
+
if (top.status !== 0) return fail("pr-post --open reads the plan report's path from the repository root, and this directory is not in a git repository");
|
|
2171
|
+
const member = args.members?.[0];
|
|
2172
|
+
const artifactDir = relative(realpathSync(top.stdout.trim()), resolve(args.output ?? PR_REPORT_DIR)).split(sep).join("/");
|
|
2173
|
+
const { postOpenPlanReports } = await import("../../pr-post");
|
|
2174
|
+
const { gitlabPlanJobName } = await import("../../components/pr-pipeline");
|
|
2175
|
+
let done: Awaited<ReturnType<typeof postOpenPlanReports>>;
|
|
2176
|
+
try {
|
|
2177
|
+
done = await postOpenPlanReports({
|
|
2178
|
+
forge,
|
|
2179
|
+
branch,
|
|
2180
|
+
job: gitlabPlanJobName(member),
|
|
2181
|
+
artifactDir,
|
|
2182
|
+
env: args.env,
|
|
2183
|
+
...(member ? { member } : {}),
|
|
2184
|
+
// #4289: the Ops at the commit this pipeline checked out, the target branch's.
|
|
2185
|
+
overdue: () => overdueOps(forge, member),
|
|
2186
|
+
});
|
|
2187
|
+
} catch (err) {
|
|
2188
|
+
return fail(err instanceof Error ? err.message : String(err));
|
|
2189
|
+
}
|
|
2190
|
+
for (const message of done.warnings) console.error(formatWarning({ message }));
|
|
2191
|
+
for (const p of done.posts) {
|
|
2192
|
+
if (p.skipped) {
|
|
2193
|
+
console.error(formatInfo(`pr-post: !${p.pr}: ${p.skipped}`));
|
|
2194
|
+
continue;
|
|
2195
|
+
}
|
|
2196
|
+
const posted = p.posted!;
|
|
2197
|
+
for (const message of posted.warnings) console.error(formatWarning({ message: `!${p.pr}: ${message}` }));
|
|
2198
|
+
if (posted.refused) console.error(formatWarning({ message: `!${p.pr}: the plan report was not used: ${posted.refused}` }));
|
|
2199
|
+
console.error(formatInfo(`pr-post: !${p.pr} ${prStatusContext("plan", member)} ${posted.state}: ${posted.description}${posted.noted ? "; note posted" : ""}`));
|
|
2200
|
+
}
|
|
2201
|
+
if (done.posts.length === 0) console.error(formatInfo(`pr-post: no open merge request into ${branch} has a ${gitlabPlanJobName(member)} job`));
|
|
2202
|
+
return 0;
|
|
2203
|
+
}
|
|
@@ -18,11 +18,23 @@ import { findWorkspaceRoot } from "../../project-root";
|
|
|
18
18
|
|
|
19
19
|
const USAGE = 'chant query "<sql>" [dir] [--member <name>] [--json]';
|
|
20
20
|
|
|
21
|
-
/**
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The ledgers `chant query` and `chant ledger` read from `cwd`: every
|
|
23
|
+
* member's in a workspace, else the project's own. With `at`, a commit of
|
|
24
|
+
* `chant/lifecycle` (`chant ledger --at`, #4363), each is read as that commit
|
|
25
|
+
* held it rather than at the branch tip.
|
|
26
|
+
*/
|
|
27
|
+
export async function queryLedgers(cwd: string, members?: readonly string[], at?: string): Promise<QueryLedger[]> {
|
|
23
28
|
const { gitLedgerReadPort } = await import("../../lifecycle/git");
|
|
24
29
|
const found = findWorkspaceRoot(cwd);
|
|
25
|
-
|
|
30
|
+
const atPort = at === undefined ? undefined : await (async () => {
|
|
31
|
+
const { resolveLedgerRevision, revisionLedgerReadPort } = await import("../../lifecycle/ledger-read");
|
|
32
|
+
const { memberLedgerPrefix } = await import("../../lifecycle/member-ledger");
|
|
33
|
+
const repo = found?.dir ?? cwd;
|
|
34
|
+
const commit = resolveLedgerRevision(repo, at);
|
|
35
|
+
return (member: string | null) => revisionLedgerReadPort(repo, commit, member === null ? "" : memberLedgerPrefix([member]));
|
|
36
|
+
})();
|
|
37
|
+
if (!found) return [{ member: null, port: atPort ? atPort(null) : gitLedgerReadPort({ cwd }) }];
|
|
26
38
|
// Workspace code loads only when there is a workspace, so a level-0 project never pays for it.
|
|
27
39
|
const { readDeclaration, WorkspaceReadError } = await import("../../workspace/declaration");
|
|
28
40
|
const { workingTree } = await import("../../workspace/tree");
|
|
@@ -41,7 +53,7 @@ export async function queryLedgers(cwd: string, members?: readonly string[]): Pr
|
|
|
41
53
|
}
|
|
42
54
|
return declaration.members
|
|
43
55
|
.filter((m) => !wanted || wanted.has(m.name))
|
|
44
|
-
.map((m) => ({ member: m.name, port: gitLedgerReadPort({ cwd: found.dir, member: m.dir === "." ? "." : m.name }) }));
|
|
56
|
+
.map((m) => ({ member: m.name, port: atPort ? atPort(m.dir === "." ? null : m.name) : gitLedgerReadPort({ cwd: found.dir, member: m.dir === "." ? "." : m.name }) }));
|
|
45
57
|
}
|
|
46
58
|
|
|
47
59
|
export async function runQueryCommand(ctx: CommandContext): Promise<number> {
|