This folder contains several helper scripts for working with Terraform. The scripts are:
terraform-update-variable: This script can automatically update a variable in a terraform.tfvars or
terragrunt.hcl file and commit and push the changes to Git. It's common practice to store the version number of the
currently deployed app in a variable and this script comes in handy for updating those variables automatically, such
as in a CI job after building a new AMI or Docker image.
git-updated-files: This script can be used to detect all the files that have have been updated between two git
refs (branch, tag, sha, etc). This can be used in a CI pipeline to find various scripts and files that were affected
and only run actions against those files (e.g., build scripts).
git-updated-folders: This script can be used to detect all the folders that have have been updated between two git
refs (branch, tag, sha, etc). This can be used in a CI pipeline to find the terraform and terragrunt modules that
have changed, and only run plan or apply on the modules that has been affected.
Imagine you have a set of Terragrunt config in the live folder to deploy an app called rails-app. You create
Amazon Machine Images (AMIs) for each new version of the app using Packer and the currently
deployed version of the app is defined in a variable called rails_app_version, set to ami-12345 in
live/rails-app/terragrunt.hcl.
If you just build a new version of the AMI, ami-67890, you could deploy it automatically, perhaps in a CI job,
as follows:
cd live/rails-app
# Due to the existence of types in terragrunt.hcl, we need to be explicit about how the variable values are quoted.terraform-update-variable --name rails_app_version --value "\"ami-67890\""
terragrunt apply
Running the commands above would:
Set the rails_app_version variable in the inputs map to the ID of the new AMI, ami-67890 in terragrunt.hcl.
commit and push the changes to terragrunt.hcl to Git.
Deploy the changes using Terragrunt.
Terraform
Imagine you have a set of Terraform templates in the templates folder to deploy an app called rails-app. You create
Amazon Machine Images (AMIs) for each new version of the app using Packer and the currently
deployed version of the app is defined in a variable called rails_app_version, set to ami-12345 in
templates/terraform.tfvars.
If you just build a new version of the AMI, ami-67890, you could deploy it automatically, perhaps in a CI job,
as follows:
cd templates
terraform-update-variable --vars-path terraform.tfvars --name rails_app_version --value "\"ami-67890\""terraform apply
Running the commands above would:
Set the rails_app_version variable to the ID of the new AMI, ami-67890 in terraform.tfvars.
commit and push the changes to terraform.tfvars to Git.
Deploy the changes using Terraform.
git-updated-files
Build scripts
Consider the following typical terragrunt folder structure:
Here we use * to indicate files that have been modified between the git refs development and master. To get the
build scripts that have changed:
$ git-updated-files --source-ref development --target-refmaster--ext sh
shared/us-east-1/_global/amis/build_web_server_ami.sh
This command looks for the files that changed with the extension sh. You can use this in your CI pipeline to act only
on the files that changed in a particular commit. For example, in this case, you might want to invoke the build scripts
that changed so that new AMIs can be built.
This command is not limited to a single extension. You can detect other files (e.g. yaml files) by passing additional
--ext arguments. For example, to get the region.yaml file, you can run:
$ git-updated-files --source-ref development --target-ref master --ext sh --ext yaml
shared/us-east-1/_global/amis/build_web_server_ami.sh
prod/us-east-1/region.yaml
You can also do search for files that changed that do not match the extension. For example, to get all files that
changes that are not terragrunt.hcl:
$ git-updated-files --source-ref development --target-ref master --exclude-ext terragrunt.hcl
shared/us-east-1/_global/amis/build_web_server_ami.sh
prod/us-east-1/region.yaml
git-updated-folders
Terragrunt
Consider the following typical terragrunt folder structure:
Here we use * to indicate files that have been modified between the git refs development and master. To get the
terragrunt modules that have changed:
$ git-updated-modules --source-ref development --target-ref master --terragrunt
non-prod/us-east-1/qa/mysql
non-prod/us-east-1/stage/mysql
prod/us-east-1/prod/mysql
Each of these folders were detected as terragrunt modules (because they contain a terragrunt.hcl file), and were
marked as changed because the underlying terragrunt config was updated.
Note that this will only detect terragrunt.hcl files that have changed. For example, in the following scenario where
the root terragrunt.hcl file and a few yaml files were changed (the files denoted with * are those that changed),
only the root folder is returned:
Here we use * to indicate files that have been modified between the git refs development and master. To get the
terraform modules that have changed:
$ git-updated-modules --source-ref development --target-ref master --terraform
modules/mysql
live/us-east-1/prod
live/us-east-1/non-prod
Each of these were detected as terraform modules (because they contain .tf files), and were marked as changed because
one of the underlying .tf or .tfvars files have changed. Specifically:
modules/mysql <= modules/mysql/outputs.tf
live/us-east-1/prod <= live/us-east-1/prod/main.tf and live/us-east-1/prod/outputs.tf
By default, git-updated-folders will include deleted folders in the return list. This can cause problems in
infrastructure pipelines as you don't want to run any plan or apply action on folders that don't exist.
To support destroy workflows, the git-updated-folders script supports two filters:
--exclude-deleted: This parameter will tell git-updated-folders to exclude folders that have been deleted when
returning the updated folders.
--include-deleted-only: This parameter will tell git-updated-folders to only include folders that have been
deleted when returning the updated folders.
Note that a folder is only considered deleted if all the tracked files in that folder is deleted. E.g., if you have a
folder that only deleted the *.tf files, but keeps a README.md, then that folder is NOT considered deleted by the
script because it still contains a tracked file.
In your infrastructure pipelines, you should use --exclude-deleted to filter out the deleted folders from your plan
and apply actions so that Terraform/Terragrunt can run. If you wish to implement destroy workflows, you can use the
--include-deleted-only parameter to setup a separate pipeline for handling destroy actions.
Questions? Ask away.
We're here to talk about our services, answer any questions, give advice, or just to chat.
{"treedata":{"name":"root","toggled":true,"children":[{"name":".circleci","children":[{"name":"config.yml","path":".circleci/config.yml","sha":"0ebc3336efb41b6ce069e48f39a8cbaed6beaa3b"},{"name":"post-upgrade-test-results.sh","path":".circleci/post-upgrade-test-results.sh","sha":"a4867e8fbdc334b7a90259568ee41ea577fbe764"},{"name":"set-upgrade-test-vars.sh","path":".circleci/set-upgrade-test-vars.sh","sha":"8d961461f09584ccd42432b5d56d64db43da1a6e"}]},{"name":".github","children":[{"name":"ISSUE_TEMPLATE","children":[{"name":"bug_report.md","path":".github/ISSUE_TEMPLATE/bug_report.md","sha":"d2e87e27c601e423865ed660ec697082470ca60f"},{"name":"feature_request.md","path":".github/ISSUE_TEMPLATE/feature_request.md","sha":"023a33099be2336476930c96e17ff1ba5dc55348"}]},{"name":"pull_request_template.md","path":".github/pull_request_template.md","sha":"6b100e40e323b5b07f40ed30616277c51c9f4b9e"}]},{"name":".gitignore","path":".gitignore","sha":"a05d4940aa35b39d0d4e0aa438d2072335a22162"},{"name":".pre-commit-config.yaml","path":".pre-commit-config.yaml","sha":"124016cb71af4e0c43dfa761466f7e739c6fbea1"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"821a961d9a4c9b551211b85f2e4978171a5b1ac3"},{"name":"LICENSE.txt","path":"LICENSE.txt","sha":"f4e3d9bd4717a044ed31ad847a300eee74371a78"},{"name":"README-CircleCI.adoc","path":"README-CircleCI.adoc","sha":"1c9f44dd12bd8f6d56705855d5ca30ddf2280af4"},{"name":"README-Jenkins.adoc","path":"README-Jenkins.adoc","sha":"2ce110c0ecfbb76d5920662f63f54c7b05589c06"},{"name":"README-Terraform-Terragrunt-Pipeline.adoc","path":"README-Terraform-Terragrunt-Pipeline.adoc","sha":"239358d991bab66d24ef0f74ddec359a1fab4d9a"},{"name":"README.adoc","path":"README.adoc","sha":"8af248131430f9a9704190703fbd3bc8e9c01674"},{"name":"_ci","children":[{"name":"output-debug-values.sh","path":"_ci/output-debug-values.sh","sha":"fa613638c76c2031b1427c2daa1d66f71fedad68"}]},{"name":"_docs","children":[{"name":"circleci-cicd-architecture.png","path":"_docs/circleci-cicd-architecture.png","sha":"06f8a55b7c123b6e589333a1ff1c3d90c43222d6"},{"name":"circleci-icon.png","path":"_docs/circleci-icon.png","sha":"d4e8df17858e6f230ff9e8d90ea388b3ff340b79"},{"name":"jenkins-architecture.png","path":"_docs/jenkins-architecture.png","sha":"a35a534eb7f13547e232635262d6b1c1506e9230"},{"name":"jenkins-icon.png","path":"_docs/jenkins-icon.png","sha":"cfb474486acb167b655c22a400fe5cc999959164"},{"name":"terraform-icon.png","path":"_docs/terraform-icon.png","sha":"85602f11c76fd989788112ba40c08d979ddb1164"},{"name":"tftg-pipeline-architecture.png","path":"_docs/tftg-pipeline-architecture.png","sha":"c016f9263be935e933db832e6e5047d6d656339c"},{"name":"travisci-cicd-architecture.png","path":"_docs/travisci-cicd-architecture.png","sha":"c7da609e901de1baba84918893af9016c3da78ed"},{"name":"travisci-icon.png","path":"_docs/travisci-icon.png","sha":"57116e900f797c8f35399929fb3a24b2cf0e7181"}]},{"name":"examples","children":[{"name":"ecs-deploy-runner","children":[{"name":"README.md","path":"examples/ecs-deploy-runner/README.md","sha":"278a6974ddf0e9a95f28b62269250ffffa54665b"},{"name":"cross-account-ecr-repo","children":[{"name":"main.tf","path":"examples/ecs-deploy-runner/cross-account-ecr-repo/main.tf","sha":"05bdcaece513603609a402b5447c305bf5bea736"},{"name":"outputs.tf","path":"examples/ecs-deploy-runner/cross-account-ecr-repo/outputs.tf","sha":"7ceaa57f462257bc0aa953b08b8fee6fd0370f83"},{"name":"variables.tf","path":"examples/ecs-deploy-runner/cross-account-ecr-repo/variables.tf","sha":"27a1d304429a8284815697b0cfb880e4e14963af"}]},{"name":"main.tf","path":"examples/ecs-deploy-runner/main.tf","sha":"b5fcfb3fe805a9775f650e63afb255232203de86"},{"name":"outputs.tf","path":"examples/ecs-deploy-runner/outputs.tf","sha":"0d39cc204673e2e92f0b6e32464ac8080fda59c2"},{"name":"variables.tf","path":"examples/ecs-deploy-runner/variables.tf","sha":"561bf2ff7fa8e8f56daefe0d22743e9d56a10463"}]},{"name":"iam-policies","children":[{"name":"README.md","path":"examples/iam-policies/README.md","sha":"4eaf42cd7b4bc254ac9aabfaa8d6c1b4b8cc4281"},{"name":"main.tf","path":"examples/iam-policies/main.tf","sha":"5283a4908432753a7923d70a1b6c72cc0ac41a04"},{"name":"vars.tf","path":"examples/iam-policies/vars.tf","sha":"aa595b933deb3717ff196517ecb6c2714b2d9afe"}]},{"name":"jenkins","children":[{"name":"README.md","path":"examples/jenkins/README.md","sha":"87fae26e2ab6ba6afc1d7245ee7c5ed6797eb0ff"},{"name":"docker-compose.yml","path":"examples/jenkins/docker-compose.yml","sha":"49ea640e3997dbd71e240d88f598b8a7832edffa"},{"name":"main.tf","path":"examples/jenkins/main.tf","sha":"5fc984b3301aaf47570a7cdcd4d75466cd397ee6"},{"name":"mock","children":[{"name":"mock-user-data.sh","path":"examples/jenkins/mock/mock-user-data.sh","sha":"610ba8091622d0bbec4301093b63c4263b5939ae"},{"name":"mount-ebs-volume","path":"examples/jenkins/mock/mount-ebs-volume","sha":"faa2394ad8a7a35657fb7f34b2014c7f05224e56"},{"name":"systemctl","path":"examples/jenkins/mock/systemctl","sha":"c656c65a7fd2b411548adb7865bc9c065333ad2e"}]},{"name":"outputs.tf","path":"examples/jenkins/outputs.tf","sha":"7283c3f6348eaaa5c0ed4c331f051b1bd436dfc6"},{"name":"packer","children":[{"name":"jenkins.json","path":"examples/jenkins/packer/jenkins.json","sha":"7b25f6dc251a3f39bc7123c3735df1f8ced796fe"}]},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/jenkins/user-data/user-data.sh","sha":"19a4ccc9a1f8cb264d6995473ece0c2b02a0091a"}]},{"name":"vars.tf","path":"examples/jenkins/vars.tf","sha":"0c50a16eb8179ae3e7c6703502376ea298ec7a20"}]}]},{"name":"modules","children":[{"name":"aws-helpers","children":[{"name":"README.md","path":"modules/aws-helpers/README.md","sha":"7ef5360df466b4aad373b73fdb5161aae67a1d61"},{"name":"bin","children":[{"name":"publish-ami","path":"modules/aws-helpers/bin/publish-ami","sha":"1d5697d411cbeed05734fb356ffbf598f7e4eeeb"}]},{"name":"install.sh","path":"modules/aws-helpers/install.sh","sha":"2700711d6a80c6f6c218e4b3d5b1b0cfe4d7609b"}]},{"name":"build-helpers","children":[{"name":"README.md","path":"modules/build-helpers/README.md","sha":"0a91a778414c82bd3d4058df343bb5c2a0d66606"},{"name":"bin","children":[{"name":"build-docker-image","path":"modules/build-helpers/bin/build-docker-image","sha":"0fde55c7e1985925fe00d2d399b190ae6b2edd26"},{"name":"build-packer-artifact","path":"modules/build-helpers/bin/build-packer-artifact","sha":"4d5847eb854bdf2040478e1cdaebefc3d97fd63f"}]},{"name":"install.sh","path":"modules/build-helpers/install.sh","sha":"a132488127b88ef8268399a0b3852aa5e0967a20"}]},{"name":"check-url","children":[{"name":"README.md","path":"modules/check-url/README.md","sha":"1c3219738597ddec48ea7f7f25ed480a96df3426"},{"name":"bin","children":[{"name":"check-url","path":"modules/check-url/bin/check-url","sha":"4e6c57dd70e0a385fb23814619dc917b7c527e57"}]},{"name":"install.sh","path":"modules/check-url/install.sh","sha":"488fad728f75e4ffb6d7156b7cc9ee9682d60183"}]},{"name":"circleci-helpers","children":[{"name":"README.md","path":"modules/circleci-helpers/README.md","sha":"2420e2ca38c96ea153dd3e80576138deed3e10b4"},{"name":"bin","children":[{"name":"install-go-version","path":"modules/circleci-helpers/bin/install-go-version","sha":"8a0121205f24358a00af129e729795013ebf7edb"},{"name":"place-repo-in-gopath","path":"modules/circleci-helpers/bin/place-repo-in-gopath","sha":"ac7085bb304a2004050e676bea658f039493fdcc"}]},{"name":"install.sh","path":"modules/circleci-helpers/install.sh","sha":"313288f93c55678a883f53106471a21f8ebbb2fa"}]},{"name":"ec2-backup","children":[{"name":"README.md","path":"modules/ec2-backup/README.md","sha":"1ecd6984bd3014c303db7e4b26db2c7227a8d6ac"},{"name":"backup-lambda-function","children":[{"name":"ec2-snapper_linux_amd64-v0.5.2","path":"modules/ec2-backup/backup-lambda-function/ec2-snapper_linux_amd64-v0.5.2","sha":"11f872d3dde35b44c160eccf3f0adf49cc5bd72f"},{"name":"index.js","path":"modules/ec2-backup/backup-lambda-function/index.js","sha":"555ea9666346d7d57588452a5a9642ff73bcf25e"}]},{"name":"main.tf","path":"modules/ec2-backup/main.tf","sha":"50d24660356bb358ef0a6d56860450332ce32e82"},{"name":"outputs.tf","path":"modules/ec2-backup/outputs.tf","sha":"770744637fcd7cafd98991397b26a82d01524192"},{"name":"vars.tf","path":"modules/ec2-backup/vars.tf","sha":"338b354b5360c49aa52048889e780b5a4000973f"}]},{"name":"ecs-deploy-runner-invoke-iam-policy","children":[{"name":"README.md","path":"modules/ecs-deploy-runner-invoke-iam-policy/README.md","sha":"66152227a29ea201358ced76a359bb5f2cfd7c9d"},{"name":"main.tf","path":"modules/ecs-deploy-runner-invoke-iam-policy/main.tf","sha":"0dd253f2a087fe6c6c97a3da75b6d294b451cd74"},{"name":"outputs.tf","path":"modules/ecs-deploy-runner-invoke-iam-policy/outputs.tf","sha":"8703d962acdf4584375558aa59831c1c873fe606"},{"name":"variables.tf","path":"modules/ecs-deploy-runner-invoke-iam-policy/variables.tf","sha":"566d414f7ef8621e8c7613847d92b77c3e08cbb6"}]},{"name":"ecs-deploy-runner-standard-configuration","children":[{"name":"README.md","path":"modules/ecs-deploy-runner-standard-configuration/README.md","sha":"8d326578110a022e139f19077991009209ff8167"},{"name":"main.tf","path":"modules/ecs-deploy-runner-standard-configuration/main.tf","sha":"affc331d624dfd99309f5a2aa5907ceb78409f97"},{"name":"outputs.tf","path":"modules/ecs-deploy-runner-standard-configuration/outputs.tf","sha":"8a49694a66a0914299b1fb73e4b9576d32ec001e"},{"name":"variables.tf","path":"modules/ecs-deploy-runner-standard-configuration/variables.tf","sha":"bafc91135373552222a57ec07461e0b9c16ba31e"}]},{"name":"ecs-deploy-runner","children":[{"name":"README.adoc","path":"modules/ecs-deploy-runner/README.adoc","sha":"4fb9fc3ea474666f60770457754b95810087c68d"},{"name":"_docs","children":[{"name":"images","children":[{"name":"sequence-diagram.png","path":"modules/ecs-deploy-runner/_docs/images/sequence-diagram.png","sha":"15c9ea45ff27d20fdc23cf918f8c9ba64c0601a3"}]}]},{"name":"core-concepts.md","path":"modules/ecs-deploy-runner/core-concepts.md","sha":"7aac14ed7deec143377c908007b07b29dea2c555"},{"name":"docker","children":[{"name":"deploy-runner","children":[{"name":"Dockerfile","path":"modules/ecs-deploy-runner/docker/deploy-runner/Dockerfile","sha":"f7936306c92e948ae8b64d9f3c9f547d1aadb2bc"},{"name":"install_additional_terraform_versions.sh","path":"modules/ecs-deploy-runner/docker/deploy-runner/install_additional_terraform_versions.sh","sha":"caaa6a422f35a27e4c2335bd3f02d26f9afb915f"},{"name":"known_hosts","path":"modules/ecs-deploy-runner/docker/deploy-runner/known_hosts","sha":"0dd0a16cd905887f363c0ba4effb5e88a8c4afac"}]},{"name":"kaniko","children":[{"name":"Dockerfile","path":"modules/ecs-deploy-runner/docker/kaniko/Dockerfile","sha":"8b1a72762fa3dbaa0cd73e4c979ff0f1d4c3b13d"},{"name":"build_docker_image.go","path":"modules/ecs-deploy-runner/docker/kaniko/build_docker_image.go","sha":"d1f1b94c5c6f63b8d5fc9db627ff25daa32af010"},{"name":"config.json","path":"modules/ecs-deploy-runner/docker/kaniko/config.json","sha":"34798d807bda1825a3285dd3ac4436eab0905d9d"},{"name":"go.mod","path":"modules/ecs-deploy-runner/docker/kaniko/go.mod","sha":"623d5e6d3c4f31113afa5b3f447248462dec275f"},{"name":"go.sum","path":"modules/ecs-deploy-runner/docker/kaniko/go.sum","sha":"913bb7b5e22e485fde74356a79beb0eca32c479d"}]}]},{"name":"entrypoint","children":[{"name":"deploy_runner_entrypoint.go","path":"modules/ecs-deploy-runner/entrypoint/deploy_runner_entrypoint.go","sha":"1642d8d8991a98dcbb3013408a96fdda7fa165da"},{"name":"go.mod","path":"modules/ecs-deploy-runner/entrypoint/go.mod","sha":"bc99dd9708ad25422cf8c242947a0754a7708273"},{"name":"go.sum","path":"modules/ecs-deploy-runner/entrypoint/go.sum","sha":"00c65fdc0736f9cfcbd08b0d6fb228729720f897"},{"name":"install.sh","path":"modules/ecs-deploy-runner/entrypoint/install.sh","sha":"6c051ab106ae9a19fe56099ae997e9ad68e0bdc6"}]},{"name":"invoker-lambda","children":[{"name":"dev_requirements.txt","path":"modules/ecs-deploy-runner/invoker-lambda/dev_requirements.txt","sha":"930bdb1c56ece3d0a28721bad49c2d9617da104e"},{"name":"invoker","children":[{"name":"__init__.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/__init__.py","sha":"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"},{"name":"assertions.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/assertions.py","sha":"137be569a1ac38b91f3e5cff5c1545c5f7473a03"},{"name":"exceptions.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/exceptions.py","sha":"79c636a4387a02c505213f89348275d58aedd876"},{"name":"index.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/index.py","sha":"ee1ad652dd7f4024e56e9c2d21cc669be616be8e"},{"name":"project_logging.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/project_logging.py","sha":"b8c1f628fcaebaca7864bb57f6dbfda0375e13c9"},{"name":"types.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/types.py","sha":"b812525d7a49aec663224160f0ecc29c15f026af"}]},{"name":"test","children":[{"name":"test_assertions.py","path":"modules/ecs-deploy-runner/invoker-lambda/test/test_assertions.py","sha":"b7cf3ad155f49fe5e631b768b45228a2d513d205"},{"name":"test_invoker.py","path":"modules/ecs-deploy-runner/invoker-lambda/test/test_invoker.py","sha":"c4aafa4a5bcaeafc100f98404236060f5d985e1b"}]}]},{"name":"main.tf","path":"modules/ecs-deploy-runner/main.tf","sha":"9c11c1c5a630df4638309ab77b92ff0fab7d2826"},{"name":"main_ecs.tf","path":"modules/ecs-deploy-runner/main_ecs.tf","sha":"a4058042dae2578615563187b0552f6c918286e2"},{"name":"main_lambda.tf","path":"modules/ecs-deploy-runner/main_lambda.tf","sha":"a83a1013e3f9664d58df5137b0a03b65e7bd75b0"},{"name":"outputs.tf","path":"modules/ecs-deploy-runner/outputs.tf","sha":"d2d2a93a57ee8a130ed1a7c6c8b1e3781812291f"},{"name":"variables.tf","path":"modules/ecs-deploy-runner/variables.tf","sha":"fcb603359cfeddd0b070ba49e0908dda8f2a73a3"}]},{"name":"git-helpers","children":[{"name":"README.md","path":"modules/git-helpers/README.md","sha":"8749b21dba677a1e2a1d2fd56af962e5ce8a8fc5"},{"name":"bin","children":[{"name":"git-add-commit-push","path":"modules/git-helpers/bin/git-add-commit-push","sha":"f270bc4da9ee46bc7754c0ce8bf8f5a6c6c38c0a"},{"name":"git-rebase","path":"modules/git-helpers/bin/git-rebase","sha":"887dd90ba36adc5c0362cbadca79707756535b24"}]},{"name":"install.sh","path":"modules/git-helpers/install.sh","sha":"f22ede2f2f085af0a065dd43ed1279c69dd5a00b"}]},{"name":"gruntwork-module-circleci-helpers","children":[{"name":"README.md","path":"modules/gruntwork-module-circleci-helpers/README.md","sha":"58f715757b3ff6ce5cdc56167de773db71cbaeb1"},{"name":"bin","children":[{"name":"build-go-binaries","path":"modules/gruntwork-module-circleci-helpers/bin/build-go-binaries","sha":"56c7085e0b63eb293d170ac64377df0ba403d23a"},{"name":"configure-environment-for-gruntwork-module","path":"modules/gruntwork-module-circleci-helpers/bin/configure-environment-for-gruntwork-module","sha":"c268a8eac4f13e83b968d7b4abf5e30726232041"},{"name":"run-go-tests","path":"modules/gruntwork-module-circleci-helpers/bin/run-go-tests","sha":"865947418d3dbcac18d644c5566a63d0ed02c3ca"},{"name":"upload-github-release-assets","path":"modules/gruntwork-module-circleci-helpers/bin/upload-github-release-assets","sha":"5091c9118c1b931079ac3c112e2b54577b52194a"}]},{"name":"install.sh","path":"modules/gruntwork-module-circleci-helpers/install.sh","sha":"a9cc16c05a73cf6c40097608838758a8de64daab"}]},{"name":"iam-policies","children":[{"name":"README.md","path":"modules/iam-policies/README.md","sha":"da28056c8749bc2c46dc99ed16286e14b7c55511"},{"name":"ecr-docker-push","children":[{"name":"README.md","path":"modules/iam-policies/ecr-docker-push/README.md","sha":"6a0a84157fe573f2c7ac1e0bd6e2169b2814f1c0"},{"name":"main.tf","path":"modules/iam-policies/ecr-docker-push/main.tf","sha":"dfb81637389b3b0df7c3606f08c0f9f2412d9564"},{"name":"outputs.tf","path":"modules/iam-policies/ecr-docker-push/outputs.tf","sha":"ba3177631efce4651f499e457cc9aa0b1afb338d"},{"name":"vars.tf","path":"modules/iam-policies/ecr-docker-push/vars.tf","sha":"d8aaeae6205750961e3deaba741ee68180a32ca7"}]},{"name":"ecs-service-deployment","children":[{"name":"README.md","path":"modules/iam-policies/ecs-service-deployment/README.md","sha":"77bb1df6db0d7cd886ee665f1d6566944521b00c"},{"name":"main.tf","path":"modules/iam-policies/ecs-service-deployment/main.tf","sha":"f0b19d1e6144de1d9e42a272e58c632270494282"},{"name":"outputs.tf","path":"modules/iam-policies/ecs-service-deployment/outputs.tf","sha":"4bf7dcb16326113889318ee8da63dadfc1ce35e9"},{"name":"vars.tf","path":"modules/iam-policies/ecs-service-deployment/vars.tf","sha":"78c2705c906b853f0e4b18b6c8f2c05e164109bf"}]},{"name":"terraform-remote-state-s3","children":[{"name":"README.md","path":"modules/iam-policies/terraform-remote-state-s3/README.md","sha":"b7892fd6dabecb66909706dbb8941e63e2c56954"},{"name":"main.tf","path":"modules/iam-policies/terraform-remote-state-s3/main.tf","sha":"68a33aa21793e3d955a2023c9192d3db68c0ad8c"},{"name":"outputs.tf","path":"modules/iam-policies/terraform-remote-state-s3/outputs.tf","sha":"07cabd2ad56a78ea31e2bf59f1cb938fdf3b9664"},{"name":"vars.tf","path":"modules/iam-policies/terraform-remote-state-s3/vars.tf","sha":"720084fa0f9cf944b19ba30f59e78efc2e7b96b9"}]},{"name":"terragrunt","children":[{"name":"README.md","path":"modules/iam-policies/terragrunt/README.md","sha":"eccacc553810fa838b23d24718ffb8f70a9a39e5"},{"name":"main.tf","path":"modules/iam-policies/terragrunt/main.tf","sha":"cf3fc37b73963231551d075e5c4db8f2717d8d2a"},{"name":"outputs.tf","path":"modules/iam-policies/terragrunt/outputs.tf","sha":"2b948005b8a1322f408e999226ac7b66629759cd"},{"name":"vars.tf","path":"modules/iam-policies/terragrunt/vars.tf","sha":"52f0480b69a57d0ff43e76ae26cb17d77dab5069"}]}]},{"name":"infrastructure-deploy-script","children":[{"name":"README.adoc","path":"modules/infrastructure-deploy-script/README.adoc","sha":"38c5f953a2f97251277650d9d7f44a5e2de5a26c"},{"name":"core-concepts.md","path":"modules/infrastructure-deploy-script/core-concepts.md","sha":"e617d3dd528507993c8162811cb6de16328e9ed3"},{"name":"dev_requirements.txt","path":"modules/infrastructure-deploy-script/dev_requirements.txt","sha":"d4f836eb792be30da6183eaba4bb57f15ffb2f54"},{"name":"infrastructure_deploy_script","children":[{"name":"__init__.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/__init__.py","sha":"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"},{"name":"deploy.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/deploy.py","sha":"e57442678159d362329d76f58a7c7772cf0bee61"},{"name":"exceptions.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/exceptions.py","sha":"dd014c3f9240871277b5a47a72ee3b4baf538e6f"},{"name":"git.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/git.py","sha":"f32161d4b04482cbe659fb18b3a1437426ef7bff"},{"name":"project_logging.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/project_logging.py","sha":"a72c2a19962838f3375390380dcf444b73e1fcef"},{"name":"py.typed","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/py.typed","sha":"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"},{"name":"shell.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/shell.py","sha":"6365772d88619273883ae02a047c6e98d8955232"},{"name":"ssh.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/ssh.py","sha":"fa487859e84a655cf69e8646b8d44b29b2e10886"},{"name":"terra.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/terra.py","sha":"ee87678613921c3f11326c385b6edf8dbd216728"}]},{"name":"install.sh","path":"modules/infrastructure-deploy-script/install.sh","sha":"5dedba5c0d9c29dee1a5f625d502dccc15c5dc36"},{"name":"requirements.txt","path":"modules/infrastructure-deploy-script/requirements.txt","sha":"6b0824aebda5ba488c0e8bb4691ff343c0a2fcfc"},{"name":"scripts","children":[{"name":"infrastructure-deploy-script","path":"modules/infrastructure-deploy-script/scripts/infrastructure-deploy-script","sha":"9adf313562163a979dbe428afd13965622ffb361"}]},{"name":"setup.py","path":"modules/infrastructure-deploy-script/setup.py","sha":"b9399339fe7f52763c705ac83252ab7f3a9fc047"},{"name":"test","children":[{"name":"conftest.py","path":"modules/infrastructure-deploy-script/test/conftest.py","sha":"ebae81d85a6ce4997c9d6f4a3d833c617822a0a0"},{"name":"fixtures","children":[{"name":"terraform-with-inputs","children":[{"name":"input.tfvars","path":"modules/infrastructure-deploy-script/test/fixtures/terraform-with-inputs/input.tfvars","sha":"68468ad2c7a8319c2674d572eec058660cddfdfb"},{"name":"main.tf","path":"modules/infrastructure-deploy-script/test/fixtures/terraform-with-inputs/main.tf","sha":"0a16a02487d5bf436440bff9b0fb1f6372a284e2"},{"name":"terragrunt.hcl","path":"modules/infrastructure-deploy-script/test/fixtures/terraform-with-inputs/terragrunt.hcl","sha":"e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"}]},{"name":"terraform","children":[{"name":"main.tf","path":"modules/infrastructure-deploy-script/test/fixtures/terraform/main.tf","sha":"e370f64097c82bca28d07e7b12befda38aa3df04"}]},{"name":"terragrunt","children":[{"name":"terragrunt.hcl","path":"modules/infrastructure-deploy-script/test/fixtures/terragrunt/terragrunt.hcl","sha":"2359b15bc6a698e481a8e99fdb352e174203b925"}]}]},{"name":"test_deploy.py","path":"modules/infrastructure-deploy-script/test/test_deploy.py","sha":"45b981d9c2b84f9aa9cdcdbd28f6316a6a785bab"},{"name":"test_git.py","path":"modules/infrastructure-deploy-script/test/test_git.py","sha":"ea5b0e3d0243ffb270d3802368a493587ce5db9f"},{"name":"test_shell.py","path":"modules/infrastructure-deploy-script/test/test_shell.py","sha":"fa0f984c4ce6218303d7f9c38c4c20d018411318"}]}]},{"name":"infrastructure-deployer","children":[{"name":"README.adoc","path":"modules/infrastructure-deployer/README.adoc","sha":"330baa82f653a9112314f097dab665cbba94c7c9"},{"name":"core-concepts.md","path":"modules/infrastructure-deployer/core-concepts.md","sha":"917f3e952686f26ba67c758216404860aabd60fc"},{"name":"deploy","children":[{"name":"aws.go","path":"modules/infrastructure-deployer/deploy/aws.go","sha":"ed547b9e816adac716b3731f0b66a428d5920fd8"},{"name":"aws_ecs.go","path":"modules/infrastructure-deployer/deploy/aws_ecs.go","sha":"c5572b0f84d7fb372b9fc9562585e18c6d8642ab"},{"name":"deploy.go","path":"modules/infrastructure-deployer/deploy/deploy.go","sha":"a4dcbc57ecaf83a0936062bbd458ec621bef3c18"},{"name":"errors.go","path":"modules/infrastructure-deployer/deploy/errors.go","sha":"21cc411d97b50e4a0e4aaa2bea42f9db591ad1a7"}]},{"name":"go.mod","path":"modules/infrastructure-deployer/go.mod","sha":"72455cd3d9e872ba3c9892ac48749a295b30924e"},{"name":"go.sum","path":"modules/infrastructure-deployer/go.sum","sha":"1fc1ee88c241493241b0612bef7cb74dba4dc7b6"},{"name":"logging","children":[{"name":"logging.go","path":"modules/infrastructure-deployer/logging/logging.go","sha":"9a7a2aa73ff0dc233bdb5b48ddfdf1d14423f011"}]},{"name":"main.go","path":"modules/infrastructure-deployer/main.go","sha":"3060e42a51789c078b1ba5249097c40cd7bf17ac"},{"name":"revshlex","children":[{"name":"revshlex.go","path":"modules/infrastructure-deployer/revshlex/revshlex.go","sha":"965c2960b0d9a0ba56e7b1868def546556167c3b"},{"name":"revshlex_test.go","path":"modules/infrastructure-deployer/revshlex/revshlex_test.go","sha":"f25d5a84e38fb4fb44930477ad999431f323f5d7"}]}]},{"name":"install-jenkins","children":[{"name":"README.md","path":"modules/install-jenkins/README.md","sha":"6d2b4a045192ce1ea32764520b6e0c6cf2627109"},{"name":"install.sh","path":"modules/install-jenkins/install.sh","sha":"d65a63c8a1c487957eb0ecc84413eced499b8732"},{"name":"run-jenkins","path":"modules/install-jenkins/run-jenkins","sha":"491b104ddedf7406e288504417bfe5f26378a961"}]},{"name":"jenkins-server","children":[{"name":"README.md","path":"modules/jenkins-server/README.md","sha":"6c209c9b27bc55215147413d6419c88243d1ebdc"},{"name":"main.tf","path":"modules/jenkins-server/main.tf","sha":"5b3823f5e8c7c6bce7fac91a0662b1eb54c35af7"},{"name":"outputs.tf","path":"modules/jenkins-server/outputs.tf","sha":"5670bd47368b97e5eeedcca805a28a337230e9e2"},{"name":"vars.tf","path":"modules/jenkins-server/vars.tf","sha":"dd471a5eb74afa3bac20b8655e8b7162c4cd0b34"}]},{"name":"kubernetes-circleci-helpers","children":[{"name":"README.md","path":"modules/kubernetes-circleci-helpers/README.md","sha":"b2f09495ef47eae1ef33db52a7d8d4ca5c712393"},{"name":"bin","children":[{"name":"setup-minikube","path":"modules/kubernetes-circleci-helpers/bin/setup-minikube","sha":"74aa11d9e0a667d29deeb1121eabb2c3889414d3"}]},{"name":"install.sh","path":"modules/kubernetes-circleci-helpers/install.sh","sha":"2ae8670872407ceb2c434dc5b117ae14073af9a2"}]},{"name":"monorepo-helpers","children":[{"name":"README.adoc","path":"modules/monorepo-helpers/README.adoc","sha":"256693033af8ecfbd050f4bd9df26a276690f74a"},{"name":"core-concepts.md","path":"modules/monorepo-helpers/core-concepts.md","sha":"72e71c8f84ec1cdd0f902c158f8ec9a3c57a5cb0"},{"name":"dev_requirements.txt","path":"modules/monorepo-helpers/dev_requirements.txt","sha":"16bf6a0c4c62e5dc99b4bf19d24cfbc608c00986"},{"name":"find_tf_monorepo_tests","children":[{"name":"__init__.py","path":"modules/monorepo-helpers/find_tf_monorepo_tests/__init__.py","sha":"9c0fa90a19fd599d0fe6668b8f3b75d6c368c500"},{"name":"config.py","path":"modules/monorepo-helpers/find_tf_monorepo_tests/config.py","sha":"ef562e400aaf6ee7c7c8081f81256e53c15fc646"},{"name":"constants.py","path":"modules/monorepo-helpers/find_tf_monorepo_tests/constants.py","sha":"b0dc5f3563e282b55a0cc544430fb0bdac5f0683"},{"name":"exceptions.py","path":"modules/monorepo-helpers/find_tf_monorepo_tests/exceptions.py","sha":"925b112424dd2d891cd1045f43901c1820ef042a"},{"name":"external_proc.py","path":"modules/monorepo-helpers/find_tf_monorepo_tests/external_proc.py","sha":"143c14cdac0b13d3b18cfd252376cc067bfc5b8e"},{"name":"string_helpers.py","path":"modules/monorepo-helpers/find_tf_monorepo_tests/string_helpers.py","sha":"01b5782d82cedd8e6ef59677c65b5fbb4c9c10b5"},{"name":"test_search.py","path":"modules/monorepo-helpers/find_tf_monorepo_tests/test_search.py","sha":"f0d9e8d34fb771fc6c57425258ad6a7c502b1b78"},{"name":"types.py","path":"modules/monorepo-helpers/find_tf_monorepo_tests/types.py","sha":"4965ca64f73effea4b3513b19178ba1c4d17617a"}]},{"name":"install.sh","path":"modules/monorepo-helpers/install.sh","sha":"137a9f21edef3d27f297b79bb0fd29b616e0668f"},{"name":"requirements.txt","path":"modules/monorepo-helpers/requirements.txt","sha":"4c2278c3d405ace58f9d18c0712e9599ac6728f4"},{"name":"scripts","children":[{"name":"find-tf-monorepo-tests","path":"modules/monorepo-helpers/scripts/find-tf-monorepo-tests","sha":"32b2e574048ca7b696bbb09bdd455928ac42c702"},{"name":"validate-monorepo-test-mappings","path":"modules/monorepo-helpers/scripts/validate-monorepo-test-mappings","sha":"4659a35f387c526edc65a3ac6a5c37cc53c5a605"}]},{"name":"setup.py","path":"modules/monorepo-helpers/setup.py","sha":"4bb9f6c04574e4ad735e856859ea20a455a2a64d"},{"name":"test","children":[{"name":"test_search.py","path":"modules/monorepo-helpers/test/test_search.py","sha":"b1b8ddcd197636fd2c596af0f215e94816aac5c0"},{"name":"test_string_helpers.py","path":"modules/monorepo-helpers/test/test_string_helpers.py","sha":"a6be235dd2a75c69056bf5a269060d50947e9049"}]}]},{"name":"sign-binary-helpers","children":[{"name":"README.md","path":"modules/sign-binary-helpers/README.md","sha":"8d9923652c25a08e7c6545e312f06c9623b3814a"},{"name":"bin","children":[{"name":"sign-binary","path":"modules/sign-binary-helpers/bin/sign-binary","sha":"ae2a67b880cb6d616d96481f1d315b94d0102d2c"}]},{"name":"install.sh","path":"modules/sign-binary-helpers/install.sh","sha":"935c76c7b9891d683ce77954aa7615990c1d1fa6"}]},{"name":"terraform-helpers","children":[{"name":"README.md","path":"modules/terraform-helpers/README.md","sha":"3436693398bf5e77a117313d0646c594441a80aa","toggled":true},{"name":"bin","children":[{"name":"git-updated-files","path":"modules/terraform-helpers/bin/git-updated-files","sha":"2790734b850e0fb7792b2f4b133f9b7815164f89"},{"name":"git-updated-folders","path":"modules/terraform-helpers/bin/git-updated-folders","sha":"e3f61e873f16b47ee02e691bce65232f7299879e"},{"name":"terraform-update-variable","path":"modules/terraform-helpers/bin/terraform-update-variable","sha":"43fb7c517d086ca8f27b9846241cdd5e34de013c"}]},{"name":"install.sh","path":"modules/terraform-helpers/install.sh","sha":"3dd11c583323c347e39fc20fb696a742decc033d"}],"toggled":true}],"toggled":true},{"name":"setup.cfg","path":"setup.cfg","sha":"fbb2d6b0a5cc69116979f432a6c390e2110c8277"},{"name":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","path":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","sha":"ae586c0fe830819580e1009d41a9074f16e65bed"},{"name":"test","children":[{"name":"README.md","path":"test/README.md","sha":"0baa161831e9c98eb68f3bd6e3c6d73992859a27"},{"name":"build_docker_image_test.go","path":"test/build_docker_image_test.go","sha":"1c3c70c8e7ae97c05acb50fdfda9c14a2762392e"},{"name":"build_helpers.go","path":"test/build_helpers.go","sha":"0e77ed869d6406431209fdbf405745dce7a7cc26"},{"name":"build_packer_artifact_test.go","path":"test/build_packer_artifact_test.go","sha":"fa5e450e71a3fea7e8b3454cf6f83ae2cf0845f5"},{"name":"build_packer_artifact_unit_test.go","path":"test/build_packer_artifact_unit_test.go","sha":"4bd517a7dca9d2bb6ccce741059e69fd43003cf2"},{"name":"check_url_test.go","path":"test/check_url_test.go","sha":"bd3419bcb07624923777c14619eba17c7edc8c64"},{"name":"destroy_test.go","path":"test/destroy_test.go","sha":"639fa96d47dbbe3431d112b12125c0e03642a09d"},{"name":"destroy_test_helpers.go","path":"test/destroy_test_helpers.go","sha":"ce1a5f2111b0d7162c677d52092c8dba859cc9e9"},{"name":"edr-tests","children":[{"name":"ecs_deploy_runner_docker_test.go","path":"test/edr-tests/ecs_deploy_runner_docker_test.go","sha":"9e8f7d1d86c2a544cb7f3d568ac4f48bfd8ae105"},{"name":"ecs_deploy_runner_ec2_test.go","path":"test/edr-tests/ecs_deploy_runner_ec2_test.go","sha":"99b17f4a1c69cdc25165b18e29497f04afde237d"},{"name":"ecs_deploy_runner_https_test.go","path":"test/edr-tests/ecs_deploy_runner_https_test.go","sha":"757903b53d25d21630675f11d0a8705872d506d9"},{"name":"ecs_deploy_runner_kaniko_test.go","path":"test/edr-tests/ecs_deploy_runner_kaniko_test.go","sha":"5830a89979df9beb08afb93adcecd5a3a8566c23"},{"name":"ecs_deploy_runner_security_test.go","path":"test/edr-tests/ecs_deploy_runner_security_test.go","sha":"f7b7380b113026876c7e74e0b9dfc982c2b1cd30"},{"name":"ecs_deploy_runner_standard_configuration_test.go","path":"test/edr-tests/ecs_deploy_runner_standard_configuration_test.go","sha":"754bba676c7f25653900a8cd9ca3ea231f63a4d9"},{"name":"ecs_deploy_runner_test.go","path":"test/edr-tests/ecs_deploy_runner_test.go","sha":"8eaa21984f797ae3b8308b5895593fc8d709dd26"},{"name":"ecs_deploy_runner_test_helpers.go","path":"test/edr-tests/ecs_deploy_runner_test_helpers.go","sha":"51565e077c0a34d02bc9576ec75154e2fd87ba4c"},{"name":"ecs_deploy_runner_workflow_test.go","path":"test/edr-tests/ecs_deploy_runner_workflow_test.go","sha":"1b347e500078a1fb7e45168a1276bdd9841f0004"},{"name":"infrastructure_deploy_script_test.go","path":"test/edr-tests/infrastructure_deploy_script_test.go","sha":"6e412f9722088350dbe87d5ac95a2d97870c727c"}]},{"name":"edrhelpers","children":[{"name":"edrhelpers.go","path":"test/edrhelpers/edrhelpers.go","sha":"278016e56aa0c886eeb155fb03acc99d8f0ab24f"},{"name":"edrhelpers_test.go","path":"test/edrhelpers/edrhelpers_test.go","sha":"5b34ed2f7d5ea1f8290b354b045554db143069f9"},{"name":"fixtures","children":[{"name":"docker","children":[{"name":"Dockerfile","path":"test/edrhelpers/fixtures/docker/Dockerfile","sha":"09bd120286de9d94d1340b658e66088f6f8ae28b"}]}]},{"name":"go.mod","path":"test/edrhelpers/go.mod","sha":"c31e30950721c4f785b6d30f3804ca3b4982063b"},{"name":"go.sum","path":"test/edrhelpers/go.sum","sha":"218718c98f6110c949157daf970a9346f59b4a02"}]},{"name":"fixtures","children":[{"name":"build-packer-image-unit","children":[{"name":"ami-name","children":[{"name":"clean-resource-name.json","path":"test/fixtures/build-packer-image-unit/ami-name/clean-resource-name.json","sha":"2601caa0afd10705ba4c023f31dd03c1b2c10417"},{"name":"formatdate.pkr.hcl","path":"test/fixtures/build-packer-image-unit/ami-name/formatdate.pkr.hcl","sha":"3b5d6a6980d571292d6f0f925550578c53a47630"},{"name":"isotime-ami-name.json","path":"test/fixtures/build-packer-image-unit/ami-name/isotime-ami-name.json","sha":"29fa01b7f32d374cca8549b2bda8b18b69953373"},{"name":"multiple.json","path":"test/fixtures/build-packer-image-unit/ami-name/multiple.json","sha":"436b13dd54866f8926ce24c7766a043ff6d1e223"},{"name":"multiple.pkr.hcl","path":"test/fixtures/build-packer-image-unit/ami-name/multiple.pkr.hcl","sha":"bceb2c26063c414ac0718e7478a921680c1009e8"},{"name":"timestamp-ami-name.json","path":"test/fixtures/build-packer-image-unit/ami-name/timestamp-ami-name.json","sha":"17bb05e841d46f41900e3f647acaec28c58a34cc"},{"name":"uuid-ami-name.json","path":"test/fixtures/build-packer-image-unit/ami-name/uuid-ami-name.json","sha":"834762f57e84d3a3b62ae2afb04ac56aa145ad00"},{"name":"variables.json","path":"test/fixtures/build-packer-image-unit/ami-name/variables.json","sha":"5743df9f17cf8056f9c553196dc49afac1dbb59d"},{"name":"variables.pkr.hcl","path":"test/fixtures/build-packer-image-unit/ami-name/variables.pkr.hcl","sha":"c0a06f9957934682fccc31d794ba8a4ccf44e02f"},{"name":"whitespace.json","path":"test/fixtures/build-packer-image-unit/ami-name/whitespace.json","sha":"35cfd5200bbd124689868f115cb1b5498a8dfbbe"},{"name":"whitespace.pkr.hcl","path":"test/fixtures/build-packer-image-unit/ami-name/whitespace.pkr.hcl","sha":"a74b0503720df65dd9b6c13e1b65af99fabd3d96"}]},{"name":"ami-region","children":[{"name":"variable.json","path":"test/fixtures/build-packer-image-unit/ami-region/variable.json","sha":"2601caa0afd10705ba4c023f31dd03c1b2c10417"},{"name":"variable.pkr.hcl","path":"test/fixtures/build-packer-image-unit/ami-region/variable.pkr.hcl","sha":"3b5d6a6980d571292d6f0f925550578c53a47630"}]},{"name":"ami-tags","children":[{"name":"multiple-tags-variable.json","path":"test/fixtures/build-packer-image-unit/ami-tags/multiple-tags-variable.json","sha":"a546cb645b151da0156251a2e40c0599945f605b"},{"name":"multiple-tags-variable.pkr.hcl","path":"test/fixtures/build-packer-image-unit/ami-tags/multiple-tags-variable.pkr.hcl","sha":"baa093ab43bd9c5a42a5ee6a1bce39e70d520089"},{"name":"no-tags.json","path":"test/fixtures/build-packer-image-unit/ami-tags/no-tags.json","sha":"d160046152b90e840fe08650cb9fb4ae8273ab40"},{"name":"no-tags.pkr.hcl","path":"test/fixtures/build-packer-image-unit/ami-tags/no-tags.pkr.hcl","sha":"3b5d6a6980d571292d6f0f925550578c53a47630"},{"name":"single-tag.json","path":"test/fixtures/build-packer-image-unit/ami-tags/single-tag.json","sha":"c2770e7139805962dfa1eab83e5d02dde42a7b95"},{"name":"single-tag.pkr.hcl","path":"test/fixtures/build-packer-image-unit/ami-tags/single-tag.pkr.hcl","sha":"b4205dc5f59762daf4bc4af09ad084f5369f7eab"}]},{"name":"assert-build-amazon","children":[{"name":"amazon-ebs.json","path":"test/fixtures/build-packer-image-unit/assert-build-amazon/amazon-ebs.json","sha":"d160046152b90e840fe08650cb9fb4ae8273ab40"},{"name":"ambiguous.json","path":"test/fixtures/build-packer-image-unit/assert-build-amazon/ambiguous.json","sha":"b516d4fd64b4fae25af1582d2a9236266740333c"},{"name":"docker.json","path":"test/fixtures/build-packer-image-unit/assert-build-amazon/docker.json","sha":"65adc353ebf9bda1f6821d42ec0b2f6f8d5fc125"}]},{"name":"scripts","children":[{"name":"ami-name-test.sh","path":"test/fixtures/build-packer-image-unit/scripts/ami-name-test.sh","sha":"af00f6ad4a819f7d3a52b927a672645115f038e7"},{"name":"ami-region-test.sh","path":"test/fixtures/build-packer-image-unit/scripts/ami-region-test.sh","sha":"eb065fe4c4f55e87f190885f3402263ef8e90e06"},{"name":"ami-tags-test.sh","path":"test/fixtures/build-packer-image-unit/scripts/ami-tags-test.sh","sha":"8018361dbbe35c8654da9a84f1cb8682c7e0e214"},{"name":"assert-builder-amazon-test.sh","path":"test/fixtures/build-packer-image-unit/scripts/assert-builder-amazon-test.sh","sha":"fdd17b5cfc834f152de4c87f11663e68729b279e"}]}]},{"name":"git-add-commit-push","children":[{"name":"auto-committed.txt","path":"test/fixtures/git-add-commit-push/auto-committed.txt","sha":"5a1b0487943a6bb6645e502dc2c550c3c043f52a"}]},{"name":"hello-world-go-app","children":[{"name":"main.go","path":"test/fixtures/hello-world-go-app/main.go","sha":"3e0c7643f51386747f1b85656a0c797f282aed04"}]},{"name":"infra-pipeline-workflow","children":[{"name":"deploy-ami","children":[{"name":"main.tf","path":"test/fixtures/infra-pipeline-workflow/deploy-ami/main.tf","sha":"ce71c0fc94842687489f9423d9983cd831c79751"},{"name":"terragrunt.hcl","path":"test/fixtures/infra-pipeline-workflow/deploy-ami/terragrunt.hcl","sha":"726d218ced39781cf10699baf05283fbfcfb22df"}]},{"name":"deploy-docker","children":[{"name":"main.tf","path":"test/fixtures/infra-pipeline-workflow/deploy-docker/main.tf","sha":"4c5b2f8e767ab37cdedc43910ee91c6e181feb6b"},{"name":"terragrunt.hcl","path":"test/fixtures/infra-pipeline-workflow/deploy-docker/terragrunt.hcl","sha":"6d6be2748d15d39b736ebdf7b9621ed001b1da09"}]}]},{"name":"null_resource_module","children":[{"name":"main.tf","path":"test/fixtures/null_resource_module/main.tf","sha":"b9ddb64d3a71c26511281e336383ae3995954c6c"}]},{"name":"null_resource_terragrunt","children":[{"name":"terragrunt.hcl","path":"test/fixtures/null_resource_terragrunt/terragrunt.hcl","sha":"91585298f1066168e7a5a379c347fe0616f38856"}]},{"name":"test-docker-image","children":[{"name":"Dockerfile","path":"test/fixtures/test-docker-image/Dockerfile","sha":"5de35bbecce145045ae22fbc5fb97c133568a1ff"},{"name":"test.sh","path":"test/fixtures/test-docker-image/test.sh","sha":"ef3083cf7f3436ac7d01acfa33e4dab143fbcafd"}]},{"name":"test-go-test-files","children":[{"name":"simple_test.go","path":"test/fixtures/test-go-test-files/simple_test.go","sha":"53007ca88996e540ddfc503ce42982bdd5e785d2"},{"name":"test.sh","path":"test/fixtures/test-go-test-files/test.sh","sha":"25b8ef156d589c8d088d026b422e3b9c751c4b53"}]},{"name":"test-packer-image","children":[{"name":"hello-world-multiple-builders.json","path":"test/fixtures/test-packer-image/hello-world-multiple-builders.json","sha":"1c3e101f8965041b7aef0f5c4cddb14e1011d520"},{"name":"hello-world-no-tags-builder.json","path":"test/fixtures/test-packer-image/hello-world-no-tags-builder.json","sha":"d160046152b90e840fe08650cb9fb4ae8273ab40"},{"name":"hello-world-one-builder.json","path":"test/fixtures/test-packer-image/hello-world-one-builder.json","sha":"44a88c43721e45e9f5d921d8c04d08fa62c26748"},{"name":"hello-world-one-builder.pkr.hcl","path":"test/fixtures/test-packer-image/hello-world-one-builder.pkr.hcl","sha":"08fa9db48f63742d94f8b0c007cfc222d8d6fdc6"}]},{"name":"test-tfvars-files","children":[{"name":"multiple-similar-variables.tfvars","path":"test/fixtures/test-tfvars-files/multiple-similar-variables.tfvars","sha":"8147977dee3d9a196177c575cd664354c601e68f"},{"name":"multiple-variables-and-comments.tfvars","path":"test/fixtures/test-tfvars-files/multiple-variables-and-comments.tfvars","sha":"8b757cfa5ed1d5049c478ed9180b9e9a5743335e"},{"name":"one-variable-extra-whitespace.tfvars","path":"test/fixtures/test-tfvars-files/one-variable-extra-whitespace.tfvars","sha":"743b02f7015bd51232f9c40564c654f424cbb523"},{"name":"one-variable-no-whitespace.tfvars","path":"test/fixtures/test-tfvars-files/one-variable-no-whitespace.tfvars","sha":"39ddb49aa78f683e3e45384d2440a904d0ad7ec9"},{"name":"one-variable.tfvars","path":"test/fixtures/test-tfvars-files/one-variable.tfvars","sha":"82a0cea8ac06d9534dd2549c73ae70afd47336bb"}]},{"name":"test-tghcl-files","children":[{"name":"multiple-similar-variables.hcl","path":"test/fixtures/test-tghcl-files/multiple-similar-variables.hcl","sha":"8224297de9667b6887136c897b473977f7013fc0"},{"name":"multiple-variables-and-comments.hcl","path":"test/fixtures/test-tghcl-files/multiple-variables-and-comments.hcl","sha":"1905719b9208e53d78a9bced9792194f6955f928"},{"name":"one-variable-extra-whitespace.hcl","path":"test/fixtures/test-tghcl-files/one-variable-extra-whitespace.hcl","sha":"aa09bc5beacd10b66660e71173d16f3b093e9415"},{"name":"one-variable-no-whitespace.hcl","path":"test/fixtures/test-tghcl-files/one-variable-no-whitespace.hcl","sha":"8e77e4baf099fdb7f1e1d1571725c835ac92093a"},{"name":"one-variable.hcl","path":"test/fixtures/test-tghcl-files/one-variable.hcl","sha":"0afe11b72b3635feb75d71d7aff4cc28806a7f67"}]},{"name":"tfpipeline","children":[{"name":"failure","children":[{"name":"terraform","children":[{"name":"main.tf","path":"test/fixtures/tfpipeline/failure/terraform/main.tf","sha":"5488bde3fbd03a58398aeeb904cfef74d7200aae"}]},{"name":"terragrunt","children":[{"name":"terragrunt.hcl","path":"test/fixtures/tfpipeline/failure/terragrunt/terragrunt.hcl","sha":"2359b15bc6a698e481a8e99fdb352e174203b925"}]}]},{"name":"nested","children":[{"name":"terraform","children":[{"name":"main.tf","path":"test/fixtures/tfpipeline/nested/terraform/main.tf","sha":"5aab075e062b66046b8a381029859b59a35c0117"}]},{"name":"terragrunt","children":[{"name":"terragrunt.hcl","path":"test/fixtures/tfpipeline/nested/terragrunt/terragrunt.hcl","sha":"2359b15bc6a698e481a8e99fdb352e174203b925"}]}]},{"name":"root","children":[{"name":"terraform","children":[{"name":"main.tf","path":"test/fixtures/tfpipeline/root/terraform/main.tf","sha":"4c38ad94d4d10a46cb1acd012f9b3e5513757ac2"}]},{"name":"terragrunt","children":[{"name":"terragrunt.hcl","path":"test/fixtures/tfpipeline/root/terragrunt/terragrunt.hcl","sha":"2359b15bc6a698e481a8e99fdb352e174203b925"}]}]}]}]},{"name":"git_updated_folders_test.go","path":"test/git_updated_folders_test.go","sha":"9ac9c0aca0de5fe4f04ee65f6db8e627ad04a701"},{"name":"github_helpers.go","path":"test/github_helpers.go","sha":"56e54040790227aab12ae1b2f43991b9f00f87f6"},{"name":"go.mod","path":"test/go.mod","sha":"5a7425a6b9348af7a0827b213208788d933a2054"},{"name":"go.sum","path":"test/go.sum","sha":"90d910e47c97b33ca445f7d4eab965056d57798d"},{"name":"gruntwork_module_circleci_helpers_integration_test.go","path":"test/gruntwork_module_circleci_helpers_integration_test.go","sha":"cf307b6ed15585a660e190c287708c188bbaeda6"},{"name":"iam_policies_test.go","path":"test/iam_policies_test.go","sha":"eac6b5cdfb473c1e15f3715d2b7a3149bc5a3534"},{"name":"jenkins_test.go","path":"test/jenkins_test.go","sha":"435ce6943986b4ea452d17dd2ab9a2ee02abe733"},{"name":"kubernetes_circleci_helpers_test.go","path":"test/kubernetes_circleci_helpers_test.go","sha":"76a87d2854c2c7cf0a57c56582796b9cdb533c1b"},{"name":"monorepo_helpers_integration_test.go","path":"test/monorepo_helpers_integration_test.go","sha":"ba3a50643d0682aed75e51b53b133468e7c21675"},{"name":"publish_ami_test.go","path":"test/publish_ami_test.go","sha":"04f7667c39445fe5d6a336641c110e2c6c1744a3"},{"name":"sign_binary_helpers_integration_test.go","path":"test/sign_binary_helpers_integration_test.go","sha":"58a2773b3b7e7ea036fdb4bd37687e0f5a95db7e"},{"name":"terraform_update_variable_unit_test.go","path":"test/terraform_update_variable_unit_test.go","sha":"c40cec18a46204ffc9fb1f29bc1b9bb1f3901327"},{"name":"terragrunt_update_variable_unit_test.go","path":"test/terragrunt_update_variable_unit_test.go","sha":"69aee2044f92db0a42acde9d9f8ee5217a840796"},{"name":"test_helpers.go","path":"test/test_helpers.go","sha":"15939ff54435659854f406fc61df250c79bc23be"},{"name":"upgrades","children":[{"name":"constants.go","path":"test/upgrades/constants.go","sha":"779b38158ec68005c5540238016bfc2aa5d3f291"},{"name":"go.mod","path":"test/upgrades/go.mod","sha":"f27a1993b36b4523faccc41fbb064fb6ca4fa284"},{"name":"go.sum","path":"test/upgrades/go.sum","sha":"81b480ef2bec4b4801cf0d9e67f4699340f94b9c"},{"name":"test_helpers_for_upgrade_tests.go","path":"test/upgrades/test_helpers_for_upgrade_tests.go","sha":"fe49c25f1bf9d7c70f8799f2600fd47102e4aa3b"},{"name":"upgrade_module.go","path":"test/upgrades/upgrade_module.go","sha":"54b1cf0dc13be3a3f15680b82ea7704ad7a61978"},{"name":"upgrade_module_iam_policies_test.go","path":"test/upgrades/upgrade_module_iam_policies_test.go","sha":"52306bff01e5d6d982a2c3b26cc4a57a7312632b"}]},{"name":"validation","children":[{"name":"validate_all_modules_and_examples_test.go","path":"test/validation/validate_all_modules_and_examples_test.go","sha":"74c928d0cbc2914e5cd708277bd857cb2375b660"}]}]}]},"detailsContent":"<h1 class=\"preview__body--title\" id=\"terraform-helpers\">Terraform Helpers</h1><div class=\"preview__body--border\"></div><p>This folder contains several helper scripts for working with <a href=\"https://www.terraform.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Terraform</a>. The scripts are:</p>\n<ol>\n<li><code>terraform-update-variable</code>: This script can automatically update a variable in a <code>terraform.tfvars</code> or\n<code>terragrunt.hcl</code> file and commit and push the changes to Git. It's common practice to store the version number of the\ncurrently deployed app in a variable and this script comes in handy for updating those variables automatically, such\nas in a CI job after building a new AMI or Docker image.</li>\n<li><code>git-updated-files</code>: This script can be used to detect all the files that have have been updated between two git\nrefs (branch, tag, sha, etc). This can be used in a CI pipeline to find various scripts and files that were affected\nand only run actions against those files (e.g., build scripts).</li>\n<li><code>git-updated-folders</code>: This script can be used to detect all the folders that have have been updated between two git\nrefs (branch, tag, sha, etc). This can be used in a CI pipeline to find the terraform and terragrunt modules that\nhave changed, and only run <code>plan</code> or <code>apply</code> on the modules that has been affected.</li>\n</ol>\n<h2 class=\"preview__body--subtitle\" id=\"using-the-helper-scripts-in-your-code\">Using the helper scripts in your code</h2>\n<p>You can install these scripts using the <a href=\"/repos/gruntwork-installer\" class=\"preview__body--description--blue\">Gruntwork Installer</a>:</p>\n<pre><span class=\"hljs-string\">gruntwork-install </span><span class=\"hljs-built_in\">--module-name</span> <span class=\"hljs-string\">\"terraform-helpers\"</span> <span class=\"hljs-built_in\">--repo</span> <span class=\"hljs-string\">\"https://github.com/gruntwork-io/terraform-aws-ci\"</span> <span class=\"hljs-built_in\">--tag</span> <span class=\"hljs-string\">\"0.0.1\"</span>\n</pre>\n<p>Note that <code>terraform-update-variable</code> depends on the <a href=\"/repos/v0.49.1/module-ci/modules/git-helpers\" class=\"preview__body--description--blue\">git-helpers module</a> being installed!</p>\n<p>See the examples in the next section for how to use them.</p>\n<h2 class=\"preview__body--subtitle\" id=\"examples\">Examples</h2>\n<p>The examples below should give you an idea of how to use the scripts. Run the scripts above with the <code>--help</code> flag to\nsee full documentation.</p>\n<ul>\n<li><a href=\"#terraform-update-variable\" class=\"preview__body--description--blue\">terraform-update-variable</a></li>\n<li><a href=\"#git-updated-files\" class=\"preview__body--description--blue\">git-updated-files</a></li>\n<li><a href=\"#git-updated-folders\" class=\"preview__body--description--blue\">git-updated-folders</a></li>\n</ul>\n<h2 class=\"preview__body--subtitle\" id=\"terraform-update-variable\">terraform-update-variable</h2>\n<h3 class=\"preview__body--subtitle\" id=\"terragrunt\">Terragrunt</h3>\n<p>Imagine you have a set of Terragrunt config in the <code>live</code> folder to deploy an app called <code>rails-app</code>. You create\nAmazon Machine Images (AMIs) for each new version of the app using <a href=\"https://www.packer.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Packer</a> and the currently\ndeployed version of the app is defined in a variable called <code>rails_app_version</code>, set to <code>ami-12345</code> in\n<code>live/rails-app/terragrunt.hcl</code>.</p>\n<p>If you just build a new version of the AMI, <code>ami-67890</code>, you could deploy it automatically, perhaps in a CI job,\nas follows:</p>\n<pre>cd live/rails-app\n<span class=\"hljs-comment\"># Due to the existence of types in terragrunt.hcl, we need to be explicit about how the variable values are quoted.</span>\n<span class=\"hljs-keyword\">terraform</span>-update-<span class=\"hljs-keyword\">variable</span> --name rails_app_version --value <span class=\"hljs-string\">\"\\\"</span>ami-<span class=\"hljs-number\">67890</span>\\<span class=\"hljs-string\">\"\"</span>\nterragrunt apply\n</pre>\n<p>Running the commands above would:</p>\n<ol>\n<li>Set the <code>rails_app_version</code> variable in the inputs map to the ID of the new AMI, <code>ami-67890</code> in <code>terragrunt.hcl</code>.</li>\n<li><code>commit</code> and <code>push</code> the changes to <code>terragrunt.hcl</code> to Git.</li>\n<li>Deploy the changes using Terragrunt.</li>\n</ol>\n<h3 class=\"preview__body--subtitle\" id=\"terraform\">Terraform</h3>\n<p>Imagine you have a set of Terraform templates in the <code>templates</code> folder to deploy an app called <code>rails-app</code>. You create\nAmazon Machine Images (AMIs) for each new version of the app using <a href=\"https://www.packer.io/\" class=\"preview__body--description--blue\" target=\"_blank\">Packer</a> and the currently\ndeployed version of the app is defined in a variable called <code>rails_app_version</code>, set to <code>ami-12345</code> in\n<code>templates/terraform.tfvars</code>.</p>\n<p>If you just build a new version of the AMI, <code>ami-67890</code>, you could deploy it automatically, perhaps in a CI job,\nas follows:</p>\n<pre>cd templates\n<span class=\"hljs-keyword\">terraform</span>-update-<span class=\"hljs-keyword\">variable</span> --vars-path <span class=\"hljs-keyword\">terraform</span>.tfvars --name rails_app_version --value <span class=\"hljs-string\">\"\\\"</span>ami-<span class=\"hljs-number\">67890</span>\\<span class=\"hljs-string\">\"\"</span>\n<span class=\"hljs-keyword\">terraform</span> apply\n</pre>\n<p>Running the commands above would:</p>\n<ol>\n<li>Set the <code>rails_app_version</code> variable to the ID of the new AMI, <code>ami-67890</code> in <code>terraform.tfvars</code>.</li>\n<li><code>commit</code> and <code>push</code> the changes to <code>terraform.tfvars</code> to Git.</li>\n<li>Deploy the changes using Terraform.</li>\n</ol>\n<h2 class=\"preview__body--subtitle\" id=\"git-updated-files\">git-updated-files</h2>\n<h3 class=\"preview__body--subtitle\" id=\"build-scripts\">Build scripts</h3>\n<p>Consider the following typical terragrunt folder structure:</p>\n<pre>.\n├── <span class=\"hljs-selector-tag\">shared</span>\n│ └── <span class=\"hljs-selector-tag\">us-east-1</span>\n│ └── _<span class=\"hljs-selector-tag\">global</span>\n│ └── <span class=\"hljs-selector-tag\">amis</span>\n│ └── <span class=\"hljs-selector-tag\">build_web_server_ami</span><span class=\"hljs-selector-class\">.sh</span>*\n├── <span class=\"hljs-selector-tag\">non-prod</span>\n│ ├── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n│ └── <span class=\"hljs-selector-tag\">us-east-1</span>\n│ ├── <span class=\"hljs-selector-tag\">qa</span>\n│ │ ├── <span class=\"hljs-selector-tag\">env</span><span class=\"hljs-selector-class\">.yaml</span>\n│ │ ├── <span class=\"hljs-selector-tag\">mysql</span>\n│ │ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n│ │ └── <span class=\"hljs-selector-tag\">webserver-cluster</span>\n│ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>*\n│ ├── <span class=\"hljs-selector-tag\">region</span><span class=\"hljs-selector-class\">.yaml</span>\n│ └── <span class=\"hljs-selector-tag\">stage</span>\n│ ├── <span class=\"hljs-selector-tag\">env</span><span class=\"hljs-selector-class\">.yaml</span>\n│ ├── <span class=\"hljs-selector-tag\">mysql</span>\n│ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n│ └── <span class=\"hljs-selector-tag\">webserver-cluster</span>\n│ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>*\n└── <span class=\"hljs-selector-tag\">prod</span>\n ├── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n └── <span class=\"hljs-selector-tag\">us-east-1</span>\n ├── <span class=\"hljs-selector-tag\">prod</span>\n │ ├── <span class=\"hljs-selector-tag\">env</span><span class=\"hljs-selector-class\">.yaml</span>\n │ ├── <span class=\"hljs-selector-tag\">mysql</span>\n │ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n │ └── <span class=\"hljs-selector-tag\">webserver-cluster</span>\n │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>*\n └── <span class=\"hljs-selector-tag\">region</span><span class=\"hljs-selector-class\">.yaml</span>*\n</pre>\n<p>Here we use <code>*</code> to indicate files that have been modified between the git refs <code>development</code> and <code>master</code>. To get the\nbuild scripts that have changed:</p>\n<pre>$ git-updated-files --source-<span class=\"hljs-keyword\">ref</span> development --target-<span class=\"hljs-keyword\">ref</span> <span class=\"hljs-keyword\">master</span> <span class=\"hljs-title\">--ext</span> sh\nshared/us-east-<span class=\"hljs-number\">1</span>/_global/amis/build_web_server_ami.sh\n</pre>\n<p>This command looks for the files that changed with the extension <code>sh</code>. You can use this in your CI pipeline to act only\non the files that changed in a particular commit. For example, in this case, you might want to invoke the build scripts\nthat changed so that new AMIs can be built.</p>\n<p>This command is not limited to a single extension. You can detect other files (e.g. <code>yaml</code> files) by passing additional\n<code>--ext</code> arguments. For example, to get the <code>region.yaml</code> file, you can run:</p>\n<pre>$ git-updated-files --source-<span class=\"hljs-built_in\">ref</span> development --target-<span class=\"hljs-built_in\">ref</span> master --ext sh --ext yaml\n<span class=\"hljs-keyword\">shared</span>/us-east<span class=\"hljs-number\">-1</span>/_global/amis/build_web_server_ami.sh\nprod/us-east<span class=\"hljs-number\">-1</span>/region.yaml\n</pre>\n<p>You can also do search for files that changed that do not match the extension. For example, to get all files that\nchanges that are not <code>terragrunt.hcl</code>:</p>\n<pre>$ git-updated-files --source-<span class=\"hljs-built_in\">ref</span> development --target-<span class=\"hljs-built_in\">ref</span> master --exclude-ext terragrunt.hcl\n<span class=\"hljs-keyword\">shared</span>/us-east<span class=\"hljs-number\">-1</span>/_global/amis/build_web_server_ami.sh\nprod/us-east<span class=\"hljs-number\">-1</span>/region.yaml\n</pre>\n<h2 class=\"preview__body--subtitle\" id=\"git-updated-folders\">git-updated-folders</h2>\n<h3 class=\"preview__body--subtitle\" id=\"terragrunt\">Terragrunt</h3>\n<p>Consider the following typical terragrunt folder structure:</p>\n<pre>.\n├── <span class=\"hljs-selector-tag\">shared</span>\n│ └── <span class=\"hljs-selector-tag\">us-east-1</span>\n│ └── _<span class=\"hljs-selector-tag\">global</span>\n│ └── <span class=\"hljs-selector-tag\">amis</span>\n│ └── <span class=\"hljs-selector-tag\">build_web_server_ami</span><span class=\"hljs-selector-class\">.sh</span>\n├── <span class=\"hljs-selector-tag\">non-prod</span>\n│ ├── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n│ └── <span class=\"hljs-selector-tag\">us-east-1</span>\n│ ├── <span class=\"hljs-selector-tag\">qa</span>\n│ │ ├── <span class=\"hljs-selector-tag\">env</span><span class=\"hljs-selector-class\">.yaml</span>\n│ │ ├── <span class=\"hljs-selector-tag\">mysql</span>\n│ │ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>*\n│ │ └── <span class=\"hljs-selector-tag\">webserver-cluster</span>\n│ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n│ ├── <span class=\"hljs-selector-tag\">region</span><span class=\"hljs-selector-class\">.yaml</span>\n│ └── <span class=\"hljs-selector-tag\">stage</span>\n│ ├── <span class=\"hljs-selector-tag\">env</span><span class=\"hljs-selector-class\">.yaml</span>\n│ ├── <span class=\"hljs-selector-tag\">mysql</span>\n│ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>*\n│ └── <span class=\"hljs-selector-tag\">webserver-cluster</span>\n│ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n└── <span class=\"hljs-selector-tag\">prod</span>\n ├── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n └── <span class=\"hljs-selector-tag\">us-east-1</span>\n ├── <span class=\"hljs-selector-tag\">prod</span>\n │ ├── <span class=\"hljs-selector-tag\">env</span><span class=\"hljs-selector-class\">.yaml</span>\n │ ├── <span class=\"hljs-selector-tag\">mysql</span>\n │ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>*\n │ └── <span class=\"hljs-selector-tag\">webserver-cluster</span>\n │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n └── <span class=\"hljs-selector-tag\">region</span><span class=\"hljs-selector-class\">.yaml</span>\n</pre>\n<p>Here we use <code>*</code> to indicate files that have been modified between the git refs <code>development</code> and <code>master</code>. To get the\nterragrunt modules that have changed:</p>\n<pre>$ git-updated-modules --source-<span class=\"hljs-built_in\">ref</span> development --target-<span class=\"hljs-built_in\">ref</span> master --terragrunt\nnon-prod/us-east<span class=\"hljs-number\">-1</span>/qa/mysql\nnon-prod/us-east<span class=\"hljs-number\">-1</span>/stage/mysql\nprod/us-east<span class=\"hljs-number\">-1</span>/prod/mysql\n</pre>\n<p>Each of these folders were detected as terragrunt modules (because they contain a <code>terragrunt.hcl</code> file), and were\nmarked as changed because the underlying terragrunt config was updated.</p>\n<p>Note that this will only detect <code>terragrunt.hcl</code> files that have changed. For example, in the following scenario where\nthe root <code>terragrunt.hcl</code> file and a few yaml files were changed (the files denoted with <code>*</code> are those that changed),\nonly the root folder is returned:</p>\n<pre>.\n├── <span class=\"hljs-selector-tag\">non-prod</span>\n│ ├── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>*\n│ └── <span class=\"hljs-selector-tag\">us-east-1</span>\n│ ├── <span class=\"hljs-selector-tag\">qa</span>\n│ │ ├── <span class=\"hljs-selector-tag\">env</span><span class=\"hljs-selector-class\">.yaml</span>\n│ │ ├── <span class=\"hljs-selector-tag\">mysql</span>\n│ │ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n│ │ └── <span class=\"hljs-selector-tag\">webserver-cluster</span>\n│ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n│ ├── <span class=\"hljs-selector-tag\">region</span><span class=\"hljs-selector-class\">.yaml</span>*\n│ └── <span class=\"hljs-selector-tag\">stage</span>\n│ ├── <span class=\"hljs-selector-tag\">env</span><span class=\"hljs-selector-class\">.yaml</span>\n│ ├── <span class=\"hljs-selector-tag\">mysql</span>\n│ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n│ └── <span class=\"hljs-selector-tag\">webserver-cluster</span>\n│ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n└── <span class=\"hljs-selector-tag\">prod</span>\n ├── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n └── <span class=\"hljs-selector-tag\">us-east-1</span>\n ├── <span class=\"hljs-selector-tag\">prod</span>\n │ ├── <span class=\"hljs-selector-tag\">env</span><span class=\"hljs-selector-class\">.yaml</span>\n │ ├── <span class=\"hljs-selector-tag\">mysql</span>\n │ │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n │ └── <span class=\"hljs-selector-tag\">webserver-cluster</span>\n │ └── <span class=\"hljs-selector-tag\">terragrunt</span><span class=\"hljs-selector-class\">.hcl</span>\n └── <span class=\"hljs-selector-tag\">region</span><span class=\"hljs-selector-class\">.yaml</span>*\n</pre>\n<pre>$ git-updated-modules --source-<span class=\"hljs-keyword\">ref</span> development --target-<span class=\"hljs-keyword\">ref</span> <span class=\"hljs-keyword\">master</span> <span class=\"hljs-title\">--terragrunt</span>\nnon-prod\n</pre>\n<p>If you want to additionally pull in the folders with the <code>yaml</code> files that changed, you can pass in <code>--ext .yaml</code>:</p>\n<pre>$ git-updated-modules --source-<span class=\"hljs-keyword\">ref</span> development --target-<span class=\"hljs-keyword\">ref</span> <span class=\"hljs-keyword\">master</span> <span class=\"hljs-title\">--terragrunt</span> --ext .yaml\nnon-prod\nnon-prod/us-east-<span class=\"hljs-number\">1</span>\nprod/us-east-<span class=\"hljs-number\">1</span>\n</pre>\n<h3 class=\"preview__body--subtitle\" id=\"terraform\">Terraform</h3>\n<p>Consider the following project structure for a monorepo terraform project:</p>\n<pre>.\n├── modules\n│ ├── mysql\n│ │ ├── main.tf\n│ │ ├── outputs.tf*\n│ │ └── variables.tf\n│ └── webserver-cluster\n│ ├── main.tf\n│ ├── outputs.tf\n│ └── variables.tf\n└── live\n └── us-east-<span class=\"hljs-number\">1</span>\n ├── prod\n │ ├── <span class=\"hljs-keyword\">terraform</span>.tfvars\n │ ├── main.tf*\n │ ├── outputs.tf*\n │ └── variables.tf\n └── non-prod\n ├── <span class=\"hljs-keyword\">terraform</span>.tfvars*\n ├── main.tf\n ├── outputs.tf\n └── variables.tf\n</pre>\n<p>Here we use <code>*</code> to indicate files that have been modified between the git refs <code>development</code> and <code>master</code>. To get the\nterraform modules that have changed:</p>\n<pre>$ git-updated-modules --source-ref development --target-ref master --<span class=\"hljs-keyword\">terraform</span>\nmodules/mysql\nlive/us-east-<span class=\"hljs-number\">1</span>/prod\nlive/us-east-<span class=\"hljs-number\">1</span>/non-prod\n</pre>\n<p>Each of these were detected as terraform modules (because they contain <code>.tf</code> files), and were marked as changed because\none of the underlying <code>.tf</code> or <code>.tfvars</code> files have changed. Specifically:</p>\n<ul>\n<li><code>modules/mysql</code> <= <code>modules/mysql/outputs.tf</code></li>\n<li><code>live/us-east-1/prod</code> <= <code>live/us-east-1/prod/main.tf</code> and <code>live/us-east-1/prod/outputs.tf</code></li>\n<li><code>live/us-east-1/non-prod</code> <= <code>live/us-east-1/non-prod/terraform.tfvars</code></li>\n</ul>\n<h3 class=\"preview__body--subtitle\" id=\"deleted-folders\">Deleted folders</h3>\n<p>By default, <code>git-updated-folders</code> will include deleted folders in the return list. This can cause problems in\ninfrastructure pipelines as you don't want to run any <code>plan</code> or <code>apply</code> action on folders that don't exist.</p>\n<p>To support destroy workflows, the <code>git-updated-folders</code> script supports two filters:</p>\n<ul>\n<li><code>--exclude-deleted</code>: This parameter will tell <code>git-updated-folders</code> to exclude folders that have been deleted when\nreturning the updated folders.</li>\n<li><code>--include-deleted-only</code>: This parameter will tell <code>git-updated-folders</code> to only include folders that have been\ndeleted when returning the updated folders.</li>\n</ul>\n<p>Note that a folder is only considered deleted if all the tracked files in that folder is deleted. E.g., if you have a\nfolder that only deleted the <code>*.tf</code> files, but keeps a <code>README.md</code>, then that folder is NOT considered deleted by the\nscript because it still contains a tracked file.</p>\n<p>In your infrastructure pipelines, you should use <code>--exclude-deleted</code> to filter out the deleted folders from your <code>plan</code>\nand <code>apply</code> actions so that Terraform/Terragrunt can run. If you wish to implement destroy workflows, you can use the\n<code>--include-deleted-only</code> parameter to setup a separate pipeline for handling <code>destroy</code> actions.</p>\n","repoName":"module-ci","repoRef":"v0.49.1","serviceDescriptor":{"serviceName":"EC2 backup","serviceRepoName":"module-ci","serviceRepoOrg":"gruntwork-io","serviceMainReadmePath":"/modules/ec2-backup","cloudProviders":["aws"],"description":"Snapshot your EC2 instances on a scheduled basis.","imageUrl":"grunt.png","licenseType":"subscriber","technologies":["Terraform","JavaScript","Lambda"],"compliance":[],"tags":[""]},"serviceCategoryName":"Backup & recovery","fileName":"README.md","filePath":"/modules/terraform-helpers/README.md","title":"Repo Browser: EC2 backup","description":"Browse the repos in the Gruntwork Infrastructure as Code Library."}