In this blog post, we are going to leverage Terraform’s Github provider to create a GitHub repository for a Github Organization.

Then we are going to use Github Actions and specifically the Hashicorp setup-terraform GitHub action to run some automated validation tests on our Terraform files.

To follow along you will need:

Use Terraform to provision and Manage GitHub repositories and team membership

Ok, let’s see how we can leverage terraform for GitHub repos.

Creating your own repositories might be easier and faster via GitHub UI for your own projects, but in the case of Organizations with many repositories and lots of members with different access rights makes sense to actually keep your repositories configuration as code.

To begin with our example we are going to create a directory github that will hold all our Terraform files related to GitHub management. Inside we are going to create 3 simple files.

In terraform.tf we set our required provider.

terraform {
    required_providers {
        github = {
            source = "integrations/github"
            version = "4.3.0"
        }
    }
}

In github.tf we set information regarding our provider and Organization.

provider "github" {
    organization = "CourageAI"
}

In repository.tf we add our configuration for our example repository my_repo. Pick the parameters that match your case.

resource "github_repository" "my_repo" {
    name = "my-repo"
    description = "My demo repository"
    visibility = "public"
    has_issues = true
    has_projects = false
    has_wiki = true

    allow_merge_commit = false
    allow_squash_merge = true
    allow_rebase_merge = false
    delete_branch_on_merge = true

    topics = [
        "my-topic-1",
        "my-topic-2"
    ]
    vulnerability_alerts = true
}

Alright, that should be sufficient to create a repository my_repo with the configuration above for an Organization CourageAI.

The Terraform Provider is quite feature-complete so you can manage everything around your GitHub repositories with Terraform files.

For a full list of options and resources that you can manage check the docs

Before move on, you’ll also need to export your GitHub token.

export GITHUB_TOKEN=<your_token>

Alright, we are ready to go. Initialize provider plugins.

cd github
terraform init

Let’s see what is going to happen.

terraform plan

We see that Terraform is going to create our repository, sweet! Let’s push the button.

terraform apply

Ok, let’s head to GitHub to validate our repo is there.

Awesome!

Let’s commit and push all these files to our newly created repo.

git init
git add repository.tf main.tf github.tf
git commit -m "Add tf files"
git remote add origin https://github.com/CourageAI/my-repo.git
git push origin master

Use GitHub actions to validate your Terraform files

In the second part of this blog post, we are going to set up a simple GitHub Action workflow which checks if our Terraform files are valid. For this, first we’ll create an example minimal terraform file that we’ll use to test our workflow.

Let’s create a folder named instances and inside we’ll create our instances.tf file that spawns an AWS EC2 instance. I am using this file as an example Terraform manifest to run the validation tests on, so don’t read much into it. Let’s assume it will spawn a new EC2 instance with the required configuration.

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
  profile = "default"
  region  = "us-east-1"
}
resource "aws_instance" "my-instance" {
  ami           = "ami-12345"
  instance_type = "t2.micro"
}

Next, we have to set up our GitHub Actions workflow. In the top directory of your repo create .github/workflows directories and inside our terraform.yaml file.

---
name: "Validate Terraform files"

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  terraform:
    name: Terraform
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        directory: ["./instances"]
    defaults:
      run:
        working-directory: ${{ matrix.directory }}
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v2
        with:
          fetch-depth: 1

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v1.2.1

      - name: Run `terraform fmt`
        id: fmt
        run: terraform fmt -diff -check -no-color -recursive

      - name: Run `terraform init`
        id: init
        run: terraform init

      - name: Run `terraform validate`
        id: validate
        if: github.event_name == 'pull_request'
        run: terraform validate -no-color

Ok, what’s happening here? We set up our GitHub Action to be triggered on push events on the main branch and on pull_requests. The last step with id validate will only be triggered if we have a pull_request event.

The stages that are triggered are using our instances directory.

Using the hashicorp/setup-terraform action we setup terraform cli and then we run the format, init and validate commands to see if our Terraform configuration files are valid.

Perfect, create the main branch and push our code here.

git checkout -b main
git add .github/
git commit -m "Add gh action to validate tf files"

As an example workflow, we’ll simulate an infrastructure change last. Change the AMI of our instances.tf file, commit and push to the main branch.

git add instances/instances.tf
git commit -m "Modify ami"
git push origin main

Back to Github, we see that our pipeline is triggered with the push event to the main branch as expected.

Click on the job and check the logs for our stages.

As expected, our validation step wasn’t triggered yet. Let’s open a Pull Request to also trigger this step.

And checking the pipeline logs again we confirm that our validation step run successfully!

You can find this repo here.

Next Steps

In this demo, we saw an example of how to provision repositories with Terraform. Check the docs for complete details on how to expand this simplistic example.

We haven’t discussed anything regarding Terraform State in this post as I wanted to keep things simple. Another demo will follow that integrates GitHub Actions with Terraform Cloud to automate your infrastructure provisioning, stay tuned.