@intentius/chant-lexicon-terraform 0.124.54 → 0.124.56

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 (351) hide show
  1. package/README.md +7 -4
  2. package/dist/ci-setup.d.ts +11 -0
  3. package/dist/ci-setup.d.ts.map +1 -0
  4. package/dist/ci-setup.js +41 -0
  5. package/dist/components/capability-plugin.d.ts +40 -6
  6. package/dist/components/capability-plugin.d.ts.map +1 -1
  7. package/dist/components/capability-plugin.js +174 -30
  8. package/dist/components/compose-group.d.ts +1 -1
  9. package/dist/components/compose-group.d.ts.map +1 -1
  10. package/dist/components/compose-group.js +1 -1
  11. package/dist/components/release-inputs.d.ts +29 -0
  12. package/dist/components/release-inputs.d.ts.map +1 -0
  13. package/dist/components/release-inputs.js +57 -0
  14. package/dist/components/trace-facts.d.ts +16 -0
  15. package/dist/components/trace-facts.d.ts.map +1 -0
  16. package/dist/components/trace-facts.js +19 -0
  17. package/dist/cone.d.ts +53 -0
  18. package/dist/cone.d.ts.map +1 -0
  19. package/dist/cone.js +119 -0
  20. package/dist/cost-hold.d.ts +27 -0
  21. package/dist/cost-hold.d.ts.map +1 -0
  22. package/dist/cost-hold.js +21 -0
  23. package/dist/drift-rows.d.ts +61 -0
  24. package/dist/drift-rows.d.ts.map +1 -0
  25. package/dist/drift-rows.js +108 -0
  26. package/dist/exit-codes.d.ts +55 -0
  27. package/dist/exit-codes.d.ts.map +1 -0
  28. package/dist/exit-codes.js +48 -0
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +3 -0
  32. package/dist/integrity.json +7 -4
  33. package/dist/lint/audit-catalog.d.ts.map +1 -1
  34. package/dist/lint/audit-catalog.js +27 -3
  35. package/dist/lint/audit-lineage.d.ts +14 -2
  36. package/dist/lint/audit-lineage.d.ts.map +1 -1
  37. package/dist/lint/post-synth/index.d.ts.map +1 -1
  38. package/dist/lint/post-synth/index.js +4 -0
  39. package/dist/lint/post-synth/record-store.d.ts +54 -0
  40. package/dist/lint/post-synth/record-store.d.ts.map +1 -0
  41. package/dist/lint/post-synth/record-store.js +104 -0
  42. package/dist/lint/post-synth/tf001.d.ts +2 -2
  43. package/dist/lint/post-synth/tf001.js +2 -2
  44. package/dist/lint/post-synth/tf024.d.ts +35 -11
  45. package/dist/lint/post-synth/tf024.d.ts.map +1 -1
  46. package/dist/lint/post-synth/tf024.js +92 -20
  47. package/dist/lint/post-synth/tf046.d.ts +64 -0
  48. package/dist/lint/post-synth/tf046.d.ts.map +1 -0
  49. package/dist/lint/post-synth/tf046.js +175 -0
  50. package/dist/lint/post-synth/tf047.d.ts +36 -0
  51. package/dist/lint/post-synth/tf047.d.ts.map +1 -0
  52. package/dist/lint/post-synth/tf047.js +94 -0
  53. package/dist/lock-rows.d.ts +36 -0
  54. package/dist/lock-rows.d.ts.map +1 -0
  55. package/dist/lock-rows.js +60 -0
  56. package/dist/lock-timeout.d.ts +22 -0
  57. package/dist/lock-timeout.d.ts.map +1 -0
  58. package/dist/lock-timeout.js +32 -0
  59. package/dist/manifest.json +1 -1
  60. package/dist/module-catalog/index.d.ts +69 -0
  61. package/dist/module-catalog/index.d.ts.map +1 -0
  62. package/dist/module-catalog/index.js +110 -0
  63. package/dist/module-catalog/refresh-cli.d.ts +4 -0
  64. package/dist/module-catalog/refresh-cli.d.ts.map +1 -0
  65. package/dist/module-catalog/refresh-cli.js +64 -0
  66. package/dist/module-catalog/static-tier.d.ts +6 -0
  67. package/dist/module-catalog/static-tier.d.ts.map +1 -0
  68. package/dist/module-catalog/static-tier.js +1650 -0
  69. package/dist/module-catalog/types.d.ts +65 -0
  70. package/dist/module-catalog/types.d.ts.map +1 -0
  71. package/dist/module-catalog/types.js +33 -0
  72. package/dist/okf/index.md +3 -1
  73. package/dist/okf/rules/TF024.md +2 -2
  74. package/dist/okf/rules/TF046.md +11 -0
  75. package/dist/okf/rules/TF047.md +11 -0
  76. package/dist/op/activities/terraform.d.ts +29 -0
  77. package/dist/op/activities/terraform.d.ts.map +1 -1
  78. package/dist/op/activities/terraform.js +19 -4
  79. package/dist/pin/consumers.d.ts +35 -0
  80. package/dist/pin/consumers.d.ts.map +1 -0
  81. package/dist/pin/consumers.js +70 -0
  82. package/dist/plugin.d.ts.map +1 -1
  83. package/dist/plugin.js +5 -0
  84. package/dist/registry/address.d.ts +63 -0
  85. package/dist/registry/address.d.ts.map +1 -0
  86. package/dist/registry/address.js +65 -0
  87. package/dist/registry/catalog-read.d.ts +14 -0
  88. package/dist/registry/catalog-read.d.ts.map +1 -0
  89. package/dist/registry/catalog-read.js +58 -0
  90. package/dist/registry/deprecated.d.ts +37 -0
  91. package/dist/registry/deprecated.d.ts.map +1 -0
  92. package/dist/registry/deprecated.js +43 -0
  93. package/dist/registry/docs.d.ts +96 -0
  94. package/dist/registry/docs.d.ts.map +1 -0
  95. package/dist/registry/docs.js +210 -0
  96. package/dist/registry/edge/edge.d.ts +46 -0
  97. package/dist/registry/edge/edge.d.ts.map +1 -0
  98. package/dist/registry/edge/edge.js +194 -0
  99. package/dist/registry/edge/index.d.ts +11 -0
  100. package/dist/registry/edge/index.d.ts.map +1 -0
  101. package/dist/registry/edge/index.js +10 -0
  102. package/dist/registry/edge/lambda-edge.d.ts +76 -0
  103. package/dist/registry/edge/lambda-edge.d.ts.map +1 -0
  104. package/dist/registry/edge/lambda-edge.js +95 -0
  105. package/dist/registry/edge/sigv4-web.d.ts +33 -0
  106. package/dist/registry/edge/sigv4-web.d.ts.map +1 -0
  107. package/dist/registry/edge/sigv4-web.js +56 -0
  108. package/dist/registry/edge/token-source.d.ts +73 -0
  109. package/dist/registry/edge/token-source.d.ts.map +1 -0
  110. package/dist/registry/edge/token-source.js +115 -0
  111. package/dist/registry/edge/worker.d.ts +45 -0
  112. package/dist/registry/edge/worker.d.ts.map +1 -0
  113. package/dist/registry/edge/worker.js +26 -0
  114. package/dist/registry/handler.d.ts +25 -0
  115. package/dist/registry/handler.d.ts.map +1 -0
  116. package/dist/registry/handler.js +75 -0
  117. package/dist/registry/headers-file.d.ts +21 -0
  118. package/dist/registry/headers-file.d.ts.map +1 -0
  119. package/dist/registry/headers-file.js +57 -0
  120. package/dist/registry/index.d.ts +31 -0
  121. package/dist/registry/index.d.ts.map +1 -0
  122. package/dist/registry/index.js +30 -0
  123. package/dist/registry/mirror-paths.d.ts +9 -0
  124. package/dist/registry/mirror-paths.d.ts.map +1 -0
  125. package/dist/registry/mirror-paths.js +8 -0
  126. package/dist/registry/mirror.d.ts +130 -0
  127. package/dist/registry/mirror.d.ts.map +1 -0
  128. package/dist/registry/mirror.js +319 -0
  129. package/dist/registry/proxies.d.ts +73 -0
  130. package/dist/registry/proxies.d.ts.map +1 -0
  131. package/dist/registry/proxies.js +111 -0
  132. package/dist/registry/reader.d.ts +57 -0
  133. package/dist/registry/reader.d.ts.map +1 -0
  134. package/dist/registry/reader.js +198 -0
  135. package/dist/registry/semver.d.ts +16 -0
  136. package/dist/registry/semver.d.ts.map +1 -0
  137. package/dist/registry/semver.js +24 -0
  138. package/dist/registry/serve.d.ts +24 -0
  139. package/dist/registry/serve.d.ts.map +1 -0
  140. package/dist/registry/serve.js +64 -0
  141. package/dist/registry/source-forms.d.ts +79 -0
  142. package/dist/registry/source-forms.d.ts.map +1 -0
  143. package/dist/registry/source-forms.js +202 -0
  144. package/dist/registry/targets/artifactory.d.ts +28 -0
  145. package/dist/registry/targets/artifactory.d.ts.map +1 -0
  146. package/dist/registry/targets/artifactory.js +206 -0
  147. package/dist/registry/targets/fake-artifactory.d.ts +30 -0
  148. package/dist/registry/targets/fake-artifactory.d.ts.map +1 -0
  149. package/dist/registry/targets/fake-artifactory.js +142 -0
  150. package/dist/registry/targets/fake-gitlab.d.ts +39 -0
  151. package/dist/registry/targets/fake-gitlab.d.ts.map +1 -0
  152. package/dist/registry/targets/fake-gitlab.js +136 -0
  153. package/dist/registry/targets/fake-hcp.d.ts +50 -0
  154. package/dist/registry/targets/fake-hcp.d.ts.map +1 -0
  155. package/dist/registry/targets/fake-hcp.js +202 -0
  156. package/dist/registry/targets/fake-http.d.ts +31 -0
  157. package/dist/registry/targets/fake-http.d.ts.map +1 -0
  158. package/dist/registry/targets/fake-http.js +87 -0
  159. package/dist/registry/targets/fake-nexus.d.ts +27 -0
  160. package/dist/registry/targets/fake-nexus.d.ts.map +1 -0
  161. package/dist/registry/targets/fake-nexus.js +137 -0
  162. package/dist/registry/targets/gitlab.d.ts +53 -0
  163. package/dist/registry/targets/gitlab.d.ts.map +1 -0
  164. package/dist/registry/targets/gitlab.js +187 -0
  165. package/dist/registry/targets/hcp.d.ts +29 -0
  166. package/dist/registry/targets/hcp.d.ts.map +1 -0
  167. package/dist/registry/targets/hcp.js +310 -0
  168. package/dist/registry/targets/hosted.d.ts +62 -0
  169. package/dist/registry/targets/hosted.d.ts.map +1 -0
  170. package/dist/registry/targets/hosted.js +74 -0
  171. package/dist/registry/targets/index.d.ts +18 -0
  172. package/dist/registry/targets/index.d.ts.map +1 -0
  173. package/dist/registry/targets/index.js +17 -0
  174. package/dist/registry/targets/module-target.d.ts +68 -0
  175. package/dist/registry/targets/module-target.d.ts.map +1 -0
  176. package/dist/registry/targets/module-target.js +63 -0
  177. package/dist/registry/targets/nexus.d.ts +43 -0
  178. package/dist/registry/targets/nexus.d.ts.map +1 -0
  179. package/dist/registry/targets/nexus.js +250 -0
  180. package/dist/registry/targets/zip.d.ts +55 -0
  181. package/dist/registry/targets/zip.d.ts.map +1 -0
  182. package/dist/registry/targets/zip.js +278 -0
  183. package/dist/registry/writer.d.ts +101 -0
  184. package/dist/registry/writer.d.ts.map +1 -0
  185. package/dist/registry/writer.js +109 -0
  186. package/dist/rules/record-store.ts +122 -0
  187. package/dist/rules/tf001.ts +2 -2
  188. package/dist/rules/tf024.ts +105 -22
  189. package/dist/rules/tf046.ts +204 -0
  190. package/dist/rules/tf047.ts +114 -0
  191. package/dist/state/azure-blob.d.ts +8 -67
  192. package/dist/state/azure-blob.d.ts.map +1 -1
  193. package/dist/state/azure-blob.js +6 -199
  194. package/dist/state/gcs.d.ts +7 -61
  195. package/dist/state/gcs.d.ts.map +1 -1
  196. package/dist/state/gcs.js +5 -222
  197. package/dist/state/object-store.d.ts +4 -33
  198. package/dist/state/object-store.d.ts.map +1 -1
  199. package/dist/state/object-store.js +4 -17
  200. package/dist/state/s3.d.ts +11 -58
  201. package/dist/state/s3.d.ts.map +1 -1
  202. package/dist/state/s3.js +10 -161
  203. package/dist/state/store.js +2 -2
  204. package/dist/state-ops.d.ts +255 -0
  205. package/dist/state-ops.d.ts.map +1 -0
  206. package/dist/state-ops.js +305 -0
  207. package/dist/state-reads.d.ts +57 -0
  208. package/dist/state-reads.d.ts.map +1 -0
  209. package/dist/state-reads.js +104 -0
  210. package/dist/used-sources.d.ts +54 -0
  211. package/dist/used-sources.d.ts.map +1 -0
  212. package/dist/used-sources.js +157 -0
  213. package/package.json +19 -3
  214. package/src/__fixtures__/drift-record/README.md +5 -0
  215. package/src/__fixtures__/drift-rows/live-root-plan.json +70 -0
  216. package/src/__fixtures__/drift-rows/refresh-plan.json +61 -0
  217. package/src/__fixtures__/used-sources/root/extra.tofu +1 -0
  218. package/src/__fixtures__/used-sources/root/main.tf +31 -0
  219. package/src/__fixtures__/used-sources/root/modules/net/main.tf +14 -0
  220. package/src/__fixtures__/used-sources/root/modules/net/versions.tf.json +7 -0
  221. package/src/__fixtures__/used-sources/unit/terragrunt.hcl +3 -0
  222. package/src/ci-setup.ts +42 -0
  223. package/src/components/capability-plugin.test.ts +26 -14
  224. package/src/components/capability-plugin.ts +185 -31
  225. package/src/components/compose-group.ts +1 -1
  226. package/src/components/pr-loop-compose.tofu.e2e.test.ts +1 -1
  227. package/src/components/pr-loop.tofu.test.ts +1 -1
  228. package/src/components/release-inputs.ts +69 -0
  229. package/src/components/trace-facts.test.ts +21 -0
  230. package/src/components/trace-facts.ts +27 -0
  231. package/src/cone.ts +138 -0
  232. package/src/cost-hold.ts +29 -0
  233. package/src/describe-resources.engine-facts.test.ts +2 -3
  234. package/src/drift-rows.test.ts +135 -0
  235. package/src/drift-rows.ts +137 -0
  236. package/src/exit-codes.test.ts +23 -0
  237. package/src/exit-codes.ts +59 -0
  238. package/src/index.ts +3 -0
  239. package/src/lint/audit-catalog.ts +29 -3
  240. package/src/lint/audit-lineage.ts +14 -2
  241. package/src/lint/post-synth/fixtures/TF024/live-with-record-store/main.tf +18 -0
  242. package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/estate.chdf.hcl +1 -0
  243. package/src/lint/post-synth/fixtures/TF024/sidecar-with-backend/main.tf +10 -0
  244. package/src/lint/post-synth/fixtures/TF046/azurerm-no-resource-group/main.tf +15 -0
  245. package/src/lint/post-synth/fixtures/TF046/backend-config-only/main.tf +14 -0
  246. package/src/lint/post-synth/fixtures/TF046/derived-s3/backend.tf +7 -0
  247. package/src/lint/post-synth/fixtures/TF046/derived-s3/main.tf +9 -0
  248. package/src/lint/post-synth/fixtures/TF046/explicit-local/main.tf +16 -0
  249. package/src/lint/post-synth/fixtures/TF046/explicit-s3-beside-local-backend/main.tf +15 -0
  250. package/src/lint/post-synth/fixtures/TF046/implied-local/main.tf +9 -0
  251. package/src/lint/post-synth/fixtures/TF046/sidecar-implied/estate.chdf.hcl +1 -0
  252. package/src/lint/post-synth/fixtures/TF046/sidecar-implied/main.tf +5 -0
  253. package/src/lint/post-synth/fixtures/TF047/clear/main.tf +12 -0
  254. package/src/lint/post-synth/fixtures/TF047/refused/main.tf +12 -0
  255. package/src/lint/post-synth/fixtures/TF047/unknown-module/main.tf +12 -0
  256. package/src/lint/post-synth/fixtures/TF047/unknown-version/main.tf +12 -0
  257. package/src/lint/post-synth/index.ts +4 -0
  258. package/src/lint/post-synth/record-store.ts +122 -0
  259. package/src/lint/post-synth/tf001.ts +2 -2
  260. package/src/lint/post-synth/tf024.test.ts +26 -5
  261. package/src/lint/post-synth/tf024.ts +105 -22
  262. package/src/lint/post-synth/tf046.test.ts +137 -0
  263. package/src/lint/post-synth/tf046.ts +204 -0
  264. package/src/lint/post-synth/tf047.test.ts +56 -0
  265. package/src/lint/post-synth/tf047.ts +114 -0
  266. package/src/lock-rows.test.ts +70 -0
  267. package/src/lock-rows.ts +82 -0
  268. package/src/lock-timeout.ts +34 -0
  269. package/src/module-catalog/index.test.ts +93 -0
  270. package/src/module-catalog/index.ts +159 -0
  271. package/src/module-catalog/refresh-cli.ts +68 -0
  272. package/src/module-catalog/static-tier.ts +1659 -0
  273. package/src/module-catalog/types.ts +88 -0
  274. package/src/op/activities/terraform.ts +46 -5
  275. package/src/op-wave-step.test.ts +109 -0
  276. package/src/pin/__fixtures__/consumers/live/dev/main.tf +4 -0
  277. package/src/pin/__fixtures__/consumers/live/prod/main.tf +21 -0
  278. package/src/pin/__fixtures__/consumers/units/vpc/terragrunt.hcl +7 -0
  279. package/src/pin/consumers.test.ts +57 -0
  280. package/src/pin/consumers.ts +95 -0
  281. package/src/plugin.ts +6 -0
  282. package/src/registry/__fixtures__/docs/documented/.terraform-docs.yml +3 -0
  283. package/src/registry/__fixtures__/docs/documented/README.md +1 -0
  284. package/src/registry/__fixtures__/docs/documented/main.tf +8 -0
  285. package/src/registry/__fixtures__/docs/json/main.tf.json +14 -0
  286. package/src/registry/__fixtures__/docs/vpc/README.md +3 -0
  287. package/src/registry/__fixtures__/docs/vpc/examples/complete/main.tf +5 -0
  288. package/src/registry/__fixtures__/docs/vpc/examples/simple/README.md +1 -0
  289. package/src/registry/__fixtures__/docs/vpc/examples/simple/main.tf +4 -0
  290. package/src/registry/__fixtures__/docs/vpc/main.tf +14 -0
  291. package/src/registry/__fixtures__/docs/vpc/outputs.tf +9 -0
  292. package/src/registry/__fixtures__/docs/vpc/variables.tf +16 -0
  293. package/src/registry/__fixtures__/proxied-root/main.tf +12 -0
  294. package/src/registry/address.ts +100 -0
  295. package/src/registry/catalog-read.ts +56 -0
  296. package/src/registry/deprecated.test.ts +139 -0
  297. package/src/registry/deprecated.ts +76 -0
  298. package/src/registry/docs.test.ts +140 -0
  299. package/src/registry/docs.ts +299 -0
  300. package/src/registry/edge/bundle.test.ts +50 -0
  301. package/src/registry/edge/edge.test.ts +176 -0
  302. package/src/registry/edge/edge.ts +211 -0
  303. package/src/registry/edge/index.ts +10 -0
  304. package/src/registry/edge/lambda-edge.ts +127 -0
  305. package/src/registry/edge/sigv4-web.ts +79 -0
  306. package/src/registry/edge/token-source.test.ts +258 -0
  307. package/src/registry/edge/token-source.ts +169 -0
  308. package/src/registry/edge/worker.ts +61 -0
  309. package/src/registry/handler.ts +89 -0
  310. package/src/registry/headers-file.ts +61 -0
  311. package/src/registry/index.ts +31 -0
  312. package/src/registry/mirror-paths.ts +10 -0
  313. package/src/registry/mirror.test.ts +198 -0
  314. package/src/registry/mirror.ts +395 -0
  315. package/src/registry/proxies.test.ts +153 -0
  316. package/src/registry/proxies.ts +132 -0
  317. package/src/registry/reader.ts +225 -0
  318. package/src/registry/registry.test.ts +262 -0
  319. package/src/registry/semver.ts +34 -0
  320. package/src/registry/serve.ts +82 -0
  321. package/src/registry/source-forms.test.ts +87 -0
  322. package/src/registry/source-forms.ts +216 -0
  323. package/src/registry/targets/artifactory.test.ts +248 -0
  324. package/src/registry/targets/artifactory.ts +257 -0
  325. package/src/registry/targets/fake-artifactory.ts +158 -0
  326. package/src/registry/targets/fake-gitlab.ts +161 -0
  327. package/src/registry/targets/fake-hcp.ts +233 -0
  328. package/src/registry/targets/fake-http.ts +97 -0
  329. package/src/registry/targets/fake-nexus.ts +152 -0
  330. package/src/registry/targets/gitlab.test.ts +208 -0
  331. package/src/registry/targets/gitlab.ts +223 -0
  332. package/src/registry/targets/hcp.test.ts +230 -0
  333. package/src/registry/targets/hcp.ts +360 -0
  334. package/src/registry/targets/hosted.ts +117 -0
  335. package/src/registry/targets/index.ts +17 -0
  336. package/src/registry/targets/module-target.ts +131 -0
  337. package/src/registry/targets/nexus.test.ts +220 -0
  338. package/src/registry/targets/nexus.ts +314 -0
  339. package/src/registry/targets/zip.test.ts +65 -0
  340. package/src/registry/targets/zip.ts +287 -0
  341. package/src/registry/writer.ts +155 -0
  342. package/src/state/azure-blob.ts +6 -221
  343. package/src/state/gcs.ts +5 -252
  344. package/src/state/object-store.ts +4 -32
  345. package/src/state/s3.ts +10 -182
  346. package/src/state/store.ts +2 -2
  347. package/src/state-ops.test.ts +182 -0
  348. package/src/state-ops.ts +462 -0
  349. package/src/state-reads.ts +116 -0
  350. package/src/used-sources.test.ts +75 -0
  351. package/src/used-sources.ts +204 -0
