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:
- HashiCorp Terraform 0.14.4 (or later)
- A GitHub Personal Access token
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.