@intentius/chant 0.124.52 → 0.124.54
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/audit/discover.d.ts.map +1 -1
- package/dist/audit/discover.js +3 -1
- package/dist/behaviour.d.ts +1 -1
- package/dist/behaviour.d.ts.map +1 -1
- package/dist/capabilities/templates.d.ts +65 -0
- package/dist/capabilities/templates.d.ts.map +1 -0
- package/dist/capabilities/templates.js +193 -0
- package/dist/capabilities/templates.json +145 -0
- package/dist/change-set-graph.d.ts +35 -3
- package/dist/change-set-graph.d.ts.map +1 -1
- package/dist/change-set-graph.js +60 -9
- package/dist/change-set.d.ts +65 -7
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +23 -12
- package/dist/ci-identity.d.ts +7 -2
- package/dist/ci-identity.d.ts.map +1 -1
- package/dist/ci-identity.js +4 -1
- package/dist/cli/commands/import-index.d.ts +52 -0
- package/dist/cli/commands/import-index.d.ts.map +1 -0
- package/dist/cli/commands/import-index.js +226 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +4 -2
- package/dist/cli/handlers/components.d.ts.map +1 -1
- package/dist/cli/handlers/components.js +11 -2
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +16 -3
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +22 -4
- package/dist/cli/handlers/index-cloud.d.ts +14 -0
- package/dist/cli/handlers/index-cloud.d.ts.map +1 -0
- package/dist/cli/handlers/index-cloud.js +22 -0
- package/dist/cli/handlers/index-diff.d.ts +18 -0
- package/dist/cli/handlers/index-diff.d.ts.map +1 -0
- package/dist/cli/handlers/index-diff.js +142 -0
- package/dist/cli/handlers/lifecycle-drift.d.ts +25 -0
- package/dist/cli/handlers/lifecycle-drift.d.ts.map +1 -0
- package/dist/cli/handlers/lifecycle-drift.js +64 -0
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.js +188 -28
- package/dist/cli/handlers/misc.d.ts +9 -0
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/misc.js +77 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +15 -2
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +89 -15
- package/dist/cli/handlers/query.d.ts.map +1 -1
- package/dist/cli/handlers/query.js +28 -4
- package/dist/cli/handlers/scenario.d.ts.map +1 -1
- package/dist/cli/handlers/scenario.js +8 -7
- package/dist/cli/handlers/search.d.ts +34 -4
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +216 -36
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +55 -1
- package/dist/cli/mcp/lifecycle-tools.d.ts.map +1 -1
- package/dist/cli/mcp/lifecycle-tools.js +3 -2
- package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
- package/dist/cli/mcp/resource-handlers.js +4 -3
- package/dist/cli/mcp/workspace-tools.js +1 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +55 -2
- package/dist/cli/registry.d.ts +19 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cloud-lister/aws.d.ts +35 -0
- package/dist/cloud-lister/aws.d.ts.map +1 -0
- package/dist/cloud-lister/aws.js +203 -0
- package/dist/cloud-lister/azure.d.ts +34 -0
- package/dist/cloud-lister/azure.d.ts.map +1 -0
- package/dist/cloud-lister/azure.js +129 -0
- package/dist/cloud-lister/common.d.ts +40 -0
- package/dist/cloud-lister/common.d.ts.map +1 -0
- package/dist/cloud-lister/common.js +83 -0
- package/dist/cloud-lister/credentials.d.ts +50 -0
- package/dist/cloud-lister/credentials.d.ts.map +1 -0
- package/dist/cloud-lister/credentials.js +86 -0
- package/dist/cloud-lister/fakes.d.ts +27 -0
- package/dist/cloud-lister/fakes.d.ts.map +1 -0
- package/dist/cloud-lister/fakes.js +50 -0
- package/dist/cloud-lister/gcp.d.ts +42 -0
- package/dist/cloud-lister/gcp.d.ts.map +1 -0
- package/dist/cloud-lister/gcp.js +143 -0
- package/dist/cloud-lister/guard.d.ts +49 -0
- package/dist/cloud-lister/guard.d.ts.map +1 -0
- package/dist/cloud-lister/guard.js +103 -0
- package/dist/cloud-lister/ids.d.ts +23 -0
- package/dist/cloud-lister/ids.d.ts.map +1 -0
- package/dist/cloud-lister/ids.js +42 -0
- package/dist/cloud-lister/index.d.ts +67 -0
- package/dist/cloud-lister/index.d.ts.map +1 -0
- package/dist/cloud-lister/index.js +102 -0
- package/dist/cloud-lister/kubernetes.d.ts +64 -0
- package/dist/cloud-lister/kubernetes.d.ts.map +1 -0
- package/dist/cloud-lister/kubernetes.js +276 -0
- package/dist/cloud-lister/markers.d.ts +31 -0
- package/dist/cloud-lister/markers.d.ts.map +1 -0
- package/dist/cloud-lister/markers.js +73 -0
- package/dist/cloud-lister/mask.d.ts +31 -0
- package/dist/cloud-lister/mask.d.ts.map +1 -0
- package/dist/cloud-lister/mask.js +74 -0
- package/dist/cloud-lister/sigv4.d.ts +29 -0
- package/dist/cloud-lister/sigv4.d.ts.map +1 -0
- package/dist/cloud-lister/sigv4.js +54 -0
- package/dist/cloud-lister/transport.d.ts +55 -0
- package/dist/cloud-lister/transport.d.ts.map +1 -0
- package/dist/cloud-lister/transport.js +86 -0
- package/dist/cloud-lister/types.d.ts +121 -0
- package/dist/cloud-lister/types.d.ts.map +1 -0
- package/dist/cloud-lister/types.js +24 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.js +6 -0
- package/dist/components/capability-plugin.d.ts +9 -0
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/capability.d.ts +215 -0
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/cli-support.d.ts +21 -0
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/cli-support.js +58 -14
- package/dist/components/declared-reads.d.ts +38 -0
- package/dist/components/declared-reads.d.ts.map +1 -0
- package/dist/components/declared-reads.js +131 -0
- package/dist/components/deploy-units.d.ts.map +1 -1
- package/dist/components/deploy-units.js +4 -0
- package/dist/components/driver.d.ts +34 -1
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +66 -3
- package/dist/components/fan-out-run.d.ts +23 -1
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +82 -14
- package/dist/components/fan-out-support.d.ts +6 -0
- package/dist/components/fan-out-support.d.ts.map +1 -1
- package/dist/components/fan-out-support.js +4 -1
- package/dist/components/fan-out.d.ts +28 -0
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/groups.d.ts +229 -0
- package/dist/components/groups.d.ts.map +1 -0
- package/dist/components/groups.js +760 -0
- package/dist/components/index.d.ts +6 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -0
- package/dist/components/plan-shape-conformance.d.ts +48 -0
- package/dist/components/plan-shape-conformance.d.ts.map +1 -0
- package/dist/components/plan-shape-conformance.js +122 -0
- package/dist/components/pr-run.d.ts +41 -4
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +209 -39
- package/dist/components/promote-rounds.d.ts +9 -0
- package/dist/components/promote-rounds.d.ts.map +1 -1
- package/dist/components/promote-rounds.js +23 -2
- package/dist/components/promote.d.ts +17 -0
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/promote.js +36 -6
- package/dist/components/release-gate.d.ts +23 -1
- package/dist/components/release-gate.d.ts.map +1 -1
- package/dist/components/release-gate.js +97 -33
- package/dist/components/run-groups.d.ts +58 -0
- package/dist/components/run-groups.d.ts.map +1 -0
- package/dist/components/run-groups.js +78 -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 +6 -1
- package/dist/components/verbs/index.d.ts +1 -0
- package/dist/components/verbs/index.d.ts.map +1 -1
- package/dist/components/verbs/index.js +1 -0
- package/dist/components/verbs/member-outputs.d.ts +187 -0
- package/dist/components/verbs/member-outputs.d.ts.map +1 -0
- package/dist/components/verbs/member-outputs.js +218 -0
- package/dist/config.d.ts +60 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +27 -0
- package/dist/deep-observation.d.ts +1 -13
- package/dist/deep-observation.d.ts.map +1 -1
- package/dist/deep-observation.js +5 -22
- package/dist/drift-record.d.ts +542 -0
- package/dist/drift-record.d.ts.map +1 -0
- package/dist/drift-record.js +886 -0
- package/dist/engine-facts.d.ts +144 -0
- package/dist/engine-facts.d.ts.map +1 -0
- package/dist/engine-facts.js +14 -0
- package/dist/graph-ir.d.ts +153 -2
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +224 -6
- package/dist/graph-refs.d.ts +145 -0
- package/dist/graph-refs.d.ts.map +1 -1
- package/dist/graph-refs.js +305 -0
- package/dist/graph-schema/fixtures/adopt.json +15 -0
- package/dist/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
- package/dist/graph-schema/fixtures/index.json +68 -0
- package/dist/graph-schema/fixtures/plunge.engine-graph.json +158 -0
- package/dist/graph-schema/fixtures.d.ts +23 -0
- package/dist/graph-schema/fixtures.d.ts.map +1 -0
- package/dist/graph-schema/fixtures.js +246 -0
- package/dist/graph-schema/generate.d.ts +15 -0
- package/dist/graph-schema/generate.d.ts.map +1 -0
- package/dist/graph-schema/generate.js +267 -0
- package/dist/graph-schema/graph.schema.json +1387 -0
- package/dist/health.schema.json +2 -1
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/instance-nodes.d.ts +159 -0
- package/dist/instance-nodes.d.ts.map +1 -0
- package/dist/instance-nodes.js +231 -0
- package/dist/lexicon.d.ts +72 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/adoption-file.d.ts +56 -0
- package/dist/lifecycle/adoption-file.d.ts.map +1 -0
- package/dist/lifecycle/adoption-file.js +123 -0
- package/dist/lifecycle/cloud-index.d.ts +186 -0
- package/dist/lifecycle/cloud-index.d.ts.map +1 -0
- package/dist/lifecycle/cloud-index.js +618 -0
- package/dist/lifecycle/derive-edges.d.ts +59 -0
- package/dist/lifecycle/derive-edges.d.ts.map +1 -0
- package/dist/lifecycle/derive-edges.js +126 -0
- package/dist/lifecycle/git.d.ts +10 -9
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/git.js +7 -1
- package/dist/lifecycle/identity-match.d.ts +133 -0
- package/dist/lifecycle/identity-match.d.ts.map +1 -0
- package/dist/lifecycle/identity-match.js +147 -0
- package/dist/lifecycle/index-diff.d.ts +224 -0
- package/dist/lifecycle/index-diff.d.ts.map +1 -0
- package/dist/lifecycle/index-diff.js +327 -0
- package/dist/lifecycle/index-document.d.ts +130 -0
- package/dist/lifecycle/index-document.d.ts.map +1 -0
- package/dist/lifecycle/index-document.js +189 -0
- package/dist/lifecycle/index-drift.d.ts +121 -0
- package/dist/lifecycle/index-drift.d.ts.map +1 -0
- package/dist/lifecycle/index-drift.js +178 -0
- package/dist/lifecycle/index-import.d.ts +168 -0
- package/dist/lifecycle/index-import.d.ts.map +1 -0
- package/dist/lifecycle/index-import.js +515 -0
- package/dist/lifecycle/index-join.d.ts +129 -0
- package/dist/lifecycle/index-join.d.ts.map +1 -0
- package/dist/lifecycle/index-join.js +248 -0
- package/dist/lifecycle/index.d.ts +4 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/index.js +4 -0
- package/dist/lifecycle/observation-baseline.d.ts +61 -21
- package/dist/lifecycle/observation-baseline.d.ts.map +1 -1
- package/dist/lifecycle/observation-baseline.js +144 -19
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/observe.js +6 -1
- package/dist/lifecycle/query.d.ts +45 -4
- package/dist/lifecycle/query.d.ts.map +1 -1
- package/dist/lifecycle/query.js +89 -7
- package/dist/lifecycle/replay.d.ts +10 -3
- package/dist/lifecycle/replay.d.ts.map +1 -1
- package/dist/lifecycle/replay.js +10 -6
- package/dist/lifecycle/scenario.d.ts +4 -3
- package/dist/lifecycle/scenario.d.ts.map +1 -1
- package/dist/lifecycle/snapshot-store-fake.d.ts +9 -0
- package/dist/lifecycle/snapshot-store-fake.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store-fake.js +21 -0
- package/dist/lifecycle/snapshot-store-s3.d.ts +102 -0
- package/dist/lifecycle/snapshot-store-s3.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store-s3.js +254 -0
- package/dist/lifecycle/snapshot-store.d.ts +170 -0
- package/dist/lifecycle/snapshot-store.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store.js +832 -0
- package/dist/lifecycle/snapshot.d.ts +11 -0
- package/dist/lifecycle/snapshot.d.ts.map +1 -1
- package/dist/lifecycle/snapshot.js +18 -5
- package/dist/lifecycle/type-listing.d.ts +148 -0
- package/dist/lifecycle/type-listing.d.ts.map +1 -0
- package/dist/lifecycle/type-listing.js +166 -0
- package/dist/lint/component-checks.d.ts +15 -1
- package/dist/lint/component-checks.d.ts.map +1 -1
- package/dist/lint/component-checks.js +1 -0
- package/dist/lint/presets/relaxed.json +2 -1
- package/dist/lint/presets/strict.json +2 -1
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.js +13 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.js +8 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts +33 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.js +123 -0
- package/dist/lint/rules/comp/index.d.ts +2 -1
- package/dist/lint/rules/comp/index.d.ts.map +1 -1
- package/dist/lint/rules/comp/index.js +4 -1
- package/dist/observation.d.ts +19 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +18 -1
- package/dist/op/activities/activity-contracts.d.ts +1 -1
- package/dist/op/activities/activity-contracts.js +1 -1
- package/dist/op/activities/change-set.d.ts +6 -4
- package/dist/op/activities/change-set.d.ts.map +1 -1
- package/dist/op/activities/change-set.js +4 -2
- package/dist/op/activity-failure.d.ts +27 -0
- package/dist/op/activity-failure.d.ts.map +1 -1
- package/dist/op/activity-failure.js +31 -0
- package/dist/op/index.d.ts +2 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/index.js +1 -1
- package/dist/op/local-executor.d.ts +5 -1
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +22 -8
- package/dist/pr-loop.d.ts +56 -1
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +51 -1
- package/dist/pulumi-urn.d.ts +101 -0
- package/dist/pulumi-urn.d.ts.map +1 -0
- package/dist/pulumi-urn.js +131 -0
- package/dist/release-floors.d.ts +23 -0
- package/dist/release-floors.d.ts.map +1 -0
- package/dist/release-floors.js +22 -0
- package/dist/sensitive-key.d.ts +23 -0
- package/dist/sensitive-key.d.ts.map +1 -0
- package/dist/sensitive-key.js +31 -0
- package/dist/wave-runtime.mjs +234 -234
- package/dist/workspace/adoption-report.d.ts +53 -0
- package/dist/workspace/adoption-report.d.ts.map +1 -0
- package/dist/workspace/adoption-report.js +76 -0
- package/dist/workspace/capabilities-contract.d.ts +7 -0
- package/dist/workspace/capabilities-contract.d.ts.map +1 -1
- package/dist/workspace/capabilities-contract.js +2 -1
- package/dist/workspace/capabilities.schema.json +98 -0
- package/dist/workspace/change-set.schema.json +42 -3
- package/dist/workspace/ci-cloud-identity.d.ts +13 -1
- package/dist/workspace/ci-cloud-identity.d.ts.map +1 -1
- package/dist/workspace/ci-cloud-identity.js +30 -1
- package/dist/workspace/compose-graph.d.ts +10 -1
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +6 -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 +6 -1
- package/dist/workspace/drift-cli.d.ts +81 -0
- package/dist/workspace/drift-cli.d.ts.map +1 -0
- package/dist/workspace/drift-cli.js +317 -0
- package/dist/workspace/drift.schema.json +672 -0
- package/dist/workspace/graph-cli.d.ts +2 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +3 -0
- package/dist/workspace/graph.schema.json +72 -0
- package/dist/workspace/init.d.ts +5 -1
- package/dist/workspace/init.d.ts.map +1 -1
- package/dist/workspace/init.js +55 -9
- package/dist/workspace/ledger.schema.json +1 -1
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +2 -0
- package/dist/workspace/pr-report.schema.json +51 -2
- package/dist/workspace/promote-waves.d.ts +112 -0
- package/dist/workspace/promote-waves.d.ts.map +1 -0
- package/dist/workspace/promote-waves.js +290 -0
- package/dist/workspace/promote.d.ts +84 -2
- package/dist/workspace/promote.d.ts.map +1 -1
- package/dist/workspace/promote.js +347 -61
- package/dist/workspace/reason-codes.d.ts +12 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +14 -0
- package/dist/workspace/search-contract.d.ts +3 -3
- package/dist/workspace/search-contract.d.ts.map +1 -1
- package/dist/workspace/search-contract.js +2 -0
- package/dist/workspace/search.schema.json +103 -5
- package/package.json +14 -1
- package/src/__fixtures__/drift-record/README.md +58 -0
- package/src/__fixtures__/drift-record/choudoufu-cone.ndjson +4 -0
- package/src/__fixtures__/drift-record/choudoufu-resource.ndjson +3 -0
- package/src/__fixtures__/drift-record/component-status-ledger.json +65 -0
- package/src/__fixtures__/drift-record/component-status.json +91 -0
- package/src/__fixtures__/drift-record/deep-diff.json +259 -0
- package/src/__fixtures__/drift-record/lifecycle-diff-live.json +825 -0
- package/src/__fixtures__/drift-record/live-diff.json +125 -0
- package/src/audit/discover.e2e.test.ts +14 -0
- package/src/audit/discover.ts +3 -1
- package/src/behaviour.ts +1 -1
- package/src/capabilities/templates.json +145 -0
- package/src/capabilities/templates.test.ts +212 -0
- package/src/capabilities/templates.ts +204 -0
- package/src/change-set-bundle.test.ts +83 -0
- package/src/change-set-graph.ts +80 -9
- package/src/change-set.test.ts +24 -0
- package/src/change-set.ts +77 -14
- package/src/ci-identity-targets.test.ts +23 -0
- package/src/ci-identity.ts +10 -4
- package/src/cli/commands/import-index.test.ts +117 -0
- package/src/cli/commands/import-index.ts +265 -0
- package/src/cli/commands/lint.ts +4 -2
- package/src/cli/handlers/components.test.ts +9 -0
- package/src/cli/handlers/components.ts +12 -2
- package/src/cli/handlers/fan-out.ts +17 -3
- package/src/cli/handlers/graph.test.ts +42 -0
- package/src/cli/handlers/graph.ts +26 -4
- package/src/cli/handlers/index-cloud.ts +32 -0
- package/src/cli/handlers/index-diff.test.ts +68 -0
- package/src/cli/handlers/index-diff.ts +146 -0
- package/src/cli/handlers/ledger-root-member.test.ts +161 -0
- package/src/cli/handlers/lifecycle-drift.ts +68 -0
- package/src/cli/handlers/lifecycle.test.ts +33 -11
- package/src/cli/handlers/lifecycle.ts +205 -30
- package/src/cli/handlers/misc.ts +73 -0
- package/src/cli/handlers/pr-waves-blocked.test.ts +37 -2
- package/src/cli/handlers/pr.ts +14 -2
- package/src/cli/handlers/promote.test.ts +64 -0
- package/src/cli/handlers/promote.ts +81 -6
- package/src/cli/handlers/query.ts +27 -4
- package/src/cli/handlers/run-declared-reads-cli.test.ts +187 -0
- package/src/cli/handlers/run-groups-cli.test.ts +229 -0
- package/src/cli/handlers/scenario.test.ts +13 -0
- package/src/cli/handlers/scenario.ts +8 -7
- package/src/cli/handlers/search-index.test.ts +255 -0
- package/src/cli/handlers/search-json.test.ts +1 -1
- package/src/cli/handlers/search-ownership.test.ts +194 -0
- package/src/cli/handlers/search.ts +271 -38
- package/src/cli/main.test.ts +7 -0
- package/src/cli/main.ts +56 -1
- package/src/cli/mcp/lifecycle-tools.ts +3 -2
- package/src/cli/mcp/resource-handlers.ts +4 -3
- package/src/cli/mcp/workspace-tools.ts +1 -1
- package/src/cli/parse-args.ts +40 -2
- package/src/cli/registry.ts +19 -1
- package/src/cloud-lister/aws.test.ts +202 -0
- package/src/cloud-lister/aws.ts +226 -0
- package/src/cloud-lister/azure.test.ts +132 -0
- package/src/cloud-lister/azure.ts +142 -0
- package/src/cloud-lister/common.ts +115 -0
- package/src/cloud-lister/credentials.ts +110 -0
- package/src/cloud-lister/fakes.ts +66 -0
- package/src/cloud-lister/gcp.test.ts +121 -0
- package/src/cloud-lister/gcp.ts +159 -0
- package/src/cloud-lister/guard.test.ts +198 -0
- package/src/cloud-lister/guard.ts +111 -0
- package/src/cloud-lister/ids.ts +54 -0
- package/src/cloud-lister/index.ts +134 -0
- package/src/cloud-lister/kubernetes.test.ts +160 -0
- package/src/cloud-lister/kubernetes.ts +284 -0
- package/src/cloud-lister/markers.ts +74 -0
- package/src/cloud-lister/mask.ts +77 -0
- package/src/cloud-lister/shape.test.ts +81 -0
- package/src/cloud-lister/sigv4.ts +70 -0
- package/src/cloud-lister/transport.ts +118 -0
- package/src/cloud-lister/types.ts +135 -0
- package/src/components/capability-plugin-loader.ts +4 -0
- package/src/components/capability-plugin.ts +10 -0
- package/src/components/capability.ts +229 -0
- package/src/components/cli-support.ts +70 -14
- package/src/components/declared-reads.test.ts +103 -0
- package/src/components/declared-reads.ts +134 -0
- package/src/components/deploy-units.ts +4 -0
- package/src/components/driver.ts +89 -4
- package/src/components/fan-out-run.ts +95 -15
- package/src/components/fan-out-support.ts +10 -1
- package/src/components/fan-out.ts +30 -0
- package/src/components/groups.test.ts +320 -0
- package/src/components/groups.ts +880 -0
- package/src/components/index.ts +42 -0
- package/src/components/plan-shape-conformance.ts +130 -0
- package/src/components/pr-env-run-bundle.test.ts +2 -0
- package/src/components/pr-run.test.ts +516 -3
- package/src/components/pr-run.ts +231 -41
- package/src/components/promote-rounds.ts +25 -2
- package/src/components/promote.ts +55 -5
- package/src/components/registry.test.ts +1 -1
- package/src/components/release-gate.ts +115 -30
- package/src/components/release-groups.test.ts +362 -0
- package/src/components/run-groups.ts +113 -0
- package/src/components/starter-plugin.ts +6 -0
- package/src/components/verbs/index.ts +1 -0
- package/src/components/verbs/member-outputs.test.ts +205 -0
- package/src/components/verbs/member-outputs.ts +308 -0
- package/src/config.ts +44 -0
- package/src/deep-observation.ts +5 -23
- package/src/drift-record.test.ts +596 -0
- package/src/drift-record.ts +1206 -0
- package/src/engine-facts.guard.test.ts +111 -0
- package/src/engine-facts.test.ts +178 -0
- package/src/engine-facts.ts +154 -0
- package/src/gated-waves-bundle.test.ts +2 -0
- package/src/graph-ir-live.test.ts +92 -0
- package/src/graph-ir.ts +317 -7
- package/src/graph-refs.ts +416 -0
- package/src/graph-schema/fixtures/adopt.json +15 -0
- package/src/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
- package/src/graph-schema/fixtures/index.json +68 -0
- package/src/graph-schema/fixtures/plunge.engine-graph.json +158 -0
- package/src/graph-schema/fixtures.ts +267 -0
- package/src/graph-schema/generate.ts +263 -0
- package/src/graph-schema/graph-schema.test.ts +153 -0
- package/src/graph-schema/graph.schema.json +1387 -0
- package/src/health.schema.json +2 -1
- package/src/identity.ts +2 -0
- package/src/index.ts +2 -0
- package/src/instance-nodes.ts +288 -0
- package/src/lexicon.ts +76 -0
- package/src/lifecycle/__fixtures__/index-diff/20261026T120000Z-aaaaaaaaaaaa.json +149 -0
- package/src/lifecycle/__fixtures__/index-diff/20261026T130000Z-bbbbbbbbbbbb.json +127 -0
- package/src/lifecycle/adoption-file.test.ts +100 -0
- package/src/lifecycle/adoption-file.ts +154 -0
- package/src/lifecycle/cloud-index.test.ts +517 -0
- package/src/lifecycle/cloud-index.ts +736 -0
- package/src/lifecycle/derive-edges.test.ts +193 -0
- package/src/lifecycle/derive-edges.ts +182 -0
- package/src/lifecycle/git.ts +10 -4
- package/src/lifecycle/identity-match.test.ts +308 -0
- package/src/lifecycle/identity-match.ts +257 -0
- package/src/lifecycle/index-diff.test.ts +198 -0
- package/src/lifecycle/index-diff.ts +476 -0
- package/src/lifecycle/index-document.test.ts +64 -0
- package/src/lifecycle/index-document.ts +299 -0
- package/src/lifecycle/index-drift.test.ts +191 -0
- package/src/lifecycle/index-drift.ts +304 -0
- package/src/lifecycle/index-import.test.ts +255 -0
- package/src/lifecycle/index-import.ts +634 -0
- package/src/lifecycle/index-join.test.ts +250 -0
- package/src/lifecycle/index-join.ts +304 -0
- package/src/lifecycle/index-store-load-bearing.test.ts +187 -0
- package/src/lifecycle/index.ts +4 -0
- package/src/lifecycle/member-ledger.test.ts +25 -7
- package/src/lifecycle/observation-baseline.test.ts +72 -1
- package/src/lifecycle/observation-baseline.ts +190 -27
- package/src/lifecycle/observe.ts +6 -1
- package/src/lifecycle/query.test.ts +69 -1
- package/src/lifecycle/query.ts +103 -10
- package/src/lifecycle/replay.test.ts +9 -5
- package/src/lifecycle/replay.ts +9 -5
- package/src/lifecycle/scenario.ts +4 -3
- package/src/lifecycle/snapshot-store-fake.ts +29 -0
- package/src/lifecycle/snapshot-store-s3.ts +316 -0
- package/src/lifecycle/snapshot-store.test.ts +385 -0
- package/src/lifecycle/snapshot-store.ts +981 -0
- package/src/lifecycle/snapshot.test.ts +13 -0
- package/src/lifecycle/snapshot.ts +23 -6
- package/src/lifecycle/type-listing.test.ts +166 -0
- package/src/lifecycle/type-listing.ts +309 -0
- package/src/lint/component-checks.ts +17 -1
- package/src/lint/config.test.ts +3 -0
- package/src/lint/presets/relaxed.json +2 -1
- package/src/lint/presets/strict.json +2 -1
- package/src/lint/rules/__fixtures__/comp/comp008/fail/dns.component.ts +15 -0
- package/src/lint/rules/__fixtures__/comp/comp008/pass/dns.component.ts +10 -0
- package/src/lint/rules/comp/comp.test.ts +2 -1
- package/src/lint/rules/comp/comp008-applies-signal-only-root.ts +121 -0
- package/src/lint/rules/comp/comp008.test.ts +77 -0
- package/src/lint/rules/comp/index.ts +4 -1
- package/src/observation-edges.test.ts +33 -0
- package/src/observation.ts +36 -1
- package/src/op/activities/activity-contracts.ts +1 -1
- package/src/op/activities/change-set.ts +8 -5
- package/src/op/activity-failure.ts +36 -0
- package/src/op/index.ts +2 -1
- package/src/op/local-executor.test.ts +80 -0
- package/src/op/local-executor.ts +27 -9
- package/src/pr-loop-bundle.test.ts +5 -2
- package/src/pr-loop.test.ts +43 -0
- package/src/pr-loop.ts +111 -2
- package/src/pulumi-urn.ts +151 -0
- package/src/release-floors.ts +22 -0
- package/src/sensitive-key.ts +34 -0
- package/src/workspace/adoption-report.test.ts +61 -0
- package/src/workspace/adoption-report.ts +103 -0
- package/src/workspace/capabilities-contract.test.ts +4 -0
- package/src/workspace/capabilities-contract.ts +9 -1
- package/src/workspace/capabilities.schema.json +98 -0
- package/src/workspace/change-set.schema.json +42 -3
- package/src/workspace/ci-cloud-identity.ts +31 -1
- package/src/workspace/compose-graph.test.ts +12 -0
- package/src/workspace/compose-graph.ts +12 -1
- package/src/workspace/conformance/conformance.e2e.test.ts +2 -1
- package/src/workspace/conformance/index.ts +6 -1
- package/src/workspace/drift-cli.test.ts +65 -0
- package/src/workspace/drift-cli.ts +365 -0
- package/src/workspace/drift.schema.json +672 -0
- package/src/workspace/graph-cli.ts +5 -0
- package/src/workspace/graph.schema.json +72 -0
- package/src/workspace/init.test.ts +38 -1
- package/src/workspace/init.ts +50 -8
- package/src/workspace/intent-gaps.test.ts +18 -2
- package/src/workspace/ledger.schema.json +1 -1
- package/src/workspace/nested-graph.ts +1 -0
- package/src/workspace/pr-report.schema.json +51 -2
- package/src/workspace/promote-waves.test.ts +296 -0
- package/src/workspace/promote-waves.ts +340 -0
- package/src/workspace/promote.test.ts +158 -4
- package/src/workspace/promote.ts +398 -57
- package/src/workspace/reason-codes.test.ts +4 -1
- package/src/workspace/reason-codes.ts +14 -0
- package/src/workspace/search-contract.ts +2 -0
- package/src/workspace/search.schema.json +103 -5
package/src/workspace/promote.ts
CHANGED
|
@@ -13,33 +13,65 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Rungs:
|
|
15
15
|
*
|
|
16
|
-
* - `terraform` to `choudoufu`: `choudoufu
|
|
16
|
+
* - `terraform` to `choudoufu`: `choudoufu init -backend=false` installs the
|
|
17
|
+
* providers in the staging worktree, which has no `.terraform/` of its own
|
|
18
|
+
* (#4461: `live-import` reads each resource through its provider), then
|
|
19
|
+
* `choudoufu live-check` in the member's
|
|
17
20
|
* directory must pass, then `choudoufu live-import -state=<--state>
|
|
18
21
|
* -estate=<member>` prints its ratification report (read-only: it stamps
|
|
19
|
-
* nothing without `-approve`). The patch changes the member's kind.
|
|
22
|
+
* nothing without `-approve`). The patch changes the member's kind. The
|
|
23
|
+
* report, one entry per resource with its status, rides on `--json` as
|
|
24
|
+
* `adoption` (INTENTIUS/behold#999, ./adoption-report.ts), so
|
|
25
|
+
* `--dry-run --json` is the read-only way to ask what adopting would claim.
|
|
20
26
|
* - `choudoufu` or `other` to `chant`: `chant import` writes TypeScript into
|
|
21
27
|
* the member's directory. The patch holds those files and the kind change.
|
|
22
28
|
*
|
|
29
|
+
* The digest covers the member, the rung, what the staging changed outside
|
|
30
|
+
* the declaration, and (for `choudoufu`) the digest of the `live-import`
|
|
31
|
+
* report, so an approval is for the report the approver read. The kind change
|
|
32
|
+
* itself is written into the tree's declaration on apply rather than carried
|
|
33
|
+
* as a hunk, so promoting one member never conflicts with another member's
|
|
34
|
+
* uncommitted promotion (#4461: `--all` promotes a workspace in waves, see
|
|
35
|
+
* `./promote-waves.ts`).
|
|
36
|
+
*
|
|
37
|
+
* The stamp (`live-import -approve`) runs in the staging worktree's member
|
|
38
|
+
* directory, where `choudoufu init -backend=false` already installed the
|
|
39
|
+
* providers, so the member's own directory needs none (chant#4492).
|
|
40
|
+
*
|
|
41
|
+
* When `live-import -approve` fails after the kind change is written, the
|
|
42
|
+
* promote leaves a stamp record under `.chant/workspace-promote/` (#4485). A
|
|
43
|
+
* re-run finds the member already of kind `choudoufu` and the record, and
|
|
44
|
+
* retries the stamp ({@link retryPendingStamp}) rather than reporting it
|
|
45
|
+
* promoted or starting the next rung. The retry has no staging of its own to
|
|
46
|
+
* reuse, so it stages one first: a worktree at HEAD with the tree's changes to
|
|
47
|
+
* the member, and `choudoufu init -backend=false` in it. The record goes once
|
|
48
|
+
* a stamp passes.
|
|
49
|
+
*
|
|
23
50
|
* Commands run through an injectable runner, so a test never starts a binary.
|
|
24
51
|
*/
|
|
25
52
|
|
|
26
53
|
import { execFileSync, spawn } from "node:child_process";
|
|
27
|
-
import { existsSync, mkdirSync, realpathSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
54
|
+
import { copyFileSync, existsSync, mkdirSync, realpathSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
28
55
|
import { tmpdir } from "node:os";
|
|
29
|
-
import { join, relative, resolve, sep } from "node:path";
|
|
56
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
30
57
|
import { formatError, formatInfo, formatSuccess, formatWarning } from "../cli/format";
|
|
31
58
|
import type { CommandContext } from "../cli/registry";
|
|
59
|
+
import { contentDigest } from "../content-digest";
|
|
32
60
|
import { computePlanDigest } from "../lifecycle/plan-digest";
|
|
33
61
|
import { LIFECYCLE_LOCAL_NOTE, isLifecycleLocalNote } from "../lifecycle/local-note";
|
|
34
62
|
import { approveCommand, describeGateMismatch, evaluateGate, gateIsSealed, gitGateLedgerPort, type GateLedgerPort } from "../op/gate";
|
|
35
63
|
import { WORKSPACE_PROMOTE_GATE_OP } from "../op/gate-name";
|
|
64
|
+
import { parseLiveImportReport, type AdoptionReport } from "./adoption-report";
|
|
36
65
|
import { DECLARATION_FILES, readDeclaration } from "./declaration";
|
|
37
66
|
import { setProperty } from "./json-edit";
|
|
38
67
|
import { workingTree } from "./tree";
|
|
39
68
|
|
|
40
69
|
export const PROMOTE_PLAN_KIND = "workspace-promote";
|
|
41
70
|
export const PROMOTE_GATED_EXIT = 3;
|
|
42
|
-
const USAGE =
|
|
71
|
+
const USAGE = [
|
|
72
|
+
"chant workspace promote <member> [--state <terraform.tfstate>] [--lexicon <lexicon>] [--dry-run] [--output <patch file>] [--json]",
|
|
73
|
+
"chant workspace promote --all [--state-dir <dir>] [--state <member>=<terraform.tfstate>]... [--canary <member>] [--wave-size <n>] [--dry-run] [--json]",
|
|
74
|
+
].join("\n");
|
|
43
75
|
|
|
44
76
|
export class PromoteError extends Error {}
|
|
45
77
|
|
|
@@ -63,6 +95,8 @@ export interface CommandRun {
|
|
|
63
95
|
argv: string[];
|
|
64
96
|
/** Directory relative to the project root. */
|
|
65
97
|
cwd: string;
|
|
98
|
+
/** The `live-import` ratification report: its output is digested into the gate. */
|
|
99
|
+
report?: boolean;
|
|
66
100
|
}
|
|
67
101
|
export type PromoteRunner = (argv: string[], cwd: string) => Promise<{ exitCode: number; output: string }>;
|
|
68
102
|
|
|
@@ -77,13 +111,19 @@ export const spawnRunner: PromoteRunner = (argv, cwd) =>
|
|
|
77
111
|
child.on("close", (code) => done({ exitCode: code ?? 1, output: Buffer.concat(out).toString("utf-8") }));
|
|
78
112
|
});
|
|
79
113
|
|
|
114
|
+
/** `choudoufu init -backend=false` in the member's staging directory: the providers `live-import` reads each resource through (#4461). */
|
|
115
|
+
function stagingInit(member: { dir: string }): CommandRun {
|
|
116
|
+
return { label: "choudoufu init", argv: ["choudoufu", "init", "-input=false", "-backend=false", "-no-color"], cwd: member.dir };
|
|
117
|
+
}
|
|
118
|
+
|
|
80
119
|
/** The commands the rung runs in the staging worktree. */
|
|
81
120
|
export function stagingRuns(rung: Rung, member: { name: string; dir: string }, opts: { state?: string; lexicon?: string }): CommandRun[] {
|
|
82
121
|
if (rung.to === "choudoufu") {
|
|
83
122
|
if (!opts.state) throw new PromoteError(`promoting ${member.name} to choudoufu reads its state for the adoption report: pass --state <terraform.tfstate>`);
|
|
84
123
|
return [
|
|
124
|
+
stagingInit(member),
|
|
85
125
|
{ label: "choudoufu live-check", argv: ["choudoufu", "live-check"], cwd: member.dir },
|
|
86
|
-
{ label: "choudoufu live-import (report)", argv: ["choudoufu", "live-import", `-state=${opts.state}`, `-estate=${member.name}`], cwd: member.dir },
|
|
126
|
+
{ label: "choudoufu live-import (report)", argv: ["choudoufu", "live-import", `-state=${opts.state}`, `-estate=${member.name}`], cwd: member.dir, report: true },
|
|
87
127
|
];
|
|
88
128
|
}
|
|
89
129
|
const lexicon = opts.lexicon ?? (rung.from === "choudoufu" ? "terraform" : undefined);
|
|
@@ -97,6 +137,219 @@ export function followUpRuns(rung: Rung, member: { name: string; dir: string },
|
|
|
97
137
|
return [{ label: "choudoufu live-import -approve", argv: ["choudoufu", "live-import", `-state=${opts.state}`, `-estate=${member.name}`, "-approve"], cwd: member.dir }];
|
|
98
138
|
}
|
|
99
139
|
|
|
140
|
+
/** Where a promote keeps what a re-run needs, relative to the project root. */
|
|
141
|
+
export const PROMOTE_RECORD_DIR = ".chant/workspace-promote";
|
|
142
|
+
export const PENDING_STAMP_SCHEMA = "chant-workspace-promote-stamp/v1";
|
|
143
|
+
|
|
144
|
+
/** A stamp the kind change was written for and that did not pass (#4485). */
|
|
145
|
+
export interface PendingStamp {
|
|
146
|
+
schema: typeof PENDING_STAMP_SCHEMA;
|
|
147
|
+
member: string;
|
|
148
|
+
/** The member's directory, relative to the project root. */
|
|
149
|
+
dir: string;
|
|
150
|
+
/** The state `live-import -approve` read, absolute. */
|
|
151
|
+
state: string;
|
|
152
|
+
/** The follow-up that failed. */
|
|
153
|
+
failed: string;
|
|
154
|
+
/** ISO 8601. */
|
|
155
|
+
at: string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function pendingStampPath(root: string, member: string): string {
|
|
159
|
+
return join(root, PROMOTE_RECORD_DIR, `${member}.stamp.json`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** The stamp a promote of `member` left failed, or undefined when none is pending. */
|
|
163
|
+
export function readPendingStamp(root: string, member: string): PendingStamp | undefined {
|
|
164
|
+
const file = pendingStampPath(root, member);
|
|
165
|
+
if (!existsSync(file)) return undefined;
|
|
166
|
+
try {
|
|
167
|
+
const record = JSON.parse(readFileSync(file, "utf-8")) as PendingStamp;
|
|
168
|
+
return record.schema === PENDING_STAMP_SCHEMA && record.member === member ? record : undefined;
|
|
169
|
+
} catch {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function writePendingStamp(root: string, record: PendingStamp): void {
|
|
175
|
+
mkdirSync(join(root, PROMOTE_RECORD_DIR), { recursive: true });
|
|
176
|
+
writeFileSync(pendingStampPath(root, record.member), `${JSON.stringify(record, null, 2)}\n`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function clearPendingStamp(root: string, member: string): void {
|
|
180
|
+
rmSync(pendingStampPath(root, member), { force: true });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** The `live-import -approve` line to run by hand for a pending stamp. */
|
|
184
|
+
export function stampCommand(member: { name: string; dir: string }, state: string): string {
|
|
185
|
+
return `\`choudoufu live-import -state=${state} -estate=${member.name} -approve\` in ${member.dir || "."}`;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Run the stamps of the `choudoufu` rung's follow-up in `cwd`, the member's
|
|
190
|
+
* directory in a staging worktree whose `choudoufu init` installed the
|
|
191
|
+
* providers (chant#4492). Keep a {@link PendingStamp} in the tree when one
|
|
192
|
+
* fails and drop it when they pass. The result is `applied`, exit 0 when
|
|
193
|
+
* every stamp passed, else exit 1 with the failed follow-up named.
|
|
194
|
+
*/
|
|
195
|
+
async function stampMember(input: {
|
|
196
|
+
root: string;
|
|
197
|
+
/** The member's directory in the staging worktree, absolute. */
|
|
198
|
+
cwd: string;
|
|
199
|
+
member: { name: string; dir: string };
|
|
200
|
+
state: string | undefined;
|
|
201
|
+
run: PromoteRunner;
|
|
202
|
+
ran: { label: string; exitCode: number }[];
|
|
203
|
+
say: (m: string) => void;
|
|
204
|
+
}): Promise<{ exitCode: number; followUpFailed?: string; failureOutput?: string; followUpOutput?: string }> {
|
|
205
|
+
const rung: Rung = { from: "terraform", to: "choudoufu" };
|
|
206
|
+
let followUpOutput: string | undefined;
|
|
207
|
+
for (const step of followUpRuns(rung, input.member, { state: input.state })) {
|
|
208
|
+
const result = await input.run(step.argv, input.cwd);
|
|
209
|
+
input.ran.push({ label: step.label, exitCode: result.exitCode });
|
|
210
|
+
followUpOutput = result.output;
|
|
211
|
+
if (result.exitCode !== 0) {
|
|
212
|
+
const tail = result.output.trimEnd().split("\n").slice(-20).join("\n");
|
|
213
|
+
input.say(formatError({ message: `${step.label} failed after the patch was applied`, hint: tail }));
|
|
214
|
+
writePendingStamp(input.root, {
|
|
215
|
+
schema: PENDING_STAMP_SCHEMA,
|
|
216
|
+
member: input.member.name,
|
|
217
|
+
dir: input.member.dir,
|
|
218
|
+
state: input.state ?? "",
|
|
219
|
+
failed: step.label,
|
|
220
|
+
at: new Date().toISOString(),
|
|
221
|
+
});
|
|
222
|
+
input.say(formatInfo(`the stamp is kept as pending in ${join(PROMOTE_RECORD_DIR, `${input.member.name}.stamp.json`)}: run the same promote again to retry it, or ${stampCommand(input.member, input.state ?? "<terraform.tfstate>")}`));
|
|
223
|
+
return { exitCode: 1, followUpFailed: step.label, failureOutput: tail, followUpOutput };
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
clearPendingStamp(input.root, input.member.name);
|
|
227
|
+
return { exitCode: 0, ...(followUpOutput !== undefined ? { followUpOutput } : {}) };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Retry the stamp an earlier promote of `member` left failed (#4485), or
|
|
232
|
+
* undefined when none is pending. The member is already of kind
|
|
233
|
+
* `choudoufu`: its kind change was written, so only the stamp runs, against
|
|
234
|
+
* `state` when given, else the state the record names. The result is
|
|
235
|
+
* `applied`: exit 0 once the stamp passed, exit 1 with the failed follow-up
|
|
236
|
+
* when it failed again.
|
|
237
|
+
*/
|
|
238
|
+
export async function retryPendingStamp(opts: {
|
|
239
|
+
root: string;
|
|
240
|
+
member: string;
|
|
241
|
+
state?: string;
|
|
242
|
+
json?: boolean;
|
|
243
|
+
runner?: PromoteRunner;
|
|
244
|
+
}): Promise<PromoteResult | undefined> {
|
|
245
|
+
const root = realpathSync(resolve(opts.root));
|
|
246
|
+
const pending = readPendingStamp(root, opts.member);
|
|
247
|
+
if (!pending) return undefined;
|
|
248
|
+
const say = (m: string): void => {
|
|
249
|
+
if (!opts.json) console.error(m);
|
|
250
|
+
};
|
|
251
|
+
const state = opts.state ? resolve(opts.state) : pending.state || undefined;
|
|
252
|
+
if (!state) throw new PromoteError(`${opts.member}'s stamp is pending and its record names no state: pass --state <terraform.tfstate>`);
|
|
253
|
+
say(formatInfo(`${opts.member}: kind choudoufu, but the stamp ${pending.at} failed (${pending.failed}); retrying it`));
|
|
254
|
+
const run = opts.runner ?? spawnRunner;
|
|
255
|
+
const member = { name: opts.member, dir: pending.dir };
|
|
256
|
+
const ran: { label: string; exitCode: number }[] = [];
|
|
257
|
+
const done = { outcome: "applied", member: opts.member, from: "terraform", to: "choudoufu", ran, retriedStamp: true } as const;
|
|
258
|
+
// No staging is left from the promote that wrote the record, so stage one (chant#4492): the stamp reads
|
|
259
|
+
// each resource through its provider, and the member's own directory need not have them installed.
|
|
260
|
+
const staging = openStaging(root);
|
|
261
|
+
try {
|
|
262
|
+
const cwd = join(staging.project, member.dir);
|
|
263
|
+
mirrorMember(staging, member.dir);
|
|
264
|
+
mkdirSync(cwd, { recursive: true });
|
|
265
|
+
const init = stagingInit(member);
|
|
266
|
+
const installed = await run(init.argv, cwd);
|
|
267
|
+
ran.push({ label: init.label, exitCode: installed.exitCode });
|
|
268
|
+
if (installed.exitCode !== 0) {
|
|
269
|
+
const tail = installed.output.trimEnd().split("\n").slice(-20).join("\n");
|
|
270
|
+
say(formatError({ message: `${init.label} failed in the staging worktree, so the stamp was not retried`, hint: tail }));
|
|
271
|
+
say(formatInfo(`the stamp stays pending in ${join(PROMOTE_RECORD_DIR, `${member.name}.stamp.json`)}: run the same promote again to retry it`));
|
|
272
|
+
return { ...done, exitCode: 1, followUpFailed: init.label, failureOutput: tail };
|
|
273
|
+
}
|
|
274
|
+
const stamped = await stampMember({ root, cwd, member, state, run, ran, say });
|
|
275
|
+
if (stamped.exitCode === 0) say(formatSuccess(`stamped "${opts.member}"; its promotion to choudoufu is complete`));
|
|
276
|
+
return { ...done, ...stamped };
|
|
277
|
+
} finally {
|
|
278
|
+
staging.dispose();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** A git worktree at HEAD to stage a promote in, and the project's directory inside it. */
|
|
283
|
+
interface Staging {
|
|
284
|
+
repo: string;
|
|
285
|
+
head: string;
|
|
286
|
+
/** The project root relative to the repo, `/` between parts; empty when they are one. */
|
|
287
|
+
projectRel: string;
|
|
288
|
+
worktree: string;
|
|
289
|
+
/** The project root inside the worktree. */
|
|
290
|
+
project: string;
|
|
291
|
+
dispose(): void;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function openStaging(root: string): Staging {
|
|
295
|
+
let repo: string;
|
|
296
|
+
let head: string;
|
|
297
|
+
try {
|
|
298
|
+
repo = git(root, ["rev-parse", "--show-toplevel"]).trim();
|
|
299
|
+
head = git(root, ["rev-parse", "HEAD"]).trim();
|
|
300
|
+
} catch {
|
|
301
|
+
throw new PromoteError("chant workspace promote stages its change in a git worktree, so the project must be in a git repository with at least one commit");
|
|
302
|
+
}
|
|
303
|
+
const projectRel = relative(repo, root).split(sep).join("/");
|
|
304
|
+
const holder = mkdtempSync(join(tmpdir(), "chant-promote-"));
|
|
305
|
+
const worktree = join(holder, "wt");
|
|
306
|
+
const dispose = (): void => {
|
|
307
|
+
try {
|
|
308
|
+
git(repo, ["worktree", "remove", "--force", worktree]);
|
|
309
|
+
} catch {
|
|
310
|
+
// Fall through to the directory removal and a prune.
|
|
311
|
+
}
|
|
312
|
+
rmSync(holder, { recursive: true, force: true });
|
|
313
|
+
try {
|
|
314
|
+
git(repo, ["worktree", "prune"]);
|
|
315
|
+
} catch {
|
|
316
|
+
// Nothing to prune.
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
try {
|
|
320
|
+
git(repo, ["worktree", "add", "-q", "--detach", worktree, head]);
|
|
321
|
+
} catch (err) {
|
|
322
|
+
dispose();
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
325
|
+
return { repo, head, projectRel, worktree, project: projectRel ? join(worktree, projectRel) : worktree, dispose };
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Bring the tree's uncommitted changes to the member's directory into the
|
|
330
|
+
* staging worktree: a promote applied but not yet committed (the lock file
|
|
331
|
+
* `init` wrote, say) is what the stamp should read. Ignored files stay out.
|
|
332
|
+
*/
|
|
333
|
+
function mirrorMember(staging: Staging, dir: string): void {
|
|
334
|
+
const path = [staging.projectRel, dir].filter(Boolean).join("/") || ".";
|
|
335
|
+
const diff = git(staging.repo, ["diff", "--binary", "HEAD", "--", path]);
|
|
336
|
+
if (diff.trim()) {
|
|
337
|
+
const patchDir = mkdtempSync(join(tmpdir(), "chant-promote-patch-"));
|
|
338
|
+
try {
|
|
339
|
+
const file = join(patchDir, "member.patch");
|
|
340
|
+
writeFileSync(file, diff);
|
|
341
|
+
git(staging.worktree, ["apply", "--binary", "--whitespace=nowarn", file]);
|
|
342
|
+
} finally {
|
|
343
|
+
rmSync(patchDir, { recursive: true, force: true });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
for (const f of git(staging.repo, ["ls-files", "--others", "--exclude-standard", "-z", "--", path]).split("\0").filter(Boolean)) {
|
|
347
|
+
const to = join(staging.worktree, f);
|
|
348
|
+
mkdirSync(dirname(to), { recursive: true });
|
|
349
|
+
copyFileSync(join(staging.repo, f), to);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
100
353
|
function git(cwd: string, args: string[]): string {
|
|
101
354
|
return execFileSync("git", args, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], maxBuffer: 256 * 1024 * 1024 });
|
|
102
355
|
}
|
|
@@ -109,6 +362,8 @@ export interface PromoteOptions {
|
|
|
109
362
|
dryRun?: boolean;
|
|
110
363
|
output?: string;
|
|
111
364
|
json?: boolean;
|
|
365
|
+
/** Run by `promote --all` (#4461): print no JSON of its own, the wave summary does. */
|
|
366
|
+
nested?: boolean;
|
|
112
367
|
/** For tests. */
|
|
113
368
|
runner?: PromoteRunner;
|
|
114
369
|
ledger?: GateLedgerPort;
|
|
@@ -124,9 +379,27 @@ export interface PromoteResult {
|
|
|
124
379
|
to?: string;
|
|
125
380
|
digest?: string;
|
|
126
381
|
patch?: string;
|
|
382
|
+
/** Digest of the `live-import` report the gate binds (terraform to choudoufu). */
|
|
383
|
+
reportDigest?: string;
|
|
127
384
|
ran?: { label: string; exitCode: number }[];
|
|
385
|
+
/** The `terraform` to `choudoufu` rung's adoption report, from `live-import` without `-approve`. */
|
|
386
|
+
adoption?: AdoptionReport;
|
|
387
|
+
/** The label of the follow-up that failed after the patch was applied. */
|
|
388
|
+
followUpFailed?: string;
|
|
389
|
+
/** The last output of the failed check or follow-up. */
|
|
390
|
+
failureOutput?: string;
|
|
391
|
+
/** The follow-up's output when it ran (the stamp report). */
|
|
392
|
+
followUpOutput?: string;
|
|
393
|
+
/** Set when this run only retried the stamp an earlier one left failed (#4485). */
|
|
394
|
+
retriedStamp?: true;
|
|
128
395
|
}
|
|
129
396
|
|
|
397
|
+
/** What a staging writes that no patch carries: the providers and modules `init` installs (#4461). */
|
|
398
|
+
const NOT_STAGED = [":(exclude,glob)**/.terraform/**"];
|
|
399
|
+
|
|
400
|
+
/** The staging step whose output is the adoption report. */
|
|
401
|
+
const REPORT_STEP = "choudoufu live-import (report)";
|
|
402
|
+
|
|
130
403
|
function declarationFile(root: string): string {
|
|
131
404
|
const f = DECLARATION_FILES.find((n) => existsSync(join(root, n)));
|
|
132
405
|
if (!f) throw new PromoteError(`no ${DECLARATION_FILES.join(" or ")} in ${root}`);
|
|
@@ -151,74 +424,105 @@ export async function promoteCommand(opts: PromoteOptions): Promise<PromoteResul
|
|
|
151
424
|
const say = (m: string): void => {
|
|
152
425
|
if (!opts.json) console.error(m);
|
|
153
426
|
};
|
|
427
|
+
// #4485: the choudoufu rung is not done until its stamp passed; retry that before any next rung.
|
|
428
|
+
if (found.kind === "choudoufu" && !opts.dryRun) {
|
|
429
|
+
const retried = await retryPendingStamp({ root, member: found.name, ...(opts.state ? { state: opts.state } : {}), ...(opts.json !== undefined ? { json: opts.json } : {}), ...(opts.runner ? { runner: opts.runner } : {}) });
|
|
430
|
+
if (retried) {
|
|
431
|
+
if (opts.json && !opts.nested) console.log(JSON.stringify(retried, null, 2));
|
|
432
|
+
return retried;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
154
435
|
const rung = nextRung(found.kind);
|
|
155
436
|
if (!rung) {
|
|
156
437
|
say(formatInfo(`${found.name} is kind ${found.kind}, which has no rung above it on the ladder (terraform or other, choudoufu, chant)`));
|
|
157
438
|
return { outcome: "top-of-ladder", exitCode: 0, member: found.name, from: found.kind };
|
|
158
439
|
}
|
|
159
440
|
const member = { name: found.name, dir: found.dir === "." ? "" : found.dir };
|
|
160
|
-
|
|
441
|
+
// The staging runs in a worktree, so a relative --state would resolve there.
|
|
442
|
+
const state = opts.state ? resolve(opts.state) : undefined;
|
|
443
|
+
const steps = stagingRuns(rung, member, { ...opts, state });
|
|
444
|
+
const emitJson = opts.json && !opts.nested;
|
|
161
445
|
|
|
162
446
|
let repo: string;
|
|
163
|
-
let head: string;
|
|
164
447
|
try {
|
|
165
448
|
repo = git(root, ["rev-parse", "--show-toplevel"]).trim();
|
|
166
|
-
|
|
449
|
+
git(root, ["rev-parse", "HEAD"]);
|
|
167
450
|
} catch {
|
|
168
451
|
throw new PromoteError("chant workspace promote stages its change in a git worktree, so the project must be in a git repository with at least one commit");
|
|
169
452
|
}
|
|
170
453
|
const projectRel = relative(repo, root).split(sep).join("/");
|
|
171
454
|
const declFile = declarationFile(root);
|
|
172
|
-
|
|
455
|
+
// The declaration is not watched: the kind change is written into the
|
|
456
|
+
// tree's declaration on apply, so another member's uncommitted promotion
|
|
457
|
+
// there does not block this one (#4461).
|
|
458
|
+
const inProject = (p: string): string => [projectRel, p].filter(Boolean).join("/") || ".";
|
|
459
|
+
const watched = [inProject(member.dir), `:(exclude)${inProject(declFile)}`];
|
|
173
460
|
const dirty = git(repo, ["status", "--porcelain", "--untracked-files=all", "--", ...watched]).split("\n").filter(Boolean);
|
|
174
461
|
if (dirty.length > 0) {
|
|
175
462
|
throw new PromoteError(`${found.name} has uncommitted changes (${dirty.slice(0, 5).map((l) => l.slice(3)).join(", ")}). Commit them: promote stages from HEAD and applies its patch to the tree.`);
|
|
176
463
|
}
|
|
177
464
|
|
|
178
|
-
const
|
|
179
|
-
const worktree =
|
|
180
|
-
const dispose = (): void => {
|
|
181
|
-
try {
|
|
182
|
-
git(repo, ["worktree", "remove", "--force", worktree]);
|
|
183
|
-
} catch {
|
|
184
|
-
// Fall through to the directory removal and a prune.
|
|
185
|
-
}
|
|
186
|
-
rmSync(holder, { recursive: true, force: true });
|
|
187
|
-
try {
|
|
188
|
-
git(repo, ["worktree", "prune"]);
|
|
189
|
-
} catch {
|
|
190
|
-
// Nothing to prune.
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
|
|
465
|
+
const staging = openStaging(root);
|
|
466
|
+
const { worktree, project } = staging;
|
|
194
467
|
try {
|
|
195
|
-
git(repo, ["worktree", "add", "-q", "--detach", worktree, head]);
|
|
196
|
-
const project = projectRel ? join(worktree, projectRel) : worktree;
|
|
197
468
|
const ran: { label: string; exitCode: number }[] = [];
|
|
198
|
-
|
|
469
|
+
let adoption: AdoptionReport | undefined;
|
|
470
|
+
let reportOutput: string | undefined;
|
|
471
|
+
for (const step of steps) {
|
|
199
472
|
const cwd = join(project, step.cwd);
|
|
200
473
|
mkdirSync(cwd, { recursive: true });
|
|
201
474
|
const result = await run(step.argv, cwd);
|
|
202
475
|
ran.push({ label: step.label, exitCode: result.exitCode });
|
|
203
476
|
if (!opts.json) say(formatInfo(`${step.label}: exit ${result.exitCode}`));
|
|
477
|
+
if (step.label === REPORT_STEP) {
|
|
478
|
+
adoption = parseLiveImportReport(result.output);
|
|
479
|
+
// The report is what the gate asks a person to review, so it is shown, not only counted.
|
|
480
|
+
if (result.exitCode === 0 && result.output.trim()) say(result.output.trimEnd());
|
|
481
|
+
}
|
|
204
482
|
if (result.exitCode !== 0) {
|
|
205
|
-
|
|
483
|
+
const tail = result.output.trimEnd().split("\n").slice(-20).join("\n");
|
|
484
|
+
say(formatError({ message: `${step.label} failed in the staging worktree`, hint: tail }));
|
|
206
485
|
say(formatError({ message: "the promotion was not gated: its checks must pass first. The tree is unchanged." }));
|
|
207
|
-
if (
|
|
208
|
-
return { outcome: "checks-failed", exitCode: 1, member: found.name, from: rung.from, to: rung.to, ran };
|
|
486
|
+
if (emitJson) console.log(JSON.stringify({ outcome: "checks-failed", member: found.name, from: rung.from, to: rung.to, ran, ...(adoption ? { adoption } : {}), failed: { label: step.label, output: tail } }, null, 2));
|
|
487
|
+
return { outcome: "checks-failed", exitCode: 1, member: found.name, from: rung.from, to: rung.to, ran, ...(adoption ? { adoption } : {}), failureOutput: tail };
|
|
209
488
|
}
|
|
489
|
+
if (step.report) reportOutput = result.output;
|
|
210
490
|
}
|
|
491
|
+
const reportDigest = reportOutput === undefined ? undefined : contentDigest(reportOutput.trimEnd());
|
|
492
|
+
const declRel = inProject(declFile);
|
|
493
|
+
// What the staging wrote outside the declaration: the hunks the apply
|
|
494
|
+
// carries. The kind change is described by from and to. The providers
|
|
495
|
+
// `choudoufu init` installed under `.terraform/` are never part of it.
|
|
496
|
+
git(worktree, ["add", "-A", "--", ".", ...NOT_STAGED]);
|
|
497
|
+
const memberPatch = git(worktree, ["diff", "--cached", "--binary", "HEAD", "--", ".", `:(exclude)${declRel}`]);
|
|
211
498
|
const declPath = join(project, declFile);
|
|
212
499
|
writeFileSync(declPath, setMemberKind(readFileSync(declPath, "utf-8"), declFile, found.name, rung.to));
|
|
213
|
-
git(worktree, ["add", "-A"]);
|
|
500
|
+
git(worktree, ["add", "-A", "--", ".", ...NOT_STAGED]);
|
|
214
501
|
const patch = git(worktree, ["diff", "--cached", "--binary", "HEAD"]);
|
|
215
|
-
const digest = computePlanDigest(PROMOTE_PLAN_KIND, {
|
|
216
|
-
|
|
502
|
+
const digest = computePlanDigest(PROMOTE_PLAN_KIND, {
|
|
503
|
+
member: found.name,
|
|
504
|
+
from: rung.from,
|
|
505
|
+
to: rung.to,
|
|
506
|
+
patch: memberPatch,
|
|
507
|
+
...(reportDigest ? { report: reportDigest } : {}),
|
|
508
|
+
});
|
|
509
|
+
const base: PromoteResult = {
|
|
510
|
+
outcome: "dry-run",
|
|
511
|
+
exitCode: 0,
|
|
512
|
+
member: found.name,
|
|
513
|
+
from: rung.from,
|
|
514
|
+
to: rung.to,
|
|
515
|
+
digest,
|
|
516
|
+
patch,
|
|
517
|
+
ran,
|
|
518
|
+
...(reportDigest ? { reportDigest } : {}),
|
|
519
|
+
...(adoption ? { adoption } : {}),
|
|
520
|
+
};
|
|
217
521
|
const report = (outcome: PromoteOutcome, exitCode: number, extra: Record<string, unknown> = {}): PromoteResult => {
|
|
218
|
-
if (
|
|
219
|
-
return { ...base, outcome, exitCode };
|
|
522
|
+
if (emitJson) console.log(JSON.stringify({ outcome, member: found.name, from: rung.from, to: rung.to, digest, ...(reportDigest ? { reportDigest } : {}), ran, ...(adoption ? { adoption } : {}), ...extra }, null, 2));
|
|
523
|
+
return { ...base, outcome, exitCode, ...extra };
|
|
220
524
|
};
|
|
221
|
-
say(formatInfo(`${found.name}: ${rung.from} to ${rung.to}, patch ${digest}`));
|
|
525
|
+
say(formatInfo(`${found.name}: ${rung.from} to ${rung.to}, patch ${digest}${reportDigest ? `, live-import report ${reportDigest}` : ""}`));
|
|
222
526
|
if (opts.output) writeFileSync(resolve(opts.output), patch);
|
|
223
527
|
if (opts.dryRun) {
|
|
224
528
|
say(formatInfo("--dry-run: staged and checked; no gate recorded, the tree is unchanged"));
|
|
@@ -228,7 +532,7 @@ export async function promoteCommand(opts: PromoteOptions): Promise<PromoteResul
|
|
|
228
532
|
const check = await evaluateGate(opts.ledger ?? gitGateLedgerPort({ cwd: repo }), {
|
|
229
533
|
op: WORKSPACE_PROMOTE_GATE_OP,
|
|
230
534
|
gate: found.name,
|
|
231
|
-
description: `promote ${found.name} from ${rung.from} to ${rung.to}`,
|
|
535
|
+
description: `promote ${found.name} from ${rung.from} to ${rung.to}${reportDigest ? ` (live-import report ${reportDigest})` : ""}`,
|
|
232
536
|
planDigest: digest,
|
|
233
537
|
...(opts.now ? { now: opts.now } : {}),
|
|
234
538
|
});
|
|
@@ -247,36 +551,73 @@ export async function promoteCommand(opts: PromoteOptions): Promise<PromoteResul
|
|
|
247
551
|
return report("gated", PROMOTE_GATED_EXIT, { pending: check.pending });
|
|
248
552
|
}
|
|
249
553
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const file = join(patchDir, "promote.patch");
|
|
253
|
-
writeFileSync(file, patch);
|
|
554
|
+
if (memberPatch.trim()) {
|
|
555
|
+
const patchDir = mkdtempSync(join(tmpdir(), "chant-promote-patch-"));
|
|
254
556
|
try {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
557
|
+
const file = join(patchDir, "promote.patch");
|
|
558
|
+
writeFileSync(file, memberPatch);
|
|
559
|
+
try {
|
|
560
|
+
git(repo, ["apply", "--binary", "--whitespace=nowarn", file]);
|
|
561
|
+
} catch (err) {
|
|
562
|
+
const stderr = (err as { stderr?: Buffer | string }).stderr?.toString().trim();
|
|
563
|
+
throw new PromoteError(`the approved patch no longer applies to the tree${stderr ? `: ${stderr}` : ""}`);
|
|
564
|
+
}
|
|
565
|
+
} finally {
|
|
566
|
+
rmSync(patchDir, { recursive: true, force: true });
|
|
259
567
|
}
|
|
260
|
-
} finally {
|
|
261
|
-
rmSync(patchDir, { recursive: true, force: true });
|
|
262
568
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
569
|
+
const treeDecl = join(root, declFile);
|
|
570
|
+
writeFileSync(treeDecl, setMemberKind(readFileSync(treeDecl, "utf-8"), declFile, found.name, rung.to));
|
|
571
|
+
let followUpOutput: string | undefined;
|
|
572
|
+
if (rung.to === "choudoufu") {
|
|
573
|
+
// In the staging's member directory, where `choudoufu init` installed the providers (chant#4492).
|
|
574
|
+
const stamped = await stampMember({ root, cwd: join(project, member.dir), member, state, run, ran, say });
|
|
575
|
+
if (stamped.exitCode !== 0) {
|
|
576
|
+
return report("applied", 1, { followUpFailed: stamped.followUpFailed, failureOutput: stamped.failureOutput, followUpOutput: stamped.followUpOutput });
|
|
269
577
|
}
|
|
578
|
+
followUpOutput = stamped.followUpOutput;
|
|
270
579
|
}
|
|
271
580
|
say(formatSuccess(`applied the approved promotion of "${found.name}" to ${rung.to} (${digest}). Review and commit it.`));
|
|
272
|
-
return report("applied", 0);
|
|
581
|
+
return report("applied", 0, followUpOutput === undefined ? {} : { followUpOutput });
|
|
273
582
|
} finally {
|
|
274
|
-
dispose();
|
|
583
|
+
staging.dispose();
|
|
275
584
|
}
|
|
276
585
|
}
|
|
277
586
|
|
|
278
587
|
export async function runWorkspacePromote(ctx: CommandContext): Promise<number> {
|
|
279
588
|
const { args } = ctx;
|
|
589
|
+
const mapped = (args.statePaths ?? []).some((s) => s.includes("="));
|
|
590
|
+
if (args.all || args.stateDir || args.waveSize !== undefined || mapped) {
|
|
591
|
+
// #4461: a workspace of roots, in waves.
|
|
592
|
+
if (args.extraPositional) {
|
|
593
|
+
console.error(formatError({ message: "promote --all takes no member: name roots with --state <member>=<path>, the canary with --canary <member>", hint: USAGE }));
|
|
594
|
+
return 1;
|
|
595
|
+
}
|
|
596
|
+
if (args.output || args.lexicon) {
|
|
597
|
+
console.error(formatError({ message: "--output and --lexicon promote one member; promote --all adopts terraform roots into choudoufu and writes no patch file", hint: USAGE }));
|
|
598
|
+
return 1;
|
|
599
|
+
}
|
|
600
|
+
try {
|
|
601
|
+
const { parseStateMappings, promoteWavesCommand } = await import("./promote-waves");
|
|
602
|
+
const result = await promoteWavesCommand({
|
|
603
|
+
root: process.cwd(),
|
|
604
|
+
all: args.all,
|
|
605
|
+
states: parseStateMappings(args.statePaths ?? []),
|
|
606
|
+
stateDir: args.stateDir,
|
|
607
|
+
canary: args.canary,
|
|
608
|
+
waveSize: args.waveSize,
|
|
609
|
+
dryRun: args.dryRun,
|
|
610
|
+
json: args.json,
|
|
611
|
+
});
|
|
612
|
+
return result.exitCode;
|
|
613
|
+
} catch (err) {
|
|
614
|
+
if (err instanceof PromoteError) {
|
|
615
|
+
console.error(formatError({ message: err.message, hint: USAGE }));
|
|
616
|
+
return 1;
|
|
617
|
+
}
|
|
618
|
+
throw err;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
280
621
|
if (!args.extraPositional || args.extraPositional2) {
|
|
281
622
|
console.error(formatError({ message: "promote takes exactly one member", hint: USAGE }));
|
|
282
623
|
return 1;
|
|
@@ -13,7 +13,7 @@ import { CHANGES_ERROR_CODES, CHANGES_FINDING_CODES, COMMIT_LINK_FINDING_CODES }
|
|
|
13
13
|
import { MEMBER_RUN_REASON_CODES } from "./compose-graph";
|
|
14
14
|
import { COMPOSITES_ENVIRONMENT_REASON_CODES, COMPOSITES_ERROR_CODES, COMPOSITES_EXECUTOR_REASON_CODES, COMPOSITES_REASON_CODES, COMPOSITES_RUNTIME_REASON_CODES } from "./composites";
|
|
15
15
|
import { WORKSPACE_ERROR_CODES } from "./declaration";
|
|
16
|
-
import { GRAPH_ERROR_CODES } from "./graph-cli";
|
|
16
|
+
import { GRAPH_ERROR_CODES, GRAPH_INSTANCE_ROLLUP_CODES } from "./graph-cli";
|
|
17
17
|
import { INTENT_ERROR_CODES, INTENT_FINDING_CODES, INTENT_REASON_CODES, INTENT_WHY_CODES } from "./intent";
|
|
18
18
|
import { CHECK_CODES, CHECK_ERROR_CODES } from "./lineage-check";
|
|
19
19
|
import { GROUP_REASON_CODES, MEMBER_REASON_CODES } from "./ls";
|
|
@@ -53,6 +53,7 @@ import { TRUST_WRITE_ERROR_CODES } from "./trust/trust-write";
|
|
|
53
53
|
import { BOX_PUBLISH_ERROR_CODES } from "./box-publish";
|
|
54
54
|
import { WRITE_LOCK_ERROR_CODES } from "./write-lock-cli";
|
|
55
55
|
import { EXIT_CODES } from "./exit";
|
|
56
|
+
import { DRIFT_ERROR_CODES } from "./drift-cli";
|
|
56
57
|
import { WIP_ERROR_CODES, WIP_WRITE_ERROR_CODES } from "./wip";
|
|
57
58
|
import { CI_GREEN_ERROR_CODES } from "./ci-green";
|
|
58
59
|
import { ROTATION_REFUSAL_CODES } from "./trust/rotation";
|
|
@@ -70,6 +71,7 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
70
71
|
GROUP_REASON_CODES,
|
|
71
72
|
MEMBER_RUN_REASON_CODES,
|
|
72
73
|
GRAPH_ERROR_CODES,
|
|
74
|
+
GRAPH_INSTANCE_ROLLUP_CODES,
|
|
73
75
|
CHECK_CODES,
|
|
74
76
|
CHECK_ERROR_CODES,
|
|
75
77
|
BOX_FINDING_CODES,
|
|
@@ -148,6 +150,7 @@ const PER_COMMAND: Record<string, readonly string[]> = {
|
|
|
148
150
|
CAPABILITIES_ERROR_CODES,
|
|
149
151
|
CAPABILITY_SUPPORT_CODES,
|
|
150
152
|
EXIT_CODES,
|
|
153
|
+
DRIFT_ERROR_CODES,
|
|
151
154
|
};
|
|
152
155
|
|
|
153
156
|
/** Every string in an `enum` under a property named `code`, anywhere in a schema. */
|