@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
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 4,
|
|
3
|
+
"terraform_version": "1.5.7",
|
|
4
|
+
"serial": 3,
|
|
5
|
+
"lineage": "00000000-0000-0000-0000-000000000000",
|
|
6
|
+
"outputs": {},
|
|
7
|
+
"resources": [
|
|
8
|
+
{
|
|
9
|
+
"mode": "managed",
|
|
10
|
+
"type": "null_resource",
|
|
11
|
+
"name": "first",
|
|
12
|
+
"provider": "provider[\"registry.terraform.io/hashicorp/null\"]",
|
|
13
|
+
"instances": [
|
|
14
|
+
{
|
|
15
|
+
"schema_version": 0,
|
|
16
|
+
"attributes": {
|
|
17
|
+
"id": "1234567890123456789",
|
|
18
|
+
"triggers": { "name": "first" }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared post-synth fixture loader.
|
|
3
|
+
*
|
|
4
|
+
* KICS lays its own query fixtures out as `positive.tf`/`negative.tf` pairs
|
|
5
|
+
* beside the query that tests them (survey, #2107): every query is
|
|
6
|
+
* externally auditable because a rule and its evidence live in the same
|
|
7
|
+
* directory. This lexicon adopts that layout: `fixtures/<id>/positive.tf`
|
|
8
|
+
* triggers the check, `fixtures/<id>/negative.tf` does not, and a rule with
|
|
9
|
+
* more than one triggering condition adds `positive-<case>.tf` beside them.
|
|
10
|
+
*
|
|
11
|
+
* KICS itself scans a whole fixture directory in one pass and tells its
|
|
12
|
+
* fixtures apart by the file each finding came from. That doesn't transfer
|
|
13
|
+
* here: TF001 (and most post-synth checks with per-root state, not
|
|
14
|
+
* per-resource) fire once per *root*, deduplicated by root name, so parsing
|
|
15
|
+
* `positive.tf` and `negative.tf` together as one root would let whichever
|
|
16
|
+
* file's terraform block is read first decide the outcome for both, silently
|
|
17
|
+
* discarding the other. `loadFixture` therefore reads exactly the one named
|
|
18
|
+
* file and parses it alone, through the same `blocksToEntities` pass
|
|
19
|
+
* `parseTerraformRootDir` wraps for a real root directory, so sibling
|
|
20
|
+
* fixtures never mix into one build.
|
|
21
|
+
*/
|
|
22
|
+
import { readFileSync } from "node:fs";
|
|
23
|
+
import { dirname, join } from "node:path";
|
|
24
|
+
import { fileURLToPath } from "node:url";
|
|
25
|
+
import type { PostSynthContext } from "@intentius/chant/lint/post-synth";
|
|
26
|
+
import { blocksToEntities } from "../../../hcl/parse";
|
|
27
|
+
import type { CallModuleType } from "../../../hcl/descend";
|
|
28
|
+
import { renderTerraformRoots } from "../../../hcl/roots";
|
|
29
|
+
|
|
30
|
+
const FIXTURES_DIR = dirname(fileURLToPath(import.meta.url));
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Parse `fixtures/<checkId>/<name>.tf` into a {@link PostSynthContext} whose
|
|
34
|
+
* `entities` are exactly what a real root module of that one file would
|
|
35
|
+
* produce. `root` (the entity key prefix and the `TerraformEntity.props.root`
|
|
36
|
+
* value) defaults to `checkId`; pass a distinct value to load two fixtures
|
|
37
|
+
* into one context under different root names.
|
|
38
|
+
*
|
|
39
|
+
* Three lines per fixture in a test:
|
|
40
|
+
* ```ts
|
|
41
|
+
* const diags = tf001.check(await loadFixture("TF001", "positive"));
|
|
42
|
+
* expect(diags).toHaveLength(1);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export async function loadFixture(
|
|
46
|
+
checkId: string,
|
|
47
|
+
name: string,
|
|
48
|
+
root: string = checkId,
|
|
49
|
+
): Promise<PostSynthContext> {
|
|
50
|
+
const file = `${name}.tf`;
|
|
51
|
+
const source = readFileSync(join(FIXTURES_DIR, checkId, file), "utf-8");
|
|
52
|
+
const entities = await blocksToEntities([{ name: file, source }], root);
|
|
53
|
+
return {
|
|
54
|
+
outputs: new Map(),
|
|
55
|
+
entities,
|
|
56
|
+
buildResult: {
|
|
57
|
+
outputs: new Map(),
|
|
58
|
+
entities,
|
|
59
|
+
warnings: [],
|
|
60
|
+
errors: [],
|
|
61
|
+
sourceFileCount: 1,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Parse a whole fixture DIRECTORY, `fixtures/<checkId>/<name>/`, the way
|
|
68
|
+
* `buildRoots()` parses a configured root: its own `.tf` files, then every
|
|
69
|
+
* local `module` call followed into its directory (chant #2112). A rule about
|
|
70
|
+
* child modules (TF014, TF015) or about a whole scope's references (TF020)
|
|
71
|
+
* cannot be shown a single file and still be tested honestly, so its fixture
|
|
72
|
+
* is a tree:
|
|
73
|
+
*
|
|
74
|
+
* ```
|
|
75
|
+
* fixtures/TF014/positive/main.tf # module "cdn" { source = "./modules/cdn" }
|
|
76
|
+
* fixtures/TF014/positive/modules/cdn/main.tf # the provider block the rule reports
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* The fixture directory is also the project root for the descent, so a
|
|
80
|
+
* fixture can exercise the outside-the-project refusal with a `../` source
|
|
81
|
+
* without reaching into the repository around it. `warnings` from the render
|
|
82
|
+
* lands on `buildResult.warnings`, where the descent's own refusals are
|
|
83
|
+
* readable by a test.
|
|
84
|
+
*/
|
|
85
|
+
export async function loadTreeFixture(
|
|
86
|
+
checkId: string,
|
|
87
|
+
name: string,
|
|
88
|
+
root: string = checkId,
|
|
89
|
+
callModuleType?: CallModuleType,
|
|
90
|
+
): Promise<PostSynthContext> {
|
|
91
|
+
const dir = join(FIXTURES_DIR, checkId, name);
|
|
92
|
+
const { entities, warnings } = await renderTerraformRoots({
|
|
93
|
+
projectRoot: dir,
|
|
94
|
+
roots: { [root]: { dir } },
|
|
95
|
+
...(callModuleType ? { callModuleType } : {}),
|
|
96
|
+
});
|
|
97
|
+
return {
|
|
98
|
+
outputs: new Map(),
|
|
99
|
+
entities,
|
|
100
|
+
buildResult: {
|
|
101
|
+
outputs: new Map(),
|
|
102
|
+
entities,
|
|
103
|
+
warnings,
|
|
104
|
+
errors: [],
|
|
105
|
+
sourceFileCount: entities.size,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
@@ -1,7 +1,55 @@
|
|
|
1
1
|
// Code generated by chant generate. DO NOT EDIT.
|
|
2
2
|
import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
|
|
3
3
|
import { tf001 } from "./tf001";
|
|
4
|
+
import { tf002 } from "./tf002";
|
|
5
|
+
import { tf003 } from "./tf003";
|
|
6
|
+
import { tf004 } from "./tf004";
|
|
7
|
+
import { tf005 } from "./tf005";
|
|
8
|
+
import { tf006 } from "./tf006";
|
|
9
|
+
import { tf007 } from "./tf007";
|
|
10
|
+
import { tf008 } from "./tf008";
|
|
11
|
+
import { tf009 } from "./tf009";
|
|
12
|
+
import { tf010 } from "./tf010";
|
|
13
|
+
import { tf011 } from "./tf011";
|
|
14
|
+
import { tf012 } from "./tf012";
|
|
15
|
+
import { tf013 } from "./tf013";
|
|
16
|
+
import { tf014 } from "./tf014";
|
|
17
|
+
import { tf015 } from "./tf015";
|
|
18
|
+
import { tf016 } from "./tf016";
|
|
19
|
+
import { tf017 } from "./tf017";
|
|
20
|
+
import { tf018 } from "./tf018";
|
|
21
|
+
import { tf019 } from "./tf019";
|
|
22
|
+
import { tf020 } from "./tf020";
|
|
23
|
+
import { tf021 } from "./tf021";
|
|
24
|
+
import { tf022 } from "./tf022";
|
|
25
|
+
import { tf024 } from "./tf024";
|
|
26
|
+
import { tf025 } from "./tf025";
|
|
27
|
+
import { tf026 } from "./tf026";
|
|
4
28
|
|
|
5
29
|
export const postSynthChecks: PostSynthCheck[] = [
|
|
6
30
|
tf001,
|
|
31
|
+
tf002,
|
|
32
|
+
tf003,
|
|
33
|
+
tf004,
|
|
34
|
+
tf005,
|
|
35
|
+
tf006,
|
|
36
|
+
tf007,
|
|
37
|
+
tf008,
|
|
38
|
+
tf009,
|
|
39
|
+
tf010,
|
|
40
|
+
tf011,
|
|
41
|
+
tf012,
|
|
42
|
+
tf013,
|
|
43
|
+
tf014,
|
|
44
|
+
tf015,
|
|
45
|
+
tf016,
|
|
46
|
+
tf017,
|
|
47
|
+
tf018,
|
|
48
|
+
tf019,
|
|
49
|
+
tf020,
|
|
50
|
+
tf021,
|
|
51
|
+
tf022,
|
|
52
|
+
tf024,
|
|
53
|
+
tf025,
|
|
54
|
+
tf026,
|
|
7
55
|
];
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The four rules module descent made possible (chant #2112): TF014 and TF015,
|
|
3
|
+
* which are about what a child module may contain, and TF020 and TF021, which
|
|
4
|
+
* need a whole scope's references or a resource's whole body.
|
|
5
|
+
*
|
|
6
|
+
* TF014, TF015 and the scoped half of TF020 read tree fixtures
|
|
7
|
+
* (`fixtures/<id>/<case>/`, parsed through `renderTerraformRoots` by
|
|
8
|
+
* `loadTreeFixture`), because a rule about a child module cannot be shown one
|
|
9
|
+
* file and still be tested honestly. TF020's own conditions and TF021 read
|
|
10
|
+
* single-file fixtures the way every rule before them does.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, expect, it } from "vitest";
|
|
14
|
+
import { loadFixture, loadTreeFixture } from "./fixtures/load";
|
|
15
|
+
import { tf001 } from "./tf001";
|
|
16
|
+
import { tf014 } from "./tf014";
|
|
17
|
+
import { tf015 } from "./tf015";
|
|
18
|
+
import { tf020 } from "./tf020";
|
|
19
|
+
import { tf021 } from "./tf021";
|
|
20
|
+
import { withCallersChain } from "./scope";
|
|
21
|
+
|
|
22
|
+
describe("TF014: a child module configures a provider", () => {
|
|
23
|
+
it("reports a provider block that sets anything beyond alias", async () => {
|
|
24
|
+
const diags = tf014.check(await loadTreeFixture("TF014", "positive", "app"));
|
|
25
|
+
expect(diags).toHaveLength(1);
|
|
26
|
+
expect(diags[0].entity).toBe("app/module.cdn/provider.aws");
|
|
27
|
+
expect(diags[0].message).toContain("profile, region");
|
|
28
|
+
expect(diags[0].message).toContain("providers = { ... }");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("leaves an alias-only block, and the root's own provider, alone", async () => {
|
|
32
|
+
const diags = tf014.check(await loadTreeFixture("TF014", "negative", "app"));
|
|
33
|
+
expect(diags).toEqual([]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("never fires on a root module's provider block", async () => {
|
|
37
|
+
// The positive fixture's ROOT configures a region too; only the child's
|
|
38
|
+
// block is reported.
|
|
39
|
+
const ctx = await loadTreeFixture("TF014", "positive", "app");
|
|
40
|
+
expect(ctx.entities.has("app/provider.aws")).toBe(true);
|
|
41
|
+
expect(tf014.check(ctx).map((d) => d.entity)).toEqual(["app/module.cdn/provider.aws"]);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("TF015: a child module declares a backend or cloud block", () => {
|
|
46
|
+
it("reports the backend block in the child", async () => {
|
|
47
|
+
const diags = tf015.check(await loadTreeFixture("TF015", "positive", "app"));
|
|
48
|
+
expect(diags).toHaveLength(1);
|
|
49
|
+
expect(diags[0].entity).toBe("app/module.cdn/terraform");
|
|
50
|
+
expect(diags[0].message).toContain("declares a backend block");
|
|
51
|
+
expect(diags[0].message).toContain("Only a root module may");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("leaves a child's required_version and required_providers alone", async () => {
|
|
55
|
+
expect(tf015.check(await loadTreeFixture("TF015", "negative", "app"))).toEqual([]);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("is TF001's mirror: the root keeps its backend and neither rule fires twice", async () => {
|
|
59
|
+
const ctx = await loadTreeFixture("TF015", "positive", "app");
|
|
60
|
+
expect(tf001.check(ctx)).toEqual([]);
|
|
61
|
+
expect(tf015.check(ctx)).toHaveLength(1);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe("TF001 still fires only on roots (#2112)", () => {
|
|
66
|
+
it("does not report a child module that has no backend", async () => {
|
|
67
|
+
// The root of the TF014 fixture declares one; the child declares none.
|
|
68
|
+
const ctx = await loadTreeFixture("TF014", "positive", "app");
|
|
69
|
+
expect(ctx.entities.has("app/module.cdn/aws_s3_bucket.assets")).toBe(true);
|
|
70
|
+
expect(tf001.check(ctx)).toEqual([]);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("still reports a root that has none, descent or no descent", async () => {
|
|
74
|
+
const ctx = await loadTreeFixture("TF020", "scoped", "app");
|
|
75
|
+
expect(tf001.check(ctx)).toEqual([]); // this root has a local backend block
|
|
76
|
+
|
|
77
|
+
const bare = await loadFixture("TF001", "positive", "app");
|
|
78
|
+
expect(tf001.check(bare)).toHaveLength(1);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("TF020: a declaration nothing in its scope references", () => {
|
|
83
|
+
it("reports an unused variable, local, data source and aliased provider", async () => {
|
|
84
|
+
const diags = tf020.check(await loadFixture("TF020", "positive"));
|
|
85
|
+
expect(diags.map((d) => d.entity).sort()).toEqual([
|
|
86
|
+
"TF020/data.aws_ami.ubuntu",
|
|
87
|
+
"TF020/locals",
|
|
88
|
+
"TF020/provider.aws",
|
|
89
|
+
"TF020/var.retention_days",
|
|
90
|
+
]);
|
|
91
|
+
expect(diags.find((d) => d.entity === "TF020/locals")?.message).toContain('"local.common_tags"');
|
|
92
|
+
expect(diags.find((d) => d.entity === "TF020/data.aws_ami.ubuntu")?.message).toContain("every plan");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("does not count a variable read only by its own validation block as used", async () => {
|
|
96
|
+
const diags = tf020.check(await loadFixture("TF020", "positive"));
|
|
97
|
+
expect(diags.some((d) => d.message.includes('"var.retention_days"'))).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("reports nothing when every declaration is referenced", async () => {
|
|
101
|
+
expect(tf020.check(await loadFixture("TF020", "negative"))).toEqual([]);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("judges each module scope on its own", async () => {
|
|
105
|
+
const diags = tf020.check(await loadTreeFixture("TF020", "scoped", "app"));
|
|
106
|
+
// The root's `var.region` is referenced by the module call; the child's
|
|
107
|
+
// `var.unused_in_child` is referenced by nothing in the child.
|
|
108
|
+
expect(diags.map((d) => d.entity)).toEqual(["app/module.cdn/var.unused_in_child"]);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("TF021: count where for_each is safer", () => {
|
|
113
|
+
it("reports a numeric count building an identity from count.index", async () => {
|
|
114
|
+
const diags = tf021.check(await loadFixture("TF021", "positive"));
|
|
115
|
+
expect(diags).toHaveLength(1);
|
|
116
|
+
expect(diags[0].message).toContain("`count = 3`");
|
|
117
|
+
expect(diags[0].message).toContain("tags.Name");
|
|
118
|
+
expect(diags[0].message).toContain("for_each");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("reports a length() count the same way", async () => {
|
|
122
|
+
const diags = tf021.check(await loadFixture("TF021", "positive-length"));
|
|
123
|
+
expect(diags).toHaveLength(1);
|
|
124
|
+
expect(diags[0].message).toContain("length(var.subnets)");
|
|
125
|
+
expect(diags[0].message).toContain("bucket");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("leaves a conditional count, a positional-only count.index and for_each alone", async () => {
|
|
129
|
+
expect(tf021.check(await loadFixture("TF021", "negative"))).toEqual([]);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe("the Callers chain on a finding inside a child module", () => {
|
|
134
|
+
it("names the root and every call site, with the file and line of each", async () => {
|
|
135
|
+
const ctx = await loadTreeFixture("TF014", "positive", "app");
|
|
136
|
+
const [wrapped] = withCallersChain([tf014]);
|
|
137
|
+
const [diag] = wrapped.check(ctx);
|
|
138
|
+
expect(diag.message).toContain("Callers: app -> module.cdn (main.tf:13).");
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("chains one hop per level", async () => {
|
|
142
|
+
const ctx = await loadTreeFixture("TF015", "positive", "app");
|
|
143
|
+
const [wrapped] = withCallersChain([tf015]);
|
|
144
|
+
const [diag] = wrapped.check(ctx);
|
|
145
|
+
expect(diag.message).toContain("Callers: app -> module.cdn (main.tf:11).");
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("says nothing on a finding in the root module", async () => {
|
|
149
|
+
const [wrapped] = withCallersChain([tf001]);
|
|
150
|
+
const [diag] = wrapped.check(await loadFixture("TF001", "positive", "app"));
|
|
151
|
+
expect(diag.message).not.toContain("Callers:");
|
|
152
|
+
});
|
|
153
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { classifyModuleSource, isDefaultBranch, isPinnedRef } from "./module-source";
|
|
3
|
+
|
|
4
|
+
describe("classifyModuleSource", () => {
|
|
5
|
+
test("local paths", () => {
|
|
6
|
+
expect(classifyModuleSource("./modules/local").kind).toBe("local");
|
|
7
|
+
expect(classifyModuleSource("../modules/local").kind).toBe("local");
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("registry addresses, three and four parts", () => {
|
|
11
|
+
expect(classifyModuleSource("terraform-aws-modules/vpc/aws").kind).toBe("registry");
|
|
12
|
+
expect(classifyModuleSource("app.terraform.io/example-corp/k8s-cluster/azurerm").kind).toBe("registry");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("a github.com or bitbucket.org host is never a registry address, even with four parts", () => {
|
|
16
|
+
expect(classifyModuleSource("github.com/hashicorp/example/extra").kind).not.toBe("registry");
|
|
17
|
+
expect(classifyModuleSource("bitbucket.org/hashicorp/example/extra").kind).not.toBe("registry");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("git sources: explicit force prefix, github/bitbucket shorthand, scp-style, .git suffix", () => {
|
|
21
|
+
expect(classifyModuleSource("git::https://example.com/vpc.git").kind).toBe("git");
|
|
22
|
+
expect(classifyModuleSource("hg::http://example.com/vpc").kind).toBe("git");
|
|
23
|
+
expect(classifyModuleSource("github.com/hashicorp/example").kind).toBe("git");
|
|
24
|
+
expect(classifyModuleSource("bitbucket.org/foo/bar").kind).toBe("git");
|
|
25
|
+
expect(classifyModuleSource("git@github.com:org/repo.git").kind).toBe("git");
|
|
26
|
+
expect(classifyModuleSource("https://example.com/vpc.git").kind).toBe("git");
|
|
27
|
+
expect(classifyModuleSource("https://example.com/vpc.git?ref=main").kind).toBe("git");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("extracts ref, falling back to rev", () => {
|
|
31
|
+
expect(classifyModuleSource("git::https://example.com/vpc.git?ref=v1.2.0").ref).toBe("v1.2.0");
|
|
32
|
+
expect(classifyModuleSource("git::https://example.com/vpc.git?rev=v1.2.0").ref).toBe("v1.2.0");
|
|
33
|
+
expect(classifyModuleSource("git::https://example.com/vpc.git?ref=v1.2.0&rev=other").ref).toBe("v1.2.0");
|
|
34
|
+
expect(classifyModuleSource("git::https://example.com/vpc.git").ref).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("a source that parses as neither local, registry nor git is other", () => {
|
|
38
|
+
expect(classifyModuleSource("s3::https://bucket.s3.amazonaws.com/vpc.zip").kind).toBe("other");
|
|
39
|
+
expect(classifyModuleSource("not a valid source at all").kind).toBe("other");
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe("isPinnedRef", () => {
|
|
44
|
+
test("accepts semver-shaped tags, with or without a leading v", () => {
|
|
45
|
+
expect(isPinnedRef("v1.2.0")).toBe(true);
|
|
46
|
+
expect(isPinnedRef("1.2.0")).toBe(true);
|
|
47
|
+
expect(isPinnedRef("v1.2.0-rc.1")).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("accepts a full 40-hex commit SHA", () => {
|
|
51
|
+
expect(isPinnedRef("abcdef1234567890abcdef1234567890abcdef12")).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("rejects a short SHA", () => {
|
|
55
|
+
expect(isPinnedRef("abcdef1")).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("rejects checkov's CKV_TF_2-passing but non-semver v1.2-dev (chant is stricter)", () => {
|
|
59
|
+
expect(isPinnedRef("v1.2-dev")).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("rejects an arbitrary branch-shaped name", () => {
|
|
63
|
+
expect(isPinnedRef("some-feature")).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe("isDefaultBranch", () => {
|
|
68
|
+
test("recognizes the four known mutable branch names", () => {
|
|
69
|
+
for (const b of ["main", "master", "develop", "trunk"]) expect(isDefaultBranch(b)).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("does not flag an arbitrary branch name as a default branch", () => {
|
|
73
|
+
expect(isDefaultBranch("some-feature")).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
});
|