This folder contains several helper scripts for automatically building deployable, versioned artifacts of your apps:
build-docker-image: This script is meant to be run from a CI job to automatically build a Docker image. It builds
the Docker image, tags the image with the sha1 of the most recent Git commit (or a custom tag, if specified), and then
pushes the new image to a Docker registry (unless the same image/tag already exists in the registry!).
build-packer-artifact: This script can be used to automatically build an artifact, such as an AMI, defined in a
Packer template. It runs a Packer build, runs an optional test command to verify the new artifact, extracts the
artifact ID from the build, and writes the ID to a properties file. This script is meant to be run from a CI job and
the properties file is a convenient way to pass information about the new artifact to another CI job.
After a successful build, the build helper scripts write the versions of the artifacts they produce to a properties
file. The idea is that this properties file is easy to use in other scripts or other CI jobs to deploy those artifacts.
The build-docker-image script adds an entry to the properties file of the form:
DOCKER_IMAGE_TAG=<IMAGE_TAG>
The build-packer-artifact script adds an entry to the properties file of the form:
ARTIFACT_ID=<ARTIFACT_ID>
Examples
The examples below should give you an idea of how to use the scripts. Run the scripts above with the --help flag to
see full documentation.
Imagine you have a Packer template templates/build.json that specifies how to build an AMI for your app. You could
set up automatic deployment for this app using two Jenkins CI jobs: build-app and deploy-app.
The build-app CI job would first use the build-packer-artifact script to automatically build your AMI:
Next, the build-app CI job would then pass the contents of artifacts.properties directly to the deploy-app CI
job using the Jenkins Parameterized Trigger
Plugin. The deploy-app CI job, in turn,
would be a parameterized build that takes as input
a parameter called ARTIFACT_ID (the same parameter name that's in the artifacts.properties file) and use it, along
with the scripts in the terraform-helpers module to automatically deploy the new AMI:
cd templates
terraform-update-variable --name rails_app_version --value $ARTIFACT_ID
terragrunt apply
Remote packer templates
build-packer-artifact also supports building Packer templates that are stored in a git repository. When a path of the
format git::GIT_REPO_URL//RELATIVE_PATH_TO_PACKER_TEMPLATE?ref=GIT_REF is passed in as the Packer template path,
build-packer-artifact will clone the repository GIT_REPO_URL at the ref GIT_REF to a temporary directory and build
the template referenced at RELATIVE_PATH_TO_PACKER_TEMPLATE in the git repository.
For example, to build the example jenkins Packer template in this repo on the release tag v0.19.0:
For AWS AMI builds that use tags, build-packer-artifact supports idempotent builds by AMI tags. When you pass in
--idempotent true to the script, build-packer-artifact will only build a new AMI if an existing AMI with the same
tags and similar name does not already exist in your account. A name is similar if everything matches except for unique
build time identifiers (e.g., that returned by isotime, uuid, or timestamp).
Note that we include the name in the idempotency check to ensure that you can preserve AMIs in a multiaccount scenario,
where AMI tags are not visible in the target account.
For example, consider the following packer template:
{
"variables": {
"aws_region": "us-east-1",
"tag": ""
},
"builders": [{
"ami_name": "gruntwork-test-{{user `tag`}}-packer-build-{{uuid | clean_resource_name}}",
"ami_description": "An AMI created as part of testing the build-packer-artifact script.",
"instance_type": "t2.micro",
"region": "{{user `aws_region`}}",
"type": "amazon-ebs",
"source_ami": "ami-fce3c696",
"ssh_username": "ubuntu",
"tags": {
"tag": "{{user `tag`}}"
}
}],
"provisioners": [{
"type": "shell",
"inline": [
"echo 'Hello, World'"
]
}]
}
If you pass in the --idempotent true and --var tag=v1, then this will only build the AMI if it does not find any AMI
with the tag tag=v1 and name that begins with gruntwork-test-v1-packer-build- in the us-east-1 region.
Under the hood the tags, names, and regions are computed at runtime using packer console with the provided vars.
Note that the following conditions must be true in order to use this feature:
Packer version is at least v1.4.2 (version that introduced packer console).
Templates are in json format (you can not use HCL based templates at this time).
Build is for an AMI (builder type amazon-ebs).
Builder is configured to tag the AMIs (tags is set).
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":"39a21f4f15394416888317f9eb003e5e9760176d"}]},{"name":".gitignore","path":".gitignore","sha":"1cd2e7ca72e5102b6b85a0c1de82d28c99d4287e"},{"name":".pre-commit-config.yaml","path":".pre-commit-config.yaml","sha":"47826a6fca6c68c6e0f0e9ac88988c2830ed4ef1"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"a834dbe979d6fb551a71156abfb7e22771115e48"},{"name":"LICENSE.txt","path":"LICENSE.txt","sha":"f4e3d9bd4717a044ed31ad847a300eee74371a78"},{"name":"README-CircleCI.adoc","path":"README-CircleCI.adoc","sha":"046b030ed6e15023530d4a29a3dcf60ac7982d27"},{"name":"README-Jenkins.adoc","path":"README-Jenkins.adoc","sha":"2587e3b59001ed39eaac88468202afdcbc2332af"},{"name":"README-Terraform-Terragrunt-Pipeline.adoc","path":"README-Terraform-Terragrunt-Pipeline.adoc","sha":"1ad99530c6cf984aa638e7c2fcd0bf4d4987ce12"},{"name":"README-TravisCI.adoc","path":"README-TravisCI.adoc","sha":"45e0d32aae5d971ee7e7670dc0da94d364c14457"},{"name":"README.adoc","path":"README.adoc","sha":"47cb10253af3b2e514678434a61ad681c02a88f2"},{"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":"f7dbc2c05f78cdeaff779eecfef93594f7a9c175"},{"name":"main.tf","path":"examples/ecs-deploy-runner/main.tf","sha":"ba5f23421fb1e4da5a44f12ba3b750ea56ac56e1"},{"name":"outputs.tf","path":"examples/ecs-deploy-runner/outputs.tf","sha":"0d39cc204673e2e92f0b6e32464ac8080fda59c2"},{"name":"variables.tf","path":"examples/ecs-deploy-runner/variables.tf","sha":"569c2a38d743951b63d72e61caeac4071d7bbd92"}]},{"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":"29ed07d00498d2964f2850a49cb9b28cce541333"},{"name":"vars.tf","path":"examples/iam-policies/vars.tf","sha":"ffd4eed9234a389e6809cbb1c149efdbe778578e"}]},{"name":"jenkins","children":[{"name":"README.md","path":"examples/jenkins/README.md","sha":"5c76af2853297fa24f0ab44dc1cdcdf6ba8e1a55"},{"name":"docker-compose.yml","path":"examples/jenkins/docker-compose.yml","sha":"cdbb01e4c39d6ad67656d7997355b03027f2358e"},{"name":"main.tf","path":"examples/jenkins/main.tf","sha":"1881a2126a139b44718e4fd54aaa8a087206b8da"},{"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":"0be347ef2da711389da6e9ab98e7717e3dfa1a02"},{"name":"packer","children":[{"name":"jenkins.json","path":"examples/jenkins/packer/jenkins.json","sha":"d35f1c232b6d5cc2f35b37eb4bac1409a4c4c391"}]},{"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":"880057af01bab8502d9c786cf2827b3f8134cc69"}]}]},{"name":"modules","children":[{"name":"aws-helpers","children":[{"name":"README.md","path":"modules/aws-helpers/README.md","sha":"2fc74c09e7880238a4c049022f455809549d2ee1"},{"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":"6816ecb1ffd0810892df24343366667a2a4ba66a","toggled":true},{"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":"70f860fd8dab2178c9a89a2ced7c548d1cc5d562"}]},{"name":"install.sh","path":"modules/build-helpers/install.sh","sha":"a132488127b88ef8268399a0b3852aa5e0967a20"}],"toggled":true},{"name":"check-url","children":[{"name":"README.md","path":"modules/check-url/README.md","sha":"070d26ac5f4cf136fc28a69d97df6710a341cf24"},{"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":"3e58d0856dd6ae04bbd22814d6243b0225a689d9"},{"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":"d9ef51b6b9a83f8e5bf15a582d5b18d48091f3de"},{"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":"78ed3754120c76cb150f6b858bc7cfdbddaa1466"},{"name":"outputs.tf","path":"modules/ec2-backup/outputs.tf","sha":"770744637fcd7cafd98991397b26a82d01524192"},{"name":"vars.tf","path":"modules/ec2-backup/vars.tf","sha":"dd8d61875d9f68596d05bf677a51119750f512e8"}]},{"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":"42b23973668008665974e714e1ca077ea96a9b9d"},{"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":"f4c49c30bd8f1675ac907077b2e59a946ee96315"},{"name":"main.tf","path":"modules/ecs-deploy-runner-standard-configuration/main.tf","sha":"000a97b59512ee87ae1afea3e091723b262befdc"},{"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":"f1475315eae8b7b3954400cf5abaa60855d1ee45"}]},{"name":"ecs-deploy-runner","children":[{"name":"README.adoc","path":"modules/ecs-deploy-runner/README.adoc","sha":"1857addf7729b043a1353863402b12b8cfb7ee4a"},{"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":"849b1db4b083d1ba6a9f4d009ae767ad4651d458"},{"name":"docker","children":[{"name":"deploy-runner","children":[{"name":"Dockerfile","path":"modules/ecs-deploy-runner/docker/deploy-runner/Dockerfile","sha":"54f947afbeeda22d76ba630f4ecd84065468764e"},{"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":"d613a7380265e94d592ec61b9935bfede120fde7"},{"name":"build_docker_image.go","path":"modules/ecs-deploy-runner/docker/kaniko/build_docker_image.go","sha":"8051d59a7a8cc839a61f860d38a68c34957feafb"},{"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":"2915250c36924f1bbfb58a7485d58e3ce386efed"},{"name":"go.sum","path":"modules/ecs-deploy-runner/docker/kaniko/go.sum","sha":"cd278d67681ad9401f9de5d3ac258b9df24ed173"}]}]},{"name":"entrypoint","children":[{"name":"deploy_runner_entrypoint.go","path":"modules/ecs-deploy-runner/entrypoint/deploy_runner_entrypoint.go","sha":"f71a662ec5653f4c3f569d0606e05058c6130cd9"},{"name":"go.mod","path":"modules/ecs-deploy-runner/entrypoint/go.mod","sha":"eeca92d303d02287f5d4b1db8e0c10e5afa7e54f"},{"name":"go.sum","path":"modules/ecs-deploy-runner/entrypoint/go.sum","sha":"a114c9668062acd899c6a833fd7c09ebd4563146"},{"name":"install.sh","path":"modules/ecs-deploy-runner/entrypoint/install.sh","sha":"08c92e1e908e330112adff47b4da225658f4369e"}]},{"name":"invoker-lambda","children":[{"name":"dev_requirements.txt","path":"modules/ecs-deploy-runner/invoker-lambda/dev_requirements.txt","sha":"e5c3080c5b1785d0bcbb0a0c0751ae3adef55c54"},{"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":"53d74960da2cd9088992f4d1e8d62297709e4e3c"},{"name":"exceptions.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/exceptions.py","sha":"bd0ae2c664b6242323c4f19e2bf4ebdd64262009"},{"name":"index.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/index.py","sha":"fc432c8beacbb0275e0dda086781e5eda24ee266"},{"name":"project_logging.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/project_logging.py","sha":"7073c22d7c70ee8940a3ab194a2edc3aef554055"},{"name":"types.py","path":"modules/ecs-deploy-runner/invoker-lambda/invoker/types.py","sha":"75f4262982bfbd5f751654b35e903be5279b7d98"}]},{"name":"test","children":[{"name":"test_assertions.py","path":"modules/ecs-deploy-runner/invoker-lambda/test/test_assertions.py","sha":"8f52d353ab727bd0e34922cfac7e98924302af65"},{"name":"test_invoker.py","path":"modules/ecs-deploy-runner/invoker-lambda/test/test_invoker.py","sha":"e99f8ee3c1314716100a1378b0d50c58c83988f3"}]}]},{"name":"main.tf","path":"modules/ecs-deploy-runner/main.tf","sha":"8af4dc91ff4e02ec58d0d7980f5a79f51542dca7"},{"name":"main_ecs.tf","path":"modules/ecs-deploy-runner/main_ecs.tf","sha":"9b3702c41b5194cd75b8b5764be111efbcc844bc"},{"name":"main_lambda.tf","path":"modules/ecs-deploy-runner/main_lambda.tf","sha":"d6d9836f72482c041841667465a3cd09e328b888"},{"name":"outputs.tf","path":"modules/ecs-deploy-runner/outputs.tf","sha":"a78322a16476d579a9f1d92846cd252a6eb8755a"},{"name":"variables.tf","path":"modules/ecs-deploy-runner/variables.tf","sha":"374b3cbcd42da8b5ed1a10e189567451ca035241"}]},{"name":"git-helpers","children":[{"name":"README.md","path":"modules/git-helpers/README.md","sha":"86803f51a9bdcca05dfd13756fe16088a6363ff4"},{"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":"074bc610447d27206bc50ba1a7b06fc95226d369"},{"name":"bin","children":[{"name":"build-go-binaries","path":"modules/gruntwork-module-circleci-helpers/bin/build-go-binaries","sha":"8aca966ed857b2d6d50a7c72c09e9181ae125e3c"},{"name":"configure-environment-for-gruntwork-module","path":"modules/gruntwork-module-circleci-helpers/bin/configure-environment-for-gruntwork-module","sha":"66538721d100ad93eac0784ab0603ddf508c6265"},{"name":"run-go-tests","path":"modules/gruntwork-module-circleci-helpers/bin/run-go-tests","sha":"d5406bdd61dae657ded161cf6f2ca66b17cd5b81"},{"name":"upload-github-release-assets","path":"modules/gruntwork-module-circleci-helpers/bin/upload-github-release-assets","sha":"b86a2f1049b1be58179569ea7fed641d960d1f05"}]},{"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":"f42bf07dbc968788e3afca42528ebf5f581ac7c8"},{"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":"01c7f850e862dc36c1930b8deb767388c631eda7"},{"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":"76eb7e37989dc731b4e304303d2a46f9f17e2779"},{"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":"e479890f7c37ce794c61022ab08e3febb91441ef"},{"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":"28e1366b934ff07de913455a42ca96555f6a8165"},{"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":"6059bddb829b89421c7e1fba8a6e330de33e1a75"},{"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":"1f204faa3579919b19067c7face5af56a2aa3785"},{"name":"exceptions.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/exceptions.py","sha":"087c7ad70e8077121d24d775af578aa238995dca"},{"name":"git.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/git.py","sha":"749ace8d9812e8a906eba2d14b6eef4f90c97e02"},{"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":"f9b98a99686b214a68c8c99d23fd8019a9f68213"},{"name":"ssh.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/ssh.py","sha":"3db8994be058bfa590bbbbdd0476128c44ad5979"},{"name":"terra.py","path":"modules/infrastructure-deploy-script/infrastructure_deploy_script/terra.py","sha":"67b1bc0f598d253e9b9ba13f54b9ca875f23f84f"}]},{"name":"install.sh","path":"modules/infrastructure-deploy-script/install.sh","sha":"c958f1065315b16e9f0474ee39728a4556c18247"},{"name":"requirements.txt","path":"modules/infrastructure-deploy-script/requirements.txt","sha":"ebe0f49e006828d7147c8ee540a278142e44e618"},{"name":"scripts","children":[{"name":"infrastructure-deploy-script","path":"modules/infrastructure-deploy-script/scripts/infrastructure-deploy-script","sha":"9f6b9fd7774de6892e9fdbb77f3200c1b1d698ae"}]},{"name":"setup.py","path":"modules/infrastructure-deploy-script/setup.py","sha":"0885421ba85af260d5e2d97ebc75e26c76fb25da"},{"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":"de3e20f9744dc757b7ea2620ebdbc2e8aa7a3ec1"},{"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":"362851fda16747e2a39abba071646933e51fbbdf"}]},{"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":"f41e53648f0c9df3c55692380ab02133f5bcde12"},{"name":"test_git.py","path":"modules/infrastructure-deploy-script/test/test_git.py","sha":"862852a92b7a7edb7276cdd3cf212e500ca3c8d9"},{"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":"ccb8ddacbca1f403e2f7487fee8da11adfff0e03"},{"name":"core-concepts.md","path":"modules/infrastructure-deployer/core-concepts.md","sha":"8b4f541bbb9986cd1ad3b27fb6896dff0f4a3b90"},{"name":"deploy","children":[{"name":"aws.go","path":"modules/infrastructure-deployer/deploy/aws.go","sha":"935179ae7f0a82af9600d2552e9c43ee48dedc77"},{"name":"aws_ecs.go","path":"modules/infrastructure-deployer/deploy/aws_ecs.go","sha":"267b65065c505ea0649a29d49f14152729258c74"},{"name":"deploy.go","path":"modules/infrastructure-deployer/deploy/deploy.go","sha":"f85db6e4e21c77103925dea13c202c2d76770d40"},{"name":"errors.go","path":"modules/infrastructure-deployer/deploy/errors.go","sha":"74d73d20144cbbac68ebe4a7c50a53b204151fb4"}]},{"name":"go.mod","path":"modules/infrastructure-deployer/go.mod","sha":"6235897ee1c45ed4259089ae217684c91946adf5"},{"name":"go.sum","path":"modules/infrastructure-deployer/go.sum","sha":"803f46872f55922e3c888dd4aff5236717352ddc"},{"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":"72ee953990c0a57554312feac5b3b733b2c03b5c"},{"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":"f3c33b9c09257522281a7be9687a53b343bc1fd8"},{"name":"install.sh","path":"modules/install-jenkins/install.sh","sha":"e9ccf35e247fc5de353f0a02e187c35246ec5655"},{"name":"run-jenkins","path":"modules/install-jenkins/run-jenkins","sha":"4f66dcc9b68b4623231de09d87c76cce40fc914e"}]},{"name":"jenkins-server","children":[{"name":"README.md","path":"modules/jenkins-server/README.md","sha":"49ecb595ff9883d9a77ddfebe1369e25f1692890"},{"name":"main.tf","path":"modules/jenkins-server/main.tf","sha":"cbecb0617d71fa5905a0fafbdf0e88892185bb35"},{"name":"outputs.tf","path":"modules/jenkins-server/outputs.tf","sha":"5670bd47368b97e5eeedcca805a28a337230e9e2"},{"name":"vars.tf","path":"modules/jenkins-server/vars.tf","sha":"c1f7433e5d2422435c256d9927eacc81db405fa3"}]},{"name":"kubernetes-circleci-helpers","children":[{"name":"README.md","path":"modules/kubernetes-circleci-helpers/README.md","sha":"833fef8b04c17c43b10c680fad7db3aa7da2e8ad"},{"name":"bin","children":[{"name":"setup-minikube","path":"modules/kubernetes-circleci-helpers/bin/setup-minikube","sha":"9a6dd7b530cdb65c314b7ca5f60c656ee6b4bbc8"}]},{"name":"install.sh","path":"modules/kubernetes-circleci-helpers/install.sh","sha":"2ae8670872407ceb2c434dc5b117ae14073af9a2"}]},{"name":"terraform-helpers","children":[{"name":"README.md","path":"modules/terraform-helpers/README.md","sha":"d6004df66f3b9684ea901f0d41592fca2aceb874"},{"name":"bin","children":[{"name":"git-updated-folders","path":"modules/terraform-helpers/bin/git-updated-folders","sha":"d1325e85a5922d482dc8a4474fe8ef547bf51589"},{"name":"terraform-update-variable","path":"modules/terraform-helpers/bin/terraform-update-variable","sha":"44fb722fa9745668b343ca85329b003a24f650f6"}]},{"name":"install.sh","path":"modules/terraform-helpers/install.sh","sha":"6b7e40c382ec391f64e54efab3367d202b123883"}]}],"toggled":true},{"name":"setup.cfg","path":"setup.cfg","sha":"dbcd773df9356e74782ad58e0a2255ffa188df49"},{"name":"test","children":[{"name":"README.md","path":"test/README.md","sha":"a5996d6e678f1d454c380b7c1722843886028589"},{"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":"e5a185070f7249f7ab84367f68a9af016b2b892c"},{"name":"build_packer_artifact_unit_test.go","path":"test/build_packer_artifact_unit_test.go","sha":"ae89bece3fa432e3b5e9c4c917bdf00a6f358c15"},{"name":"check_url_test.go","path":"test/check_url_test.go","sha":"bd3419bcb07624923777c14619eba17c7edc8c64"},{"name":"ecs_deploy_runner_docker_test.go","path":"test/ecs_deploy_runner_docker_test.go","sha":"be41be9e908257499a9b0487a8cec36c1a98b923"},{"name":"ecs_deploy_runner_ec2_test.go","path":"test/ecs_deploy_runner_ec2_test.go","sha":"99b17f4a1c69cdc25165b18e29497f04afde237d"},{"name":"ecs_deploy_runner_kaniko_test.go","path":"test/ecs_deploy_runner_kaniko_test.go","sha":"383e5c3ed6eda4fc3a1169f2f66b29baac4de516"},{"name":"ecs_deploy_runner_security_test.go","path":"test/ecs_deploy_runner_security_test.go","sha":"9ae42634a2bd561004d393fd969f2aad07454c2f"},{"name":"ecs_deploy_runner_standard_configuration_test.go","path":"test/ecs_deploy_runner_standard_configuration_test.go","sha":"b1ae7b1b051397409d6a54e72049c21fc78d7678"},{"name":"ecs_deploy_runner_test.go","path":"test/ecs_deploy_runner_test.go","sha":"d8feacfc2ed21631b470bd6660fe4191b1997f66"},{"name":"ecs_deploy_runner_test_helpers.go","path":"test/ecs_deploy_runner_test_helpers.go","sha":"e5b0b03e0db4ee754aeee0e5cf5f32b74ac1481a"},{"name":"ecs_deploy_runner_workflow_test.go","path":"test/ecs_deploy_runner_workflow_test.go","sha":"122bb8888a3364dd34c87e6aaf8aff4c93c8b3f2"},{"name":"edrhelpers","children":[{"name":"edrhelpers.go","path":"test/edrhelpers/edrhelpers.go","sha":"d07d2f6de7ef7eaecba18bae75ffa92751abdb9a"},{"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":"dbd47ade4dfa1a18d5e97992f373775e7b62d2a8"},{"name":"go.sum","path":"test/edrhelpers/go.sum","sha":"5c7ba66f33aa2c50f25dc66c190ed7fc9aa0e892"}]},{"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":"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":"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":"whitespace.json","path":"test/fixtures/build-packer-image-unit/ami-name/whitespace.json","sha":"35cfd5200bbd124689868f115cb1b5498a8dfbbe"}]},{"name":"ami-region","children":[{"name":"variable.json","path":"test/fixtures/build-packer-image-unit/ami-region/variable.json","sha":"2601caa0afd10705ba4c023f31dd03c1b2c10417"}]},{"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":"no-tags.json","path":"test/fixtures/build-packer-image-unit/ami-tags/no-tags.json","sha":"d160046152b90e840fe08650cb9fb4ae8273ab40"},{"name":"single-tag.json","path":"test/fixtures/build-packer-image-unit/ami-tags/single-tag.json","sha":"c2770e7139805962dfa1eab83e5d02dde42a7b95"}]},{"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":"07137cff13ec18cc3bb6c3b31e706f8a0b754882"},{"name":"ami-region-test.sh","path":"test/fixtures/build-packer-image-unit/scripts/ami-region-test.sh","sha":"7211f8d2e27f00395b2355eed780aa7e0c245196"},{"name":"ami-tags-test.sh","path":"test/fixtures/build-packer-image-unit/scripts/ami-tags-test.sh","sha":"2848b4aa11df09e8aed559a9e0b9119cdee10468"},{"name":"assert-builder-amazon-test.sh","path":"test/fixtures/build-packer-image-unit/scripts/assert-builder-amazon-test.sh","sha":"ff33aabd963e7971017901988f408c628c0dabb9"}]}]},{"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":"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":"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":"19538a8d8cb3820ffc99138ecf3b19004e7afa8f"}]},{"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":"365224f7ed12aa3ccf6df765af3669d844274726"},{"name":"github_helpers.go","path":"test/github_helpers.go","sha":"56e54040790227aab12ae1b2f43991b9f00f87f6"},{"name":"go.mod","path":"test/go.mod","sha":"5cba1f1d742d8e433c44a513d43f79c06ae36126"},{"name":"go.sum","path":"test/go.sum","sha":"eeeb026c64c831e119900a51d8d12d3d9a96c455"},{"name":"gruntwork_module_circleci_helpers_integration_test.go","path":"test/gruntwork_module_circleci_helpers_integration_test.go","sha":"b6962168427fd2bae16cd6b5cca6f27afd9a0808"},{"name":"iam_policies_test.go","path":"test/iam_policies_test.go","sha":"75daff44988b41977dcfd064c868f038f77ffbb0"},{"name":"infrastructure_deploy_script_test.go","path":"test/infrastructure_deploy_script_test.go","sha":"1f4c3698ade167ba793813c2326e8aa7eb04ee6a"},{"name":"jenkins_test.go","path":"test/jenkins_test.go","sha":"d2cdf692eec0d4344ea052028d9a80155b1f9bcd"},{"name":"kubernetes_circleci_helpers_test.go","path":"test/kubernetes_circleci_helpers_test.go","sha":"76a87d2854c2c7cf0a57c56582796b9cdb533c1b"},{"name":"publish_ami_test.go","path":"test/publish_ami_test.go","sha":"04f7667c39445fe5d6a336641c110e2c6c1744a3"},{"name":"terraform_update_variable_unit_test.go","path":"test/terraform_update_variable_unit_test.go","sha":"5b405d87a457c0983d1bc804d1b78bc86c6e82f3"},{"name":"terragrunt_update_variable_unit_test.go","path":"test/terragrunt_update_variable_unit_test.go","sha":"69aee2044f92db0a42acde9d9f8ee5217a840796"},{"name":"test-git-add-commit-push.sh","path":"test/test-git-add-commit-push.sh","sha":"95fd142ed3d26e85c2873ee55c0e2718f0927ffd"},{"name":"test_helpers.go","path":"test/test_helpers.go","sha":"d4eb5b752450f221e5d615ffd1e470edbf7adfa0"}]},{"name":"testdep","children":[{"name":"Gopkg.lock","path":"testdep/Gopkg.lock","sha":"f12dfa4652085a0043d69d1b3bff7cc16b64551f"},{"name":"Gopkg.toml","path":"testdep/Gopkg.toml","sha":"092de38583d1bb2aff2b194753b7cc18aecddd87"},{"name":"dep_test.go","path":"testdep/dep_test.go","sha":"b87facc135093c5258a5f2da43e5f9177bc008b7"},{"name":"fixtures","children":[{"name":"hello-world-godep-app","children":[{"name":"Gopkg.lock","path":"testdep/fixtures/hello-world-godep-app/Gopkg.lock","sha":"623c785ee006b1ff3c524d18935ebdeb45395d55"},{"name":"Gopkg.toml","path":"testdep/fixtures/hello-world-godep-app/Gopkg.toml","sha":"26f5a8f783bb942cf6fba93c10b6a09017329526"},{"name":"main.go","path":"testdep/fixtures/hello-world-godep-app/main.go","sha":"0a09ad54ada955edd8e8ae731e0c113cc708766c"}]}]}]}]},"detailsContent":"<h1 class=\"preview__body--title\" id=\"build-helpers\">Build Helpers</h1><div class=\"preview__body--border\"></div><p>This folder contains several helper scripts for automatically building deployable, versioned artifacts of your apps:</p>\n<ul>\n<li>\n<p><code>build-docker-image</code>: This script is meant to be run from a CI job to automatically build a Docker image. It builds\nthe Docker image, tags the image with the sha1 of the most recent Git commit (or a custom tag, if specified), and then\npushes the new image to a Docker registry (unless the same image/tag already exists in the registry!).</p>\n</li>\n<li>\n<p><code>build-packer-artifact</code>: This script can be used to automatically build an artifact, such as an AMI, defined in a\nPacker template. It runs a Packer build, runs an optional test command to verify the new artifact, extracts the\nartifact ID from the build, and writes the ID to a properties file. This script is meant to be run from a CI job and\nthe properties file is a convenient way to pass information about the new artifact to another CI job.</p>\n</li>\n</ul>\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\">\"build-helpers\"</span> <span class=\"hljs-built_in\">--repo</span> <span class=\"hljs-string\">\"https://github.com/gruntwork-io/module-ci\"</span> <span class=\"hljs-built_in\">--tag</span> <span class=\"hljs-string\">\"v0.29.1\"</span>\n</pre>\n<h2 class=\"preview__body--subtitle\" id=\"properties-files\">Properties files</h2>\n<p>After a successful build, the build helper scripts write the versions of the artifacts they produce to a properties\nfile. The idea is that this properties file is easy to use in other scripts or other CI jobs to deploy those artifacts.</p>\n<p>The <code>build-docker-image</code> script adds an entry to the properties file of the form:</p>\n<pre><span class=\"hljs-attr\">DOCKER_IMAGE_TAG</span>=<IMAGE_TAG>\n</pre>\n<p>The <code>build-packer-artifact</code> script adds an entry to the properties file of the form:</p>\n<pre><span class=\"hljs-attr\">ARTIFACT_ID</span>=<ARTIFACT_ID>\n</pre>\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<p>Imagine you have a Packer template <code>templates/build.json</code> that specifies how to build an AMI for your app. You could\nset up automatic deployment for this app using two Jenkins CI jobs: <code>build-app</code> and <code>deploy-app</code>.</p>\n<p>The <code>build-app</code> CI job would first use the <code>build-packer-artifact</code> script to automatically build your AMI:</p>\n<pre><span class=\"hljs-keyword\">build</span>-packer-artifact --packer-template-<span class=\"hljs-keyword\">path</span> templates/<span class=\"hljs-keyword\">build</span>.json --output-properties-file artifacts.properties\n</pre>\n<p>Next, the <code>build-app</code> CI job would then pass the contents of <code>artifacts.properties</code> directly to the <code>deploy-app</code> CI\njob using the <a href=\"https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin\" class=\"preview__body--description--blue\" target=\"_blank\">Jenkins Parameterized Trigger\nPlugin</a>. The <code>deploy-app</code> CI job, in turn,\nwould be a <a href=\"https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Build\" class=\"preview__body--description--blue\" target=\"_blank\">parameterized build</a> that takes as input\na parameter called <code>ARTIFACT_ID</code> (the same parameter name that's in the <code>artifacts.properties</code> file) and use it, along\nwith the scripts in the <a href=\"/repos/v0.29.2/module-ci/modules/terraform-helpers\" class=\"preview__body--description--blue\">terraform-helpers module</a> to automatically deploy the new AMI:</p>\n<pre>cd templates\n<span class=\"hljs-keyword\">terraform</span>-update-<span class=\"hljs-keyword\">variable</span> --name rails_app_version --value $ARTIFACT_ID\nterragrunt apply\n</pre>\n<h2 class=\"preview__body--subtitle\" id=\"remote-packer-templates\">Remote packer templates</h2>\n<p><code>build-packer-artifact</code> also supports building Packer templates that are stored in a git repository. When a path of the\nformat <code>git::GIT_REPO_URL//RELATIVE_PATH_TO_PACKER_TEMPLATE?ref=GIT_REF</code> is passed in as the Packer template path,\n<code>build-packer-artifact</code> will clone the repository <code>GIT_REPO_URL</code> at the ref <code>GIT_REF</code> to a temporary directory and build\nthe template referenced at <code>RELATIVE_PATH_TO_PACKER_TEMPLATE</code> in the git repository.</p>\n<p>For example, to build the example jenkins Packer template in this repo on the release tag <code>v0.19.0</code>:</p>\n<pre>build-packer-artifact \\\n --packer-template-path <span class=\"hljs-string\">git:</span>:git<span class=\"hljs-meta\">@github</span>.<span class=\"hljs-string\">com:</span>gruntwork-io<span class=\"hljs-regexp\">/module-ci.git/</span><span class=\"hljs-regexp\">/examples/</span>jenkins<span class=\"hljs-regexp\">/packer/</span>jenkins.json?ref=v0.19.0\n</pre>\n<h2 class=\"preview__body--subtitle\" id=\"idempotent-packer-templates\">Idempotent packer templates</h2>\n<p>For AWS AMI builds that use <code>tags</code>, <code>build-packer-artifact</code> supports idempotent builds by AMI tags. When you pass in\n<code>--idempotent true</code> to the script, <code>build-packer-artifact</code> will only build a new AMI if an existing AMI with the same\ntags and similar name does not already exist in your account. A name is similar if everything matches except for unique\nbuild time identifiers (e.g., that returned by <code>isotime</code>, <code>uuid</code>, or <code>timestamp</code>).</p>\n<p>Note that we include the name in the idempotency check to ensure that you can preserve AMIs in a multiaccount scenario,\nwhere AMI tags are not visible in the target account.</p>\n<p>For example, consider the following packer template:</p>\n<pre>{\n <span class=\"hljs-attr\">\"variables\"</span>: {\n <span class=\"hljs-attr\">\"aws_region\"</span>: <span class=\"hljs-string\">\"us-east-1\"</span>,\n <span class=\"hljs-attr\">\"tag\"</span>: <span class=\"hljs-string\">\"\"</span>\n },\n <span class=\"hljs-attr\">\"builders\"</span>: [{\n <span class=\"hljs-attr\">\"ami_name\"</span>: <span class=\"hljs-string\">\"gruntwork-test-{{user `tag`}}-packer-build-{{uuid | clean_resource_name}}\"</span>,\n <span class=\"hljs-attr\">\"ami_description\"</span>: <span class=\"hljs-string\">\"An AMI created as part of testing the build-packer-artifact script.\"</span>,\n <span class=\"hljs-attr\">\"instance_type\"</span>: <span class=\"hljs-string\">\"t2.micro\"</span>,\n <span class=\"hljs-attr\">\"region\"</span>: <span class=\"hljs-string\">\"{{user `aws_region`}}\"</span>,\n <span class=\"hljs-attr\">\"type\"</span>: <span class=\"hljs-string\">\"amazon-ebs\"</span>,\n <span class=\"hljs-attr\">\"source_ami\"</span>: <span class=\"hljs-string\">\"ami-fce3c696\"</span>,\n <span class=\"hljs-attr\">\"ssh_username\"</span>: <span class=\"hljs-string\">\"ubuntu\"</span>,\n <span class=\"hljs-attr\">\"tags\"</span>: {\n <span class=\"hljs-attr\">\"tag\"</span>: <span class=\"hljs-string\">\"{{user `tag`}}\"</span>\n }\n }],\n <span class=\"hljs-attr\">\"provisioners\"</span>: [{\n <span class=\"hljs-attr\">\"type\"</span>: <span class=\"hljs-string\">\"shell\"</span>,\n <span class=\"hljs-attr\">\"inline\"</span>: [\n <span class=\"hljs-string\">\"echo 'Hello, World'\"</span>\n ]\n }]\n}\n</pre>\n<p>If you pass in the <code>--idempotent true</code> and <code>--var tag=v1</code>, then this will only build the AMI if it does not find any AMI\nwith the tag <code>tag=v1</code> and name that begins with <code>gruntwork-test-v1-packer-build-</code> in the <code>us-east-1</code> region.</p>\n<p>Under the hood the tags, names, and regions are computed at runtime using <code>packer console</code> with the provided vars.</p>\n<p>Note that the following conditions must be true in order to use this feature:</p>\n<ul>\n<li>Packer version is at least <code>v1.4.2</code> (version that introduced <code>packer console</code>).</li>\n<li>Templates are in <code>json</code> format (you can not use HCL based templates at this time).</li>\n<li>Build is for an AMI (builder type <code>amazon-ebs</code>).</li>\n<li>Builder is configured to tag the AMIs (<code>tags</code> is set).</li>\n</ul>\n","repoName":"module-ci","repoRef":"v0.29.2","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/build-helpers","title":"Repo Browser: EC2 backup","description":"Browse the repos in the Gruntwork Infrastructure as Code Library."}