My Workflow :
When I wanted to start managing my Github with Terraform using the integrations/terraform-provider-github I felt that my terraform statefile should belong with the code, and not as a remote state in Azure/AWS/etc.
I couldn't find a suitable solution so I decided to roll my own:
It took me a while to figure out but I finally settled on keeping my state as a workflow artifact that is de/encrypted on each run. I decided to create my first action out of the whole thing only to find out that there actually was an #ActionsHackathon21 going on!
π What this action does: π
- π οΈ First off, it downloads your repository with
actions/checkout@v2
and then installs terraform usinghashicorp/setup-terraform@v1
. - π₯ Using environment variables it downloads the most recent workflow artifact called
terraformstatefile
and decrypts using the user input variableencryptionkey
.- If no artifact with that name is found (maybe it's your first run) then it proceeds with the following.
- ποΈ It then proceeds to run
terraform plan
with any flags from the optional variablecustom_plan_flags
- π’ Next it runs
terraform apply
with any flags from the optional variablecustom_apply_flags
.- This can be skipped by setting the optional variable
apply
tofalse
.
- This can be skipped by setting the optional variable
- ποΈ If all is well then Terraform has now produced a statefile
./terraform.tfstate
. This file is encrypted using the providedencryptionkey
.- π€« I'd recommend getting this from a
${{secret.variable}}
since the output isn't hidden.
- π€« I'd recommend getting this from a
- πΎ Finally the new statefile is uploaded as an artifact!
- π Lather, rinse, repeat! π
Submission Category:
DIY Deployments
Yaml File or Link to Code :
Here is an example to get you started:
steps:
- uses: sturlabragason/terraform_state_artifact@v1
with:
encryptionkey: ${{ secrets.encryptionkey }}
sturlabragason / terraform_state_artifact
The terraform_state_artifact action is a composite action that stores your Terraform state file as an encrypted Github workflow artifact.
terraform_state_artifact
The sturlabragason/terraform_state_artifact
action is a composite action that stores your Terraform state file as an encrypted Github workflow artifact and downloads and decrypts the state on subsequent runs. Built-in are the actions: actions/checkout@v2
, hashicorp/setup-terraform@v1
and actions/upload-artifact@v2
.
Be aware that Github delets artifacts older then 90 days by default. You can run your pipeline on a schedule to create a new artifact at least once every 90 days.
- π οΈ First off, it downloads your repository with
actions/checkout@v2
and then installs terraform usinghashicorp/setup-terraform@v1
. - π₯ Using environment variables it downloads the most recent workflow artifact called
terraformstatefile
and decrypts using the user input variableencryptionkey
- If no artifact with that name is found (maybe it's your first run) then it proceeds with the following.
- ποΈ It then proceeds to run
terraform plan
with any flags from the optional variablecustom_plan_flags
- β¦
Top comments (3)
Thank you for creating this. After testing few things, one caveat is that GitHub artifact download URL only last for one minute. Thus, this probably worked well for hackathon because your script immediately uploaded to artifact and downloaded within 1 minute. However, most real production scenarios will require Terraform states to last for quite sometime.
Thanks for the article!
How do you handle the issue that your Terraform state file will be deleted, as "by default, the artifacts and log files generated by workflows are retained for 90 days before they are automatically deleted"?
That's an excellent point @dennislwm that, truth be told, I hadn't thought of.
Reading the log retention docs tells me I don't have a lot of options so my first thought would be to run whatever pipeline that uses the action on a cron schedule. I'd guess that most pipelines using this could handle that, likely being stateful.
I'll make sure to mention it in the action's footnotes, thanks!π
Edit: I've added it to the readme! Thanks π₯