fbpx

HashiCorp Terraform infrastructure deployments can always be run manual, but using GitHub Actions to implement Continuous Integration and Continuous Deployment (CI/CD) can be used to streamline and automate the Terraform infrastructure as code (IaC) deployment workflow. Developers will use GitHub Actions to automate the code build and deployment for an applications code, and the same tools can be used to automate infrastructure as code deployments with HashiCorp Terraform.

GitHub Action Steps for setting up Infrastructure Deployment Automation

These are the primary steps necessary to setup an Infrastructure as Code (IaC) deployment automation process to both deploy and manage cloud infrastructure using HashiCorp Terraform:

  1. Define your infrastructure
    The desired state for cloud infrastructure needs to be defined using Terraform code. This will define all the various infrastructure components and their configurations, such as virtual machines, storage accounts, networking, etc.
  2. Store code in a GitHub repository
    In order to use GitHub Actions to manage the automated deployment process using Terraform, a GitHub repository will need to be created and used to store the Terraform code.
  3. Create a GitHub Action
    Once the Terraform code is stored in the GitHub repository, a GitHub Action can then be created and configured to run the Terraform deployment.
  4. Configure your GitHub Action
    The GitHub Action will be configured for the different steps that need to be executed in order to automate the Terraform infrastructure deployment workflow. This includes an automated CI/CD configuration, such as automatically running deployments based on code commits when Terraform code changes are made.
  5. Monitor your infrastructure
    Once cloud infrastructure is deployed and configured using Terraform, the infrastructure needs to be monitored to ensure it’s running correctly.
  6. Update your infrastructure
    Once the Terraform infrastructure deployment and management workflow is automated using GitHub Actions, then configuration updates and other changes to the infrastructure can be easily deployed automatically using the GitHub Action that was created.

GitHub repositories are source control repositories using Git version control along with additional features provided by GitHub, like pull requests and forking. GitHub offers a rich set of code collaboration tools that can be used to streamline the software development process as well as the infrastructure as code development process. The same GitHub version control workflow of using GitHub projects, git repositories, pull requests, and other features applies to managing infrastructure as code (IaC) deployments with HashiCorp Terraform as it does to application code builds and deployments.

GitHub Action to run Terraform Plan

There are multiple options for organizing Terraform code in sub-directories and branches within a GitHub repository. There are ways to use multiple sub-directories to manage the organization of Terraform infrastructure code for deploying multiple cloud environments, like Production, Test, and Development. For simplicity, this article focuses on assuming the Terraform project code is located within the root of the GitHub repository inside the main branch. The GitHub Action example in this article can be easily modified to handle any other configuration.

The following shows a simple GitHub Action to run the Terraform init, and plan commands, then store the Terraform Plan using a commit to the GitHub repository:

name: Terraform Plan

# configure to run on merges to 'main' branchbranchon:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    # be sure to authenticate with cloud provider
    - name: Login to Microsoft Azure
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v2

    - name: Terraform Init
      run: terraform init

    # generate Terraform Plan and store in .tfplan file
    - name: Terraform Plan
      run: terraform plan -out:terraform.tfplan

    # commit Terraform plan if running on 'main' branch
    # commit is made to the 'terraform-plan' branch
    - name: Commit Terraform Plan for Approval
      if: github.ref == 'refs/heads/main'
      uses: peter-evans/create-pull-request@v4
      with:
        commit-message: 'Terraform Plan'
        branch: 'terraform-plan'
        base: 'main'
        token: ${{ secrets.GITHUB_TOKEN }}

The previous GitHub Action example runs the following steps:

  1. GitHub Action runs on pushes to the main branch
  2. Repository code is checked out
  3. Cloud provider is authenticated. In this example, Microsoft Azure is authenticated against.
  4. Terraform is setup using the hashicorp/setup-terraform action.
  5. The Terraform init command is run to initialize the Terraform project.
  6. The Terraform plan command is run to generate the Terraform plan for later approval.
  7. The generated Terraform Plan file (.tfplan) is committed to the GitHub repository under the terraform-plan branch.

Keep in mind, the “Login to Microsoft Azure” action uses the secrets.AZURE_CREDENTIALS GitHub secret. This secret will need to be created and populated with the correct credentials value when using this action to authenticate with the Microsoft Azure cloud.

The next step left out of this GitHub Action is the Terraform Apply step. Generally, the Terraform Apply is going to be run manually so that the Terraform plan can be verified before execution.

GitHub Action to Run Terraform Apply

Once the previous GitHub Action is run when Terraform code is pushed to the main branch of the GitHub repository, then another GitHub Action is necessary for the manual step of approving the execution of the plan to apply the infrastructure changes to the cloud environment. Sure, the Terraform apply can be automatically run after the plan is generated, but it’s best practice to use a manual step to verify the plan before applying it. This is done to ensure the cloud infrastructure environment is modified only in a safe way, just in case there are any errors in the Terraform code or unexpected infrastructure changes triggered by the latest Terraform code changes.

The following is an example of a GitHub Action that will run on the terraform-plan branch in the GitHub repository when triggered manually, then execute the previously generated plan:

name: Terraform Apply

# configure manual trigger for GitHub Action
on:
  workflow_dispatch:
    branches: [ terraform-plan ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    # be sure to authenticate with cloud provider
    - name: Login to Microsoft Azure
      uses: azure/login@v1
      with:
        creds: ${{ secrets.AZURE_CREDENTIALS }}

    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v2

    - name: Terraform Init
      run: terraform init

    # apply previously generated Terraform Plan
    # from the terraform.tfplan file in the branch
    - name: Terraform Apply
      run: terraform apply "terraform.tfplan"

The previous GitHub Action runs the following steps:

  1. GitHub Action runs on pushes to the main branch
  2. Repository code is checked out
  3. Cloud provider is authenticated. In this example, Microsoft Azure is authenticated against.
  4. Terraform is setup using the hashicorp/setup-terraform action.
  5. The Terraform init command is run to initialize the Terraform project.
  6. The Terraform apply command is run, passing in the terraform.tfplan file to tell it what Terraform Plan to apply.

The GitHub Actions to automatically generate a Terraform Plan and then manually trigger the Terraform Apply of the plan in this article is a very simplistic example. This code can be easily modified to extend it to handle any custom deployment scenarios. When using this example and modifying it, be sure to use any GitHub Actions and Terraform best practices to ensure the security of the infrastructure environments being deployed.

Additionally, these GitHub Actions examples for applying HashiCorp Terraform infrastructure configurations assume the Terraform state is stored in a cloud storage account or other shared state location as configured in the Terraform code itself. If HashiCorp’s Terraform Cloud is being used to store the Terraform state, then the Terraform infrastructure as code (IaC) deployment will be executed and managed differently.

Microsoft MVP

Chris Pietschmann is a Microsoft MVP, HashiCorp Ambassador, and Microsoft Certified Trainer (MCT) with 20+ years of experience designing and building Cloud & Enterprise systems. He has worked with companies of all sizes from startups to large enterprises. He has a passion for technology and sharing what he learns with others to help enable them to learn faster and be more productive.
HashiCorp Ambassador Microsoft Certified Trainer (MCT) Microsoft Certified: Azure Solutions Architect