CICD for Terraform with GitHub Actions
Introduction
This post is about using Terraform in CICD pipeline with GitHub actions.
Most of the time we make use of popular CICD tools like Jenkins for Infra deployment. Because its nice as we can have stages for deployment, add custom variables or jobs and we can also add prompts for user inputs to continue, which is really important. With GitHub actions, its fully automated and it can be risky sometimes, because with automated, there is a pretty good chance, that a mistake in the config and wipe off the full infrastructure.
What if we can use GitHub Actions in a safe way for CICD for Terraform? Lets get to it
Configuration
Terraform Plan
If you are familiar with GitHub Actions workflw, then this config looks really simple:
name
section is the name of the workflowon
defines when the workflow should be triggered. Here when there is a Pull Request created to themain
branch and when there is changes for files insideinfrastructure
env
defines the environment variables required for this particular workflow or for the jobs that is going to run. The variables are related to terraform config that is run. All those secrets are stored in GitHub Secrets.jobs
section contains all the jobs that needs to run for this workflow. There is:
- Install terraform
- Check terraform formatting is proper
- Initialize terraform
- Validate terraform
- Run terraform Plan
- Run commands to update the PR if its passed or failed- Terraform is installed all the time, because I am using a public
ubuntu
image and I am not sure if proper version of terraform is installed or not. This additional help is better than building my own custom image and using it. - The posting info job uses
actions/github-script@v6
. You will need to give more attention on the format on printing information, otherwise it might look a bit ugly :P
Terraform Apply
So the jobs are similar to the ones in the terraform plan workflow. Except in here we are running plan and apply as well together. I can actually merge both these workflows into one and then check if its PR or not to run the apply
part.
At this point of time when I am writing, there was an issue with the actions/github-script@v6
action. When the Pull Request is merged, then for some reason, the GITHUB_TOKEN
cannot write on the closed PR discussion. I tried to use the same action to use with the PR state
in closed.
Still it didn’t work. So I had to use a different action, which someone created due to the same issue.
So now create a new branch from main
and add some TF code and create a a PR against the main
branch. This is how my plan looks like
And when I merge the PR, it looks like this:
Next Steps
This is for setting up simple infrastructure. In this infra, the tfvars
file is inside the infrastructure
folder in the repo. For more complex environment like multiple environments, then it would be better to use terraform workspaces, provide separate tfvars
files and change the directory structure itself and based on branch, deploy to different environments.
For example:
- PR and merge from feature to development branch, goes to DEV
- PR and merge from development to main branch, goes to TEST/UAT
- And creation of tag and deploying it will go to PROD.
This is what I would see as a proper infra deployment. With this base workflows, you can also easily integrate tests with localstack or mock environments
Conclusion
CICD for infrastructure deployment is getting more and more as a requirement, because Infrastructure as a Code is moving as a defacto standard for provisioning Infra on any provider whether its cloud or on-premise. It would be nice to have CICD for infra with unit and integration testing. I hope this post helped you to understand how to build a CICD pipeline. With this info as a base, you can actually build complex pipelines.
Hope you enjoyed and have a nice day!