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.

something like this ;)

What if we can use GitHub Actions in a safe way for CICD for Terraform? Lets get to it

Configuration

If you are familiar with GitHub Actions workflw, then this config looks really simple:

  • name section is the name of the workflow
  • on defines when the workflow should be triggered. Here when there is a Pull Request created to the main branch and when there is changes for files inside infrastructure
  • 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

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

Terraform plan

And when I merge the PR, it looks like this:

terraform apply

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!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store