@intentius/chant-lexicon-terraform 0.57.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/composites/terraform-adopt-op.d.ts +126 -0
- package/dist/composites/terraform-adopt-op.d.ts.map +1 -0
- package/dist/composites/terraform-apply-op.d.ts +63 -16
- package/dist/composites/terraform-apply-op.d.ts.map +1 -1
- package/dist/composites/terraform-watch-op.d.ts +80 -36
- package/dist/composites/terraform-watch-op.d.ts.map +1 -1
- package/dist/config.d.ts +49 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/describe-resources.d.ts +256 -16
- package/dist/describe-resources.d.ts.map +1 -1
- package/dist/hcl/descend.d.ts +98 -0
- package/dist/hcl/descend.d.ts.map +1 -0
- package/dist/hcl/marker.d.ts +130 -0
- package/dist/hcl/marker.d.ts.map +1 -0
- package/dist/hcl/parse.d.ts +142 -9
- package/dist/hcl/parse.d.ts.map +1 -1
- package/dist/hcl/references.d.ts +76 -0
- package/dist/hcl/references.d.ts.map +1 -0
- package/dist/hcl/roots.d.ts +22 -3
- package/dist/hcl/roots.d.ts.map +1 -1
- package/dist/hcl/suppressions.d.ts +54 -0
- package/dist/hcl/suppressions.d.ts.map +1 -0
- package/dist/hcl/value.d.ts +77 -0
- package/dist/hcl/value.d.ts.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +32 -5
- package/dist/lint/audit-catalog.d.ts +3 -2
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/audit-lineage.d.ts +68 -0
- package/dist/lint/audit-lineage.d.ts.map +1 -1
- package/dist/lint/post-synth/blocks.d.ts +53 -0
- package/dist/lint/post-synth/blocks.d.ts.map +1 -0
- package/dist/lint/post-synth/fixtures/load.d.ts +37 -0
- package/dist/lint/post-synth/fixtures/load.d.ts.map +1 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/module-source.d.ts +38 -0
- package/dist/lint/post-synth/module-source.d.ts.map +1 -0
- package/dist/lint/post-synth/scope.d.ts +65 -0
- package/dist/lint/post-synth/scope.d.ts.map +1 -0
- package/dist/lint/post-synth/tf001.d.ts +18 -0
- package/dist/lint/post-synth/tf001.d.ts.map +1 -1
- package/dist/lint/post-synth/tf002.d.ts +32 -0
- package/dist/lint/post-synth/tf002.d.ts.map +1 -0
- package/dist/lint/post-synth/tf003.d.ts +22 -0
- package/dist/lint/post-synth/tf003.d.ts.map +1 -0
- package/dist/lint/post-synth/tf004.d.ts +22 -0
- package/dist/lint/post-synth/tf004.d.ts.map +1 -0
- package/dist/lint/post-synth/tf005.d.ts +28 -0
- package/dist/lint/post-synth/tf005.d.ts.map +1 -0
- package/dist/lint/post-synth/tf006.d.ts +21 -0
- package/dist/lint/post-synth/tf006.d.ts.map +1 -0
- package/dist/lint/post-synth/tf007.d.ts +21 -0
- package/dist/lint/post-synth/tf007.d.ts.map +1 -0
- package/dist/lint/post-synth/tf008.d.ts +22 -0
- package/dist/lint/post-synth/tf008.d.ts.map +1 -0
- package/dist/lint/post-synth/tf009.d.ts +24 -0
- package/dist/lint/post-synth/tf009.d.ts.map +1 -0
- package/dist/lint/post-synth/tf010.d.ts +19 -0
- package/dist/lint/post-synth/tf010.d.ts.map +1 -0
- package/dist/lint/post-synth/tf011.d.ts +18 -0
- package/dist/lint/post-synth/tf011.d.ts.map +1 -0
- package/dist/lint/post-synth/tf012.d.ts +17 -0
- package/dist/lint/post-synth/tf012.d.ts.map +1 -0
- package/dist/lint/post-synth/tf013.d.ts +21 -0
- package/dist/lint/post-synth/tf013.d.ts.map +1 -0
- package/dist/lint/post-synth/tf014.d.ts +25 -0
- package/dist/lint/post-synth/tf014.d.ts.map +1 -0
- package/dist/lint/post-synth/tf015.d.ts +21 -0
- package/dist/lint/post-synth/tf015.d.ts.map +1 -0
- package/dist/lint/post-synth/tf016.d.ts +30 -0
- package/dist/lint/post-synth/tf016.d.ts.map +1 -0
- package/dist/lint/post-synth/tf017.d.ts +19 -0
- package/dist/lint/post-synth/tf017.d.ts.map +1 -0
- package/dist/lint/post-synth/tf018.d.ts +20 -0
- package/dist/lint/post-synth/tf018.d.ts.map +1 -0
- package/dist/lint/post-synth/tf019.d.ts +25 -0
- package/dist/lint/post-synth/tf019.d.ts.map +1 -0
- package/dist/lint/post-synth/tf020.d.ts +38 -0
- package/dist/lint/post-synth/tf020.d.ts.map +1 -0
- package/dist/lint/post-synth/tf021.d.ts +41 -0
- package/dist/lint/post-synth/tf021.d.ts.map +1 -0
- package/dist/lint/post-synth/tf022.d.ts +24 -0
- package/dist/lint/post-synth/tf022.d.ts.map +1 -0
- package/dist/lint/post-synth/tf024.d.ts +24 -0
- package/dist/lint/post-synth/tf024.d.ts.map +1 -0
- package/dist/lint/post-synth/tf025.d.ts +29 -0
- package/dist/lint/post-synth/tf025.d.ts.map +1 -0
- package/dist/lint/post-synth/tf026.d.ts +21 -0
- package/dist/lint/post-synth/tf026.d.ts.map +1 -0
- package/dist/lint/rules/fixtures/load.d.ts +13 -0
- package/dist/lint/rules/fixtures/load.d.ts.map +1 -0
- package/dist/lint/rules/plan-before-apply.d.ts +11 -0
- package/dist/lint/rules/plan-before-apply.d.ts.map +1 -1
- package/dist/lint/secret-shape.d.ts +68 -0
- package/dist/lint/secret-shape.d.ts.map +1 -0
- package/dist/live-ownership.d.ts +55 -0
- package/dist/live-ownership.d.ts.map +1 -0
- package/dist/lsp/option-keys.d.ts.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/okf/index.md +24 -0
- package/dist/okf/rules/TF002.md +11 -0
- package/dist/okf/rules/TF003.md +11 -0
- package/dist/okf/rules/TF004.md +11 -0
- package/dist/okf/rules/TF005.md +11 -0
- package/dist/okf/rules/TF006.md +11 -0
- package/dist/okf/rules/TF007.md +11 -0
- package/dist/okf/rules/TF008.md +11 -0
- package/dist/okf/rules/TF009.md +11 -0
- package/dist/okf/rules/TF010.md +11 -0
- package/dist/okf/rules/TF011.md +11 -0
- package/dist/okf/rules/TF012.md +11 -0
- package/dist/okf/rules/TF013.md +11 -0
- package/dist/okf/rules/TF014.md +11 -0
- package/dist/okf/rules/TF015.md +11 -0
- package/dist/okf/rules/TF016.md +11 -0
- package/dist/okf/rules/TF017.md +11 -0
- package/dist/okf/rules/TF018.md +11 -0
- package/dist/okf/rules/TF019.md +11 -0
- package/dist/okf/rules/TF020.md +11 -0
- package/dist/okf/rules/TF021.md +11 -0
- package/dist/okf/rules/TF022.md +11 -0
- package/dist/okf/rules/TF024.md +11 -0
- package/dist/okf/rules/TF025.md +11 -0
- package/dist/okf/rules/TF026.md +11 -0
- package/dist/op/activities/index.d.ts +13 -6
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/live-detect.d.ts +51 -0
- package/dist/op/activities/live-detect.d.ts.map +1 -0
- package/dist/op/activities/terraform.d.ts +445 -17
- package/dist/op/activities/terraform.d.ts.map +1 -1
- package/dist/op/activity-contracts.d.ts +148 -0
- package/dist/op/activity-contracts.d.ts.map +1 -0
- package/dist/op/adoption.d.ts +118 -0
- package/dist/op/adoption.d.ts.map +1 -0
- package/dist/op/builders.d.ts +46 -6
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/resolve-root-mode.d.ts +45 -0
- package/dist/op/resolve-root-mode.d.ts.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/rules/blocks.ts +109 -0
- package/dist/rules/module-source.ts +121 -0
- package/dist/rules/plan-before-apply.ts +11 -0
- package/dist/rules/scope.ts +107 -0
- package/dist/rules/tf001.ts +32 -8
- package/dist/rules/tf002.ts +151 -0
- package/dist/rules/tf003.ts +71 -0
- package/dist/rules/tf004.ts +63 -0
- package/dist/rules/tf005.ts +76 -0
- package/dist/rules/tf006.ts +53 -0
- package/dist/rules/tf007.ts +78 -0
- package/dist/rules/tf008.ts +75 -0
- package/dist/rules/tf009.ts +59 -0
- package/dist/rules/tf010.ts +51 -0
- package/dist/rules/tf011.ts +49 -0
- package/dist/rules/tf012.ts +47 -0
- package/dist/rules/tf013.ts +63 -0
- package/dist/rules/tf014.ts +72 -0
- package/dist/rules/tf015.ts +63 -0
- package/dist/rules/tf016.ts +75 -0
- package/dist/rules/tf017.ts +50 -0
- package/dist/rules/tf018.ts +72 -0
- package/dist/rules/tf019.ts +72 -0
- package/dist/rules/tf020.ts +123 -0
- package/dist/rules/tf021.ts +126 -0
- package/dist/rules/tf022.ts +61 -0
- package/dist/rules/tf024.ts +70 -0
- package/dist/rules/tf025.ts +101 -0
- package/dist/rules/tf026.ts +80 -0
- package/dist/skills/chant-terraform.md +1 -1
- package/package.json +7 -2
- package/src/__fixtures__/live/main.tf +28 -0
- package/src/__fixtures__/live-adopt/estate.chdf.hcl +6 -0
- package/src/__fixtures__/live-adopt/main.tf +21 -0
- package/src/__fixtures__/live-estate/README.md +58 -0
- package/src/__fixtures__/live-estate/compute.tf +10 -0
- package/src/__fixtures__/live-estate/estate.chdf.hcl +1 -0
- package/src/__fixtures__/live-estate/logs.tf +8 -0
- package/src/__fixtures__/live-estate/network.tf +24 -0
- package/src/__fixtures__/live-estate/rule.tf +11 -0
- package/src/__fixtures__/live-estate/unowned.tf +21 -0
- package/src/__fixtures__/live-estate/versions.tf +31 -0
- package/src/__fixtures__/live-ls.json +98 -0
- package/src/__fixtures__/live-plan.json +285 -0
- package/src/__fixtures__/live-sidecar/estate.chdf.hcl +3 -0
- package/src/__fixtures__/live-sidecar/main.tf +24 -0
- package/src/__fixtures__/module-tree/README.md +16 -0
- package/src/__fixtures__/module-tree/cycle/main.tf +3 -0
- package/src/__fixtures__/module-tree/cycle/modules/a/main.tf +9 -0
- package/src/__fixtures__/module-tree/cycle/modules/b/main.tf +9 -0
- package/src/__fixtures__/module-tree/missing/main.tf +9 -0
- package/src/__fixtures__/module-tree/outside/root/main.tf +9 -0
- package/src/__fixtures__/module-tree/root/main.tf +28 -0
- package/src/__fixtures__/module-tree/root/modules/cdn/main.tf +15 -0
- package/src/__fixtures__/module-tree/root/modules/cdn/modules/bucket/main.tf +11 -0
- package/src/__fixtures__/module-tree/shared/main.tf +5 -0
- package/src/__fixtures__/references/main.tf +56 -0
- package/src/codegen/lint-rules-page.test.ts +28 -0
- package/src/composites/terraform-adopt-op.acceptance.test.ts +166 -0
- package/src/composites/terraform-adopt-op.test.ts +170 -0
- package/src/composites/terraform-adopt-op.ts +197 -0
- package/src/composites/terraform-apply-op.acceptance.test.ts +183 -5
- package/src/composites/terraform-apply-op.test.ts +167 -15
- package/src/composites/terraform-apply-op.ts +105 -28
- package/src/composites/terraform-watch-op.test.ts +85 -26
- package/src/composites/terraform-watch-op.ts +130 -73
- package/src/config.ts +32 -3
- package/src/describe-resources.live.test.ts +598 -0
- package/src/describe-resources.test.ts +53 -0
- package/src/describe-resources.ts +811 -28
- package/src/hcl/descend.test.ts +162 -0
- package/src/hcl/descend.ts +273 -0
- package/src/hcl/marker.test.ts +147 -0
- package/src/hcl/marker.ts +235 -0
- package/src/hcl/parse.test.ts +69 -0
- package/src/hcl/parse.ts +249 -27
- package/src/hcl/references.test.ts +116 -0
- package/src/hcl/references.ts +172 -0
- package/src/hcl/roots.ts +59 -5
- package/src/hcl/suppressions.test.ts +147 -0
- package/src/hcl/suppressions.ts +204 -0
- package/src/hcl/value.test.ts +73 -0
- package/src/hcl/value.ts +106 -0
- package/src/index.ts +31 -1
- package/src/lint/audit-catalog.ts +264 -3
- package/src/lint/audit-lineage.ts +319 -1
- package/src/lint/audit.test.ts +40 -1
- package/src/lint/post-synth/blocks.ts +109 -0
- package/src/lint/post-synth/fixtures/TF001/negative.tf +28 -0
- package/src/lint/post-synth/fixtures/TF001/positive.tf +24 -0
- package/src/lint/post-synth/fixtures/TF002/negative.tf +17 -0
- package/src/lint/post-synth/fixtures/TF002/positive-legacy.tf +10 -0
- package/src/lint/post-synth/fixtures/TF002/positive-no-version.tf +12 -0
- package/src/lint/post-synth/fixtures/TF002/positive.tf +7 -0
- package/src/lint/post-synth/fixtures/TF003/negative.tf +10 -0
- package/src/lint/post-synth/fixtures/TF003/positive.tf +8 -0
- package/src/lint/post-synth/fixtures/TF004/negative-git.tf +3 -0
- package/src/lint/post-synth/fixtures/TF004/negative-local.tf +3 -0
- package/src/lint/post-synth/fixtures/TF004/negative.tf +4 -0
- package/src/lint/post-synth/fixtures/TF004/positive.tf +3 -0
- package/src/lint/post-synth/fixtures/TF005/negative-local.tf +3 -0
- package/src/lint/post-synth/fixtures/TF005/negative-registry.tf +3 -0
- package/src/lint/post-synth/fixtures/TF005/negative-sha.tf +3 -0
- package/src/lint/post-synth/fixtures/TF005/negative.tf +3 -0
- package/src/lint/post-synth/fixtures/TF005/positive-branch.tf +3 -0
- package/src/lint/post-synth/fixtures/TF005/positive-non-semver.tf +3 -0
- package/src/lint/post-synth/fixtures/TF005/positive.tf +3 -0
- package/src/lint/post-synth/fixtures/TF006/negative.tf +5 -0
- package/src/lint/post-synth/fixtures/TF006/positive-empty-default.tf +11 -0
- package/src/lint/post-synth/fixtures/TF006/positive.tf +6 -0
- package/src/lint/post-synth/fixtures/TF007/negative.tf +10 -0
- package/src/lint/post-synth/fixtures/TF007/positive.tf +9 -0
- package/src/lint/post-synth/fixtures/TF008/negative-variable.tf +10 -0
- package/src/lint/post-synth/fixtures/TF008/negative.tf +8 -0
- package/src/lint/post-synth/fixtures/TF008/positive-other-provider.tf +10 -0
- package/src/lint/post-synth/fixtures/TF008/positive.tf +5 -0
- package/src/lint/post-synth/fixtures/TF009/negative.tf +10 -0
- package/src/lint/post-synth/fixtures/TF009/positive.tf +4 -0
- package/src/lint/post-synth/fixtures/TF010/negative.tf +5 -0
- package/src/lint/post-synth/fixtures/TF010/positive.tf +4 -0
- package/src/lint/post-synth/fixtures/TF011/negative.tf +5 -0
- package/src/lint/post-synth/fixtures/TF011/positive-blank.tf +5 -0
- package/src/lint/post-synth/fixtures/TF011/positive.tf +4 -0
- package/src/lint/post-synth/fixtures/TF012/negative.tf +4 -0
- package/src/lint/post-synth/fixtures/TF012/positive.tf +3 -0
- package/src/lint/post-synth/fixtures/TF013/negative.tf +8 -0
- package/src/lint/post-synth/fixtures/TF013/positive-data.tf +8 -0
- package/src/lint/post-synth/fixtures/TF013/positive.tf +8 -0
- package/src/lint/post-synth/fixtures/TF014/negative/main.tf +26 -0
- package/src/lint/post-synth/fixtures/TF014/negative/modules/cdn/main.tf +19 -0
- package/src/lint/post-synth/fixtures/TF014/positive/main.tf +16 -0
- package/src/lint/post-synth/fixtures/TF014/positive/modules/cdn/main.tf +15 -0
- package/src/lint/post-synth/fixtures/TF015/negative/main.tf +13 -0
- package/src/lint/post-synth/fixtures/TF015/negative/modules/cdn/main.tf +16 -0
- package/src/lint/post-synth/fixtures/TF015/positive/main.tf +13 -0
- package/src/lint/post-synth/fixtures/TF015/positive/modules/cdn/main.tf +14 -0
- package/src/lint/post-synth/fixtures/TF016/negative-template.tf +7 -0
- package/src/lint/post-synth/fixtures/TF016/negative.tf +16 -0
- package/src/lint/post-synth/fixtures/TF016/positive-shared-file.tf +12 -0
- package/src/lint/post-synth/fixtures/TF016/positive.tf +13 -0
- package/src/lint/post-synth/fixtures/TF017/negative.tf +4 -0
- package/src/lint/post-synth/fixtures/TF017/positive.tf +5 -0
- package/src/lint/post-synth/fixtures/TF018/negative.tf +9 -0
- package/src/lint/post-synth/fixtures/TF018/positive-data.tf +9 -0
- package/src/lint/post-synth/fixtures/TF018/positive.tf +4 -0
- package/src/lint/post-synth/fixtures/TF019/negative.tf +14 -0
- package/src/lint/post-synth/fixtures/TF019/positive-output.tf +5 -0
- package/src/lint/post-synth/fixtures/TF019/positive.tf +16 -0
- package/src/lint/post-synth/fixtures/TF020/negative.tf +43 -0
- package/src/lint/post-synth/fixtures/TF020/positive.tf +32 -0
- package/src/lint/post-synth/fixtures/TF020/scoped/main.tf +21 -0
- package/src/lint/post-synth/fixtures/TF020/scoped/modules/cdn/main.tf +13 -0
- package/src/lint/post-synth/fixtures/TF021/negative.tf +31 -0
- package/src/lint/post-synth/fixtures/TF021/positive-length.tf +8 -0
- package/src/lint/post-synth/fixtures/TF021/positive.tf +8 -0
- package/src/lint/post-synth/fixtures/TF022/negative-locator.tf +7 -0
- package/src/lint/post-synth/fixtures/TF022/negative.tf +10 -0
- package/src/lint/post-synth/fixtures/TF022/positive-nested.tf +10 -0
- package/src/lint/post-synth/fixtures/TF022/positive.tf +6 -0
- package/src/lint/post-synth/fixtures/TF023/negative/main.tf +15 -0
- package/src/lint/post-synth/fixtures/TF023/positive/main.tf +9 -0
- package/src/lint/post-synth/fixtures/TF023/positive/state.json +24 -0
- package/src/lint/post-synth/fixtures/TF024/live-clean/main.tf +9 -0
- package/src/lint/post-synth/fixtures/TF024/live-with-backend/main.tf +14 -0
- package/src/lint/post-synth/fixtures/TF024/live-with-cloud/main.tf +16 -0
- package/src/lint/post-synth/fixtures/TF025/live-clean/main.tf +13 -0
- package/src/lint/post-synth/fixtures/TF025/live-with-workspace-ref/main.tf +13 -0
- package/src/lint/post-synth/fixtures/TF026/live-default/main.tf +9 -0
- package/src/lint/post-synth/fixtures/TF026/live-explicit-delete/main.tf +13 -0
- package/src/lint/post-synth/fixtures/TF026/live-keep/main.tf +13 -0
- package/src/lint/post-synth/fixtures/load.ts +108 -0
- package/src/lint/post-synth/index.ts +48 -0
- package/src/lint/post-synth/module-rules.test.ts +153 -0
- package/src/lint/post-synth/module-source.test.ts +75 -0
- package/src/lint/post-synth/module-source.ts +121 -0
- package/src/lint/post-synth/post-synth.test.ts +14 -15
- package/src/lint/post-synth/scope.ts +107 -0
- package/src/lint/post-synth/single-block.test.ts +263 -0
- package/src/lint/post-synth/suppression.test.ts +110 -0
- package/src/lint/post-synth/tf001.ts +32 -8
- package/src/lint/post-synth/tf002.test.ts +93 -0
- package/src/lint/post-synth/tf002.ts +151 -0
- package/src/lint/post-synth/tf003.test.ts +75 -0
- package/src/lint/post-synth/tf003.ts +71 -0
- package/src/lint/post-synth/tf004.test.ts +47 -0
- package/src/lint/post-synth/tf004.ts +63 -0
- package/src/lint/post-synth/tf005.test.ts +57 -0
- package/src/lint/post-synth/tf005.ts +76 -0
- package/src/lint/post-synth/tf006.ts +53 -0
- package/src/lint/post-synth/tf007.ts +78 -0
- package/src/lint/post-synth/tf008.ts +75 -0
- package/src/lint/post-synth/tf009.ts +59 -0
- package/src/lint/post-synth/tf010.ts +51 -0
- package/src/lint/post-synth/tf011.ts +49 -0
- package/src/lint/post-synth/tf012.ts +47 -0
- package/src/lint/post-synth/tf013.ts +63 -0
- package/src/lint/post-synth/tf014.ts +72 -0
- package/src/lint/post-synth/tf015.ts +63 -0
- package/src/lint/post-synth/tf016.ts +75 -0
- package/src/lint/post-synth/tf017.ts +50 -0
- package/src/lint/post-synth/tf018.ts +72 -0
- package/src/lint/post-synth/tf019.ts +72 -0
- package/src/lint/post-synth/tf020.ts +123 -0
- package/src/lint/post-synth/tf021.ts +126 -0
- package/src/lint/post-synth/tf022.ts +61 -0
- package/src/lint/post-synth/tf024.test.ts +42 -0
- package/src/lint/post-synth/tf024.ts +70 -0
- package/src/lint/post-synth/tf025.test.ts +46 -0
- package/src/lint/post-synth/tf025.ts +101 -0
- package/src/lint/post-synth/tf026.test.ts +56 -0
- package/src/lint/post-synth/tf026.ts +80 -0
- package/src/lint/presets.test.ts +72 -0
- package/src/lint/rules/fixtures/TF101/negative-op.ts +2 -0
- package/src/lint/rules/fixtures/TF101/positive-op.ts +2 -0
- package/src/lint/rules/fixtures/load.ts +53 -0
- package/src/lint/rules/plan-before-apply.test.ts +112 -7
- package/src/lint/rules/plan-before-apply.ts +11 -0
- package/src/lint/secret-shape.test.ts +150 -0
- package/src/lint/secret-shape.ts +159 -0
- package/src/live-ownership.ts +60 -0
- package/src/lsp/completions.test.ts +3 -2
- package/src/lsp/option-keys.ts +10 -5
- package/src/op/activities/choudoufu.acceptance.test.ts +143 -0
- package/src/op/activities/choudoufu.test.ts +693 -0
- package/src/op/activities/index.ts +40 -4
- package/src/op/activities/live-detect.test.ts +143 -0
- package/src/op/activities/live-detect.ts +162 -0
- package/src/op/activities/registry.test.ts +11 -3
- package/src/op/activities/terraform.test.ts +7 -3
- package/src/op/activities/terraform.ts +823 -69
- package/src/op/activity-contracts.test.ts +147 -0
- package/src/op/activity-contracts.ts +178 -0
- package/src/op/adoption.test.ts +170 -0
- package/src/op/adoption.ts +241 -0
- package/src/op/builders.test.ts +60 -5
- package/src/op/builders.ts +93 -5
- package/src/op/resolve-root-mode.test.ts +85 -0
- package/src/op/resolve-root-mode.ts +72 -0
- package/src/plugin.test.ts +68 -0
- package/src/plugin.ts +75 -9
- package/src/skills/chant-terraform.md +1 -1
|
@@ -8,30 +8,53 @@
|
|
|
8
8
|
* - terraformInit — `init` with the root's `backendConfig`.
|
|
9
9
|
* - terraformPlan — `plan -detailed-exitcode -out=<planFile>`, plus both
|
|
10
10
|
* `show` renders of the written plan.
|
|
11
|
-
* - terraformApply
|
|
11
|
+
* - terraformApply: `apply <planFile>` on a stock root, a saved plan only;
|
|
12
|
+
* `apply -auto-approve` with no plan file on a live root (#2103).
|
|
12
13
|
* - terraformShow — state, or a saved plan, as JSON and as text.
|
|
14
|
+
* - choudoufuLivePlan: `live-plan -detailed-exitcode -json -estate=<estate>`,
|
|
15
|
+
* plus a second `live-plan` for the human render (#2103).
|
|
16
|
+
* - choudoufuLiveLs: `live-ls -estate=<estate> -json [-consistent]` (#2103).
|
|
17
|
+
* - choudoufuLiveCheck: `live-check -json`, no cloud calls (#2103).
|
|
18
|
+
* - choudoufuAdopt: the tag writes that claim an adoption ledger's matches (#2105).
|
|
13
19
|
*
|
|
14
20
|
* The module is dependency-light on purpose: it shells out to the configured
|
|
15
21
|
* binary and reads the `terraform` config namespace, and never touches the
|
|
16
|
-
* lexicon's HCL parse or serializer, so
|
|
17
|
-
* The pure command and environment builders are exported alongside
|
|
18
|
-
* activities because they are what the tests assert on.
|
|
22
|
+
* lexicon's HCL parse or serializer, so `loadActivities` imports it cheaply at
|
|
23
|
+
* run time. The pure command and environment builders are exported alongside
|
|
24
|
+
* the activities because they are what the tests assert on.
|
|
19
25
|
*/
|
|
20
26
|
export {
|
|
21
27
|
terraformInit,
|
|
22
28
|
terraformPlan,
|
|
23
29
|
terraformApply,
|
|
24
30
|
terraformShow,
|
|
31
|
+
choudoufuLivePlan,
|
|
32
|
+
choudoufuLiveLs,
|
|
33
|
+
choudoufuLiveCheck,
|
|
34
|
+
choudoufuAdopt,
|
|
25
35
|
terraformInitCommand,
|
|
26
36
|
terraformPlanCommand,
|
|
27
37
|
terraformApplyCommand,
|
|
28
38
|
terraformShowCommand,
|
|
39
|
+
choudoufuLivePlanCommand,
|
|
40
|
+
choudoufuLiveLsCommand,
|
|
41
|
+
choudoufuLiveCheckCommand,
|
|
29
42
|
terraformEnvironment,
|
|
30
43
|
terraformBinary,
|
|
31
44
|
countPlanChanges,
|
|
45
|
+
countLivePlanUnowned,
|
|
46
|
+
isOlderVersion,
|
|
47
|
+
parseChoudoufuVersion,
|
|
32
48
|
quoteArg,
|
|
33
49
|
DEFAULT_PLAN_FILE,
|
|
34
50
|
DEFAULT_TERRAFORM_BINARY,
|
|
51
|
+
DEFAULT_LIVE_PLAN_DOCUMENT_FILE,
|
|
52
|
+
MIN_CHOUDOUFU_VERSION,
|
|
53
|
+
classifyApprovalRefusal,
|
|
54
|
+
CHOUDOUFU_LIVE_PLAN_OUT_REFUSAL,
|
|
55
|
+
CHOUDOUFU_APPROVAL_EXIT_CODE,
|
|
56
|
+
CHOUDOUFU_APPROVAL_MISMATCH_REFUSAL,
|
|
57
|
+
CHOUDOUFU_WRONG_ESTATE_REFUSAL,
|
|
35
58
|
} from "./terraform";
|
|
36
59
|
|
|
37
60
|
export type {
|
|
@@ -40,9 +63,22 @@ export type {
|
|
|
40
63
|
TerraformPlanArgs,
|
|
41
64
|
TerraformApplyArgs,
|
|
42
65
|
TerraformShowArgs,
|
|
66
|
+
ChoudoufuLivePlanArgs,
|
|
67
|
+
ChoudoufuLiveLsArgs,
|
|
68
|
+
ChoudoufuLiveCheckArgs,
|
|
69
|
+
ChoudoufuAdoptArgs,
|
|
43
70
|
TerraformInitResult,
|
|
44
71
|
TerraformPlanResult,
|
|
45
72
|
TerraformApplyResult,
|
|
73
|
+
TerraformApprovalRefusal,
|
|
46
74
|
TerraformShowResult,
|
|
75
|
+
ChoudoufuLivePlanResult,
|
|
76
|
+
ChoudoufuLiveLsResult,
|
|
77
|
+
ChoudoufuLiveCheckResult,
|
|
78
|
+
ChoudoufuAdoptResult,
|
|
79
|
+
AdoptionRefusal,
|
|
47
80
|
PlanChangeCounts,
|
|
81
|
+
LivePlanUnownedCounts,
|
|
48
82
|
} from "./terraform";
|
|
83
|
+
|
|
84
|
+
export { detectLiveEstate } from "./live-detect";
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, describe, expect, test } from "vitest";
|
|
5
|
+
import { detectLiveEstate, detectLivePolicyVerbs } from "./live-detect";
|
|
6
|
+
|
|
7
|
+
const dirs: string[] = [];
|
|
8
|
+
|
|
9
|
+
function tempDir(): string {
|
|
10
|
+
const dir = mkdtempSync(join(tmpdir(), "chant-tf-live-detect-"));
|
|
11
|
+
dirs.push(dir);
|
|
12
|
+
return dir;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
for (const dir of dirs.splice(0)) rmSync(dir, { recursive: true, force: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("detectLiveEstate (#2103)", () => {
|
|
20
|
+
test("reads the estate from an estate.chdf.hcl sidecar", () => {
|
|
21
|
+
const dir = tempDir();
|
|
22
|
+
writeFileSync(join(dir, "estate.chdf.hcl"), 'estate = "prod-networking"\n');
|
|
23
|
+
writeFileSync(join(dir, "main.tf"), 'resource "null_resource" "x" {}\n');
|
|
24
|
+
expect(detectLiveEstate(dir)).toBe("prod-networking");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("reads the estate from a live block nested in a terraform block", () => {
|
|
28
|
+
const dir = tempDir();
|
|
29
|
+
writeFileSync(
|
|
30
|
+
dir + "/main.tf",
|
|
31
|
+
[
|
|
32
|
+
"terraform {",
|
|
33
|
+
" required_version = \">= 1.5.0\"",
|
|
34
|
+
" live {",
|
|
35
|
+
' estate = "fixture-estate"',
|
|
36
|
+
" }",
|
|
37
|
+
"}",
|
|
38
|
+
"",
|
|
39
|
+
'resource "null_resource" "x" {}',
|
|
40
|
+
"",
|
|
41
|
+
].join("\n"),
|
|
42
|
+
);
|
|
43
|
+
expect(detectLiveEstate(dir)).toBe("fixture-estate");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("ignores an unrelated nested block with its own braces", () => {
|
|
47
|
+
const dir = tempDir();
|
|
48
|
+
writeFileSync(
|
|
49
|
+
join(dir, "main.tf"),
|
|
50
|
+
[
|
|
51
|
+
"terraform {",
|
|
52
|
+
" required_providers {",
|
|
53
|
+
' aws = { source = "hashicorp/aws" }',
|
|
54
|
+
" }",
|
|
55
|
+
" live {",
|
|
56
|
+
' estate = "still-found"',
|
|
57
|
+
" record_store \"local\" {",
|
|
58
|
+
' path = ".tofu-records"',
|
|
59
|
+
" }",
|
|
60
|
+
" }",
|
|
61
|
+
"}",
|
|
62
|
+
"",
|
|
63
|
+
].join("\n"),
|
|
64
|
+
);
|
|
65
|
+
expect(detectLiveEstate(dir)).toBe("still-found");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("undefined when neither form is present", () => {
|
|
69
|
+
const dir = tempDir();
|
|
70
|
+
mkdirSync(dir, { recursive: true });
|
|
71
|
+
writeFileSync(join(dir, "main.tf"), 'resource "null_resource" "x" {}\n');
|
|
72
|
+
expect(detectLiveEstate(dir)).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("undefined for a directory that does not exist", () => {
|
|
76
|
+
expect(detectLiveEstate(join(tmpdir(), "chant-tf-live-detect-does-not-exist"))).toBeUndefined();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("the sidecar wins when both forms are present", () => {
|
|
80
|
+
const dir = tempDir();
|
|
81
|
+
writeFileSync(join(dir, "estate.chdf.hcl"), 'estate = "from-sidecar"\n');
|
|
82
|
+
writeFileSync(
|
|
83
|
+
join(dir, "main.tf"),
|
|
84
|
+
["terraform {", " live {", ' estate = "from-block"', " }", "}", ""].join("\n"),
|
|
85
|
+
);
|
|
86
|
+
expect(detectLiveEstate(dir)).toBe("from-sidecar");
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("detectLivePolicyVerbs (#2106)", () => {
|
|
91
|
+
test("reads undeclared_tagged and undeclared_untagged out of a nested policy block", () => {
|
|
92
|
+
const dir = tempDir();
|
|
93
|
+
writeFileSync(
|
|
94
|
+
join(dir, "main.tf"),
|
|
95
|
+
[
|
|
96
|
+
"terraform {",
|
|
97
|
+
" live {",
|
|
98
|
+
' estate = "fixture-estate"',
|
|
99
|
+
" policy {",
|
|
100
|
+
' undeclared_tagged = "keep"',
|
|
101
|
+
' undeclared_untagged = "delete"',
|
|
102
|
+
" scope {",
|
|
103
|
+
' services = ["ec2"]',
|
|
104
|
+
" }",
|
|
105
|
+
" }",
|
|
106
|
+
" }",
|
|
107
|
+
"}",
|
|
108
|
+
"",
|
|
109
|
+
].join("\n"),
|
|
110
|
+
);
|
|
111
|
+
expect(detectLivePolicyVerbs(dir)).toEqual({ undeclaredTagged: "keep", undeclaredUntagged: "delete" });
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("undefined fields when the policy block sets only one of the two", () => {
|
|
115
|
+
const dir = tempDir();
|
|
116
|
+
writeFileSync(
|
|
117
|
+
join(dir, "main.tf"),
|
|
118
|
+
["terraform {", " live {", ' estate = "fixture-estate"', " policy {", ' undeclared_tagged = "untag"', " }", " }", "}", ""].join(
|
|
119
|
+
"\n",
|
|
120
|
+
),
|
|
121
|
+
);
|
|
122
|
+
expect(detectLivePolicyVerbs(dir)).toEqual({ undeclaredTagged: "untag", undeclaredUntagged: undefined });
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("undefined when the live block declares no policy block", () => {
|
|
126
|
+
const dir = tempDir();
|
|
127
|
+
writeFileSync(
|
|
128
|
+
join(dir, "main.tf"),
|
|
129
|
+
["terraform {", " live {", ' estate = "fixture-estate"', " }", "}", ""].join("\n"),
|
|
130
|
+
);
|
|
131
|
+
expect(detectLivePolicyVerbs(dir)).toBeUndefined();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("undefined when the directory declares no live block at all", () => {
|
|
135
|
+
const dir = tempDir();
|
|
136
|
+
writeFileSync(join(dir, "main.tf"), 'resource "null_resource" "x" {}\n');
|
|
137
|
+
expect(detectLivePolicyVerbs(dir)).toBeUndefined();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("undefined for a directory that does not exist", () => {
|
|
141
|
+
expect(detectLivePolicyVerbs(join(tmpdir(), "chant-tf-live-detect-does-not-exist"))).toBeUndefined();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fast, regex-based read of whether a root module directory declares a
|
|
3
|
+
* live estate: an `estate.chdf.hcl` sidecar, or a `live { ... }` block nested
|
|
4
|
+
* inside a `terraform { ... }` block of some `.tf` file (#2103).
|
|
5
|
+
*
|
|
6
|
+
* Deliberately separate from `../../hcl/parse.ts`'s AST-accurate detection
|
|
7
|
+
* (`blocksToEntities`'s `liveBlocksIn`), which the build and lint paths use.
|
|
8
|
+
* `op/activities/terraform.ts` is imported by core's activity registry at run
|
|
9
|
+
* time and is dependency-light on purpose, since it shells out to the
|
|
10
|
+
* configured binary and never touches the lexicon's HCL parse or serializer,
|
|
11
|
+
* so it never pulls in
|
|
12
|
+
* the ~1.8 MB `@cdktf/hcl2json` wasm parser just to decide whether an apply
|
|
13
|
+
* should run `apply -auto-approve` with no plan file. Plain text and a
|
|
14
|
+
* hand-rolled brace counter are enough for that narrower question, and the
|
|
15
|
+
* literal sidecar filename below is kept in sync with `LIVE_SIDECAR_FILENAME`
|
|
16
|
+
* in `../../hcl/parse.ts` by hand rather than by importing it, for the same
|
|
17
|
+
* reason.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
|
|
23
|
+
/** Kept in sync with `LIVE_SIDECAR_FILENAME` in `../../hcl/parse.ts`. */
|
|
24
|
+
const LIVE_SIDECAR_FILENAME = "estate.chdf.hcl";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Find `keyword {` and return the matching `{ ... }` body's inner text, via
|
|
28
|
+
* brace counting rather than a regex (HCL bodies nest, and a lone regex
|
|
29
|
+
* cannot match balanced braces).
|
|
30
|
+
*/
|
|
31
|
+
function extractBalancedBlock(source: string, keyword: string): string | undefined {
|
|
32
|
+
const re = new RegExp(`\\b${keyword}\\s*\\{`);
|
|
33
|
+
const opening = re.exec(source);
|
|
34
|
+
if (!opening) return undefined;
|
|
35
|
+
|
|
36
|
+
let depth = 0;
|
|
37
|
+
let start = -1;
|
|
38
|
+
for (let i = opening.index; i < source.length; i++) {
|
|
39
|
+
const ch = source[i];
|
|
40
|
+
if (ch === "{") {
|
|
41
|
+
if (depth === 0) start = i + 1;
|
|
42
|
+
depth++;
|
|
43
|
+
} else if (ch === "}") {
|
|
44
|
+
depth--;
|
|
45
|
+
if (depth === 0) return source.slice(start, i);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return undefined; // unbalanced, malformed HCL, not this function's problem to diagnose
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Pull a quoted `estate = "..."` attribute's value out of a block's inner text. */
|
|
52
|
+
function extractEstateAttr(body: string): string | undefined {
|
|
53
|
+
const match = /estate\s*=\s*"([^"]*)"/.exec(body);
|
|
54
|
+
return match && match[1] !== "" ? match[1] : undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Pull a quoted `<key> = "..."` attribute's value out of a block's inner text. */
|
|
58
|
+
function extractQuotedAttr(body: string, key: string): string | undefined {
|
|
59
|
+
const match = new RegExp(`\\b${key}\\s*=\\s*"([^"]*)"`).exec(body);
|
|
60
|
+
return match && match[1] !== "" ? match[1] : undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The declared estate name for the root module directory `dir`, or
|
|
65
|
+
* `undefined` when none is declared. Checks the `estate.chdf.hcl` sidecar
|
|
66
|
+
* first (cheaper: one file, no brace matching), then every `.tf` file in
|
|
67
|
+
* directory order for a `live { }` block nested in a `terraform { }` block.
|
|
68
|
+
* Returns the first estate name found; a directory with no `.tf` files and
|
|
69
|
+
* no sidecar (or one this function cannot read) yields `undefined` rather
|
|
70
|
+
* than throwing, since this is a best-effort check, not the authoritative parse.
|
|
71
|
+
*/
|
|
72
|
+
export function detectLiveEstate(dir: string): string | undefined {
|
|
73
|
+
const sidecarPath = join(dir, LIVE_SIDECAR_FILENAME);
|
|
74
|
+
if (existsSync(sidecarPath)) {
|
|
75
|
+
try {
|
|
76
|
+
const estate = extractEstateAttr(readFileSync(sidecarPath, "utf-8"));
|
|
77
|
+
if (estate) return estate;
|
|
78
|
+
} catch {
|
|
79
|
+
// fall through to the in-block form
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let names: string[];
|
|
84
|
+
try {
|
|
85
|
+
names = readdirSync(dir)
|
|
86
|
+
.filter((f) => f.endsWith(".tf"))
|
|
87
|
+
.sort();
|
|
88
|
+
} catch {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (const name of names) {
|
|
93
|
+
let source: string;
|
|
94
|
+
try {
|
|
95
|
+
source = readFileSync(join(dir, name), "utf-8");
|
|
96
|
+
} catch {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const terraformBlock = extractBalancedBlock(source, "terraform");
|
|
100
|
+
if (terraformBlock === undefined) continue;
|
|
101
|
+
const liveBlock = extractBalancedBlock(terraformBlock, "live");
|
|
102
|
+
if (liveBlock === undefined) continue;
|
|
103
|
+
const estate = extractEstateAttr(liveBlock);
|
|
104
|
+
if (estate) return estate;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The `undeclared_tagged`/`undeclared_untagged` verbs a live root's `policy {
|
|
112
|
+
* }` block assigns, or `undefined` when the directory declares no `policy`
|
|
113
|
+
* block at all (#2106). Same best-effort posture as {@link detectLiveEstate}:
|
|
114
|
+
* a plain read of the in-block form only (the `estate.chdf.hcl` sidecar's own
|
|
115
|
+
* `policy` block, if choudoufu ever admits one there, is not read here — a
|
|
116
|
+
* known, narrower gap than the estate check above, which does read the
|
|
117
|
+
* sidecar). `TerraformApplyOp` (`../../composites/terraform-apply-op.ts`)
|
|
118
|
+
* uses this to refuse a root whose `policy` sets
|
|
119
|
+
* `undeclared_untagged = "delete"` outright, at build time, before any
|
|
120
|
+
* activity runs; TF026 (`../../lint/post-synth/tf026.ts`) checks the same
|
|
121
|
+
* block's `undeclared_tagged` verb against a root's declared `delete: "never"`
|
|
122
|
+
* from the parsed HCL entities instead, since a post-synth check already has
|
|
123
|
+
* the block body in hand and has no need of this file-reading version.
|
|
124
|
+
*/
|
|
125
|
+
export interface LivePolicyVerbs {
|
|
126
|
+
/** The `undeclared_tagged` quadrant's verb, verbatim, or `undefined` when the attribute is absent (defaults to `"delete"`). */
|
|
127
|
+
undeclaredTagged?: string;
|
|
128
|
+
/** The `undeclared_untagged` quadrant's verb, verbatim, or `undefined` when the attribute is absent. */
|
|
129
|
+
undeclaredUntagged?: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function detectLivePolicyVerbs(dir: string): LivePolicyVerbs | undefined {
|
|
133
|
+
let names: string[];
|
|
134
|
+
try {
|
|
135
|
+
names = readdirSync(dir)
|
|
136
|
+
.filter((f) => f.endsWith(".tf"))
|
|
137
|
+
.sort();
|
|
138
|
+
} catch {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
for (const name of names) {
|
|
143
|
+
let source: string;
|
|
144
|
+
try {
|
|
145
|
+
source = readFileSync(join(dir, name), "utf-8");
|
|
146
|
+
} catch {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const terraformBlock = extractBalancedBlock(source, "terraform");
|
|
150
|
+
if (terraformBlock === undefined) continue;
|
|
151
|
+
const liveBlock = extractBalancedBlock(terraformBlock, "live");
|
|
152
|
+
if (liveBlock === undefined) continue;
|
|
153
|
+
const policyBlock = extractBalancedBlock(liveBlock, "policy");
|
|
154
|
+
if (policyBlock === undefined) continue;
|
|
155
|
+
return {
|
|
156
|
+
undeclaredTagged: extractQuotedAttr(policyBlock, "undeclared_tagged"),
|
|
157
|
+
undeclaredUntagged: extractQuotedAttr(policyBlock, "undeclared_untagged"),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
@@ -14,10 +14,18 @@
|
|
|
14
14
|
import { describe, test, expect } from "vitest";
|
|
15
15
|
import { loadActivities, resolveActivity } from "@intentius/chant/op";
|
|
16
16
|
|
|
17
|
-
describe("loadActivities([\"terraform\"]) (#2086)", () => {
|
|
18
|
-
test("resolves all
|
|
17
|
+
describe("loadActivities([\"terraform\"]) (#2086, #2103)", () => {
|
|
18
|
+
test("resolves all seven activity names", async () => {
|
|
19
19
|
const activities = await loadActivities(["terraform"]);
|
|
20
|
-
for (const name of [
|
|
20
|
+
for (const name of [
|
|
21
|
+
"terraformInit",
|
|
22
|
+
"terraformPlan",
|
|
23
|
+
"terraformApply",
|
|
24
|
+
"terraformShow",
|
|
25
|
+
"choudoufuLivePlan",
|
|
26
|
+
"choudoufuLiveLs",
|
|
27
|
+
"choudoufuLiveCheck",
|
|
28
|
+
]) {
|
|
21
29
|
expect(typeof resolveActivity(activities, name)).toBe("function");
|
|
22
30
|
}
|
|
23
31
|
});
|
|
@@ -53,7 +53,11 @@ function execError(code: number, stderr: string, stdout = ""): Error & { code: n
|
|
|
53
53
|
return Object.assign(new Error(`Command failed (exit ${code})`), { code, stdout, stderr });
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
// Partial, via `importOriginal`: `@intentius/chant/op` reaches the base
|
|
57
|
+
// activities now (chant #2114), and modules on that path promisify
|
|
58
|
+
// `execFile` at load. A wholesale replacement of node:child_process would
|
|
59
|
+
// make them fail to import rather than fail an assertion.
|
|
60
|
+
vi.mock("node:child_process", async (importOriginal) => {
|
|
57
61
|
const custom = Symbol.for("nodejs.util.promisify.custom");
|
|
58
62
|
const exec = ((_cmd: string, _opts: unknown, cb?: (...a: unknown[]) => void) => {
|
|
59
63
|
cb?.(new Error("unmocked exec path"));
|
|
@@ -78,7 +82,7 @@ vi.mock("node:child_process", () => {
|
|
|
78
82
|
}
|
|
79
83
|
return { stdout: "", stderr: "" };
|
|
80
84
|
};
|
|
81
|
-
return { exec };
|
|
85
|
+
return { ...(await importOriginal<typeof import("node:child_process")>()), exec };
|
|
82
86
|
});
|
|
83
87
|
|
|
84
88
|
// ── A real project config to resolve roots against ──────────────────────────
|
|
@@ -376,7 +380,7 @@ describe("terraformApply — saved plans only (#2086)", () => {
|
|
|
376
380
|
expect(result).toMatchObject({ planFile: "chant.tfplan", applied: true });
|
|
377
381
|
});
|
|
378
382
|
|
|
379
|
-
test("no planFile
|
|
383
|
+
test("no planFile on a stock root: refused, with no bare apply run", async () => {
|
|
380
384
|
const dir = project({ roots: { app: { dir: "./infra" } } });
|
|
381
385
|
await expect(
|
|
382
386
|
terraformApply({ root: "app", cwd: dir } as unknown as { root: string; cwd: string; planFile: string }),
|