Git-aware directory watching with Terraform

Isaiah Taylor
2 min readJul 8, 2021

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:

This is bad, don’t do this.

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:

Yeah, I made a gist just for this line. Because I care.

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 :)

--

--