@intentius/chant-lexicon-terraform 0.102.0 → 0.104.1

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.
Files changed (270) hide show
  1. package/dist/__fixtures__/terragrunt/affected-cases.d.ts +23 -0
  2. package/dist/__fixtures__/terragrunt/affected-cases.d.ts.map +1 -0
  3. package/dist/__fixtures__/terragrunt/record.d.ts +17 -0
  4. package/dist/__fixtures__/terragrunt/record.d.ts.map +1 -0
  5. package/dist/change-set.d.ts +67 -0
  6. package/dist/change-set.d.ts.map +1 -0
  7. package/dist/changed-roots.d.ts +30 -0
  8. package/dist/changed-roots.d.ts.map +1 -0
  9. package/dist/commands.d.ts +26 -0
  10. package/dist/commands.d.ts.map +1 -0
  11. package/dist/components/capability-plugin.d.ts +54 -0
  12. package/dist/components/capability-plugin.d.ts.map +1 -0
  13. package/dist/composites/terraform-pin-rollout-op.d.ts +44 -0
  14. package/dist/composites/terraform-pin-rollout-op.d.ts.map +1 -0
  15. package/dist/hcl/descend.d.ts +1 -1
  16. package/dist/hcl/descend.d.ts.map +1 -1
  17. package/dist/hcl/edges.d.ts +2 -2
  18. package/dist/hcl/edges.d.ts.map +1 -1
  19. package/dist/hcl/parse.d.ts +29 -1
  20. package/dist/hcl/parse.d.ts.map +1 -1
  21. package/dist/hcl/roots.d.ts +1 -1
  22. package/dist/hcl/roots.d.ts.map +1 -1
  23. package/dist/hcl/suppressions.d.ts.map +1 -1
  24. package/dist/index.d.ts +4 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/integrity.json +13 -4
  27. package/dist/lint/audit-catalog.d.ts.map +1 -1
  28. package/dist/lint/post-synth/index.d.ts.map +1 -1
  29. package/dist/lint/post-synth/module-source.d.ts +27 -1
  30. package/dist/lint/post-synth/module-source.d.ts.map +1 -1
  31. package/dist/lint/post-synth/terragrunt.d.ts +37 -0
  32. package/dist/lint/post-synth/terragrunt.d.ts.map +1 -0
  33. package/dist/lint/post-synth/tf002.d.ts +3 -1
  34. package/dist/lint/post-synth/tf002.d.ts.map +1 -1
  35. package/dist/lint/post-synth/tf038.d.ts +22 -0
  36. package/dist/lint/post-synth/tf038.d.ts.map +1 -0
  37. package/dist/lint/post-synth/tf039.d.ts +23 -0
  38. package/dist/lint/post-synth/tf039.d.ts.map +1 -0
  39. package/dist/lint/post-synth/tf040.d.ts +30 -0
  40. package/dist/lint/post-synth/tf040.d.ts.map +1 -0
  41. package/dist/lint/post-synth/tf041.d.ts +20 -0
  42. package/dist/lint/post-synth/tf041.d.ts.map +1 -0
  43. package/dist/lint/post-synth/tf042.d.ts +18 -0
  44. package/dist/lint/post-synth/tf042.d.ts.map +1 -0
  45. package/dist/lint/post-synth/tf043.d.ts +17 -0
  46. package/dist/lint/post-synth/tf043.d.ts.map +1 -0
  47. package/dist/lint/post-synth/tf044.d.ts +17 -0
  48. package/dist/lint/post-synth/tf044.d.ts.map +1 -0
  49. package/dist/lint/post-synth/tf045.d.ts +22 -0
  50. package/dist/lint/post-synth/tf045.d.ts.map +1 -0
  51. package/dist/manifest.json +1 -1
  52. package/dist/okf/index.md +8 -0
  53. package/dist/okf/rules/TF038.md +11 -0
  54. package/dist/okf/rules/TF039.md +11 -0
  55. package/dist/okf/rules/TF040.md +11 -0
  56. package/dist/okf/rules/TF041.md +11 -0
  57. package/dist/okf/rules/TF042.md +11 -0
  58. package/dist/okf/rules/TF043.md +11 -0
  59. package/dist/okf/rules/TF044.md +11 -0
  60. package/dist/okf/rules/TF045.md +11 -0
  61. package/dist/op/activities/index.d.ts +4 -0
  62. package/dist/op/activities/index.d.ts.map +1 -1
  63. package/dist/op/activities/pin-rollout.d.ts +46 -0
  64. package/dist/op/activities/pin-rollout.d.ts.map +1 -0
  65. package/dist/op/activities/terraform.d.ts +24 -50
  66. package/dist/op/activities/terraform.d.ts.map +1 -1
  67. package/dist/op/activity-contracts.d.ts +48 -0
  68. package/dist/op/activity-contracts.d.ts.map +1 -1
  69. package/dist/op/builders.d.ts +9 -0
  70. package/dist/op/builders.d.ts.map +1 -1
  71. package/dist/pin/edit-ts.d.ts +21 -0
  72. package/dist/pin/edit-ts.d.ts.map +1 -0
  73. package/dist/pin/edit.d.ts +52 -0
  74. package/dist/pin/edit.d.ts.map +1 -0
  75. package/dist/pin/forge.d.ts +39 -0
  76. package/dist/pin/forge.d.ts.map +1 -0
  77. package/dist/pin/index.d.ts +22 -0
  78. package/dist/pin/index.d.ts.map +1 -0
  79. package/dist/pin/rollout.d.ts +116 -0
  80. package/dist/pin/rollout.d.ts.map +1 -0
  81. package/dist/pin/scan.d.ts +54 -0
  82. package/dist/pin/scan.d.ts.map +1 -0
  83. package/dist/pin/source.d.ts +93 -0
  84. package/dist/pin/source.d.ts.map +1 -0
  85. package/dist/pin/waves.d.ts +66 -0
  86. package/dist/pin/waves.d.ts.map +1 -0
  87. package/dist/plan-digest.d.ts +59 -0
  88. package/dist/plan-digest.d.ts.map +1 -0
  89. package/dist/plugin.d.ts.map +1 -1
  90. package/dist/rules/module-source.ts +56 -1
  91. package/dist/rules/terragrunt.ts +76 -0
  92. package/dist/rules/tf002.ts +1 -1
  93. package/dist/rules/tf038.ts +71 -0
  94. package/dist/rules/tf039.ts +64 -0
  95. package/dist/rules/tf040.ts +76 -0
  96. package/dist/rules/tf041.ts +56 -0
  97. package/dist/rules/tf042.ts +42 -0
  98. package/dist/rules/tf043.ts +49 -0
  99. package/dist/rules/tf044.ts +51 -0
  100. package/dist/rules/tf045.ts +47 -0
  101. package/dist/terragrunt/affected.d.ts +119 -0
  102. package/dist/terragrunt/affected.d.ts.map +1 -0
  103. package/dist/terragrunt/index.d.ts +11 -0
  104. package/dist/terragrunt/index.d.ts.map +1 -0
  105. package/dist/terragrunt/mocks.d.ts +147 -0
  106. package/dist/terragrunt/mocks.d.ts.map +1 -0
  107. package/dist/terragrunt/run.d.ts +130 -0
  108. package/dist/terragrunt/run.d.ts.map +1 -0
  109. package/dist/terragrunt/units.d.ts +103 -0
  110. package/dist/terragrunt/units.d.ts.map +1 -0
  111. package/dist/terragrunt/wave.d.ts +89 -0
  112. package/dist/terragrunt/wave.d.ts.map +1 -0
  113. package/package.json +12 -2
  114. package/src/__fixtures__/change-set/choudoufu-set-plan.change-set.golden.json +95 -0
  115. package/src/__fixtures__/change-set/choudoufu-set-plan.json +76 -0
  116. package/src/__fixtures__/change-set/choudoufu.part.golden.json +173 -0
  117. package/src/__fixtures__/change-set/choudoufu.plan.json +610 -0
  118. package/src/__fixtures__/change-set/terraform.import-forget.plan.json +81 -0
  119. package/src/__fixtures__/change-set/terraform.part.golden.json +173 -0
  120. package/src/__fixtures__/change-set/terraform.plan.json +589 -0
  121. package/src/__fixtures__/change-set/tofu.part.golden.json +173 -0
  122. package/src/__fixtures__/change-set/tofu.plan.json +588 -0
  123. package/src/__fixtures__/change-set/v1.tf.txt +21 -0
  124. package/src/__fixtures__/change-set/v2-module-app.tf.txt +4 -0
  125. package/src/__fixtures__/change-set/v2.tf.txt +21 -0
  126. package/src/__fixtures__/pin/choudoufu-live-waves-n5.json +83 -0
  127. package/src/__fixtures__/pin/largeset-oci-n5/apply-order.txt +5 -0
  128. package/src/__fixtures__/pin/largeset-oci-n5/estates/e01/estate.chdf.hcl +6 -0
  129. package/src/__fixtures__/pin/largeset-oci-n5/estates/e01/main.tf +33 -0
  130. package/src/__fixtures__/pin/largeset-oci-n5/estates/e02/estate.chdf.hcl +6 -0
  131. package/src/__fixtures__/pin/largeset-oci-n5/estates/e02/main.tf +45 -0
  132. package/src/__fixtures__/pin/largeset-oci-n5/estates/e03/estate.chdf.hcl +6 -0
  133. package/src/__fixtures__/pin/largeset-oci-n5/estates/e03/main.tf +47 -0
  134. package/src/__fixtures__/pin/largeset-oci-n5/estates/e04/estate.chdf.hcl +6 -0
  135. package/src/__fixtures__/pin/largeset-oci-n5/estates/e04/main.tf +31 -0
  136. package/src/__fixtures__/pin/largeset-oci-n5/estates/e05/estate.chdf.hcl +6 -0
  137. package/src/__fixtures__/pin/largeset-oci-n5/estates/e05/main.tf +27 -0
  138. package/src/__fixtures__/pin/largeset-oci-n5/fixture.json +77 -0
  139. package/src/__fixtures__/plan-summary/largeset-n5-bump.json +2071 -0
  140. package/src/__fixtures__/plan-summary/largeset-n5.summary.golden.json +95 -0
  141. package/src/__fixtures__/plan-summary/largeset-n5.summary.golden.md +22 -0
  142. package/src/__fixtures__/plan-summary/largeset-n5.summary.golden.txt +12 -0
  143. package/src/__fixtures__/terragrunt/affected/catalog/units/web/terragrunt.hcl +3 -0
  144. package/src/__fixtures__/terragrunt/affected/gitignore +3 -0
  145. package/src/__fixtures__/terragrunt/affected/live/dev/app/terragrunt.hcl +3 -0
  146. package/src/__fixtures__/terragrunt/affected/live/dev/vpc/terragrunt.hcl +3 -0
  147. package/src/__fixtures__/terragrunt/affected/live/prod/app/terragrunt.hcl +3 -0
  148. package/src/__fixtures__/terragrunt/affected/live/stg/terragrunt.stack.hcl +5 -0
  149. package/src/__fixtures__/terragrunt/affected/modules/app/main.tf +6 -0
  150. package/src/__fixtures__/terragrunt/affected/modules/app/policy.json +1 -0
  151. package/src/__fixtures__/terragrunt/affected/modules/net/main.tf +2 -0
  152. package/src/__fixtures__/terragrunt/affected/modules/thing/main.tf +3 -0
  153. package/src/__fixtures__/terragrunt/affected/root.hcl +5 -0
  154. package/src/__fixtures__/terragrunt/affected-cases.ts +126 -0
  155. package/src/__fixtures__/terragrunt/five-units/catalog/units/thing/terragrunt.hcl +3 -0
  156. package/src/__fixtures__/terragrunt/five-units/live/dev/app/terragrunt.hcl +13 -0
  157. package/src/__fixtures__/terragrunt/five-units/live/dev/db/terragrunt.hcl +8 -0
  158. package/src/__fixtures__/terragrunt/five-units/live/dev/vpc/terragrunt.hcl +3 -0
  159. package/src/__fixtures__/terragrunt/five-units/live/prod/app/terragrunt.hcl +8 -0
  160. package/src/__fixtures__/terragrunt/five-units/live/prod/vpc/terragrunt.hcl +3 -0
  161. package/src/__fixtures__/terragrunt/five-units/modules/thing/main.tf +7 -0
  162. package/src/__fixtures__/terragrunt/five-units/root.hcl +5 -0
  163. package/src/__fixtures__/terragrunt/record.ts +56 -0
  164. package/src/__fixtures__/terragrunt/recorded/affected-find.json +50 -0
  165. package/src/__fixtures__/terragrunt/recorded/failed-plan-report.json +36 -0
  166. package/src/__fixtures__/terragrunt/recorded/find.json +67 -0
  167. package/src/__fixtures__/terragrunt/recorded/version.txt +1 -0
  168. package/src/__fixtures__/terragrunt/recorded/wave-1/apply-report.json +22 -0
  169. package/src/__fixtures__/terragrunt/recorded/wave-1/json/live/dev/vpc/tfplan.json +1 -0
  170. package/src/__fixtures__/terragrunt/recorded/wave-1/json/live/prod/vpc/tfplan.json +1 -0
  171. package/src/__fixtures__/terragrunt/recorded/wave-1/plan-report.json +22 -0
  172. package/src/__fixtures__/terragrunt/recorded/wave-2/json/live/dev/db/tfplan.json +1 -0
  173. package/src/__fixtures__/terragrunt/recorded/wave-2/json/live/prod/app/tfplan.json +1 -0
  174. package/src/__fixtures__/terragrunt/recorded/wave-2/plan-report.json +22 -0
  175. package/src/change-set-combined-run.test.ts +156 -0
  176. package/src/change-set.test.ts +151 -0
  177. package/src/change-set.ts +273 -0
  178. package/src/changed-roots.test.ts +58 -0
  179. package/src/changed-roots.ts +102 -0
  180. package/src/commands.ts +112 -0
  181. package/src/components/capability-plugin.test.ts +91 -0
  182. package/src/components/capability-plugin.ts +131 -0
  183. package/src/components/pr-loop.tofu.test.ts +244 -0
  184. package/src/composites/terraform-pin-rollout-op.test.ts +69 -0
  185. package/src/composites/terraform-pin-rollout-op.ts +60 -0
  186. package/src/hcl/descend.ts +1 -1
  187. package/src/hcl/edges.ts +2 -2
  188. package/src/hcl/parse.test.ts +25 -0
  189. package/src/hcl/parse.ts +91 -6
  190. package/src/hcl/roots.ts +1 -1
  191. package/src/hcl/suppressions.ts +8 -2
  192. package/src/index.ts +18 -0
  193. package/src/lint/audit-catalog.ts +82 -0
  194. package/src/lint/audit.test.ts +3 -1
  195. package/src/lint/post-synth/fixtures/TF038/positive.tf +3 -0
  196. package/src/lint/post-synth/fixtures/TF039/positive.tf +4 -0
  197. package/src/lint/post-synth/fixtures/TF041/negative/terragrunt.hcl +12 -0
  198. package/src/lint/post-synth/fixtures/TF041/positive/terragrunt.hcl +7 -0
  199. package/src/lint/post-synth/fixtures/TF041/positive-apply/terragrunt.hcl +8 -0
  200. package/src/lint/post-synth/fixtures/TF042/negative/terragrunt.hcl +13 -0
  201. package/src/lint/post-synth/fixtures/TF042/positive/terragrunt.hcl +9 -0
  202. package/src/lint/post-synth/fixtures/TF043/negative/terragrunt.hcl +3 -0
  203. package/src/lint/post-synth/fixtures/TF043/negative-other/terragrunt.hcl +3 -0
  204. package/src/lint/post-synth/fixtures/TF043/positive-git/terragrunt.hcl +3 -0
  205. package/src/lint/post-synth/fixtures/TF043/positive-oci/terragrunt.hcl +3 -0
  206. package/src/lint/post-synth/fixtures/TF043/positive-tfr/terragrunt.hcl +3 -0
  207. package/src/lint/post-synth/fixtures/TF044/negative/terragrunt.hcl +9 -0
  208. package/src/lint/post-synth/fixtures/TF044/positive/terragrunt.hcl +7 -0
  209. package/src/lint/post-synth/fixtures/TF044/positive-generate/terragrunt.hcl +9 -0
  210. package/src/lint/post-synth/fixtures/TF045/negative/root.hcl +1 -0
  211. package/src/lint/post-synth/fixtures/TF045/negative/terragrunt.hcl +3 -0
  212. package/src/lint/post-synth/fixtures/TF045/positive/root.hcl +9 -0
  213. package/src/lint/post-synth/fixtures/TF045/positive/terragrunt.hcl +3 -0
  214. package/src/lint/post-synth/fixtures/TF045/unit-only/terragrunt.hcl +3 -0
  215. package/src/lint/post-synth/index.ts +16 -0
  216. package/src/lint/post-synth/module-source.test.ts +42 -1
  217. package/src/lint/post-synth/module-source.ts +56 -1
  218. package/src/lint/post-synth/terragrunt.ts +76 -0
  219. package/src/lint/post-synth/tf002.ts +1 -1
  220. package/src/lint/post-synth/tf038.test.ts +51 -0
  221. package/src/lint/post-synth/tf038.ts +71 -0
  222. package/src/lint/post-synth/tf039.test.ts +40 -0
  223. package/src/lint/post-synth/tf039.ts +64 -0
  224. package/src/lint/post-synth/tf040.test.ts +55 -0
  225. package/src/lint/post-synth/tf040.ts +76 -0
  226. package/src/lint/post-synth/tf041.test.ts +50 -0
  227. package/src/lint/post-synth/tf041.ts +56 -0
  228. package/src/lint/post-synth/tf042.test.ts +19 -0
  229. package/src/lint/post-synth/tf042.ts +42 -0
  230. package/src/lint/post-synth/tf043.test.ts +65 -0
  231. package/src/lint/post-synth/tf043.ts +49 -0
  232. package/src/lint/post-synth/tf044.test.ts +27 -0
  233. package/src/lint/post-synth/tf044.ts +51 -0
  234. package/src/lint/post-synth/tf045.test.ts +30 -0
  235. package/src/lint/post-synth/tf045.ts +47 -0
  236. package/src/op/activities/index.ts +4 -0
  237. package/src/op/activities/pin-rollout.ts +77 -0
  238. package/src/op/activities/terraform.test.ts +13 -0
  239. package/src/op/activities/terraform.ts +46 -86
  240. package/src/op/activity-contracts.test.ts +4 -1
  241. package/src/op/activity-contracts.ts +42 -0
  242. package/src/op/builders.ts +13 -0
  243. package/src/pin/bundle.test.ts +53 -0
  244. package/src/pin/edit-ts.test.ts +39 -0
  245. package/src/pin/edit-ts.ts +77 -0
  246. package/src/pin/edit.test.ts +199 -0
  247. package/src/pin/edit.ts +157 -0
  248. package/src/pin/forge.ts +85 -0
  249. package/src/pin/index.ts +22 -0
  250. package/src/pin/rollout.test.ts +232 -0
  251. package/src/pin/rollout.ts +451 -0
  252. package/src/pin/scan.ts +309 -0
  253. package/src/pin/source.ts +206 -0
  254. package/src/pin/waves.test.ts +101 -0
  255. package/src/pin/waves.ts +125 -0
  256. package/src/plan-digest.ts +99 -0
  257. package/src/plan-summary.test.ts +154 -0
  258. package/src/plugin.ts +25 -2
  259. package/src/terragrunt/affected.acceptance.test.ts +83 -0
  260. package/src/terragrunt/affected.test.ts +177 -0
  261. package/src/terragrunt/affected.ts +348 -0
  262. package/src/terragrunt/index.ts +11 -0
  263. package/src/terragrunt/mocks.acceptance.test.ts +105 -0
  264. package/src/terragrunt/mocks.test.ts +309 -0
  265. package/src/terragrunt/mocks.ts +324 -0
  266. package/src/terragrunt/run.ts +369 -0
  267. package/src/terragrunt/terragrunt.acceptance.test.ts +122 -0
  268. package/src/terragrunt/terragrunt.test.ts +332 -0
  269. package/src/terragrunt/units.ts +235 -0
  270. package/src/terragrunt/wave.ts +181 -0