package/README.md CHANGED
@@ -1,9 +1,12 @@
1
1
  # @intentius/chant-lexicon-terraform
2
2
 
3
- Terraform lexicon plugin for [chant](https://github.com/intentius/chant).
3
+ Terraform and OpenTofu lexicon for [chant](https://github.com/intentius/chant).
4
+ It reads your roots as they are, and runs them on terraform, tofu or
5
+ [choudoufu](https://github.com/INTENTIUS/choudoufu), an OpenTofu fork that
6
+ keeps ownership as markers on the resources.
4
7
 
5
- Unlike the lexicons that generate typed resource classes from an upstream
6
- schema, this one reads the HCL an estate already has. Name your root modules in
8
+ This lexicon reads the HCL an estate already has, where other lexicons
9
+ generate typed resource classes from an upstream schema. Name your root modules in
7
10
  `chant.config.ts` and each `.tf` block joins the build as an entity, so the
8
11
  post-synth checks and `chant audit` can see the root without anything being
9
12
  written back over it.
@@ -16,7 +19,7 @@ import "@intentius/chant-lexicon-terraform";
16
19
  export default {
17
20
  lexicons: ["terraform"],
18
21
  terraform: {
19
- binary: "terraform", // or "tofu"
22
+ binary: "terraform", // or "tofu", or "choudoufu" for ownership markers
20
23
  roots: {
21
24
  app: { dir: "./terraform", workspace: "prod", varFiles: ["prod.tfvars"] },
22
25
  },
@@ -0,0 +1,11 @@
1
+ /** The choudoufu release the default lines install. A product's images pin their own. */
2
+ export declare const CHOUDOUFU_CI_VERSION = "0.31.0";
3
+ /** choudoufu into /usr/local/bin from its release archive. */
4
+ export declare function choudoufuInstallLine(version?: string): string;
5
+ /** Whether the project's config names choudoufu as a root's binary. */
6
+ export declare function usesChoudoufu(dir: string): boolean;
7
+ /** The lines for the project at `dir`. */
8
+ export declare function terraformCiSetup(ctx: {
9
+ dir: string;
10
+ }): string[];
11
+ //# sourceMappingURL=ci-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-setup.d.ts","sourceRoot":"","sources":["../src/ci-setup.ts"],"names":[],"mappings":"AAcA,yFAAyF;AACzF,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,OAAO,SAAuB,GAAG,MAAM,CAI3E;AAED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAWlD;AAED,0CAA0C;AAC1C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,EAAE,CAE/D"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The engine install lines a Terraform project's pull request pipeline runs
3
+ * in chant's default image (#4550, `LexiconPlugin.ciSetup`): OpenTofu, and
4
+ * choudoufu when a root runs it. Each line skips the install when the binary
5
+ * is already on PATH.
6
+ *
7
+ * Whether a root runs choudoufu is read from the text of the project's
8
+ * `chant.config.ts` (`binary: "choudoufu"`), never by running it, as lexicon
9
+ * detection reads source.
10
+ */
11
+ import { existsSync, readFileSync } from "node:fs";
12
+ import { join } from "node:path";
13
+ import { PR_LOOP_SETUP } from "@intentius/chant/components/pr-pipeline";
14
+ /** The choudoufu release the default lines install. A product's images pin their own. */
15
+ export const CHOUDOUFU_CI_VERSION = "0.31.0";
16
+ /** choudoufu into /usr/local/bin from its release archive. */
17
+ export function choudoufuInstallLine(version = CHOUDOUFU_CI_VERSION) {
18
+ const arch = `$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')`;
19
+ const url = `https://github.com/INTENTIUS/choudoufu/releases/download/v${version}/choudoufu_v${version}_linux_${arch}.tar.gz`;
20
+ return `command -v choudoufu >/dev/null 2>&1 || (mkdir -p /tmp/choudoufu && curl -fsSL "${url}" | tar -xz -C /tmp/choudoufu && install "$(find /tmp/choudoufu -type f -name choudoufu | head -n 1)" /usr/local/bin/choudoufu)`;
21
+ }
22
+ /** Whether the project's config names choudoufu as a root's binary. */
23
+ export function usesChoudoufu(dir) {
24
+ for (const name of ["chant.config.ts", "chant.config.mts", "chant.config.js"]) {
25
+ const file = join(dir, name);
26
+ if (!existsSync(file))
27
+ continue;
28
+ try {
29
+ if (/binary\s*:\s*["']choudoufu["']/.test(readFileSync(file, "utf-8")))
30
+ return true;
31
+ }
32
+ catch {
33
+ // unreadable: no choudoufu line
34
+ }
35
+ }
36
+ return false;
37
+ }
38
+ /** The lines for the project at `dir`. */
39
+ export function terraformCiSetup(ctx) {
40
+ return [...PR_LOOP_SETUP, ...(usesChoudoufu(ctx.dir) ? [choudoufuInstallLine()] : [])];
41
+ }
@@ -22,7 +22,7 @@
22
22
  * system and refuses with exit 3 when its fresh plan differs (choudoufu
23
23
  * #878). Either refusal fails the step. choudoufu's refusal of a plan the
24
24
  * wave handed `run` throws {@link TerraformPlanMovedError}, so the command
25
- * that applied it exits 3 (#3997). terraform's and tofu's stale-plan error
25
+ * that applied it exits 4, the table's moved code (#3997, #4553). terraform's and tofu's stale-plan error
26
26
  * is not classified and exits 1.
27
27
  *
28
28
  * Run without a wave plan (`chant run --components`, or a fan-out with no
@@ -100,11 +100,34 @@
100
100
  * read the way `plan` reads a root's (`terraformPlannedOutputs`). The member
101
101
  * is not a `terraform.roots` entry of the reading project; its directory
102
102
  * comes from the workspace declaration.
103
+ *
104
+ * ## Op waves (#4545)
105
+ *
106
+ * The step is what an op wave's `step` names to plan and apply each root
107
+ * through chant (`chant run wave`), so terragucci's waves and plywood's run
108
+ * the engine in chant. Three inputs come from terragucci's wave callbacks:
109
+ *
110
+ * - `lockTimeout` (default `5m`, `false` for none): `plan` and `apply` wait
111
+ * that long for another run's state lock, unless `TF_CLI_ARGS` sets
112
+ * `-lock-timeout` already (`../lock-timeout.ts`).
113
+ * - `cone`: a revision. A live choudoufu root plans the cone of the change
114
+ * since it (`plan -cone`, `../cone.ts`), and the cone's targets join the
115
+ * plan digest, so an approval of one cone counts for no other. Such a root
116
+ * plans with `plan`, never as a one-root set.
117
+ * - `reads`: vars read from another root's outputs, Atmos's
118
+ * `!terraform.state` (`../state-reads.ts`). An upstream with no such output
119
+ * yet makes the member a hole naming it, so the root is never planned on a
120
+ * stand-in.
121
+ *
122
+ * Every plan also writes its `show -json` beside the plan file and names it
123
+ * as `artifact.planJson`, the document a wave's cost hold prices
124
+ * (`../cost-hold.ts`).
103
125
  */
104
126
  import type { Capability, PlannedOutputs } from "@intentius/chant/components/capability";
105
127
  import { type PlanShapeArtifact } from "@intentius/chant/components/covered-round";
106
128
  import { type CapabilityPlugin } from "@intentius/chant/components/capability-plugin";
107
129
  import type { EngineOutputSource, EnginePlannedOutputs } from "@intentius/chant/components/verbs/member-outputs";
130
+ import { type TerraformStateRead } from "../state-reads.js";
108
131
  /** The `terraform-apply` step's input. */
109
132
  export interface TerraformApplyStepInput {
110
133
  /** Key into `terraform.roots`. Also the member's name in a wave's set digest. */
@@ -113,6 +136,14 @@ export interface TerraformApplyStepInput {
113
136
  vars?: Record<string, unknown>;
114
137
  /** Where the `chant.config.*` search starts. Default: the current directory. */
115
138
  cwd?: string;
139
+ /** The root's files from here instead of its entry's `dir` (#4542): a promote under a release sets it to the recorded copy. */
140
+ dir?: string;
141
+ /** How long `plan` and `apply` wait for a state lock (#4545). Default `"5m"`; `false` passes no flag. */
142
+ lockTimeout?: string | false;
143
+ /** choudoufu live roots (#4545): plan the cone of the change since this revision. */
144
+ cone?: string;
145
+ /** Vars read from other roots' outputs (#4545), Atmos's `!terraform.state`. The step's `vars` win over them. */
146
+ reads?: TerraformStateRead[];
116
147
  }
117
148
  /** What `terraform-apply` returns. `outputs` is what a dependent's `stackOutput()` reads. */
118
149
  export interface TerraformApplyStepOutput {
@@ -155,11 +186,12 @@ export interface TerraformShapeArtifact extends PlanShapeArtifact {
155
186
  kind: "terraform-apply-shape";
156
187
  }
157
188
  /**
158
- * choudoufu refused the plan `run` was handed by its wave (its exit 3):
159
- * the live system moved since the plan, or the plan names another estate.
160
- * Nothing was applied. `planMoved` is core's mark for a moved plan
161
- * (`isPlanMovedError`), so the command that applied it exits 3, as for the
162
- * other capabilities that refuse a moved plan (#3997).
189
+ * choudoufu refused the plan `run` was handed by its wave (its exit 3)
190
+ * because the live system moved since the plan. Nothing was applied.
191
+ * `planMoved` is core's mark for a moved plan (`isPlanMovedError`), so the
192
+ * command that applied it exits `CHANT_EXIT.moved`, 4, as for the other
193
+ * capabilities that refuse a moved plan (#3997, #4553). A plan made against
194
+ * another estate is a plain failure (`terraformExitOf` in ../exit-codes).
163
195
  */
164
196
  export declare class TerraformPlanMovedError extends Error {
165
197
  readonly root: string;
@@ -169,6 +201,8 @@ export declare class TerraformPlanMovedError extends Error {
169
201
  export declare const terraformApplyCapability: Capability<TerraformApplyStepInput, TerraformApplyStepOutput>;
170
202
  export declare const TERRAFORM_VERB_FAMILIES: {
171
203
  readonly apply: readonly ["terraform-apply"];
204
+ readonly state: readonly ["terraform-state-unlock", "terraform-state-push"];
205
+ readonly copy: readonly ["terraform-copy"];
172
206
  };
173
207
  export declare const terraformCapabilityPlugin: CapabilityPlugin;
174
208
  //# sourceMappingURL=capability-plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"capability-plugin.d.ts","sourceRoot":"","sources":["../../src/components/capability-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsGG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAiC,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAExH,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,2CAA2C,CAAC;AAGnD,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AACzG,OAAO,KAAK,EAAmB,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,kDAAkD,CAAC;AAoBlI,0CAA0C;AAC1C,MAAM,WAAW,uBAAuB;IACtC,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,6FAA6F;AAC7F,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,YAAY,EAAE,OAAO,CAAC;IACtB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AA8CD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAerE;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,oBAAoB,CAEhI;AAID;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,kBAInC,CAAC;AA4BF,4GAA4G;AAC5G,eAAO,MAAM,iBAAiB,0BAA0B,CAAC;AAEzD,iHAAiH;AACjH,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,IAAI,EAAE,uBAAuB,CAAC;CAC/B;AAqFD;;;;;;GAMG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;aAEpB,IAAI,EAAE,MAAM;IADxC,QAAQ,CAAC,SAAS,QAAQ;IAC1B,YAA4B,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAGxD;CACF;AA+CD,eAAO,MAAM,wBAAwB,EAAE,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CA8ElG,CAAC;AAEF,eAAO,MAAM,uBAAuB;aAClC,KAAK,YAAG,iBAAiB;CACjB,CAAC;AAEX,eAAO,MAAM,yBAAyB,EAAE,gBAcvC,CAAC"}
1
+ {"version":3,"file":"capability-plugin.d.ts","sourceRoot":"","sources":["../../src/components/capability-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4HG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAiC,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAExH,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,2CAA2C,CAAC;AAGnD,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AACzG,OAAO,KAAK,EAAmB,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,kDAAkD,CAAC;AA0BlI,OAAO,EAA0D,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGjH,0CAA0C;AAC1C,MAAM,WAAW,uBAAuB;IACtC,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+HAA+H;IAC/H,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yGAAyG;IACzG,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC7B,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gHAAgH;IAChH,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAC9B;AAED,6FAA6F;AAC7F,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,YAAY,EAAE,OAAO,CAAC;IACtB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAyGD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAerE;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,oBAAoB,CAEhI;AAID;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,kBAInC,CAAC;AA4BF,4GAA4G;AAC5G,eAAO,MAAM,iBAAiB,0BAA0B,CAAC;AAEzD,iHAAiH;AACjH,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,IAAI,EAAE,uBAAuB,CAAC;CAC/B;AAsFD;;;;;;;GAOG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;aAEpB,IAAI,EAAE,MAAM;IADxC,QAAQ,CAAC,SAAS,QAAQ;IAC1B,YAA4B,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAGxD;CACF;AA6DD,eAAO,MAAM,wBAAwB,EAAE,UAAU,CAAC,uBAAuB,EAAE,wBAAwB,CAmHlG,CAAC;AAEF,eAAO,MAAM,uBAAuB;aAClC,KAAK,YAAG,iBAAiB;aAEzB,KAAK,YAAG,wBAAwB,EAAE,sBAAsB;aACxD,IAAI,YAAG,gBAAgB;CACf,CAAC;AAEX,eAAO,MAAM,yBAAyB,EAAE,gBAcvC,CAAC"}
@@ -22,7 +22,7 @@
22
22
  * system and refuses with exit 3 when its fresh plan differs (choudoufu
23
23
  * #878). Either refusal fails the step. choudoufu's refusal of a plan the
24
24
  * wave handed `run` throws {@link TerraformPlanMovedError}, so the command
25
- * that applied it exits 3 (#3997). terraform's and tofu's stale-plan error
25
+ * that applied it exits 4, the table's moved code (#3997, #4553). terraform's and tofu's stale-plan error
26
26
  * is not classified and exits 1.
27
27
  *
28
28
  * Run without a wave plan (`chant run --components`, or a fan-out with no
@@ -100,21 +100,92 @@
100
100
  * read the way `plan` reads a root's (`terraformPlannedOutputs`). The member
101
101
  * is not a `terraform.roots` entry of the reading project; its directory
102
102
  * comes from the workspace declaration.
103
+ *
104
+ * ## Op waves (#4545)
105
+ *
106
+ * The step is what an op wave's `step` names to plan and apply each root
107
+ * through chant (`chant run wave`), so terragucci's waves and plywood's run
108
+ * the engine in chant. Three inputs come from terragucci's wave callbacks:
109
+ *
110
+ * - `lockTimeout` (default `5m`, `false` for none): `plan` and `apply` wait
111
+ * that long for another run's state lock, unless `TF_CLI_ARGS` sets
112
+ * `-lock-timeout` already (`../lock-timeout.ts`).
113
+ * - `cone`: a revision. A live choudoufu root plans the cone of the change
114
+ * since it (`plan -cone`, `../cone.ts`), and the cone's targets join the
115
+ * plan digest, so an approval of one cone counts for no other. Such a root
116
+ * plans with `plan`, never as a one-root set.
117
+ * - `reads`: vars read from another root's outputs, Atmos's
118
+ * `!terraform.state` (`../state-reads.ts`). An upstream with no such output
119
+ * yet makes the member a hole naming it, so the root is never planned on a
120
+ * stand-in.
121
+ *
122
+ * Every plan also writes its `show -json` beside the plan file and names it
123
+ * as `artifact.planJson`, the document a wave's cost hold prices
124
+ * (`../cost-hold.ts`).
103
125
  */
104
- import { rmSync } from "node:fs";
126
+ import { rmSync, writeFileSync } from "node:fs";
105
127
  import { dirname, join, resolve } from "node:path";
106
128
  import { loadChantConfigUpward } from "@intentius/chant/config";
107
129
  import { PlanShapeMovedError, planShapeDifferences, planShapeDigest, } from "@intentius/chant/components/covered-round";
108
130
  import { computePlanDigest } from "@intentius/chant/lifecycle/plan-digest";
109
131
  import { ownPackageVersion } from "@intentius/chant/components/capability-plugin";
110
132
  import { choudoufuMemberOutputs, choudoufuMemberPlanSet, choudoufuPlanSet, choudoufuWaveApply, choudoufuWaveRoot, terraformApply, terraformInit, terraformOutputs, terraformPlan, } from "../op/activities/terraform.js";
133
+ import { terraformPlanMoved } from "../exit-codes.js";
111
134
  import { terraformPlanShape } from "../plan-shape.js";
112
- import { terraformChangeSetPart } from "../change-set.js";
135
+ import { plannerForBinary, terraformChangeSetPart } from "../change-set.js";
136
+ import { terraformDefaultLockGrain, terraformLockGrainRefusal, terraformLockRows, terraformLockRowsFromPart } from "../lock-rows.js";
113
137
  import { rootTexts } from "../compose/hcl.js";
114
138
  import { declaredVariables } from "../compose/root.js";
115
139
  import { terraformComposeGroup } from "./compose-group.js";
116
140
  import { markPlaceholderDriven, placeholderVars, waitingHole } from "./placeholder-preview.js";
117
- const rootArgs = (input) => ({ root: input.root, ...(input.cwd ? { cwd: input.cwd } : {}) });
141
+ import { terraformReleaseInputs } from "./release-inputs.js";
142
+ import { terraformTraceFacts } from "./trace-facts.js";
143
+ import { DEFAULT_LOCK_TIMEOUT, isLockTimeout } from "../lock-timeout.js";
144
+ import { conePlanDigest } from "../cone.js";
145
+ import { fillStateReads, stateReadsProblems, waitingReadsReason } from "../state-reads.js";
146
+ import { terraformStateOpCapabilities } from "../state-ops.js";
147
+ /** The lock timeout a step's plan and apply pass (#4545). */
148
+ function lockTimeoutOf(input) {
149
+ if (input.lockTimeout === false)
150
+ return {};
151
+ const value = input.lockTimeout ?? DEFAULT_LOCK_TIMEOUT;
152
+ if (!isLockTimeout(value))
153
+ throw new Error(`terraform-apply: root "${input.root}": lockTimeout "${String(value)}" is not a duration such as "5m"`);
154
+ return { lockTimeout: value };
155
+ }
156
+ /**
157
+ * The step's input with its `reads` filled (#4545): each upstream's outputs
158
+ * read once, the values under the step's own `vars`. `waiting` when an
159
+ * upstream has no such output yet. Throws when a state cannot be read.
160
+ */
161
+ async function withReads(input) {
162
+ const reads = input.reads ?? [];
163
+ if (reads.length === 0)
164
+ return { input };
165
+ const problems = stateReadsProblems(reads);
166
+ if (problems.length > 0)
167
+ throw new Error(`terraform-apply: root "${input.root}": ${problems.join("; ")}`);
168
+ const filled = await fillStateReads(reads, async (root) => {
169
+ const at = { root, ...(input.cwd ? { cwd: input.cwd } : {}) };
170
+ await terraformInit(at);
171
+ return terraformOutputs(at);
172
+ });
173
+ if (filled.errors.length > 0)
174
+ throw new Error(`terraform-apply: root "${input.root}": ${filled.errors.join("; ")}`);
175
+ if (filled.waiting.length > 0)
176
+ return { waiting: waitingReadsReason(filled.waiting), upstreams: [...new Set(filled.waiting.map((w) => w.read.root))].sort() };
177
+ return { input: { ...input, vars: { ...filled.vars, ...(input.vars ?? {}) } } };
178
+ }
179
+ /** A root whose reads wait on an upstream (#4545): a hole naming it, and a digest over the root and those upstreams. */
180
+ function waitingOnReads(ctx, input, waiting) {
181
+ const planDigest = computePlanDigest("terraform-apply-reads-waiting", { env: ctx.env, root: input.root, upstreams: waiting.upstreams });
182
+ const changeSet = {
183
+ member: { member: input.root, lexicon: "terraform", planner: "chant", status: "planned", planDigest, holes: [{ address: input.root, type: "terraform_root", reason: waiting.waiting }] },
184
+ entries: [],
185
+ };
186
+ return { member: input.root, planDigest, changeSet };
187
+ }
188
+ const rootArgs = (input) => ({ root: input.root, ...(input.cwd ? { cwd: input.cwd } : {}), ...(input.dir ? { dir: input.dir } : {}) });
118
189
  function requireRoot(input) {
119
190
  if (typeof input.root !== "string" || input.root === "") {
120
191
  throw new Error('terraform-apply: "root" is required and names an entry in terraform.roots');
@@ -130,12 +201,28 @@ async function planRoot(input, targets) {
130
201
  ...rootArgs(input),
131
202
  ...(input.vars ? { vars: input.vars } : {}),
132
203
  ...(targets && targets.length > 0 ? { targets } : {}),
204
+ ...lockTimeoutOf(input),
205
+ ...(input.cone && !(targets && targets.length > 0) ? { cone: input.cone } : {}),
133
206
  text: false,
134
207
  });
208
+ // #4545: the cone's targets join the digest, so an approval of this cone counts for no other.
209
+ const planDigest = conePlanDigest(planned.planDigest, planned.cone);
210
+ const changeSet = planned.changeSet && planDigest !== planned.planDigest ? { ...planned.changeSet, member: { ...planned.changeSet.member, planDigest } } : planned.changeSet;
211
+ // #4545: the plan document beside the plan file, which a wave's cost hold prices.
212
+ const planJson = join(planned.dir, `${planned.planFile}.json`);
213
+ let wrote = true;
214
+ try {
215
+ writeFileSync(planJson, JSON.stringify(planned.json));
216
+ }
217
+ catch {
218
+ wrote = false;
219
+ }
135
220
  return {
136
221
  planFile: planned.planFile,
137
- planDigest: planned.planDigest,
138
- ...(planned.changeSet ? { changeSet: planned.changeSet } : {}),
222
+ planDigest,
223
+ ...(wrote ? { planJson } : {}),
224
+ ...(planned.cone ? { cone: planned.cone } : {}),
225
+ ...(changeSet ? { changeSet } : {}),
139
226
  json: planned.json,
140
227
  };
141
228
  }
@@ -231,9 +318,10 @@ async function rootDir(input) {
231
318
  const start = resolve(input.cwd ?? process.cwd());
232
319
  const { config, configPath } = await loadChantConfigUpward(start);
233
320
  const terraform = config.terraform;
234
- const dir = terraform?.roots?.[input.root]?.dir;
235
- if (dir === undefined)
321
+ const declared = terraform?.roots?.[input.root]?.dir;
322
+ if (declared === undefined)
236
323
  return undefined;
324
+ const dir = input.dir ?? declared;
237
325
  return { dir: resolve(configPath ? dirname(configPath) : start, dir), ...(terraform?.binary ? { binary: terraform.binary } : {}) };
238
326
  }
239
327
  const firstLines = (err) => {
@@ -308,11 +396,12 @@ async function previewRoot(ctx, input, unresolved, targets) {
308
396
  };
309
397
  }
310
398
  /**
311
- * choudoufu refused the plan `run` was handed by its wave (its exit 3):
312
- * the live system moved since the plan, or the plan names another estate.
313
- * Nothing was applied. `planMoved` is core's mark for a moved plan
314
- * (`isPlanMovedError`), so the command that applied it exits 3, as for the
315
- * other capabilities that refuse a moved plan (#3997).
399
+ * choudoufu refused the plan `run` was handed by its wave (its exit 3)
400
+ * because the live system moved since the plan. Nothing was applied.
401
+ * `planMoved` is core's mark for a moved plan (`isPlanMovedError`), so the
402
+ * command that applied it exits `CHANT_EXIT.moved`, 4, as for the other
403
+ * capabilities that refuse a moved plan (#3997, #4553). A plan made against
404
+ * another estate is a plain failure (`terraformExitOf` in ../exit-codes).
316
405
  */
317
406
  export class TerraformPlanMovedError extends Error {
318
407
  constructor(root, message) {
@@ -322,8 +411,6 @@ export class TerraformPlanMovedError extends Error {
322
411
  this.name = "TerraformPlanMovedError";
323
412
  }
324
413
  }
325
- /** `live-wave-apply`'s exit status for a set whose plan moved (`CHOUDOUFU_WAVE_EXIT.setMoved`). */
326
- const CHOUDOUFU_SET_MOVED_EXIT = 3;
327
414
  function isPlannedRoot(value) {
328
415
  const v = value;
329
416
  return typeof v?.planFile === "string" && typeof v.planDigest === "string";
@@ -346,13 +433,28 @@ async function runChoudoufuWave(ctx, input, planned) {
346
433
  ctx.carry?.(input.root, applied.carry);
347
434
  if (!applied.landed) {
348
435
  const message = `terraform-apply: root "${input.root}": ${applied.message}`;
349
- if (applied.exitCode === CHOUDOUFU_SET_MOVED_EXIT)
436
+ if (terraformPlanMoved({ command: "live-wave-apply", code: applied.exitCode }))
350
437
  throw new TerraformPlanMovedError(input.root, message);
351
438
  throw new Error(message);
352
439
  }
353
440
  const outputs = await terraformOutputs(rootArgs(input));
354
441
  return { root: input.root, planDigest: planned.planDigest, fromWavePlan: true, outputs };
355
442
  }
443
+ /** The input a `run` that plans for itself plans with (#4545): its reads filled, or an error naming the upstream to apply first. */
444
+ async function readsForRun(input) {
445
+ const read = await withReads(input);
446
+ if ("waiting" in read)
447
+ throw new Error(`terraform-apply: root "${input.root}": ${read.waiting}`);
448
+ return read.input;
449
+ }
450
+ /** The engine a root plans with (#4552): the configured binary's, else the plan's planner. */
451
+ async function plannerOf(input, plan) {
452
+ const binary = (await rootDir(input).catch(() => undefined))?.binary;
453
+ if (binary !== undefined)
454
+ return plannerForBinary(binary);
455
+ const planner = plan?.changeSet?.member.planner;
456
+ return planner === "terraform" || planner === "tofu" || planner === "choudoufu" ? planner : "terraform";
457
+ }
356
458
  export const terraformApplyCapability = {
357
459
  kind: "terraform-apply",
358
460
  // A root's apply has no undo short of applying the previous configuration,
@@ -360,27 +462,42 @@ export const terraformApplyCapability = {
360
462
  rollbackPolicy: "needs-opt-out",
361
463
  // #4300: `--target` passes through as `-target`, and the saved plan holds those addresses alone.
362
464
  targets: "accept",
363
- async plan(ctx, input) {
364
- requireRoot(input);
465
+ // #4627: `plan` refreshes the root's state before it plans unless told `-refresh=false`, which chant never passes,
466
+ // so `--refresh` asks for what every plan does and the digest still binds it. `-target` plans a resource with what it
467
+ // depends on and never what depends on it, so `--target-dependents` has nothing to map onto.
468
+ planFlags: {
469
+ refresh: "accept",
470
+ targetDependents: { refuse: "terraform and tofu plan a -target with what it depends on, never what depends on it, so there is no flag to widen it to its dependents; name each dependent with --target" },
471
+ },
472
+ async plan(ctx, given) {
473
+ requireRoot(given);
474
+ // #4545: a root reading an upstream's output that is not there yet is a hole naming the upstream.
475
+ const read = await withReads(given);
476
+ if ("waiting" in read)
477
+ return waitingOnReads(ctx, given, read);
478
+ const { input } = read;
365
479
  const unresolved = [...(ctx.unresolvedInputs ?? [])].sort();
366
480
  const targets = ctx.targets && ctx.targets.length > 0 ? ctx.targets : undefined;
367
481
  if (unresolved.length > 0)
368
482
  return previewRoot(ctx, input, unresolved, targets);
369
- // A targeted root plans with `plan -target`, never as a choudoufu one-root set.
370
- const wave = targets ? { wave: false } : await choudoufuWaveRoot({ ...rootArgs(input), ...(input.vars ? { vars: input.vars } : {}) });
483
+ // A targeted root plans with `plan -target`, and a cone plan with `plan -cone` (#4545), never as a choudoufu one-root set.
484
+ const wave = targets || input.cone ? { wave: false } : await choudoufuWaveRoot({ ...rootArgs(input), ...(input.vars ? { vars: input.vars } : {}) });
371
485
  if (wave.wave) {
372
486
  const set = await choudoufuPlanSet(rootArgs(input));
373
487
  const artifact = {
374
488
  planDigest: set.planDigest,
375
489
  choudoufu: { planSetFile: set.planSetFile, setDigest: set.setDigest },
490
+ lockRows: terraformLockRows(input.root, set.changeSet.member.scope, set.json),
376
491
  };
377
492
  return { member: input.root, planDigest: set.planDigest, artifact, changeSet: set.changeSet, outputs: terraformPlannedOutputs(set.json), shape: terraformPlanShape(set.json, input.root) };
378
493
  }
379
494
  const { changeSet, json, ...planned } = await planRoot(input, targets);
495
+ // #4552: a choudoufu root's rows, keyed from the plan document while it is at hand.
496
+ const lockRows = changeSet?.member.planner === "choudoufu" ? terraformLockRows(input.root, changeSet.member.scope, json) : undefined;
380
497
  return {
381
498
  member: input.root,
382
499
  planDigest: planned.planDigest,
383
- artifact: planned,
500
+ artifact: { ...planned, ...(lockRows ? { lockRows } : {}) },
384
501
  ...(changeSet ? { changeSet } : {}),
385
502
  outputs: terraformPlannedOutputs(json),
386
503
  shape: terraformPlanShape(json, input.root),
@@ -397,7 +514,30 @@ export const terraformApplyCapability = {
397
514
  // #4447 (ws-107): a group core forms of components that read each other plans and applies as one composed run
398
515
  // when `terraform.compose.enabled` is set (./compose-group.ts). Delegates, so the methods are read when called.
399
516
  groupReads: (ctx, members) => terraformComposeGroup.groupReads(ctx, members),
400
- groupFallback: (ctx, members) => terraformComposeGroup.groupFallback(ctx, members),
517
+ // #4542: a member pointed at a release's recorded copy plans alone, since a composition reads the declared roots.
518
+ groupFallback: async (ctx, members) => members.some((m) => typeof m.step.dir === "string")
519
+ ? { kind: "release-copy", reason: "a member deploys a release's recorded copy of its root, which a composition does not read" }
520
+ : terraformComposeGroup.groupFallback(ctx, members),
521
+ // #4542: the root's files, which a release cut records and a promote under it plans.
522
+ releaseInputs: (input, ctx) => terraformReleaseInputs(input, ctx),
523
+ // #4552: resource under choudoufu, the root under Terraform, tofu and Terragrunt, which refuse resource by name.
524
+ async defaultLockGrain(input, plan) {
525
+ return terraformDefaultLockGrain(await plannerOf(input, plan));
526
+ },
527
+ async lockGrainRefusal(input, grain, plan) {
528
+ if (grain !== "resource")
529
+ return undefined;
530
+ const binary = (await rootDir(input).catch(() => undefined))?.binary;
531
+ return terraformLockGrainRefusal(grain, await plannerOf(input, plan), binary);
532
+ },
533
+ lockRows(input, plan) {
534
+ const kept = plan.artifact?.lockRows;
535
+ if (Array.isArray(kept))
536
+ return kept;
537
+ return plan.changeSet ? terraformLockRowsFromPart(input.root, plan.changeSet) : [];
538
+ },
539
+ // #4555: the root and the binary, for the step's span and run record.
540
+ traceFacts: async (input, outcome) => terraformTraceFacts(input, outcome, (await rootDir(input).catch(() => undefined))?.binary),
401
541
  planGroup: (ctx, members) => terraformComposeGroup.planGroup(ctx, members),
402
542
  runGroup: (ctx, run, members) => terraformComposeGroup.runGroup(ctx, run, members),
403
543
  async run(ctx, input) {
@@ -407,11 +547,11 @@ export const terraformApplyCapability = {
407
547
  if (isShapeArtifact(fromWave)) {
408
548
  // A root previewed with stand-ins (#4463): plan it now with the real
409
549
  // values, and apply that plan only when it is within the preview's shape.
410
- const fresh = await planRoot(input, ctx.targets);
550
+ const fresh = await planRoot(await readsForRun(input), ctx.targets);
411
551
  const differences = planShapeDifferences(fromWave.shape, terraformPlanShape(fresh.json, input.root));
412
552
  if (differences.length > 0)
413
553
  throw new PlanShapeMovedError(input.root, differences);
414
- const applied = await terraformApply({ ...rootArgs(input), planFile: fresh.planFile });
554
+ const applied = await terraformApply({ ...rootArgs(input), planFile: fresh.planFile, ...lockTimeoutOf(input) });
415
555
  if (!applied.applied) {
416
556
  throw new Error(`terraform-apply: root "${input.root}" refused the plan it was given (${applied.refused ?? "refused"}). ${applied.refusal ?? ""}`);
417
557
  }
@@ -420,14 +560,15 @@ export const terraformApplyCapability = {
420
560
  }
421
561
  const planned = isPlannedRoot(fromWave)
422
562
  ? fromWave
423
- : await planRoot(input, ctx.targets).then(({ planFile, planDigest }) => ({ planFile, planDigest }));
424
- const applied = await terraformApply({ ...rootArgs(input), planFile: planned.planFile });
563
+ : await planRoot(await readsForRun(input), ctx.targets).then(({ planFile, planDigest }) => ({ planFile, planDigest }));
564
+ const applied = await terraformApply({ ...rootArgs(input), planFile: planned.planFile, ...lockTimeoutOf(input) });
425
565
  if (!applied.applied) {
426
566
  const message = `terraform-apply: root "${input.root}" refused the plan it was given (${applied.refused ?? "refused"}). ` +
427
567
  (applied.refusal ?? "");
428
- // A plan the wave approved that choudoufu refuses moved since the
429
- // approval. One this run made itself is planned afresh by the next run.
430
- if (applied.refused !== undefined && isPlannedRoot(fromWave))
568
+ // A plan the wave approved that choudoufu refuses as no longer matching
569
+ // moved since the approval (#4553: one made against another estate is a
570
+ // failure). One this run made itself is planned afresh by the next run.
571
+ if (applied.refused === "approval-mismatch" && isPlannedRoot(fromWave))
431
572
  throw new TerraformPlanMovedError(input.root, message);
432
573
  throw new Error(message);
433
574
  }
@@ -437,6 +578,9 @@ export const terraformApplyCapability = {
437
578
  };
438
579
  export const TERRAFORM_VERB_FAMILIES = {
439
580
  apply: ["terraform-apply"],
581
+ // #4618: the binary runs outside waves, each a fixed operation; the two that change state on their own run under a gated request.
582
+ state: ["terraform-state-unlock", "terraform-state-push"],
583
+ copy: ["terraform-copy"],
440
584
  };
441
585
  export const terraformCapabilityPlugin = {
442
586
  name: "terraform",
@@ -444,7 +588,7 @@ export const terraformCapabilityPlugin = {
444
588
  return ownPackageVersion(import.meta.url);
445
589
  },
446
590
  capabilities() {
447
- return [terraformApplyCapability];
591
+ return [terraformApplyCapability, ...terraformStateOpCapabilities.map((c) => c)];
448
592
  },
449
593
  families() {
450
594
  return TERRAFORM_VERB_FAMILIES;
@@ -132,7 +132,7 @@ export declare function groupFallbackOf(c: Composition, members: readonly string
132
132
  * them: `writeComposedRoot` turns those reads into literals.
133
133
  */
134
134
  export declare function outsideOutputs(members: readonly GroupMember<StepInput>[]): Record<string, Record<string, unknown>>;
135
- /** A composed plan that no longer matches the one approved. Core's moved-plan mark, so nothing applies and the command exits 3. */
135
+ /** A composed plan that no longer matches the one approved. Core's moved-plan mark, so nothing applies and the command exits `CHANT_EXIT.moved`, 4 (#4553). */
136
136
  export declare class ComposedPlanMovedError extends Error {
137
137
  readonly planMoved = true;
138
138
  constructor(message: string);
@@ -1 +1 @@
1
- {"version":3,"file":"compose-group.d.ts","sourceRoot":"","sources":["../../src/components/compose-group.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compose-group.d.ts","sourceRoot":"","sources":["../../src/components/compose-group.ts"],"names":[],"mappings":"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"}
@@ -251,7 +251,7 @@ function waitingGroup(ctx, members, unresolved) {
251
251
  }
252
252
  return { members: plans, digest: computePlanDigest("terraform-apply-group-unresolved", { components: ctx.components, unresolved: waits }) };
253
253
  }
254
- /** A composed plan that no longer matches the one approved. Core's moved-plan mark, so nothing applies and the command exits 3. */
254
+ /** A composed plan that no longer matches the one approved. Core's moved-plan mark, so nothing applies and the command exits `CHANT_EXIT.moved`, 4 (#4553). */
255
255
  export class ComposedPlanMovedError extends Error {
256
256
  constructor(message) {
257
257
  super(message);
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The files a release records for a `terraform-apply` step (chant#4542).
3
+ *
4
+ * The step names its root by key, so core can't see which files it deploys.
5
+ * `terraformReleaseInputs` answers core's `releaseInputs` with the set a
6
+ * pull request's plan treats as the root's change (`rootWatchPaths`): the
7
+ * root's directory, each local module it reaches, and its var files, plus
8
+ * its backend-config files. A release cut records them for the component,
9
+ * and a promote or rollback under the release writes them under
10
+ * `.chant/release-templates/<digest>/` and sets the step's `dir` to the copy
11
+ * of the root, so `terraform-apply` plans the release's configuration against
12
+ * the environment's state.
13
+ *
14
+ * A root whose state is a file in its own directory (the `local` backend) is
15
+ * unbound: a plan run in a copy elsewhere would read no state and propose
16
+ * creating everything. Such a root rolls back through `chant lifecycle
17
+ * rollback --to`. A live choudoufu root has no state file and is recorded.
18
+ */
19
+ import type { ReleaseInputs, ReleaseInputsContext, ReleaseInputsUnbound } from "@intentius/chant/components/capability";
20
+ /** The parts of the `terraform-apply` input this reads. */
21
+ interface StepInput {
22
+ root: string;
23
+ cwd?: string;
24
+ dir?: string;
25
+ }
26
+ /** What a release records for one `terraform-apply` step, relative to the member's directory. Null when the root is not declared. */
27
+ export declare function terraformReleaseInputs(input: StepInput, ctx: ReleaseInputsContext): Promise<ReleaseInputs | ReleaseInputsUnbound | null>;
28
+ export {};
29
+ //# sourceMappingURL=release-inputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-inputs.d.ts","sourceRoot":"","sources":["../../src/components/release-inputs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAOxH,2DAA2D;AAC3D,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAID,qIAAqI;AACrI,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,GAAG,oBAAoB,GAAG,IAAI,CAAC,CA+B9I"}