@intentius/chant 0.124.45 → 0.124.48
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/capabilities/aws.paths +148 -0
- package/dist/capabilities/base-mappings.json +122 -0
- package/dist/capabilities/catalog.d.ts +89 -0
- package/dist/capabilities/catalog.d.ts.map +1 -0
- package/dist/capabilities/catalog.js +204 -0
- package/dist/capabilities/language.d.ts +103 -0
- package/dist/capabilities/language.d.ts.map +1 -0
- package/dist/capabilities/language.js +335 -0
- package/dist/capabilities/matcher.d.ts +65 -0
- package/dist/capabilities/matcher.d.ts.map +1 -0
- package/dist/capabilities/matcher.js +299 -0
- package/dist/capabilities/view.d.ts +207 -0
- package/dist/capabilities/view.d.ts.map +1 -0
- package/dist/capabilities/view.js +484 -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/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +1 -0
- 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 +21 -2
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +6 -1
- package/dist/cli/handlers/declared-graph.d.ts +44 -0
- package/dist/cli/handlers/declared-graph.d.ts.map +1 -0
- package/dist/cli/handlers/declared-graph.js +87 -0
- package/dist/cli/handlers/graph.d.ts +25 -0
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +93 -87
- 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.d.ts.map +1 -1
- package/dist/cli/handlers/pr-env.js +4 -3
- 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 +143 -39
- 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-count.d.ts +89 -0
- package/dist/cli/handlers/search-count.d.ts.map +1 -0
- package/dist/cli/handlers/search-count.js +132 -0
- package/dist/cli/handlers/search.d.ts +356 -6
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +1039 -155
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +88 -17
- package/dist/cli/mcp/server.d.ts.map +1 -1
- package/dist/cli/mcp/server.js +3 -0
- package/dist/cli/mcp/tools/capabilities.d.ts +7 -0
- package/dist/cli/mcp/tools/capabilities.d.ts.map +1 -0
- package/dist/cli/mcp/tools/capabilities.js +27 -0
- package/dist/cli/mcp/workspace-tools.d.ts +3 -1
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.js +47 -2
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +100 -19
- package/dist/cli/registry.d.ts +36 -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-env-ports.d.ts +29 -0
- package/dist/components/pr-env-ports.d.ts.map +1 -0
- package/dist/components/pr-env-ports.js +77 -0
- package/dist/components/pr-env-run.d.ts +5 -21
- package/dist/components/pr-env-run.d.ts.map +1 -1
- package/dist/components/pr-env-run.js +6 -70
- package/dist/components/pr-environment.d.ts +2 -1
- package/dist/components/pr-environment.d.ts.map +1 -1
- package/dist/components/pr-environment.js +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/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 +112 -0
- package/dist/config-environments.d.ts.map +1 -0
- package/dist/config-environments.js +114 -0
- package/dist/config.d.ts +32 -84
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -96
- package/dist/gate-decision.d.ts +11 -2
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +15 -3
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +15 -3
- package/dist/graph-effective.d.ts +33 -2
- package/dist/graph-effective.d.ts.map +1 -1
- package/dist/graph-effective.js +215 -68
- package/dist/graph-ir.d.ts +48 -0
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +130 -0
- package/dist/graph-sub-template.d.ts +11 -0
- package/dist/graph-sub-template.d.ts.map +1 -0
- package/dist/graph-sub-template.js +19 -0
- 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 +80 -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/observe.d.ts +28 -0
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/observe.js +23 -1
- 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/rule.d.ts +6 -0
- package/dist/lint/rule.d.ts.map +1 -1
- 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/live-endpoint.d.ts +1 -1
- package/dist/live-endpoint.d.ts.map +1 -1
- package/dist/live-endpoint.js +1 -1
- package/dist/observation.d.ts +48 -1
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +21 -5
- 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.d.ts +11 -5
- package/dist/op/gate-approval.d.ts.map +1 -1
- package/dist/op/gate-approval.js +11 -6
- 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 +44 -3
- 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 +38 -3
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +48 -6
- 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-post.d.ts +42 -0
- package/dist/pr-post.d.ts.map +1 -1
- package/dist/pr-post.js +67 -1
- 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 +266 -256
- package/dist/workspace/capabilities-contract.d.ts +66 -0
- package/dist/workspace/capabilities-contract.d.ts.map +1 -0
- package/dist/workspace/capabilities-contract.js +107 -0
- package/dist/workspace/capabilities.schema.json +229 -0
- package/dist/workspace/check.schema.json +11 -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/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 +11 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +59 -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 +23 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +3 -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/conformance/index.d.ts +1 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/index.js +39 -2
- 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 +43 -2
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +45 -11
- package/dist/workspace/declaration.schema.json +133 -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/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 +8 -0
- package/dist/workspace/graph-cache.d.ts.map +1 -1
- package/dist/workspace/graph-cache.js +27 -3
- package/dist/workspace/graph-cli.d.ts +39 -2
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +92 -32
- package/dist/workspace/graph.schema.json +182 -0
- 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 +3 -0
- package/dist/workspace/kind-readers.d.ts.map +1 -1
- package/dist/workspace/kind-readers.js +7 -1
- package/dist/workspace/kinds.d.ts +66 -2
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +98 -4
- 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/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 +10 -1
- package/dist/workspace/member-commands.d.ts.map +1 -1
- package/dist/workspace/member-commands.js +71 -6
- 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/nested-graph.d.ts +2 -0
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +32 -1
- package/dist/workspace/reason-codes.d.ts +18 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +23 -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-cli.d.ts +204 -0
- package/dist/workspace/search-cli.d.ts.map +1 -0
- package/dist/workspace/search-cli.js +466 -0
- package/dist/workspace/search-contract.d.ts +56 -0
- package/dist/workspace/search-contract.d.ts.map +1 -0
- package/dist/workspace/search-contract.js +70 -0
- package/dist/workspace/search.schema.json +822 -0
- 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 +58 -3
- 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/__snapshots__/okf.test.ts.snap +10 -0
- package/src/action-pins.test.ts +78 -0
- package/src/action-pins.ts +92 -0
- package/src/capabilities/aws.paths +148 -0
- package/src/capabilities/base-mappings.json +122 -0
- package/src/capabilities/catalog.ts +230 -0
- package/src/capabilities/language.test.ts +191 -0
- package/src/capabilities/language.ts +373 -0
- package/src/capabilities/matcher.ts +315 -0
- package/src/capabilities/view-compose.test.ts +76 -0
- package/src/capabilities/view.ts +631 -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/lint.ts +1 -0
- 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 +23 -2
- package/src/cli/handlers/build.ts +7 -1
- package/src/cli/handlers/declared-graph.ts +99 -0
- package/src/cli/handlers/graph.test.ts +94 -3
- package/src/cli/handlers/graph.ts +123 -96
- 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 +3 -4
- package/src/cli/handlers/pr.ts +138 -36
- package/src/cli/handlers/query.ts +16 -4
- package/src/cli/handlers/release.ts +6 -3
- package/src/cli/handlers/search-build-roots.test.ts +144 -0
- package/src/cli/handlers/search-count.test.ts +191 -0
- package/src/cli/handlers/search-count.ts +165 -0
- package/src/cli/handlers/search-json.test.ts +333 -0
- package/src/cli/handlers/search-live.test.ts +387 -0
- package/src/cli/handlers/search-paths.test.ts +235 -0
- package/src/cli/handlers/search.ts +1291 -166
- package/src/cli/main.test.ts +43 -3
- package/src/cli/main.ts +88 -17
- package/src/cli/mcp/server.test.ts +3 -3
- package/src/cli/mcp/server.ts +3 -0
- package/src/cli/mcp/tools/capabilities.ts +32 -0
- package/src/cli/mcp/workspace-tools.e2e.test.ts +21 -1
- package/src/cli/mcp/workspace-tools.ts +47 -2
- package/src/cli/parse-args.ts +79 -15
- package/src/cli/registry.ts +36 -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-ports.ts +89 -0
- package/src/components/pr-env-run-bundle.test.ts +54 -0
- package/src/components/pr-env-run.ts +5 -76
- package/src/components/pr-environment.ts +2 -1
- 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/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 +160 -0
- package/src/config.ts +44 -124
- package/src/gate-decision-bundle.test.ts +1 -0
- package/src/gate-decision-identity.test.ts +9 -0
- package/src/gate-decision.ts +26 -3
- package/src/graph-detail.ts +15 -3
- package/src/graph-effective.ts +226 -75
- package/src/graph-ir.test.ts +163 -0
- package/src/graph-ir.ts +174 -0
- package/src/graph-sub-template.ts +22 -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 +84 -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/observe.test.ts +27 -1
- package/src/lifecycle/observe.ts +43 -1
- 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/rule.ts +6 -0
- package/src/lint/rules/op/index.ts +2 -0
- package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
- package/src/live-endpoint.ts +1 -1
- package/src/observation.test.ts +25 -0
- package/src/observation.ts +69 -5
- 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.test.ts +6 -1
- package/src/op/gate-approval.ts +12 -6
- 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 +67 -8
- package/src/op/index.ts +3 -2
- package/src/op/local-executor.ts +69 -9
- 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-post-open.e2e.test.ts +36 -0
- package/src/pr-post.test.ts +102 -3
- package/src/pr-post.ts +89 -1
- 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/behold-kinds.test.ts +1 -1
- package/src/workspace/capabilities-contract.test.ts +88 -0
- package/src/workspace/capabilities-contract.ts +132 -0
- package/src/workspace/capabilities.schema.json +229 -0
- package/src/workspace/check-contract.test.ts +7 -6
- package/src/workspace/check.schema.json +11 -2
- package/src/workspace/checks/ci-branch.test.ts +128 -0
- package/src/workspace/checks/ci-branch.ts +141 -0
- package/src/workspace/checks/links.ts +12 -1
- package/src/workspace/checks/org.ts +169 -0
- package/src/workspace/checks.ts +64 -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 +19 -3
- 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/conformance/conformance.e2e.test.ts +14 -1
- package/src/workspace/conformance/index.ts +31 -2
- 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 +133 -24
- package/src/workspace/declaration.ts +84 -15
- package/src/workspace/environments.ts +40 -4
- package/src/workspace/flyway-dir.ts +113 -0
- package/src/workspace/flyway-layout.ts +337 -0
- package/src/workspace/graph-cache.ts +27 -3
- package/src/workspace/graph-cli.ts +119 -32
- package/src/workspace/graph-contract.test.ts +4 -2
- package/src/workspace/graph.schema.json +182 -0
- package/src/workspace/identity.test.ts +14 -2
- package/src/workspace/intent.ts +6 -14
- package/src/workspace/kind-link-readers.ts +68 -3
- package/src/workspace/kind-readers.e2e.test.ts +28 -0
- package/src/workspace/kind-readers.test.ts +1 -1
- package/src/workspace/kind-readers.ts +7 -1
- package/src/workspace/kinds.test.ts +12 -7
- package/src/workspace/kinds.ts +132 -7
- 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/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 +82 -3
- 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/nested-graph.ts +32 -1
- package/src/workspace/org-scope.test.ts +238 -0
- package/src/workspace/reason-codes.test.ts +13 -1
- package/src/workspace/reason-codes.ts +23 -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/search-cli.e2e.test.ts +305 -0
- package/src/workspace/search-cli.ts +591 -0
- package/src/workspace/search-contract.ts +95 -0
- package/src/workspace/search.schema.json +822 -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 +58 -3
- 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,99 @@
|
|
|
1
|
+
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { carveJson } from "./carve";
|
|
3
|
+
import { boundaryIndex, boundaryReport } from "../../terraform/carve";
|
|
4
|
+
import { scoreEstate } from "../../terraform/score";
|
|
5
|
+
import type { TfEdge, TfGraph, TfNode } from "../../terraform/types";
|
|
6
|
+
|
|
7
|
+
const node = (type: string, name: string): TfNode => ({
|
|
8
|
+
address: `${type}.${name}`,
|
|
9
|
+
kind: "resource",
|
|
10
|
+
type,
|
|
11
|
+
name,
|
|
12
|
+
instances: 1,
|
|
13
|
+
hasDynamic: false,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const edge = (from: string, to: string, extra: Partial<TfEdge> = {}): TfEdge => ({
|
|
17
|
+
from,
|
|
18
|
+
to,
|
|
19
|
+
attrs: ["id"],
|
|
20
|
+
via: ["bucket"],
|
|
21
|
+
...extra,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
/** A fixture with a fold, an output edge, a module, an unmapped type and a duplicate edge. */
|
|
25
|
+
function fixture(): TfGraph {
|
|
26
|
+
return {
|
|
27
|
+
nodes: [
|
|
28
|
+
node("aws_s3_bucket", "assets"),
|
|
29
|
+
node("aws_s3_bucket_versioning", "assets"),
|
|
30
|
+
node("aws_lambda_function", "api"),
|
|
31
|
+
node("aws_sqs_queue", "q"),
|
|
32
|
+
node("random_pet", "name"),
|
|
33
|
+
{ address: "module.cdn", kind: "module", name: "cdn", instances: 1, hasDynamic: false },
|
|
34
|
+
],
|
|
35
|
+
edges: [
|
|
36
|
+
edge("aws_s3_bucket_versioning.assets", "aws_s3_bucket.assets"),
|
|
37
|
+
edge("aws_lambda_function.api", "aws_s3_bucket.assets", { attrs: ["bucket"] }),
|
|
38
|
+
edge("aws_lambda_function.api", "aws_s3_bucket.assets", { attrs: ["arn"], via: ["env"] }),
|
|
39
|
+
edge("output.bucket", "aws_s3_bucket.assets", { fromKind: "output", via: ["value"] }),
|
|
40
|
+
edge("aws_lambda_function.api", "aws_sqs_queue.q"),
|
|
41
|
+
edge("module.cdn", "aws_lambda_function.api"),
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The old path: every resource's boundary rescored the whole estate. */
|
|
47
|
+
function legacyJson(graph: TfGraph) {
|
|
48
|
+
const results = scoreEstate(graph);
|
|
49
|
+
return results.map((r) => {
|
|
50
|
+
const report = boundaryReport(graph, r.address, { dialect: "terraform" });
|
|
51
|
+
return report ? { ...r, boundary: { inbound: report.inbound, outbound: report.outbound } } : r;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function chain(n: number): TfGraph {
|
|
56
|
+
const nodes: TfNode[] = [];
|
|
57
|
+
const edges: TfEdge[] = [];
|
|
58
|
+
for (let i = 0; i < n; i++) {
|
|
59
|
+
nodes.push(node("aws_sqs_queue", `q${i}`));
|
|
60
|
+
if (i > 0) edges.push(edge(`aws_sqs_queue.q${i}`, `aws_sqs_queue.q${i - 1}`));
|
|
61
|
+
if (i > 1) edges.push(edge(`aws_sqs_queue.q${i}`, `aws_sqs_queue.q${i - 2}`));
|
|
62
|
+
}
|
|
63
|
+
return { nodes, edges };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
describe("carve advise scores the estate once (#4391)", () => {
|
|
67
|
+
test("output is byte-identical to the per-resource rescoring path", () => {
|
|
68
|
+
const graph = fixture();
|
|
69
|
+
const payload = carveJson({ ok: true, from: "x", source: "terraform", results: scoreEstate(graph), graph });
|
|
70
|
+
expect(JSON.stringify(payload.resources)).toBe(JSON.stringify(legacyJson(graph)));
|
|
71
|
+
expect(payload.resources.some((r) => r.boundary?.inbound.length)).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("a supplied peelability and edge index give the same report", () => {
|
|
75
|
+
const graph = fixture();
|
|
76
|
+
for (const r of scoreEstate(graph)) {
|
|
77
|
+
expect(JSON.stringify(boundaryReport(graph, r.address, { peelability: r, index: boundaryIndex(graph) }))).toBe(
|
|
78
|
+
JSON.stringify(boundaryReport(graph, r.address)),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("on a few thousand nodes the old path costs more per resource than the whole new pass", () => {
|
|
84
|
+
const graph = chain(3000);
|
|
85
|
+
// Radius is its own walk per node (#2326), not what this test is about.
|
|
86
|
+
const t0 = performance.now();
|
|
87
|
+
const results = scoreEstate(graph, { radius: false });
|
|
88
|
+
const payload = carveJson({ ok: true, from: "x", source: "terraform", results, graph });
|
|
89
|
+
const fresh = performance.now() - t0;
|
|
90
|
+
expect(payload.resources).toHaveLength(3000);
|
|
91
|
+
|
|
92
|
+
// Rescoring is O(V) per resource, so 50 of them already outweigh the one pass over all 3000.
|
|
93
|
+
const sample = results.slice(0, 50);
|
|
94
|
+
const t1 = performance.now();
|
|
95
|
+
for (const r of sample) boundaryReport(graph, r.address);
|
|
96
|
+
const legacy = performance.now() - t1;
|
|
97
|
+
expect(legacy).toBeGreaterThan(fresh);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -19,7 +19,7 @@ import { adviseCloudAssembly, CDK_DIALECT } from "../../cdk/advise";
|
|
|
19
19
|
import { isCloudAssembly } from "../../cdk/assembly";
|
|
20
20
|
import { parseTerraformDir, Hcl2JsonNotInstalled } from "../../terraform/parse";
|
|
21
21
|
import { scoreEstate, type Peelability, type PeelabilityBand, type ScoreOptions } from "../../terraform/score";
|
|
22
|
-
import { boundaryReport, type BoundaryEdge, type CarveDialect } from "../../terraform/carve";
|
|
22
|
+
import { boundaryIndex, boundaryReport, type BoundaryIndex, type BoundaryEdge, type CarveDialect } from "../../terraform/carve";
|
|
23
23
|
import type { TfGraph } from "../../terraform/types";
|
|
24
24
|
|
|
25
25
|
export interface CarveAdviseOptions {
|
|
@@ -141,6 +141,9 @@ async function adviseTerraform(opts: CarveAdviseOptions): Promise<CarveAdviseRes
|
|
|
141
141
|
* additive and ignorable: the top-level `source` discriminator, per-resource
|
|
142
142
|
* `notes` and `members`, and two more `bridge` values in a list that was
|
|
143
143
|
* already declared open-ended.
|
|
144
|
+
*
|
|
145
|
+
* Per-resource `radius` (#2326) is additive the same way: a new field beside
|
|
146
|
+
* `score`, not a term inside it, so the score and its penalties are unchanged.
|
|
144
147
|
*/
|
|
145
148
|
export const CARVE_REPORT_VERSION = 1;
|
|
146
149
|
|
|
@@ -201,6 +204,7 @@ export function carveJson(result: CarveAdviseResult): CarveJsonReport {
|
|
|
201
204
|
);
|
|
202
205
|
const source = result.source ?? "terraform";
|
|
203
206
|
const dialect: CarveDialect = source === "cdk" ? CDK_DIALECT : "terraform";
|
|
207
|
+
const index = result.graph ? boundaryIndex(result.graph) : undefined;
|
|
204
208
|
return {
|
|
205
209
|
version: CARVE_REPORT_VERSION,
|
|
206
210
|
from: result.from,
|
|
@@ -209,7 +213,7 @@ export function carveJson(result: CarveAdviseResult): CarveJsonReport {
|
|
|
209
213
|
count: results.length,
|
|
210
214
|
bands: counts,
|
|
211
215
|
...(result.diagnostics?.length ? { diagnostics: result.diagnostics } : {}),
|
|
212
|
-
resources: results.map((r) => withBoundary(r, result.graph, dialect, result.scoreOptions)),
|
|
216
|
+
resources: results.map((r) => withBoundary(r, result.graph, dialect, result.scoreOptions, index)),
|
|
213
217
|
};
|
|
214
218
|
}
|
|
215
219
|
|
|
@@ -219,9 +223,11 @@ function withBoundary(
|
|
|
219
223
|
graph: TfGraph | undefined,
|
|
220
224
|
dialect: CarveDialect,
|
|
221
225
|
score: ScoreOptions | undefined,
|
|
226
|
+
index: BoundaryIndex | undefined,
|
|
222
227
|
): CarveJsonResource {
|
|
223
228
|
if (!graph) return r;
|
|
224
|
-
|
|
229
|
+
// The ranking already scored this resource; the report reads it back rather than rescoring the estate (#4391).
|
|
230
|
+
const report = boundaryReport(graph, r.address, { dialect, score, peelability: r, index });
|
|
225
231
|
if (!report) return r;
|
|
226
232
|
return { ...r, boundary: { inbound: report.inbound, outbound: report.outbound } };
|
|
227
233
|
}
|
|
@@ -246,6 +252,8 @@ export function formatCarveReport(result: CarveAdviseResult): string {
|
|
|
246
252
|
);
|
|
247
253
|
for (const note of result.diagnostics ?? []) lines.push(` ! ${note}`);
|
|
248
254
|
lines.push("");
|
|
255
|
+
const cells = new Map(results.map((r) => [r.address, radiusCell(r)]));
|
|
256
|
+
const cellWidth = Math.max(...[...cells.values()].map((c) => c.length));
|
|
249
257
|
|
|
250
258
|
for (const band of BAND_ORDER) {
|
|
251
259
|
const inBand = results.filter((r) => r.band === band);
|
|
@@ -253,9 +261,11 @@ export function formatCarveReport(result: CarveAdviseResult): string {
|
|
|
253
261
|
lines.push(`${bandLabel(band, cdk)} (${inBand.length})`);
|
|
254
262
|
for (const r of inBand) {
|
|
255
263
|
const target = r.mapsTo ? ` -> ${r.mapsTo}` : "";
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
264
|
+
const cell = cellWidth > 0 ? `${cells.get(r.address)!.padEnd(cellWidth)} ` : "";
|
|
265
|
+
const indent = " ".repeat(7 + (cellWidth > 0 ? cellWidth + 2 : 0));
|
|
266
|
+
lines.push(` ${String(r.score).padStart(3)} ${cell}${r.address}${target}`);
|
|
267
|
+
lines.push(`${indent}${reasons(r, cdk)}`);
|
|
268
|
+
for (const note of r.notes ?? []) lines.push(`${indent}${note}`);
|
|
259
269
|
}
|
|
260
270
|
lines.push("");
|
|
261
271
|
}
|
|
@@ -263,9 +273,30 @@ export function formatCarveReport(result: CarveAdviseResult): string {
|
|
|
263
273
|
lines.push(
|
|
264
274
|
`Bands: 80-100 carve now | 50-79 carve with boundary edits | 0-49 leave in ${cdk ? "CDK" : "Terraform"}`,
|
|
265
275
|
);
|
|
276
|
+
if (cellWidth > 0) {
|
|
277
|
+
lines.push(
|
|
278
|
+
"Radius: resources+outputs that depend on it at any depth, dN the farthest hop; - none; " +
|
|
279
|
+
(cdk ? "xN across a stack boundary." : "? a module or unresolved count/for_each hides how many."),
|
|
280
|
+
);
|
|
281
|
+
}
|
|
266
282
|
return lines.join("\n").trimEnd();
|
|
267
283
|
}
|
|
268
284
|
|
|
285
|
+
/**
|
|
286
|
+
* The radius column (#2326): `3+1 d2` is three resources and one output that
|
|
287
|
+
* depend on the node, the farthest two hops away; `-` is nothing; `?` stands in
|
|
288
|
+
* for a count a module or unresolved `count` hides; ` x2` is how many sit
|
|
289
|
+
* across a stack boundary. Empty when the result carries no radius.
|
|
290
|
+
*/
|
|
291
|
+
function radiusCell(r: Peelability): string {
|
|
292
|
+
const radius = r.radius;
|
|
293
|
+
if (!radius) return "";
|
|
294
|
+
if (radius.depth === 0) return "-";
|
|
295
|
+
const n = (v: number | "unknown"): string => (v === "unknown" ? "?" : String(v));
|
|
296
|
+
const cross = radius.crossStack !== undefined && radius.crossStack !== 0 ? ` x${n(radius.crossStack)}` : "";
|
|
297
|
+
return `${n(radius.resources)}+${radius.outputs} d${radius.depth}${cross}`;
|
|
298
|
+
}
|
|
299
|
+
|
|
269
300
|
function bandLabel(band: PeelabilityBand, cdk: boolean): string {
|
|
270
301
|
switch (band) {
|
|
271
302
|
case "clean leaf":
|
|
@@ -85,8 +85,8 @@ describe("coverageReportCheck", () => {
|
|
|
85
85
|
describe("countRequiredNames (#3377)", () => {
|
|
86
86
|
const read = (lex: string) => readFileSync(join(repoRoot, "lexicons", lex, "src/validate.ts"), "utf8");
|
|
87
87
|
|
|
88
|
-
test("counts names with digits: otel reports
|
|
89
|
-
expect(countRequiredNames(read("otel"))).toBe(
|
|
88
|
+
test("counts names with digits: otel reports 38", () => {
|
|
89
|
+
expect(countRequiredNames(read("otel"))).toBe(38);
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
test("counts only the REQUIRED_NAMES entries: prometheus reports the array length", () => {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The review report of `chant import` (#4398): the parser's diagnostics as
|
|
3
|
+
* SARIF (`--report <path>`), a summary on stderr, and the exit code under
|
|
4
|
+
* `--strict`. The shape follows `chant migrate`: a needs-review diagnostic is
|
|
5
|
+
* a `warning`, and `--strict` makes any open `warning` or `error` fail the
|
|
6
|
+
* run. An `info` diagnostic names something not carried that needs no
|
|
7
|
+
* decision, and never fails a run.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { writeFileSync } from "fs";
|
|
11
|
+
import type { ImportDiagnostic } from "../../import/parser";
|
|
12
|
+
import type { LintDiagnostic } from "../../lint/rule";
|
|
13
|
+
import { formatSarif } from "../reporters/stylish";
|
|
14
|
+
|
|
15
|
+
/** Import diagnostics as lint diagnostics against `file`, the template that was imported. */
|
|
16
|
+
export function importDiagnosticsToLint(file: string, diagnostics: readonly ImportDiagnostic[]): LintDiagnostic[] {
|
|
17
|
+
return diagnostics.map((d) => ({
|
|
18
|
+
file,
|
|
19
|
+
line: d.line ?? 1,
|
|
20
|
+
column: d.column ?? 1,
|
|
21
|
+
ruleId: d.ruleId,
|
|
22
|
+
severity: d.severity,
|
|
23
|
+
message: d.message,
|
|
24
|
+
...(d.entity ? { entity: d.entity } : {}),
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The SARIF document for a run. */
|
|
29
|
+
export function importSarif(file: string, diagnostics: readonly ImportDiagnostic[], version?: string): string {
|
|
30
|
+
return formatSarif(importDiagnosticsToLint(file, diagnostics), undefined, undefined, version);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Write the SARIF report; an unwritable path is returned as a message, not thrown. */
|
|
34
|
+
export function writeImportReport(path: string, file: string, diagnostics: readonly ImportDiagnostic[], version?: string): string | undefined {
|
|
35
|
+
try {
|
|
36
|
+
writeFileSync(path, importSarif(file, diagnostics, version));
|
|
37
|
+
return undefined;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
return `could not write SARIF report to ${path}: ${err instanceof Error ? err.message : String(err)}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Diagnostics that are open: everything but `info`. */
|
|
44
|
+
export function openDiagnostics(diagnostics: readonly ImportDiagnostic[]): ImportDiagnostic[] {
|
|
45
|
+
return diagnostics.filter((d) => d.severity !== "info");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The exit code for a finished import. An `error` always fails (a failed
|
|
50
|
+
* `--validate`); a `warning` fails under `--strict`.
|
|
51
|
+
*/
|
|
52
|
+
export function importExitCode(diagnostics: readonly ImportDiagnostic[] | undefined, strict: boolean): number {
|
|
53
|
+
if (!diagnostics) return 0;
|
|
54
|
+
if (diagnostics.some((d) => d.severity === "error")) return 1;
|
|
55
|
+
return strict && diagnostics.some((d) => d.severity === "warning") ? 1 : 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Counts by severity and rule, as the lines printed after an import. */
|
|
59
|
+
export function summarizeImportDiagnostics(diagnostics: readonly ImportDiagnostic[]): string {
|
|
60
|
+
const bySeverity = { error: 0, warning: 0, info: 0 };
|
|
61
|
+
const byRule = new Map<string, number>();
|
|
62
|
+
for (const d of diagnostics) {
|
|
63
|
+
bySeverity[d.severity]++;
|
|
64
|
+
byRule.set(d.ruleId, (byRule.get(d.ruleId) ?? 0) + 1);
|
|
65
|
+
}
|
|
66
|
+
const rules = [...byRule].sort(([a], [b]) => a.localeCompare(b)).map(([id, n]) => `${id} x${String(n)}`);
|
|
67
|
+
return [
|
|
68
|
+
`Review: ${String(bySeverity.warning)} to review, ${String(bySeverity.error)} errors, ${String(bySeverity.info)} notes (${rules.join(", ")}).`,
|
|
69
|
+
"Write them with --report <path> as SARIF; --strict fails while any to review or error is open.",
|
|
70
|
+
].join("\n");
|
|
71
|
+
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync } from "fs";
|
|
2
2
|
import { join, resolve, basename, dirname } from "path";
|
|
3
3
|
import { formatSuccess, formatWarning, formatError } from "../format";
|
|
4
|
-
import type { TemplateIR, ResourceIR, ParameterIR, ParseContext } from "../../import/parser";
|
|
4
|
+
import type { TemplateIR, ResourceIR, ParameterIR, ParseContext, ImportDiagnostic } from "../../import/parser";
|
|
5
5
|
import type { GeneratedFile, TypeScriptGenerator } from "../../import/generator";
|
|
6
6
|
import { listInstalledLexicons, loadPlugin, loadPlugins, resolveProjectLexicons } from "../plugins";
|
|
7
7
|
import type { ExportedTemplate, LexiconPlugin, ResourceSelector } from "../../lexicon";
|
|
8
8
|
import { parseYAMLDocument, splitYAMLDocuments } from "../../yaml";
|
|
9
9
|
import { importLexiconPackage } from "../../lexicon-module";
|
|
10
10
|
import { resolveParserOptions } from "../../import/parser-options";
|
|
11
|
+
import { summarizeImportDiagnostics } from "./import-report";
|
|
11
12
|
import { EmbeddedImports, type EmbeddedContent, type RegisteredEmbeddedImporter } from "../../import/embedded";
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -31,6 +32,8 @@ export interface ImportOptions {
|
|
|
31
32
|
* fails the import before anything is parsed.
|
|
32
33
|
*/
|
|
33
34
|
parserOptions?: string[];
|
|
35
|
+
/** `--validate` (#4398): check the parsed template on the lexicon's emulator before writing. */
|
|
36
|
+
validate?: boolean;
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
/**
|
|
@@ -52,6 +55,12 @@ export interface ImportResult {
|
|
|
52
55
|
* it was named (`--lexicon`, `--kustomize`) (#2965).
|
|
53
56
|
*/
|
|
54
57
|
detected?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* What the parser flagged for review (#4398), then what `--validate`
|
|
60
|
+
* rejected. `--report` writes them as SARIF and `--strict` fails while a
|
|
61
|
+
* `warning` or `error` is open; see `./import-report.ts`.
|
|
62
|
+
*/
|
|
63
|
+
diagnostics?: ImportDiagnostic[];
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
/**
|
|
@@ -353,6 +362,7 @@ export async function importCommand(options: ImportOptions): Promise<ImportResul
|
|
|
353
362
|
output: options.output,
|
|
354
363
|
force: options.force,
|
|
355
364
|
parserOptions: options.parserOptions,
|
|
365
|
+
validate: options.validate,
|
|
356
366
|
});
|
|
357
367
|
}
|
|
358
368
|
|
|
@@ -391,7 +401,7 @@ export async function importCommand(options: ImportOptions): Promise<ImportResul
|
|
|
391
401
|
);
|
|
392
402
|
}
|
|
393
403
|
|
|
394
|
-
const result = await parseAndWrite(plugin, content, outputDir, options.force, warnings, generatedFiles, plugin.name, projectDir, options.parserOptions);
|
|
404
|
+
const result = await parseAndWrite(plugin, content, outputDir, options.force, warnings, generatedFiles, plugin.name, projectDir, options.parserOptions, options.validate);
|
|
395
405
|
return { ...result, detected: true };
|
|
396
406
|
}
|
|
397
407
|
|
|
@@ -412,6 +422,8 @@ export interface ContentImportOptions {
|
|
|
412
422
|
force?: boolean;
|
|
413
423
|
/** `--parser-option` entries for the lexicon's parser (#2994); see {@link ImportOptions.parserOptions}. */
|
|
414
424
|
parserOptions?: string[];
|
|
425
|
+
/** `--validate`; see {@link ImportOptions.validate}. */
|
|
426
|
+
validate?: boolean;
|
|
415
427
|
}
|
|
416
428
|
|
|
417
429
|
export async function importFromContent(options: ContentImportOptions): Promise<ImportResult> {
|
|
@@ -432,7 +444,7 @@ export async function importFromContent(options: ContentImportOptions): Promise<
|
|
|
432
444
|
return { success: false, generatedFiles: [], warnings: [], error: `Lexicon "${options.lexicon}" not available.` };
|
|
433
445
|
}
|
|
434
446
|
const projectDir = resolve(options.output ? dirname(options.output) : ".");
|
|
435
|
-
return parseAndWrite(plugin, options.content, outputDir, options.force, [], [], plugin.name, projectDir, options.parserOptions);
|
|
447
|
+
return parseAndWrite(plugin, options.content, outputDir, options.force, [], [], plugin.name, projectDir, options.parserOptions, options.validate);
|
|
436
448
|
}
|
|
437
449
|
|
|
438
450
|
/**
|
|
@@ -568,6 +580,7 @@ async function parseAndWrite(
|
|
|
568
580
|
lexicon: string,
|
|
569
581
|
projectDir: string,
|
|
570
582
|
parserOptionEntries?: readonly string[],
|
|
583
|
+
validate?: boolean,
|
|
571
584
|
): Promise<ImportResult> {
|
|
572
585
|
// A lexicon can recognize a template (detectTemplate) without being able to
|
|
573
586
|
// import it (grafana had no parser until #2945). Every path funnels through here, so
|
|
@@ -609,6 +622,18 @@ async function parseAndWrite(
|
|
|
609
622
|
if (ir.warnings) {
|
|
610
623
|
warnings.push(...ir.warnings);
|
|
611
624
|
}
|
|
625
|
+
// Findings for review (#4398), and what the lexicon's emulator rejects.
|
|
626
|
+
const diagnostics: ImportDiagnostic[] = [...(ir.diagnostics ?? [])];
|
|
627
|
+
if (validate) {
|
|
628
|
+
if (!plugin.validateImport) {
|
|
629
|
+
return { success: false, generatedFiles: [], warnings: [], error: `lexicon "${plugin.name}" has no emulator to validate an import against`, lexicon: plugin.name };
|
|
630
|
+
}
|
|
631
|
+
try {
|
|
632
|
+
diagnostics.push(...(await plugin.validateImport(ir, resolved.options)));
|
|
633
|
+
} catch (err) {
|
|
634
|
+
return { success: false, generatedFiles: [], warnings: [], error: `--validate failed to run: ${err instanceof Error ? err.message : String(err)}`, lexicon: plugin.name };
|
|
635
|
+
}
|
|
636
|
+
}
|
|
612
637
|
// Embedded content the owner could not carry, or that no installed lexicon imports.
|
|
613
638
|
if (embedded) warnings.push(...embedded.warnings);
|
|
614
639
|
|
|
@@ -660,6 +685,7 @@ async function parseAndWrite(
|
|
|
660
685
|
generatedFiles,
|
|
661
686
|
warnings,
|
|
662
687
|
lexicon,
|
|
688
|
+
...(diagnostics.length > 0 ? { diagnostics } : {}),
|
|
663
689
|
};
|
|
664
690
|
}
|
|
665
691
|
|
|
@@ -894,6 +920,10 @@ export function printImportResult(result: ImportResult): void {
|
|
|
894
920
|
console.log(`${result.detected ? "Detected lexicon" : "Lexicon"}: ${result.lexicon}`);
|
|
895
921
|
}
|
|
896
922
|
|
|
923
|
+
if (result.diagnostics && result.diagnostics.length > 0) {
|
|
924
|
+
console.error(summarizeImportDiagnostics(result.diagnostics));
|
|
925
|
+
}
|
|
926
|
+
|
|
897
927
|
if (result.generatedFiles.length > 0) {
|
|
898
928
|
console.log(formatSuccess("Generated files:"));
|
|
899
929
|
for (const file of result.generatedFiles) {
|
package/src/cli/commands/lint.ts
CHANGED
|
@@ -785,6 +785,7 @@ async function runLexiconPostSynthDiagnostics(
|
|
|
785
785
|
ruleId: d.checkId,
|
|
786
786
|
severity: d.severity,
|
|
787
787
|
message: `${d.entity ? `[${d.entity}] ` : ""}${d.message}`,
|
|
788
|
+
...(d.entity ? { entity: d.entity } : {}),
|
|
788
789
|
});
|
|
789
790
|
|
|
790
791
|
for (const { plugin, diagnostics: raw } of runLexiconPostSynthChecks(withChecks, result, env, { activityContracts, telemetry, projectDir: configDir, ...(loadedConfig ? { projectConfig: loadedConfig } : {}) })) {
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant migrate` naming and the target-server `--validate` (#4399): a side is
|
|
3
|
+
* `lexicon` or `lexicon/dialect`, a directory is a source only when the
|
|
4
|
+
* lexicon says so, and a result's own `validate` replaces the external linter.
|
|
5
|
+
*/
|
|
6
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
7
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { lexiconOfSide, migrateCommand } from "./migrate";
|
|
11
|
+
import type { LexiconPlugin, MigrationResult, MigrationSource } from "../../lexicon";
|
|
12
|
+
|
|
13
|
+
const seen: Array<{ from: string; to: string | undefined }> = [];
|
|
14
|
+
|
|
15
|
+
function sqlPlugin(over: { directory?: boolean; result?: Partial<MigrationResult>; transform?: MigrationSource["transform"] } = {}): LexiconPlugin {
|
|
16
|
+
return {
|
|
17
|
+
name: "sql",
|
|
18
|
+
serializer: { name: "sql", rulePrefix: "SQL", serialize: () => "" },
|
|
19
|
+
async generate() {},
|
|
20
|
+
async validate() {},
|
|
21
|
+
async coverage() {},
|
|
22
|
+
async package() {},
|
|
23
|
+
migrationSource(from: string, to?: string) {
|
|
24
|
+
seen.push({ from, to });
|
|
25
|
+
if (from !== "sql/postgres" || (to !== undefined && to !== "sql/clickhouse")) return undefined;
|
|
26
|
+
return {
|
|
27
|
+
detect: (content: string) => content.includes("CREATE TABLE"),
|
|
28
|
+
...(over.directory ? { directory: true } : {}),
|
|
29
|
+
transform: over.transform ?? (async () => ({ output: "-- ddl\n", provenance: [], diagnostics: [], ...over.result })),
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const base = { emit: "sql" as const, strict: false, validate: false, useComposites: false };
|
|
36
|
+
|
|
37
|
+
describe("lexiconOfSide", () => {
|
|
38
|
+
test("is the part before the slash", () => {
|
|
39
|
+
expect(lexiconOfSide("sql/clickhouse")).toBe("sql");
|
|
40
|
+
expect(lexiconOfSide("gitlab")).toBe("gitlab");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("migrateCommand with lexicon/dialect sides", () => {
|
|
45
|
+
let dir: string;
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
dir = mkdtempSync(join(tmpdir(), "chant-migrate-dialect-"));
|
|
48
|
+
seen.length = 0;
|
|
49
|
+
});
|
|
50
|
+
afterEach(() => rmSync(dir, { recursive: true, force: true }));
|
|
51
|
+
const file = () => {
|
|
52
|
+
const f = join(dir, "schema.sql");
|
|
53
|
+
writeFileSync(f, "CREATE TABLE t (id int);");
|
|
54
|
+
return f;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
test("finds the plugin by the lexicon part, and hands the source both sides as written", async () => {
|
|
58
|
+
const r = await migrateCommand({ ...base, sourceFile: file(), from: "sql/postgres", to: "sql/clickhouse", output: join(dir, "out.sql"), plugins: [sqlPlugin()] });
|
|
59
|
+
expect(r.exitCode).toBe(0);
|
|
60
|
+
expect(seen).toEqual([{ from: "sql/postgres", to: "sql/clickhouse" }]);
|
|
61
|
+
expect(readFileSync(join(dir, "out.sql"), "utf8")).toBe("-- ddl\n");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("a dialect the lexicon does not know is refused by name", async () => {
|
|
65
|
+
const r = await migrateCommand({ ...base, sourceFile: file(), from: "sql/postgres", to: "sql/mysql", plugins: [sqlPlugin()] });
|
|
66
|
+
expect(r.exitCode).toBe(1);
|
|
67
|
+
expect(r.error).toContain('Lexicon "sql/mysql" does not support migration from "sql/postgres"');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("creates the output's directory", async () => {
|
|
71
|
+
const out = join(dir, "a/b/out.sql");
|
|
72
|
+
const r = await migrateCommand({ ...base, sourceFile: file(), from: "sql/postgres", to: "sql/clickhouse", output: out, plugins: [sqlPlugin()] });
|
|
73
|
+
expect(r.exitCode).toBe(0);
|
|
74
|
+
expect(readFileSync(out, "utf8")).toBe("-- ddl\n");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("a directory is refused unless the source reads directories; then detect is skipped and content is empty", async () => {
|
|
78
|
+
const member = join(dir, "db");
|
|
79
|
+
mkdirSync(member);
|
|
80
|
+
const refused = await migrateCommand({ ...base, sourceFile: member, from: "sql/postgres", to: "sql/clickhouse", plugins: [sqlPlugin()] });
|
|
81
|
+
expect(refused.exitCode).toBe(1);
|
|
82
|
+
expect(refused.error).toContain("is a directory");
|
|
83
|
+
let got: { content: string; sourceFile?: string } | undefined;
|
|
84
|
+
const ok = await migrateCommand({
|
|
85
|
+
...base,
|
|
86
|
+
sourceFile: member,
|
|
87
|
+
from: "sql/postgres",
|
|
88
|
+
to: "sql/clickhouse",
|
|
89
|
+
output: join(dir, "o.sql"),
|
|
90
|
+
plugins: [sqlPlugin({ directory: true, transform: async (content, opts) => ((got = { content, sourceFile: opts.sourceFile }), { output: "x", provenance: [], diagnostics: [] }) })],
|
|
91
|
+
});
|
|
92
|
+
expect(ok.exitCode).toBe(0);
|
|
93
|
+
expect(got).toEqual({ content: "", sourceFile: member });
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe("--validate with a result that checks itself", () => {
|
|
98
|
+
let dir: string;
|
|
99
|
+
beforeEach(() => {
|
|
100
|
+
dir = mkdtempSync(join(tmpdir(), "chant-migrate-validate-"));
|
|
101
|
+
});
|
|
102
|
+
afterEach(() => rmSync(dir, { recursive: true, force: true }));
|
|
103
|
+
const run = (result: Partial<MigrationResult>, extra: { strict?: boolean } = {}) => {
|
|
104
|
+
const f = join(dir, "schema.sql");
|
|
105
|
+
writeFileSync(f, "CREATE TABLE t (id int);");
|
|
106
|
+
return migrateCommand({ ...base, ...extra, validate: true, sourceFile: f, from: "sql/postgres", to: "sql/clickhouse", output: join(dir, "o.sql"), plugins: [sqlPlugin({ result })] });
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
test("a clean check passes and its diagnostics join the result", async () => {
|
|
110
|
+
const r = await run({ validate: async () => [] });
|
|
111
|
+
expect(r.exitCode).toBe(0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("a refused statement fails the run without --strict, and is in the diagnostics", async () => {
|
|
115
|
+
const r = await run({ validate: async () => [{ ruleId: "SQLRV012", severity: "error", message: "t: the emulator rejected the statement." }] });
|
|
116
|
+
expect(r.exitCode).toBe(1);
|
|
117
|
+
expect(r.diagnostics.map((d) => d.ruleId)).toEqual(["SQLRV012"]);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("a server that cannot start is a validation that did not run, which fails", async () => {
|
|
121
|
+
const r = await run({
|
|
122
|
+
validate: async () => {
|
|
123
|
+
throw new Error("Docker is not available, so the ClickHouse emulator cannot start");
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
expect(r.exitCode).toBe(1);
|
|
127
|
+
expect(r.error).toContain("--validate did not run: Docker is not available");
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("without --validate the check is not run", async () => {
|
|
131
|
+
let ran = false;
|
|
132
|
+
const f = join(dir, "schema.sql");
|
|
133
|
+
writeFileSync(f, "CREATE TABLE t (id int);");
|
|
134
|
+
const r = await migrateCommand({
|
|
135
|
+
...base,
|
|
136
|
+
sourceFile: f,
|
|
137
|
+
from: "sql/postgres",
|
|
138
|
+
to: "sql/clickhouse",
|
|
139
|
+
output: join(dir, "o.sql"),
|
|
140
|
+
plugins: [sqlPlugin({ result: { validate: async () => ((ran = true), []) } })],
|
|
141
|
+
});
|
|
142
|
+
expect(r.exitCode).toBe(0);
|
|
143
|
+
expect(ran).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
});
|