@@ -0,0 +1,181 @@
1
+ /**
2
+ * One wave of Terragrunt units as one `terragrunt run --all` (#3414): the
3
+ * arguments, the environment, the run report and the change-set parts.
4
+ *
5
+ * A wave names its units with explicit path filters, so it plans and applies
6
+ * exactly those units. `.terragrunt-filters` is not read by a wave run:
7
+ * Terragrunt unions its filters with the ones given on the command line
8
+ * (observed on 1.1.6), so a filters file selecting `live/prod/**` would pull
9
+ * every prod unit into every wave. Discovery reads it; the wave's paths came
10
+ * from discovery.
11
+ *
12
+ * Plan writes `<outDir>/<unit>/tfplan.tfplan` and
13
+ * `<jsonOutDir>/<unit>/tfplan.json`; apply reads the saved plans from the
14
+ * same `outDir` with the same filters.
15
+ *
16
+ * Pure: nothing here spawns or reads files, so terragucci can bundle it. It
17
+ * imports `../change-set` and chant's `change-set` types only.
18
+ */
19
+
20
+ import type { ChangeSetPart, ChangeSetPlanner } from "@intentius/chant/change-set";
21
+ import { terraformChangeSetPart } from "../change-set";
22
+ import { stackOfUnit, unitPathFilter } from "./units";
23
+
24
+ export type TerragruntWaveCommand = "plan" | "apply";
25
+
26
+ export interface TerragruntWaveArgsInput {
27
+ /** The wave's units, by path relative to where Terragrunt runs. */
28
+ units: readonly string[];
29
+ command: TerragruntWaveCommand;
30
+ /** Where plan writes and apply reads the saved plan files. */
31
+ outDir: string;
32
+ /** Where plan writes each unit's `show -json`. Plan only. */
33
+ jsonOutDir?: string;
34
+ /** Where Terragrunt writes the run report (JSON). */
35
+ reportFile: string;
36
+ /** A destroy wave: plan runs `plan -destroy`, and both pass `--filter-allow-destroy`. */
37
+ destroy?: boolean;
38
+ /** `--parallelism`. Unset, Terragrunt runs every unit of the wave at once. */
39
+ parallelism?: number;
40
+ /** Arguments after `--`, beside the ones the command needs (`-lock-timeout=5m`). */
41
+ extra?: readonly string[];
42
+ }
43
+
44
+ /** Arguments to `terragrunt` for one wave. Throws on an empty wave: with no filter, `run --all` runs every unit. */
45
+ export function terragruntWaveArgs(input: TerragruntWaveArgsInput): string[] {
46
+ if (input.units.length === 0) throw new Error("a Terragrunt wave needs at least one unit; with no path filter run --all would run every unit");
47
+ if (input.parallelism !== undefined && (!Number.isInteger(input.parallelism) || input.parallelism < 1)) {
48
+ throw new Error(`parallelism must be a whole number of 1 or more, got ${input.parallelism}`);
49
+ }
50
+ const units = [...new Set(input.units)].sort();
51
+ const args = [
52
+ "run",
53
+ "--all",
54
+ "--non-interactive",
55
+ "--no-color",
56
+ "--no-filters-file",
57
+ ...units.flatMap((u) => ["--filter", unitPathFilter(u)]),
58
+ ...(input.destroy ? ["--filter-allow-destroy"] : []),
59
+ "--out-dir",
60
+ input.outDir,
61
+ ...(input.command === "plan" && input.jsonOutDir ? ["--json-out-dir", input.jsonOutDir] : []),
62
+ "--report-file",
63
+ input.reportFile,
64
+ "--report-format",
65
+ "json",
66
+ ...(input.parallelism !== undefined ? ["--parallelism", String(input.parallelism)] : []),
67
+ "--",
68
+ input.command,
69
+ ...(input.command === "plan" && input.destroy ? ["-destroy"] : []),
70
+ ...(input.extra ?? []),
71
+ ];
72
+ return args;
73
+ }
74
+
75
+ /**
76
+ * The environment a wave adds: `TG_TF_PATH` when the project names a binary,
77
+ * nothing otherwise, so Terragrunt's own choice (tofu, then terraform, or a
78
+ * unit's `terraform_binary`) stands.
79
+ */
80
+ export function terragruntEnv(binary: string | undefined): Record<string, string> {
81
+ return binary ? { TG_TF_PATH: binary } : {};
82
+ }
83
+
84
+ /** One row of a Terragrunt run report (`run/report` JSON). */
85
+ export interface TerragruntReportRow {
86
+ name: string;
87
+ /** `succeeded`, `failed`, `early exit`, `excluded`, as Terragrunt writes them. */
88
+ result: string;
89
+ reason?: string;
90
+ cause?: string;
91
+ cmd?: string;
92
+ started?: string;
93
+ ended?: string;
94
+ }
95
+
96
+ /** The rows of a run report, keyed by unit path. Malformed rows are dropped. */
97
+ export function parseTerragruntReport(text: string | unknown): Map<string, TerragruntReportRow> {
98
+ const doc = typeof text === "string" ? (JSON.parse(text.trim() === "" ? "[]" : text) as unknown) : text;
99
+ const rows = Array.isArray(doc) ? doc : [];
100
+ const out = new Map<string, TerragruntReportRow>();
101
+ for (const raw of rows) {
102
+ if (raw === null || typeof raw !== "object") continue;
103
+ const r = raw as Record<string, unknown>;
104
+ if (typeof r.Name !== "string" || typeof r.Result !== "string") continue;
105
+ const name = r.Name.replace(/\\/g, "/").replace(/^\.\//, "");
106
+ out.set(name, {
107
+ name,
108
+ result: r.Result,
109
+ ...(typeof r.Reason === "string" && r.Reason ? { reason: r.Reason } : {}),
110
+ ...(typeof r.Cause === "string" && r.Cause ? { cause: r.Cause.trim() } : {}),
111
+ ...(typeof r.Cmd === "string" ? { cmd: r.Cmd } : {}),
112
+ ...(typeof r.Started === "string" ? { started: r.Started } : {}),
113
+ ...(typeof r.Ended === "string" ? { ended: r.Ended } : {}),
114
+ });
115
+ }
116
+ return out;
117
+ }
118
+
119
+ /** How one unit of a wave ended. */
120
+ export interface TerragruntUnitResult {
121
+ unit: string;
122
+ /** `succeeded` only when the run report says so; a unit missing from it did not run. */
123
+ status: "succeeded" | "failed";
124
+ /** The report's result, or `not run` when the unit is not in it. */
125
+ result: string;
126
+ /** Why it failed, from the report's reason and cause. */
127
+ error?: string;
128
+ }
129
+
130
+ /** Each of the wave's units against the run report. A unit the report leaves out failed: nothing says it ran. */
131
+ export function terragruntUnitResults(units: readonly string[], report: Map<string, TerragruntReportRow>): TerragruntUnitResult[] {
132
+ return [...new Set(units)].sort().map((unit) => {
133
+ const row = report.get(unit);
134
+ if (!row) return { unit, status: "failed", result: "not run", error: "not in Terragrunt's run report, so it did not run" };
135
+ if (row.result === "succeeded") return { unit, status: "succeeded", result: row.result };
136
+ const why = [row.reason, row.cause].filter(Boolean).join(": ");
137
+ return { unit, status: "failed", result: row.result, error: `${row.result}${why ? ` (${why})` : ""}` };
138
+ });
139
+ }
140
+
141
+ export interface TerragruntWavePartsInput {
142
+ units: readonly string[];
143
+ report: Map<string, TerragruntReportRow>;
144
+ /** A unit's `tfplan.json`, parsed, or undefined when plan wrote none. */
145
+ planFor: (unit: string) => unknown;
146
+ /** The binary Terragrunt called. */
147
+ planner: ChangeSetPlanner;
148
+ /** The scope a unit's member carries. Default: its stack, {@link stackOfUnit}. */
149
+ scopeFor?: (unit: string) => string | undefined;
150
+ }
151
+
152
+ /**
153
+ * The change-set parts of a planned wave: one member per unit, named by the
154
+ * unit's path. A unit the run report marks succeeded, with a plan JSON, goes
155
+ * through {@link terraformChangeSetPart}; any other is a failed member
156
+ * carrying the report's result, so a unit that never planned cannot read as
157
+ * planned with nothing to do.
158
+ */
159
+ export function terragruntWaveParts(input: TerragruntWavePartsInput): ChangeSetPart[] {
160
+ const scopeFor = input.scopeFor ?? stackOfUnit;
161
+ return terragruntUnitResults(input.units, input.report).map((r) => {
162
+ const scope = scopeFor(r.unit);
163
+ const plan = r.status === "succeeded" ? input.planFor(r.unit) : undefined;
164
+ if (r.status === "succeeded" && plan !== undefined) {
165
+ return terraformChangeSetPart({ member: r.unit, plan, planner: input.planner, ...(scope ? { scope } : {}) });
166
+ }
167
+ return {
168
+ member: {
169
+ member: r.unit,
170
+ lexicon: "terraform",
171
+ planner: input.planner,
172
+ ...(scope ? { scope } : {}),
173
+ status: "failed" as const,
174
+ error: r.error ?? "Terragrunt reported the unit succeeded but wrote no plan JSON for it",
175
+ planDigest: null,
176
+ holes: [],
177
+ },
178
+ entries: [],
179
+ };
180
+ });
181
+ }