Caching problem with Terraform

UPDATE: After much experimentation and reflection, I’ve come to the conclusion that my original goal is Not A Good Idea. You should definitely always use a Terraform state backend and, even better, a locking mechanism as well. So don’t respond to this question, take it as a cautionary tale. A CI caching system is going to produce pain.

I’m having an issue that I’ve really been banging my head against the wall about and I’m hoping that someone here can help. What I’m trying to do is fairly simply: I needed to make a build artifact available across all branches/jobs/pipelines/everything, but my efforts to do so thus far have been fruitless.

Basically I’m trying to apply Terraform configurations using GitLab CI, but no matter what, I end up recreating Terraform resources, even when that shouldn’t happen (I’ve done plenty of local runs that work as expected). To be more concrete, I need to:

  1. Create a Terraform plan (terraform.tfplan) during every build using terraform plan. The resulting file should be available at the later apply stage.
  2. During the apply stage, a terraform.tfstate file is created that lists the actual resources created the last time around. Without this file, Terraform will create the resources anew, which is not the intended behavior. Every time terraform apply is run, the resulting terraform.tfstate file needs to be available to all builds, regardless of branch, job, etc.

I’ve tried several ways of doing this (largely using cache and artifacts directives) but to no avail. No matter what I do, Terraform keeps re-creating resources that it should. For context, here’s my most recent configuration, which is also my best guess about how this could work: https://gitlab.com/lucperkins/shear/blob/master/.gitlab-ci.yml. I have temporarily commented out the plan stage to avoid the issue.

Any ideas? Happy to provide more context if necessary. Thanks for reading!

PS—I am aware that there’s a GitLab CI template for Terraform that you can see here. That template, however, is actively harmful, as it doesn’t cache the terraform.tfstate file. Anyone who uses that template unmodified will almost certainly end up re-creating existing resources.

PPS—Yes, I am aware that I should be using a Terraform backend. Trying to make this easier—perhaps easier than it was meant to be. Mea culpa.