Terraform and GitHub

Blog banner image


Find out how we use Terraform to manage our GitHub organisation, control users and teams and create repositories.



Introduction

As part of our ongoing mission to minimise ClickOps (it’s a thing!) we recently decided to use Terraform to manage our GitHub organisation. While, in theory, this is a relatively simple process there was always the risk of destroying all our repositories and losing months of hard work. This meant we had to ensure the configuration was spot on before we applied any changes.

Our goal

Our goal was to create something that allowed us to easily manage users, teams and repositories in a concise way allowing anyone to make changes within minutes. We also wanted to ensure branch protection was consistently applied across all our repositories including any that are created in the future.

We had already made the decision to use Terraform and I was given the task of writing the configuration as my first official Terraform project.

What is Terraform?

Terraform is an infrastructure as code (IaC) tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. Terraform can manage low-level components like compute, storage, and networking resources, as well as high-level components like DNS entries and SaaS features.

Writing the configuration

In order to keep things as simple as possible we broke down the configuration files into multiple smaller modules. One for users, one for teams and one for repositories.

The modules themselves define which resources we want to create. Using the “repo” module as an example we can see that we want to create a GitHub Repository and apply branch protection to it.

resource "github_repository" "repo" {
  name        = var.name
  description = var.description

  visibility = var.private ? "private" : "public"

  has_issues   = true
  has_projects = false
  has_wiki     = false
  is_template  = false
  auto_init    = true

  lifecycle {
    ignore_changes = [pages, auto_init]
  }
  
  archived = var.archived

  allow_auto_merge       = false
  delete_branch_on_merge = false
  vulnerability_alerts   = !var.private

}


resource "github_branch_protection" "protect_main" {
  repository_id = github_repository.repo.node_id

  pattern                         = "main"
  enforce_admins                  = true
  allows_deletions                = false
  require_signed_commits          = true
  required_linear_history         = false
  require_conversation_resolution = true
  push_restrictions               = []

  required_pull_request_reviews {
    dismiss_stale_reviews           = true
    required_approving_review_count = var.reviewers_count
    dismissal_restrictions          = []
    pull_request_bypassers          = []
  }

  allows_force_pushes = false

}

In order to create a new repository we pass through a module similar to the one below. If we need to remove a repository we can simply delete the module and Terraform will recognise the change and remove the repository without impacting anything else.

module "module_name" {
  reviewers_count = 1
  source          = "./repo"
  name            = "repo_name"
  team            = "team_name" 
  description     = " "
}

Instead of relying on a human to click around in GitHub’s web interface (ClickOps), we rely on Terraform to build, change, and manage our organisation in a safe, consistent, and repeatable way.

Whether you are managing a massive enterprise with hundreds of GitHub users or implementing a consistent labeling scheme across your personal projects, Terraform is the right tool for the job.

For more information, email us at [email protected] or call us on 01609 635 932