Git-aware directory watching with Terraform
Watching a directory with Terraform in order to update your resources is simple and brilliant! I’ve seen this done many times to do things like update lambda code or S3 bucket websites. The common way to accomplish this is zipping up a source folder with archive_file
and then triggering a null_resource
based on the output_sha
. Here’s an example of that setup:
That’s bad, don’t do that
The problem with archive_file
is that it grabs everything in a directory, including things like node_modules
or build logs. That means terraform plan
will show spurious updates, like when you do a new build or when a team member runs npm install
on their own machine.
You can try to get around this by only zipping up strict source files (e.g. project/src
); but what about the top-level files like package.json
? In almost every language, there will be times that you have a combination of important and non-important files in the same directory.
In almost every language, there will be times that you have a combination of important and non-important files in the same directory.
The irony is, you already know which files you do and don’t care about; that’s what a .gitignore
is for!
In this post I’m going to show you an incredibly simple way to only trigger a null_resource
when git-worthy changes are made to your source code.
Hash it up
First, we need a way to create a hash of the directory that only includes files that are important to git. Let’s call them git-portant files. The following bash command does just that:
Deleting node_modules
, or changing any file ignored in .gitignore
, will not change this hash, but adding new files or changing tracked files will. Awesome!
Terraform it
To track the value of this hash in Terraform so that our null_resource
can depend on it, we’ll use an external
data source. This data source will run the bash script with the specified query and then store the resulting JSON, which will be accessible to the null_resource
. Here’s what that looks like:
Now that’s slick!
The bash script
Now since Terraform interacts with that external source via JSON (in and out), our gethash.sh
is not as simple as the one-liner I showed at the beginning. We’ll need jq to parse the command query, and then we’ll need to output the checksum as JSON for Terraform to read. Here’s the final script:
Simply make sure that:
- The script is executable (
chmod +x gethash.sh
) - It’s in the same directory as your Terraform (or you’ve pointed to it correctly in the tf code)
That’s it! You’re ready to watch that directory for changes with git-telligence!
If this helped you, please like, share, and comment :)