@intentius/chant-lexicon-terraform 0.124.51 → 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/README.md +7 -6
- package/dist/__fixtures__/pr-loop/estate.component.d.ts +7 -0
- package/dist/__fixtures__/pr-loop/estate.component.d.ts.map +1 -0
- package/dist/__fixtures__/pr-loop/estate.component.js +7 -0
- package/dist/__fixtures__/report/generate.d.ts +26 -0
- package/dist/__fixtures__/report/generate.d.ts.map +1 -0
- package/dist/__fixtures__/report/generate.js +58 -0
- package/dist/applied-state.d.ts +27 -0
- package/dist/applied-state.d.ts.map +1 -0
- package/dist/applied-state.js +44 -0
- package/dist/backend-config.d.ts +53 -0
- package/dist/backend-config.d.ts.map +1 -0
- package/dist/backend-config.js +136 -0
- package/dist/behaviour/kinds.d.ts.map +1 -1
- package/dist/behaviour/kinds.js +4 -0
- package/dist/behaviour/predict.d.ts.map +1 -1
- package/dist/behaviour/predict.js +6 -2
- package/dist/behaviour/reference-catalog.d.ts +16 -5
- package/dist/behaviour/reference-catalog.d.ts.map +1 -1
- package/dist/behaviour/reference-catalog.js +16 -5
- package/dist/behaviour/request.d.ts.map +1 -1
- package/dist/behaviour/request.js +3 -2
- package/dist/changed-roots.d.ts +6 -4
- package/dist/changed-roots.d.ts.map +1 -1
- package/dist/changed-roots.js +14 -18
- package/dist/commands.d.ts +5 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +87 -4
- package/dist/components/capability-plugin.d.ts +65 -3
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/capability-plugin.js +197 -13
- package/dist/components/compose-group.d.ts +145 -0
- package/dist/components/compose-group.d.ts.map +1 -0
- package/dist/components/compose-group.js +407 -0
- package/dist/components/placeholder-preview.d.ts +78 -0
- package/dist/components/placeholder-preview.d.ts.map +1 -0
- package/dist/components/placeholder-preview.js +254 -0
- package/dist/compose/apply-events.d.ts +46 -0
- package/dist/compose/apply-events.d.ts.map +1 -0
- package/dist/compose/apply-events.js +77 -0
- package/dist/compose/estate.d.ts +194 -0
- package/dist/compose/estate.d.ts.map +1 -0
- package/dist/compose/estate.js +363 -0
- package/dist/compose/hcl.d.ts +99 -0
- package/dist/compose/hcl.d.ts.map +1 -0
- package/dist/compose/hcl.js +302 -0
- package/dist/compose/module-address.d.ts +24 -0
- package/dist/compose/module-address.d.ts.map +1 -0
- package/dist/compose/module-address.js +43 -0
- package/dist/compose/root.d.ts +127 -0
- package/dist/compose/root.d.ts.map +1 -0
- package/dist/compose/root.js +586 -0
- package/dist/compose/run.d.ts +183 -0
- package/dist/compose/run.d.ts.map +1 -0
- package/dist/compose/run.js +447 -0
- package/dist/compose/slice.d.ts +102 -0
- package/dist/compose/slice.d.ts.map +1 -0
- package/dist/compose/slice.js +249 -0
- package/dist/compose/state-address.d.ts +28 -0
- package/dist/compose/state-address.d.ts.map +1 -0
- package/dist/compose/state-address.js +154 -0
- package/dist/compose/state-merge.d.ts +52 -0
- package/dist/compose/state-merge.d.ts.map +1 -0
- package/dist/compose/state-merge.js +135 -0
- package/dist/compose.d.ts +179 -0
- package/dist/compose.d.ts.map +1 -0
- package/dist/compose.js +482 -0
- package/dist/composites/terraform-apply-op.d.ts.map +1 -1
- package/dist/composites/terraform-apply-op.js +7 -3
- package/dist/config.d.ts +59 -13
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +43 -9
- package/dist/describe-resources.d.ts +74 -12
- package/dist/describe-resources.d.ts.map +1 -1
- package/dist/describe-resources.js +374 -66
- package/dist/drift-read.d.ts +33 -0
- package/dist/drift-read.d.ts.map +1 -0
- package/dist/drift-read.js +243 -0
- package/dist/drift-record.d.ts +147 -0
- package/dist/drift-record.d.ts.map +1 -0
- package/dist/drift-record.js +383 -0
- package/dist/hcl/edges.d.ts.map +1 -1
- package/dist/hcl/edges.js +24 -1
- package/dist/hcl/files.d.ts +61 -0
- package/dist/hcl/files.d.ts.map +1 -0
- package/dist/hcl/files.js +221 -0
- package/dist/hcl/instances.d.ts +82 -0
- package/dist/hcl/instances.d.ts.map +1 -0
- package/dist/hcl/instances.js +390 -0
- package/dist/hcl/parse.d.ts +81 -9
- package/dist/hcl/parse.d.ts.map +1 -1
- package/dist/hcl/parse.js +114 -16
- package/dist/hcl/roots.d.ts.map +1 -1
- package/dist/hcl/roots.js +5 -0
- package/dist/hcl/suppressions.d.ts.map +1 -1
- package/dist/hcl/suppressions.js +8 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -2
- package/dist/integrity.json +3 -3
- package/dist/live-plan-reasons.d.ts +21 -0
- package/dist/live-plan-reasons.d.ts.map +1 -0
- package/dist/live-plan-reasons.js +47 -0
- package/dist/lsp/option-keys.d.ts.map +1 -1
- package/dist/lsp/option-keys.js +2 -0
- package/dist/manifest.json +1 -1
- package/dist/op/activities/index.d.ts +6 -2
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/index.js +5 -1
- package/dist/op/activities/live-detect.d.ts +4 -3
- package/dist/op/activities/live-detect.d.ts.map +1 -1
- package/dist/op/activities/live-detect.js +57 -32
- package/dist/op/activities/pin-rollout.d.ts +2 -0
- package/dist/op/activities/pin-rollout.d.ts.map +1 -1
- package/dist/op/activities/pin-rollout.js +1 -0
- package/dist/op/activities/terraform.d.ts +153 -5
- package/dist/op/activities/terraform.d.ts.map +1 -1
- package/dist/op/activities/terraform.js +205 -20
- package/dist/op/activity-contracts.d.ts +27 -0
- package/dist/op/activity-contracts.d.ts.map +1 -1
- package/dist/op/activity-contracts.js +19 -1
- package/dist/op/builders.d.ts +7 -1
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +9 -0
- package/dist/pin/edit.d.ts.map +1 -1
- package/dist/pin/edit.js +35 -0
- package/dist/pin/rollout.d.ts +2 -0
- package/dist/pin/rollout.d.ts.map +1 -1
- package/dist/pin/rollout.js +14 -11
- package/dist/plan-shape.d.ts +30 -0
- package/dist/plan-shape.d.ts.map +1 -0
- package/dist/plan-shape.js +125 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +32 -18
- package/dist/report.d.ts +216 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +666 -0
- package/dist/skills/chant-terraform.md +1 -1
- package/dist/state/azure-blob.d.ts +68 -0
- package/dist/state/azure-blob.d.ts.map +1 -0
- package/dist/state/azure-blob.js +201 -0
- package/dist/state/backend.d.ts +158 -0
- package/dist/state/backend.d.ts.map +1 -0
- package/dist/state/backend.js +406 -0
- package/dist/state/exec.d.ts +39 -0
- package/dist/state/exec.d.ts.map +1 -0
- package/dist/state/exec.js +80 -0
- package/dist/state/gcs.d.ts +62 -0
- package/dist/state/gcs.d.ts.map +1 -0
- package/dist/state/gcs.js +224 -0
- package/dist/state/index.d.ts +15 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +14 -0
- package/dist/state/locks.d.ts +105 -0
- package/dist/state/locks.d.ts.map +1 -0
- package/dist/state/locks.js +130 -0
- package/dist/state/object-store.d.ts +37 -0
- package/dist/state/object-store.d.ts.map +1 -0
- package/dist/state/object-store.js +20 -0
- package/dist/state/root-states.d.ts +131 -0
- package/dist/state/root-states.d.ts.map +1 -0
- package/dist/state/root-states.js +241 -0
- package/dist/state/s3.d.ts +68 -0
- package/dist/state/s3.d.ts.map +1 -0
- package/dist/state/s3.js +170 -0
- package/dist/state/store.d.ts +51 -0
- package/dist/state/store.d.ts.map +1 -0
- package/dist/state/store.js +185 -0
- package/dist/terragrunt/affected.d.ts.map +1 -1
- package/dist/terragrunt/affected.js +2 -1
- package/package.json +7 -3
- package/src/__fixtures__/ACCEPTANCE.md +69 -7
- package/src/__fixtures__/compose/apply-failed-in-app.jsonl +12 -0
- package/src/__fixtures__/compose/state-app.json +66 -0
- package/src/__fixtures__/compose/state-edge.json +40 -0
- package/src/__fixtures__/compose/state-net.json +58 -0
- package/src/__fixtures__/compose/three-app.plan.json +184 -0
- package/src/__fixtures__/compose/three-composed.plan.json +509 -0
- package/src/__fixtures__/compose/three-edge.plan.json +144 -0
- package/src/__fixtures__/compose/three-net.plan.json +174 -0
- package/src/__fixtures__/compose/unknown-composed.plan.json +228 -0
- package/src/__fixtures__/compose/working-after-apply.json +145 -0
- package/src/__fixtures__/config-blocks/app/main.tf +61 -0
- package/src/__fixtures__/config-blocks/app/modules/network/main.tf +4 -0
- package/src/__fixtures__/config-blocks/app-json/main.tf.json +39 -0
- package/src/__fixtures__/config-files/shadow/main.tf +3 -0
- package/src/__fixtures__/config-files/shadow/main.tofu +3 -0
- package/src/__fixtures__/config-files/shadow/other.tf +3 -0
- package/src/__fixtures__/config-files/tf/main.tf +11 -0
- package/src/__fixtures__/config-files/tf-json/main.tf.json +18 -0
- package/src/__fixtures__/config-files/tofu/main.tofu +11 -0
- package/src/__fixtures__/config-files/tofu-json/main.tofu.json +18 -0
- package/src/__fixtures__/config-files/tofu-only/main.tofu +3 -0
- package/src/__fixtures__/drift-record/README.md +11 -0
- package/src/__fixtures__/drift-record/live-plan-sections.json +27 -0
- package/src/__fixtures__/instance-forms/app/main.tf +110 -0
- package/src/__fixtures__/instance-forms/app/modules/svc/main.tf +3 -0
- package/src/__fixtures__/instance-vars/app/main.tf +52 -0
- package/src/__fixtures__/instance-vars/app/modules/app/main.tf +12 -0
- package/src/__fixtures__/instance-vars/app/modules/edge/main.tf +3 -0
- package/src/__fixtures__/instance-vars/app/terraform.tfvars +1 -0
- package/src/__fixtures__/live-module-keyed/live-graph.json +259 -0
- package/src/__fixtures__/live-module-keyed/live-plan.json +87 -0
- package/src/__fixtures__/live-module-keyed/root/estate.chdf.hcl +1 -0
- package/src/__fixtures__/live-module-keyed/root/main.tf +21 -0
- package/src/__fixtures__/live-module-keyed/root/modules/app/main.tf +17 -0
- package/src/__fixtures__/live-module-keyed/root/modules/edge/main.tf +7 -0
- package/src/__fixtures__/live-module-keyed/root/versions.tf +30 -0
- package/src/__fixtures__/live-module-keyed/show-state.json +146 -0
- package/src/__fixtures__/pr-loop/README.md +50 -0
- package/src/__fixtures__/pr-loop/chant.config.json +13 -0
- package/src/__fixtures__/pr-loop/estate.component.ts +10 -0
- package/src/__fixtures__/pr-loop/roots/a/main.tf +11 -0
- package/src/__fixtures__/pr-loop/roots/app/main.tf +19 -0
- package/src/__fixtures__/pr-loop/roots/b/main.tf +7 -0
- package/src/__fixtures__/pr-loop/roots/dns/main.tf +3 -0
- package/src/__fixtures__/pr-loop/roots/net/main.tf +7 -0
- package/src/__fixtures__/report/applied.show.json +51 -0
- package/src/__fixtures__/report/generate.ts +63 -0
- package/src/__fixtures__/report/plan.show.json +200 -0
- package/src/__fixtures__/report/tf-apply/change-set.json +170 -0
- package/src/__fixtures__/report/tf-apply/report.json +338 -0
- package/src/__fixtures__/report/tf-plan/change-set.json +170 -0
- package/src/__fixtures__/report/tf-plan/report.json +320 -0
- package/src/__fixtures__/three-cloud-azure.graph.json +290 -0
- package/src/applied-state.ts +52 -0
- package/src/backend-config.test.ts +105 -0
- package/src/backend-config.ts +133 -0
- package/src/behaviour/kinds.ts +4 -0
- package/src/behaviour/predict.ts +5 -2
- package/src/behaviour/reference-catalog.plugin.test.ts +65 -0
- package/src/behaviour/reference-catalog.ts +16 -5
- package/src/behaviour/request.ts +3 -2
- package/src/change-set-instances.test.ts +98 -0
- package/src/changed-roots.ts +14 -16
- package/src/commands.ts +84 -4
- package/src/components/capability-plugin.test.ts +172 -5
- package/src/components/capability-plugin.ts +212 -11
- package/src/components/change-set-graph.e2e.test.ts +11 -5
- package/src/components/compose-group.test.ts +486 -0
- package/src/components/compose-group.ts +489 -0
- package/src/components/demo-composed-roots.e2e.test.ts +440 -0
- package/src/components/member-outputs.test.ts +76 -0
- package/src/components/placeholder-preview.test.ts +147 -0
- package/src/components/placeholder-preview.ts +257 -0
- package/src/components/pr-loop-compose.tofu.e2e.test.ts +363 -0
- package/src/components/pr-loop.tofu.test.ts +112 -56
- package/src/compose/apply-events.test.ts +62 -0
- package/src/compose/apply-events.ts +100 -0
- package/src/compose/estate.choudoufu.e2e.test.ts +112 -0
- package/src/compose/estate.test.ts +421 -0
- package/src/compose/estate.ts +443 -0
- package/src/compose/hcl.ts +311 -0
- package/src/compose/module-address.ts +49 -0
- package/src/compose/root.test.ts +416 -0
- package/src/compose/root.ts +592 -0
- package/src/compose/run.test.ts +440 -0
- package/src/compose/run.tofu.test.ts +176 -0
- package/src/compose/run.ts +527 -0
- package/src/compose/slice.test.ts +184 -0
- package/src/compose/slice.ts +290 -0
- package/src/compose/state-address.ts +157 -0
- package/src/compose/state-merge.test.ts +131 -0
- package/src/compose/state-merge.ts +148 -0
- package/src/compose.test.ts +248 -0
- package/src/compose.ts +627 -0
- package/src/composites/terraform-apply-op.test.ts +9 -0
- package/src/composites/terraform-apply-op.ts +7 -3
- package/src/composites/terraform-pin-rollout-op.test.ts +2 -2
- package/src/config-file-listers.test.ts +265 -0
- package/src/config.ts +44 -9
- package/src/describe-resources.engine-facts.test.ts +412 -0
- package/src/describe-resources.live-module-keyed.test.ts +290 -0
- package/src/describe-resources.ts +416 -70
- package/src/drift-read.ts +284 -0
- package/src/drift-record.test.ts +223 -0
- package/src/drift-record.ts +455 -0
- package/src/hcl/config-blocks.test.ts +174 -0
- package/src/hcl/edges.ts +21 -1
- package/src/hcl/files.ts +234 -0
- package/src/hcl/instance-forms.test.ts +94 -0
- package/src/hcl/instances.test.ts +137 -0
- package/src/hcl/instances.ts +422 -0
- package/src/hcl/parse.test.ts +139 -1
- package/src/hcl/parse.ts +149 -16
- package/src/hcl/roots.ts +6 -0
- package/src/hcl/suppressions.ts +8 -2
- package/src/index.ts +76 -0
- package/src/live-plan-reasons.ts +54 -0
- package/src/lsp/completions.test.ts +1 -1
- package/src/lsp/option-keys.ts +2 -0
- package/src/op/activities/choudoufu-plan-set-op.test.ts +111 -0
- package/src/op/activities/index.ts +9 -0
- package/src/op/activities/live-detect.ts +55 -26
- package/src/op/activities/pin-rollout.ts +3 -0
- package/src/op/activities/registry.test.ts +2 -1
- package/src/op/activities/terraform.test.ts +55 -0
- package/src/op/activities/terraform.ts +266 -22
- package/src/op/activity-contracts.test.ts +1 -0
- package/src/op/activity-contracts.ts +24 -1
- package/src/op/builders.ts +14 -0
- package/src/pin/bundle.test.ts +2 -0
- package/src/pin/edit.ts +30 -0
- package/src/pin/rollout.ts +16 -11
- package/src/plan-shape.test.ts +148 -0
- package/src/plan-shape.ts +128 -0
- package/src/plugin.ts +33 -19
- package/src/report.test.ts +423 -0
- package/src/report.ts +752 -0
- package/src/signal-only-root.test.ts +72 -0
- package/src/skills/chant-terraform.md +1 -1
- package/src/state/azure-blob.ts +223 -0
- package/src/state/backend-verdict.test.ts +187 -0
- package/src/state/backend.test.ts +127 -0
- package/src/state/backend.ts +488 -0
- package/src/state/exec.ts +111 -0
- package/src/state/gcs.ts +254 -0
- package/src/state/index.ts +15 -0
- package/src/state/locks.test.ts +84 -0
- package/src/state/locks.ts +201 -0
- package/src/state/object-store.ts +35 -0
- package/src/state/root-states-floci.e2e.test.ts +66 -0
- package/src/state/root-states.test.ts +462 -0
- package/src/state/root-states.ts +309 -0
- package/src/state/s3.ts +193 -0
- package/src/state/store.ts +225 -0
- package/src/terragrunt/affected.ts +2 -1
- package/src/workspace-kinds.test.ts +4 -17
- package/workspace-kinds.json +1 -24
- package/dist/workspace-member.d.ts +0 -30
- package/dist/workspace-member.d.ts.map +0 -1
- package/dist/workspace-member.js +0 -91
- package/schemas/pulumi.schema.json +0 -34
- package/src/testdata/pulumi-member/Pulumi.yaml +0 -2
- package/src/testdata/pulumi-member/stack-export.json +0 -53
- package/src/testdata/pulumi-unexported/Pulumi.yaml +0 -2
- package/src/workspace-member.test.ts +0 -89
- package/src/workspace-member.ts +0 -126
|
@@ -44,10 +44,12 @@ import { tmpdir } from "node:os";
|
|
|
44
44
|
import { promisify } from "node:util";
|
|
45
45
|
import { resolve, dirname, join, relative, sep } from "node:path";
|
|
46
46
|
import { loadChantConfigUpward } from "@intentius/chant/config";
|
|
47
|
+
import { findWorkspaceRoot } from "@intentius/chant/project-root";
|
|
47
48
|
import { liveReadKey, memoLiveRead } from "@intentius/chant/live-read-session";
|
|
48
49
|
import { terraformPlanDigest } from "../../plan-digest.js";
|
|
49
50
|
import { choudoufuSetPlanParts, plannerForBinary, terraformChangeSetPart } from "../../change-set.js";
|
|
50
51
|
import { detectLiveEstate } from "./live-detect.js";
|
|
52
|
+
import { backendConfigValues } from "../../backend-config.js";
|
|
51
53
|
import { parseAdoptionCommands, readAdoptionLedger, renderAdoptionLedger, } from "../adoption.js";
|
|
52
54
|
const execAsync = promisify(exec);
|
|
53
55
|
/**
|
|
@@ -100,6 +102,34 @@ export const MIN_CHOUDOUFU_VERSION = "0.15.0";
|
|
|
100
102
|
* choudoufu#1754, and {@link choudoufuPlanSet} refuses it.
|
|
101
103
|
*/
|
|
102
104
|
export const MIN_CHOUDOUFU_WAVES_VERSION = "0.22.0";
|
|
105
|
+
/**
|
|
106
|
+
* The choudoufu release a composed run of estates needs (#4445): a root with
|
|
107
|
+
* no `live` block that calls estate directories as modules, planned and
|
|
108
|
+
* applied as one walk, with a `terraform_estate_outputs` read of another
|
|
109
|
+
* estate in the run answered inside it (choudoufu#2059, first released in
|
|
110
|
+
* v0.31.0). Only the composed estate run (`compose/estate.ts`) checks it;
|
|
111
|
+
* below it the members plan wave by wave. A dev build names no release and
|
|
112
|
+
* passes, as for the other floors.
|
|
113
|
+
*/
|
|
114
|
+
export const MIN_CHOUDOUFU_ESTATES_VERSION = "0.31.0";
|
|
115
|
+
/**
|
|
116
|
+
* The choudoufu release whose `live-graph -json -from-plan=<file>` prints the
|
|
117
|
+
* engine graph document (chant#4520's design section 4, choudoufu#2285), the
|
|
118
|
+
* one `describeResources()` reads engine facts from on a live root
|
|
119
|
+
* (chant#4528). choudoufu's changelog lists the command under
|
|
120
|
+
* `v0.32.0 (Unreleased)`, so this is the version it releases as. The chant
|
|
121
|
+
* side of the same contract, the first chant that writes those facts, is
|
|
122
|
+
* `ENGINE_FACTS_FLOOR` in core's engine-facts.ts, which is NEXT_RELEASE
|
|
123
|
+
* until the cut.
|
|
124
|
+
*
|
|
125
|
+
* Not a refusal. Facts are for people and never feed a decision, so a
|
|
126
|
+
* choudoufu without the command (a usage error, see
|
|
127
|
+
* {@link classifyLiveGraphFailure}) leaves `facts` absent with one note
|
|
128
|
+
* naming this version, and the rest of the read is unchanged. The check is
|
|
129
|
+
* the capability, not the version string: a local or dev build names a
|
|
130
|
+
* version below this or none at all, and still carries the command.
|
|
131
|
+
*/
|
|
132
|
+
export const MIN_CHOUDOUFU_GRAPH_VERSION = "0.32.0";
|
|
103
133
|
/**
|
|
104
134
|
* Where a choudoufu root's wave files live, relative to the project root:
|
|
105
135
|
* `<root>/plan-set.json` (the set plan document chant planned and the
|
|
@@ -151,16 +181,21 @@ export function terraformEnvironment(root) {
|
|
|
151
181
|
...(root?.workspace ? { TF_WORKSPACE: root.workspace } : {}),
|
|
152
182
|
};
|
|
153
183
|
}
|
|
154
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* `terraform init`, with the root's `backendConfigFiles` as
|
|
186
|
+
* `-backend-config=<path>` flags and then its `backendConfig` as
|
|
187
|
+
* `-backend-config=k=v` flags (chant#4459): init applies later flags over
|
|
188
|
+
* earlier ones, so a pair overrides a file. A path is passed as written; init
|
|
189
|
+
* runs in the root's directory, which a relative one resolves against.
|
|
190
|
+
*/
|
|
155
191
|
export function terraformInitCommand(opts) {
|
|
156
192
|
const parts = [opts.binary, "init", "-input=false"];
|
|
157
193
|
if (opts.upgrade)
|
|
158
194
|
parts.push("-upgrade");
|
|
159
195
|
if (opts.reconfigure)
|
|
160
196
|
parts.push("-reconfigure");
|
|
161
|
-
for (const
|
|
162
|
-
parts.push(`-backend-config=${quoteArg(
|
|
163
|
-
}
|
|
197
|
+
for (const value of backendConfigValues(opts))
|
|
198
|
+
parts.push(`-backend-config=${quoteArg(value)}`);
|
|
164
199
|
return parts.join(" ");
|
|
165
200
|
}
|
|
166
201
|
/**
|
|
@@ -229,6 +264,39 @@ export function choudoufuLivePlanCommand(opts) {
|
|
|
229
264
|
parts.push(`-estate=${quoteArg(opts.estate)}`);
|
|
230
265
|
return parts.join(" ");
|
|
231
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* `live-graph -json -from-plan=<file> [-estate=<estate>]` (choudoufu#2285).
|
|
269
|
+
* No `DIR` argument: like {@link choudoufuLiveCheckCommand}, the activity
|
|
270
|
+
* runs in the root directory, which is DIR's default. `-estate` follows
|
|
271
|
+
* {@link choudoufuLivePlanCommand}'s rule: only for a root that does not
|
|
272
|
+
* name its own estate. `-history` is never passed: record versions take a
|
|
273
|
+
* listing per record and `s3:ListBucketVersions`, and an observation read
|
|
274
|
+
* has no use for them (the #4520 ruling, Q6: opt-in).
|
|
275
|
+
*/
|
|
276
|
+
export function choudoufuLiveGraphCommand(opts) {
|
|
277
|
+
const parts = [opts.binary, "live-graph", "-json", `-from-plan=${quoteArg(opts.fromPlan)}`];
|
|
278
|
+
if (opts.estate !== undefined)
|
|
279
|
+
parts.push(`-estate=${quoteArg(opts.estate)}`);
|
|
280
|
+
return parts.join(" ");
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Whether a failed `live-graph` run is a choudoufu that has no such command
|
|
284
|
+
* or flag (`"unsupported"`), or a real failure (`"failed"`). Older builds
|
|
285
|
+
* answer an unknown command two ways: the new CLI prints `OpenTofu has no
|
|
286
|
+
* command named "live-graph"` and exits 1 (cmd/choudoufu/command_main.go),
|
|
287
|
+
* and the older mitchellh/cli path prints its usage and exits 127. A build
|
|
288
|
+
* whose `live-graph` predates `-from-plan` fails the flag parse with `flag
|
|
289
|
+
* provided but not defined`.
|
|
290
|
+
*/
|
|
291
|
+
export function classifyLiveGraphFailure(code, output) {
|
|
292
|
+
if (code === 127)
|
|
293
|
+
return "unsupported";
|
|
294
|
+
if (/no command named "?live-graph"?/i.test(output))
|
|
295
|
+
return "unsupported";
|
|
296
|
+
if (/flag provided but not defined: -(?:from-plan|json|estate)\b/.test(output))
|
|
297
|
+
return "unsupported";
|
|
298
|
+
return "failed";
|
|
299
|
+
}
|
|
232
300
|
/** `live-ls -estate=<estate> -json [-consistent]`. */
|
|
233
301
|
export function choudoufuLiveLsCommand(opts) {
|
|
234
302
|
const parts = [opts.binary, "live-ls", `-estate=${quoteArg(opts.estate)}`, "-json"];
|
|
@@ -477,8 +545,8 @@ function report(stdout, stderr) {
|
|
|
477
545
|
}
|
|
478
546
|
// ── Activities ──────────────────────────────────────────────────────────────
|
|
479
547
|
/**
|
|
480
|
-
* `terraform init` in the named root, with the root's `
|
|
481
|
-
* as `-backend-config` flags. Uses the longInfra profile: init downloads
|
|
548
|
+
* `terraform init` in the named root, with the root's `backendConfigFiles` and
|
|
549
|
+
* `backendConfig` supplied as `-backend-config` flags. Uses the longInfra profile: init downloads
|
|
482
550
|
* providers and modules, a network call of unpredictable size.
|
|
483
551
|
*/
|
|
484
552
|
export async function terraformInit(args, signal) {
|
|
@@ -486,16 +554,53 @@ export async function terraformInit(args, signal) {
|
|
|
486
554
|
const cmd = terraformInitCommand({
|
|
487
555
|
binary,
|
|
488
556
|
...(root.backendConfig ? { backendConfig: root.backendConfig } : {}),
|
|
557
|
+
...(root.backendConfigFiles ? { backendConfigFiles: root.backendConfigFiles } : {}),
|
|
489
558
|
...(args.upgrade ? { upgrade: true } : {}),
|
|
490
559
|
...(args.reconfigure ? { reconfigure: true } : {}),
|
|
491
560
|
});
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
561
|
+
// Known once the root resolves, before init runs (chant#4512), so a failed
|
|
562
|
+
// init still publishes them and the ledger names the root it was for.
|
|
563
|
+
const rootPath = workspaceRelativePath(dir);
|
|
564
|
+
const result = { dir, ...(root.workspace ? { workspace: root.workspace } : {}), ...(rootPath !== undefined ? { rootPath } : {}) };
|
|
565
|
+
let out;
|
|
566
|
+
try {
|
|
567
|
+
out = await run(cmd, dir, terraformEnvironment(root), signal);
|
|
568
|
+
}
|
|
569
|
+
catch (err) {
|
|
570
|
+
throw withKnownOutputs(err, result);
|
|
571
|
+
}
|
|
572
|
+
report(out.stdout, out.stderr);
|
|
573
|
+
return result;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* `err` carrying `outputs` as the outputs the activity knew when it failed
|
|
577
|
+
* (chant#4512): the `knownOutputs` property core's executor reads a failed
|
|
578
|
+
* step's outcome attributes from (core's `withKnownOutputs`). It is set here
|
|
579
|
+
* rather than imported so the lexicon needs no newer core; an older executor
|
|
580
|
+
* reads the error as any other failure.
|
|
581
|
+
*/
|
|
582
|
+
function withKnownOutputs(err, outputs) {
|
|
583
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
584
|
+
return Object.assign(e, { knownOutputs: outputs });
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* `dir` relative to the chant workspace that holds it, `/`-separated, or
|
|
588
|
+
* undefined outside a workspace or outside its root (chant#4482). The
|
|
589
|
+
* workspace root `"."` stands for itself.
|
|
590
|
+
*/
|
|
591
|
+
export function workspaceRelativePath(dir) {
|
|
592
|
+
const found = findWorkspaceRoot(dir);
|
|
593
|
+
if (!found)
|
|
594
|
+
return undefined;
|
|
595
|
+
const rel = relative(found.dir, dir);
|
|
596
|
+
if (rel.startsWith(".."))
|
|
597
|
+
return undefined;
|
|
598
|
+
return rel === "" ? "." : rel.split(sep).join("/");
|
|
495
599
|
}
|
|
496
600
|
/**
|
|
497
601
|
* `terraform plan -detailed-exitcode -out=<planFile>` in the named root, then
|
|
498
|
-
* `terraform show` over the written plan in both `-json` and `-no-color` form
|
|
602
|
+
* `terraform show` over the written plan in both `-json` and `-no-color` form
|
|
603
|
+
* (`-json` alone with `text: false`).
|
|
499
604
|
*
|
|
500
605
|
* The exit code is the answer, not an error condition: 0 is a plan with no
|
|
501
606
|
* changes, 2 is a plan with changes, and anything else, 1 included, is a
|
|
@@ -538,14 +643,14 @@ export async function terraformPlan(args, signal) {
|
|
|
538
643
|
changed = true;
|
|
539
644
|
}
|
|
540
645
|
const jsonRun = await run(terraformShowCommand({ binary, json: true, planFile }), dir, env, signal);
|
|
541
|
-
const
|
|
646
|
+
const text = args.text === false ? "" : (await run(terraformShowCommand({ binary, json: false, planFile }), dir, env, signal)).stdout;
|
|
542
647
|
const json = JSON.parse(jsonRun.stdout);
|
|
543
648
|
return {
|
|
544
649
|
changed,
|
|
545
650
|
planFile,
|
|
546
651
|
dir,
|
|
547
652
|
json,
|
|
548
|
-
text
|
|
653
|
+
text,
|
|
549
654
|
planDigest: terraformPlanDigest(json),
|
|
550
655
|
changeSet: terraformChangeSetPart({
|
|
551
656
|
member: args.root,
|
|
@@ -629,7 +734,10 @@ export async function terraformApply(args, signal) {
|
|
|
629
734
|
* asked for the values to hand them on.
|
|
630
735
|
*/
|
|
631
736
|
export async function terraformOutputs(args, signal) {
|
|
632
|
-
|
|
737
|
+
return outputsIn(await resolveRoot(args, signal), signal);
|
|
738
|
+
}
|
|
739
|
+
/** `<binary> output -json` in a resolved root, as `{ name: value }`. */
|
|
740
|
+
async function outputsIn({ binary, root, dir }, signal) {
|
|
633
741
|
const { stdout } = await run(`${binary} output -json`, dir, terraformEnvironment(root), signal);
|
|
634
742
|
const parsed = JSON.parse(stdout || "{}");
|
|
635
743
|
return Object.fromEntries(Object.entries(parsed).map(([name, entry]) => [name, entry?.value]));
|
|
@@ -694,7 +802,7 @@ export async function choudoufuWaveRoot(args, signal) {
|
|
|
694
802
|
if (resolved.root.varFiles && resolved.root.varFiles.length > 0) {
|
|
695
803
|
return { wave: false, reason: "the root has var files, which live-plan-set does not take" };
|
|
696
804
|
}
|
|
697
|
-
if (resolved.root.backendConfig && Object.keys(resolved.root.backendConfig).length > 0) {
|
|
805
|
+
if ((resolved.root.backendConfig && Object.keys(resolved.root.backendConfig).length > 0) || (resolved.root.backendConfigFiles?.length ?? 0) > 0) {
|
|
698
806
|
return { wave: false, reason: "the root has backend config, which live-plan-set does not take" };
|
|
699
807
|
}
|
|
700
808
|
const root = choudoufuSetRootPath(resolved.projectRoot, resolved.dir);
|
|
@@ -764,15 +872,18 @@ function fromProject(projectRoot, path) {
|
|
|
764
872
|
* `live-wave-apply` hands back to choudoufu with the set digest.
|
|
765
873
|
*/
|
|
766
874
|
export async function choudoufuPlanSet(args, signal) {
|
|
767
|
-
|
|
875
|
+
return planSetIn(await resolveRoot(args, signal), args.root, signal);
|
|
876
|
+
}
|
|
877
|
+
/** {@link choudoufuPlanSet} over a resolved root, `key` naming it in errors, in the waves directory and as the change-set member. */
|
|
878
|
+
async function planSetIn(resolved, key, signal) {
|
|
768
879
|
const { binary, root, dir, projectRoot } = resolved;
|
|
769
880
|
if (binary !== "choudoufu")
|
|
770
|
-
throw new Error(`choudoufuPlanSet: root "${
|
|
881
|
+
throw new Error(`choudoufuPlanSet: root "${key}" runs ${binary}, not choudoufu`);
|
|
771
882
|
await ensureChoudoufuWavesVersion(binary, signal);
|
|
772
883
|
const rootPath = choudoufuSetRootPath(projectRoot, dir);
|
|
773
884
|
if (rootPath === undefined)
|
|
774
|
-
throw new Error(`choudoufuPlanSet: root "${
|
|
775
|
-
const wavesDir = choudoufuWavesDir(projectRoot,
|
|
885
|
+
throw new Error(`choudoufuPlanSet: root "${key}" (${dir}) is not inside ${projectRoot}`);
|
|
886
|
+
const wavesDir = choudoufuWavesDir(projectRoot, key);
|
|
776
887
|
mkdirSync(wavesDir, { recursive: true });
|
|
777
888
|
const cmd = choudoufuPlanSetCommand({ binary, root: rootPath, outDir: fromProject(projectRoot, join(wavesDir, "out")) });
|
|
778
889
|
let stdout;
|
|
@@ -790,11 +901,42 @@ export async function choudoufuPlanSet(args, signal) {
|
|
|
790
901
|
report("", failure.stderr ?? "");
|
|
791
902
|
stdout = failure.stdout ?? "";
|
|
792
903
|
}
|
|
793
|
-
const parsed = parseChoudoufuPlanSet(stdout, { member:
|
|
904
|
+
const parsed = parseChoudoufuPlanSet(stdout, { member: key, root: rootPath });
|
|
794
905
|
const planSetFile = join(wavesDir, "plan-set.json");
|
|
795
906
|
writeFileSync(planSetFile, stdout);
|
|
796
907
|
return { ...parsed, planSetFile, root: rootPath };
|
|
797
908
|
}
|
|
909
|
+
async function resolveMemberRoot(args, signal) {
|
|
910
|
+
const binary = "choudoufu";
|
|
911
|
+
await ensureChoudoufuVersion(binary, signal);
|
|
912
|
+
const dir = resolve(args.dir);
|
|
913
|
+
const estate = detectLiveEstate(dir);
|
|
914
|
+
return { binary, root: { dir }, dir, ...(estate !== undefined ? { estate } : {}), live: estate !== undefined, projectRoot: resolve(args.projectRoot) };
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* The member's outputs as applied (#4455): `choudoufu init`, then `choudoufu
|
|
918
|
+
* output -json` in its directory, the read the `terraform-apply` capability's
|
|
919
|
+
* `outputs` makes for a root. A live estate's outputs come from its record
|
|
920
|
+
* store.
|
|
921
|
+
*/
|
|
922
|
+
export async function choudoufuMemberOutputs(args, signal) {
|
|
923
|
+
const resolved = await resolveMemberRoot(args, signal);
|
|
924
|
+
const { stdout, stderr } = await run(terraformInitCommand({ binary: resolved.binary }), resolved.dir, terraformEnvironment(resolved.root), signal);
|
|
925
|
+
report(stdout, stderr);
|
|
926
|
+
return outputsIn(resolved, signal);
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* The member planned as a one-root set (#4455), the way a choudoufu root in
|
|
930
|
+
* a gated wave is ({@link choudoufuPlanSet}): `live-plan-set -json` from
|
|
931
|
+
* `projectRoot`. The document's embedded plan carries `planned_values` and
|
|
932
|
+
* `output_changes`, which say what the member's outputs will be.
|
|
933
|
+
*/
|
|
934
|
+
export async function choudoufuMemberPlanSet(args, signal) {
|
|
935
|
+
const resolved = await resolveMemberRoot(args, signal);
|
|
936
|
+
if (!resolved.live)
|
|
937
|
+
throw new Error(`choudoufu member "${args.member}" (${resolved.dir}) declares no live estate, so live-plan-set cannot plan it`);
|
|
938
|
+
return planSetIn(resolved, args.member, signal);
|
|
939
|
+
}
|
|
798
940
|
/**
|
|
799
941
|
* The resume file to hand choudoufu for `setDigest`, from what an earlier
|
|
800
942
|
* attempt carried, or `undefined`. choudoufu refuses a resume file written
|
|
@@ -958,6 +1100,7 @@ export function terraformInitLine(opts) {
|
|
|
958
1100
|
const init = terraformInitCommand({
|
|
959
1101
|
binary: opts.binary,
|
|
960
1102
|
...(opts.backendConfig ? { backendConfig: opts.backendConfig } : {}),
|
|
1103
|
+
...(opts.backendConfigFiles ? { backendConfigFiles: opts.backendConfigFiles } : {}),
|
|
961
1104
|
});
|
|
962
1105
|
return init.replace(`${opts.binary} init`, `${opts.binary} -chdir=${quoteArg(opts.dir)} init`);
|
|
963
1106
|
}
|
|
@@ -1019,7 +1162,12 @@ export function rootIsInitialised(dir, env = process.env) {
|
|
|
1019
1162
|
export async function terraformPlanRead(args, signal) {
|
|
1020
1163
|
const { binary, root, dir } = await resolveRoot(args, signal);
|
|
1021
1164
|
const env = terraformEnvironment(root);
|
|
1022
|
-
const initLine = terraformInitLine({
|
|
1165
|
+
const initLine = terraformInitLine({
|
|
1166
|
+
binary,
|
|
1167
|
+
dir,
|
|
1168
|
+
...(root.backendConfig ? { backendConfig: root.backendConfig } : {}),
|
|
1169
|
+
...(root.backendConfigFiles ? { backendConfigFiles: root.backendConfigFiles } : {}),
|
|
1170
|
+
});
|
|
1023
1171
|
const notInitialised = (detail) => new TerraformPlanReadError("not-initialised", `terraform.roots.${args.root} (${dir}) ${detail}: run \`${initLine}\` first. chant never runs init on a read, since init writes into the root.`, dir, initLine);
|
|
1024
1172
|
if (!rootIsInitialised(dir, { ...process.env, ...env }))
|
|
1025
1173
|
throw notInitialised("has never been initialised");
|
|
@@ -1255,6 +1403,43 @@ export async function choudoufuLivePlan(args, signal) {
|
|
|
1255
1403
|
...parseChoudoufuPlanSummary(text),
|
|
1256
1404
|
};
|
|
1257
1405
|
}
|
|
1406
|
+
/**
|
|
1407
|
+
* `choudoufu live-graph -json -from-plan=<file>` (choudoufu#2285, read by
|
|
1408
|
+
* chant#4528): the root's graph as one engine graph document, its facts taken
|
|
1409
|
+
* from a `live-plan -json` document this process already read. No second live
|
|
1410
|
+
* read: choudoufu builds the graph from the configuration and that file
|
|
1411
|
+
* alone, starts no provider and calls no cloud, so facts and verdicts come
|
|
1412
|
+
* from the same refresh (choudoufu #1014).
|
|
1413
|
+
*
|
|
1414
|
+
* A usage error ({@link classifyLiveGraphFailure}) resolves `supported:
|
|
1415
|
+
* false` rather than throwing, since the caller degrades to no facts; any
|
|
1416
|
+
* other failure throws with choudoufu's output. Warnings (an empty scope
|
|
1417
|
+
* estate, a plan without `observed_at`) go to stderr and are echoed like
|
|
1418
|
+
* every other activity's.
|
|
1419
|
+
*/
|
|
1420
|
+
export async function choudoufuLiveGraph(args, signal) {
|
|
1421
|
+
const resolved = await resolveRoot(args, signal);
|
|
1422
|
+
const { binary, dir } = resolved;
|
|
1423
|
+
const env = terraformEnvironment(resolved.root);
|
|
1424
|
+
const estateFlag = resolved.estate === undefined && args.estate !== undefined ? { estate: args.estate } : {};
|
|
1425
|
+
const cmd = choudoufuLiveGraphCommand({ binary, fromPlan: args.fromPlan, ...estateFlag });
|
|
1426
|
+
try {
|
|
1427
|
+
const { stdout, stderr } = await run(cmd, dir, env, signal);
|
|
1428
|
+
if (stderr)
|
|
1429
|
+
console.error(stderr);
|
|
1430
|
+
return { supported: true, json: JSON.parse(liveDocumentFrom(stdout)), dir };
|
|
1431
|
+
}
|
|
1432
|
+
catch (err) {
|
|
1433
|
+
const failure = err;
|
|
1434
|
+
if (typeof failure.code !== "number")
|
|
1435
|
+
throw err;
|
|
1436
|
+
const output = `${failure.stderr ?? ""}\n${failure.stdout ?? ""}`;
|
|
1437
|
+
const detail = output.trim().split("\n").find((line) => line.trim() !== "")?.trim() ?? `exit ${failure.code}`;
|
|
1438
|
+
if (classifyLiveGraphFailure(failure.code, output) === "unsupported")
|
|
1439
|
+
return { supported: false, detail, dir };
|
|
1440
|
+
throw new Error(`${binary} live-graph failed in ${dir} (exit ${failure.code})${detail ? `\n${output.trim()}` : ""}`);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1258
1443
|
/**
|
|
1259
1444
|
* `choudoufu live-ls -estate=<estate> -json [-consistent]`: every resource
|
|
1260
1445
|
* the account holds under the estate, read straight from the Resource Groups
|
|
@@ -37,6 +37,7 @@ export declare const terraformInitContract: import("@intentius/chant/op").Activi
|
|
|
37
37
|
}, {
|
|
38
38
|
dir: string;
|
|
39
39
|
workspace?: string | undefined;
|
|
40
|
+
rootPath?: string | undefined;
|
|
40
41
|
}>;
|
|
41
42
|
export declare const terraformPlanContract: import("@intentius/chant/op").ActivityContract<{
|
|
42
43
|
root: string;
|
|
@@ -155,6 +156,32 @@ export declare const choudoufuAdoptContract: import("@intentius/chant/op").Activ
|
|
|
155
156
|
ambiguous: number;
|
|
156
157
|
dir: string;
|
|
157
158
|
}>;
|
|
159
|
+
/**
|
|
160
|
+
* `choudoufuPlanSet` (#4483): one live choudoufu root planned as a one-root
|
|
161
|
+
* set. `changeSet` is the root's part, the field an Op hands to
|
|
162
|
+
* `composeChangeSet`; `planDigest` is what a gate binds; `planSetFile` and
|
|
163
|
+
* `setDigest` are what a later `live-wave-apply` takes.
|
|
164
|
+
*/
|
|
165
|
+
export declare const choudoufuPlanSetContract: import("@intentius/chant/op").ActivityContract<{
|
|
166
|
+
root: string;
|
|
167
|
+
cwd?: string | undefined;
|
|
168
|
+
}, {
|
|
169
|
+
setDigest: string;
|
|
170
|
+
rootDigest: string;
|
|
171
|
+
planDigest: string;
|
|
172
|
+
changed: boolean;
|
|
173
|
+
json: unknown;
|
|
174
|
+
changeSet: {
|
|
175
|
+
member: {
|
|
176
|
+
[x: string]: unknown;
|
|
177
|
+
member: string;
|
|
178
|
+
planDigest: string | null;
|
|
179
|
+
};
|
|
180
|
+
entries: unknown[];
|
|
181
|
+
};
|
|
182
|
+
planSetFile: string;
|
|
183
|
+
root: string;
|
|
184
|
+
}>;
|
|
158
185
|
/**
|
|
159
186
|
* `terraformPinRollout` (#3189). It names no `terraform.roots` key: a rollout
|
|
160
187
|
* moves a module's pin across many roots, found by directory, so it carries no
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-contracts.d.ts","sourceRoot":"","sources":["../../src/op/activity-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AA+BH,eAAO,MAAM,qBAAqB
|
|
1
|
+
{"version":3,"file":"activity-contracts.d.ts","sourceRoot":"","sources":["../../src/op/activity-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AA+BH,eAAO,MAAM,qBAAqB;;;;;;;;;EAUjC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;EAoBjC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;EAWlC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;EAYjC,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;EAwBrC,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;EASnC,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;EAKtC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;EAgBlC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;EAcpC,CAAC;AAKF;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BvC,CAAC"}
|
|
@@ -57,7 +57,9 @@ export const terraformInitContract = activityContract("terraformInit", z.strictO
|
|
|
57
57
|
...rootArgs,
|
|
58
58
|
upgrade: z.boolean().optional(),
|
|
59
59
|
reconfigure: z.boolean().optional(),
|
|
60
|
-
}),
|
|
60
|
+
}),
|
|
61
|
+
// `rootPath` (#4482) is what TerraformApplyOp's Init step publishes as `TerraformRootPath`; OPS012 checks it here.
|
|
62
|
+
z.object({ dir: z.string(), workspace: z.string().optional(), rootPath: z.string().optional() }), rootEntity);
|
|
61
63
|
export const terraformPlanContract = activityContract("terraformPlan", z.strictObject({
|
|
62
64
|
...rootArgs,
|
|
63
65
|
planFile: z.string().optional(),
|
|
@@ -127,6 +129,22 @@ export const choudoufuAdoptContract = activityContract("choudoufuAdopt", z.stric
|
|
|
127
129
|
ambiguous: z.number(),
|
|
128
130
|
dir: z.string(),
|
|
129
131
|
}), rootEntity);
|
|
132
|
+
/**
|
|
133
|
+
* `choudoufuPlanSet` (#4483): one live choudoufu root planned as a one-root
|
|
134
|
+
* set. `changeSet` is the root's part, the field an Op hands to
|
|
135
|
+
* `composeChangeSet`; `planDigest` is what a gate binds; `planSetFile` and
|
|
136
|
+
* `setDigest` are what a later `live-wave-apply` takes.
|
|
137
|
+
*/
|
|
138
|
+
export const choudoufuPlanSetContract = activityContract("choudoufuPlanSet", z.strictObject({ ...rootArgs }), z.object({
|
|
139
|
+
setDigest: z.string(),
|
|
140
|
+
rootDigest: z.string(),
|
|
141
|
+
planDigest: z.string(),
|
|
142
|
+
changed: z.boolean(),
|
|
143
|
+
json: z.unknown(),
|
|
144
|
+
changeSet: z.object({ member: z.object({ member: z.string(), planDigest: z.string().nullable() }).passthrough(), entries: z.array(z.unknown()) }),
|
|
145
|
+
planSetFile: z.string(),
|
|
146
|
+
root: z.string(),
|
|
147
|
+
}), rootEntity);
|
|
130
148
|
/** One root of a pin-bump rollout ({@link PinRoot} in `../pin/waves.ts`). */
|
|
131
149
|
const pinRoot = z.strictObject({ root: z.string(), dependsOn: z.array(z.string()).optional(), tsSource: z.string().optional() });
|
|
132
150
|
/**
|
package/dist/op/builders.d.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* path a second time.
|
|
16
16
|
*/
|
|
17
17
|
import { type ActivityStep, type NamedActivityStep, type WithStepRefs } from "@intentius/chant/op";
|
|
18
|
-
import type { TerraformInitArgs, TerraformPlanArgs, TerraformApplyArgs, TerraformShowArgs, ChoudoufuLivePlanArgs, ChoudoufuLiveLsArgs, ChoudoufuLiveCheckArgs, ChoudoufuAdoptArgs } from "./activities/terraform.js";
|
|
18
|
+
import type { TerraformInitArgs, TerraformPlanArgs, TerraformApplyArgs, TerraformShowArgs, ChoudoufuLivePlanArgs, ChoudoufuLiveLsArgs, ChoudoufuLiveCheckArgs, ChoudoufuAdoptArgs, TerraformRootArgs } from "./activities/terraform.js";
|
|
19
19
|
import type { TerraformPinRolloutArgs } from "./activities/pin-rollout.js";
|
|
20
20
|
/** Extra opts every wrapper below accepts alongside its activity's own fields. */
|
|
21
21
|
type StepOpts = {
|
|
@@ -95,6 +95,12 @@ export declare const choudoufuAdopt: (root: string, opts: WithStepRefs<Omit<Chou
|
|
|
95
95
|
* provider.
|
|
96
96
|
*/
|
|
97
97
|
export declare const terraformShow: (root: string, opts?: WithStepRefs<Omit<TerraformShowArgs, "root">> & StepOpts) => NamedActivityStep;
|
|
98
|
+
/**
|
|
99
|
+
* `choudoufuPlanSet` (#4483): `live-plan-set -json` over one live choudoufu
|
|
100
|
+
* root. Hand `step.out.changeSet` from each root's step to `composeChangeSet`
|
|
101
|
+
* to make one change-set document over several roots, such as one per cloud.
|
|
102
|
+
*/
|
|
103
|
+
export declare const choudoufuPlanSet: (root: string, opts?: WithStepRefs<Omit<TerraformRootArgs, "root">> & StepOpts) => NamedActivityStep;
|
|
98
104
|
/**
|
|
99
105
|
* One run of a pin-bump rollout (#3189). `opts` is
|
|
100
106
|
* {@link TerraformPinRolloutArgs} itself. It names no root: the rollout finds
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,kFAAkF;AAClF,KAAK,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAClB,MAAM,SACL,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAGF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,SAClB,MAAM,SACL,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAGF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,SACnB,MAAM,SACL,YAAY,CAAC,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC/D,iBAGF,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,SACtB,MAAM,SACL,YAAY,CAAC,IAAI,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAClE,iBAOF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,SACpB,MAAM,SACL,YAAY,CAAC,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAChE,iBAOF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,SACvB,MAAM,SACL,YAAY,CAAC,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KACnE,iBAOF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,SACnB,MAAM,QACN,YAAY,CAAC,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAOF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAClB,MAAM,SACL,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAOF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,SACrB,MAAM,SACL,YAAY,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,GAAG,QAAQ,KAC9D,iBAGF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,SAAU,YAAY,CAAC,uBAAuB,CAAC,GAAG,QAAQ,KAAG,iBAG5F,CAAC"}
|
package/dist/op/builders.js
CHANGED
|
@@ -112,6 +112,15 @@ export const terraformShow = (root, opts) => {
|
|
|
112
112
|
const { args, profile, id } = takeProfileAndId(opts);
|
|
113
113
|
return activity("terraformShow", { root, ...args }, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
|
|
114
114
|
};
|
|
115
|
+
/**
|
|
116
|
+
* `choudoufuPlanSet` (#4483): `live-plan-set -json` over one live choudoufu
|
|
117
|
+
* root. Hand `step.out.changeSet` from each root's step to `composeChangeSet`
|
|
118
|
+
* to make one change-set document over several roots, such as one per cloud.
|
|
119
|
+
*/
|
|
120
|
+
export const choudoufuPlanSet = (root, opts) => {
|
|
121
|
+
const { args, profile, id } = takeProfileAndId(opts);
|
|
122
|
+
return activity("choudoufuPlanSet", { root, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
|
|
123
|
+
};
|
|
115
124
|
/**
|
|
116
125
|
* One run of a pin-bump rollout (#3189). `opts` is
|
|
117
126
|
* {@link TerraformPinRolloutArgs} itself. It names no root: the rollout finds
|
package/dist/pin/edit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/pin/edit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/pin/edit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,UAAU,CAAC;AAIjD,4FAA4F;AAC5F,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,mEAAmE;AACnE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,yGAAyG;IACzG,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AA2CD;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAiDxH"}
|
package/dist/pin/edit.js
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* module (terragucci's `tf-rollout` stage, #3421) decides how it is loaded.
|
|
23
23
|
*/
|
|
24
24
|
import { movePin } from "./source.js";
|
|
25
|
+
import { isJsonConfigFile, jsonConfigTree } from "../hcl/files.js";
|
|
25
26
|
import { escapeHcl, scanBlocks, unescapeHcl } from "./scan.js";
|
|
26
27
|
/** Whether a file is read as a Terragrunt configuration rather than a `.tf` file. */
|
|
27
28
|
export function isTerragruntFile(file) {
|
|
@@ -58,6 +59,8 @@ function sites(tree, blocks, terragrunt) {
|
|
|
58
59
|
* is reported with its reason and left as it was.
|
|
59
60
|
*/
|
|
60
61
|
export async function editPins(text, file, request, parser) {
|
|
62
|
+
if (isJsonConfigFile(file))
|
|
63
|
+
return jsonPins(text, file, request);
|
|
61
64
|
const terragrunt = isTerragruntFile(file);
|
|
62
65
|
const tree = (await parser.parse(file, text));
|
|
63
66
|
const blocks = scanBlocks(text, file);
|
|
@@ -116,3 +119,35 @@ export async function editPins(text, file, request, parser) {
|
|
|
116
119
|
function rewriteLiteral(raw, was, value) {
|
|
117
120
|
return raw === was ? value : escapeHcl(value);
|
|
118
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* The calls of the module in a `.tf.json` or `.tofu.json` file (chant#4457).
|
|
124
|
+
* The pin edit splices HCL text and has no splice for JSON syntax, so a call
|
|
125
|
+
* that would move is refused by name and the file is left as it is; a call
|
|
126
|
+
* already at the new pin, or at another one, reads as it does in HCL.
|
|
127
|
+
*/
|
|
128
|
+
function jsonPins(text, file, request) {
|
|
129
|
+
const calls = [];
|
|
130
|
+
let tree;
|
|
131
|
+
try {
|
|
132
|
+
tree = jsonConfigTree(text);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
return { content: text, calls: [{ outcome: "refused", reason: `not JSON the binary reads: ${err instanceof Error ? err.message : String(err)}`, file, call: "(file)" }] };
|
|
136
|
+
}
|
|
137
|
+
const modules = (tree.module && typeof tree.module === "object" ? tree.module : {});
|
|
138
|
+
for (const [name, bodies] of Object.entries(modules)) {
|
|
139
|
+
for (const body of Array.isArray(bodies) ? bodies : []) {
|
|
140
|
+
if (typeof body.source !== "string")
|
|
141
|
+
continue;
|
|
142
|
+
const move = movePin(body.source, typeof body.version === "string" ? body.version : undefined, request);
|
|
143
|
+
if (!move)
|
|
144
|
+
continue;
|
|
145
|
+
const at = { file, call: `module.${name}` };
|
|
146
|
+
if (move.outcome === "moved")
|
|
147
|
+
calls.push({ outcome: "refused", reason: "the call is in Terraform's JSON syntax, which the pin edit does not write; move its pin by hand", ...at });
|
|
148
|
+
else
|
|
149
|
+
calls.push({ ...move, ...at });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return { content: text, calls };
|
|
153
|
+
}
|
package/dist/pin/rollout.d.ts
CHANGED
|
@@ -70,6 +70,8 @@ export interface PinRolloutOptions extends PinRequest {
|
|
|
70
70
|
editTs?: TsPinEditor;
|
|
71
71
|
/** Markdown appended to a wave's PR body, such as the grouped plan summary of #3188 once a caller has the wave's plans. */
|
|
72
72
|
planSummary?: (wave: PinWave) => Promise<string | undefined>;
|
|
73
|
+
/** The binary the roots run: `tofu` or `choudoufu` reads `.tofu` files too (chant#4457). Default `terraform`. */
|
|
74
|
+
binary?: string;
|
|
73
75
|
}
|
|
74
76
|
/** Where one root's pin stood on the base branch. */
|
|
75
77
|
export interface PinRootState {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rollout.d.ts","sourceRoot":"","sources":["../../src/pin/rollout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAC;AAEpF,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE3F,OAAO,EAAuD,KAAK,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAC1G,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"rollout.d.ts","sourceRoot":"","sources":["../../src/pin/rollout.ts"],"names":[],"mappings":"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"}
|
package/dist/pin/rollout.js
CHANGED
|
@@ -45,6 +45,7 @@ import { editPins } from "./edit.js";
|
|
|
45
45
|
import { checkPinRequest, moduleOf } from "./source.js";
|
|
46
46
|
import { planPinWaves, restrictWaves, terragruntDependencies } from "./waves.js";
|
|
47
47
|
import { ghPinForge } from "./forge.js";
|
|
48
|
+
import { isConfigFileFor, listConfigFilesSafe } from "../hcl/files.js";
|
|
48
49
|
const execFileAsync = /* @__PURE__ */ promisify(execFile);
|
|
49
50
|
// `gh pr list/create` and `gh api repos/{owner}/{repo}/...` name no host, so
|
|
50
51
|
// a `gh` call is told the job's forge or `origin`'s host (core's `ghHostEnv`,
|
|
@@ -73,22 +74,24 @@ function slug(value) {
|
|
|
73
74
|
export function pinWaveBranch(request, wave) {
|
|
74
75
|
return `chant/pin/${slug(request.module)}/${slug(request.to)}/wave-${wave}`;
|
|
75
76
|
}
|
|
76
|
-
/**
|
|
77
|
-
|
|
77
|
+
/**
|
|
78
|
+
* The files the pin edit reads in a root directory: the configuration files
|
|
79
|
+
* the root's binary reads (the lexicon's one lister, chant#4457) and its
|
|
80
|
+
* `terragrunt.hcl`.
|
|
81
|
+
*/
|
|
82
|
+
function rootFiles(worktree, root, binary) {
|
|
78
83
|
const dir = join(worktree, root);
|
|
79
84
|
if (!existsSync(dir))
|
|
80
85
|
return [];
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
.sort()
|
|
84
|
-
.map((f) => posix.join(root, f));
|
|
86
|
+
const names = [...listConfigFilesSafe(dir, binary), ...(existsSync(join(dir, "terragrunt.hcl")) ? ["terragrunt.hcl"] : [])];
|
|
87
|
+
return names.sort().map((f) => posix.join(root, f));
|
|
85
88
|
}
|
|
86
|
-
/** Every directory under the worktree with a
|
|
87
|
-
function candidateRoots(worktree) {
|
|
89
|
+
/** Every directory under the worktree with a configuration file the binary reads, or a `terragrunt.hcl`. */
|
|
90
|
+
function candidateRoots(worktree, binary) {
|
|
88
91
|
const out = [];
|
|
89
92
|
const walk = (rel) => {
|
|
90
93
|
const entries = readdirSync(join(worktree, rel), { withFileTypes: true });
|
|
91
|
-
if (entries.some((e) => e.isFile() && (e.name
|
|
94
|
+
if (entries.some((e) => e.isFile() && (isConfigFileFor(e.name, binary) || e.name === "terragrunt.hcl")))
|
|
92
95
|
out.push(rel || ".");
|
|
93
96
|
for (const e of entries)
|
|
94
97
|
if (e.isDirectory() && !SKIP_DIRS.has(e.name))
|
|
@@ -108,7 +111,7 @@ async function editRoot(worktree, root, request, options) {
|
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
else {
|
|
111
|
-
files = rootFiles(worktree, root.root);
|
|
114
|
+
files = rootFiles(worktree, root.root, options.binary);
|
|
112
115
|
}
|
|
113
116
|
for (const file of files) {
|
|
114
117
|
const path = join(worktree, file);
|
|
@@ -216,7 +219,7 @@ export async function runPinRollout(options) {
|
|
|
216
219
|
await run("git", ["worktree", "add", "--quiet", "--detach", worktree, baseRef], repo);
|
|
217
220
|
try {
|
|
218
221
|
// 1. Every root's pin on the base branch.
|
|
219
|
-
const declared = (options.roots ?? candidateRoots(worktree).map((root) => ({ root }))).map((r) => ({
|
|
222
|
+
const declared = (options.roots ?? candidateRoots(worktree, options.binary).map((root) => ({ root }))).map((r) => ({
|
|
220
223
|
...r,
|
|
221
224
|
root: dirOf(r.root),
|
|
222
225
|
...(r.dependsOn ? { dependsOn: r.dependsOn.map(dirOf) } : {}),
|