Terraform

How to Manage GitHub with Terraform

how to manage GitHub with Terraform

Terraform is one of the most popular tools for deploying and managing infrastructure as code (IaC). As it continues to push the boundaries of IaC, web-based repository hosting platforms like GitHub are being used widely for storing Terraform code and other artifacts.

In this article, we will explore some of the efficient ways to manage GitHub repositories with Terraform.

We will cover:

  1. Managing GitHub repositories — challenges
  2. How to set up Terraform GitHub provider
  3. Managing GitHub repositories with Terraform
  4. Managing GitHub branches with Terraform
  5. Managing GitHub issues with Terraform
  6. Managing GitHub Actions with Terraform

Managing GitHub repositories — challenges

GitHub provides a web-based centralized platform to store, manage, and share code. With its user-friendly interface and collaborative tools, it has become a popular choice for version control and project management.

Challenges in managing GitHub repositories and projects include: 

  • Access control, particularly when the number of contributors and repositories grows.
  • Security concerns such as exposure of secrets, unauthorized access, data leaks, and breaches.
  • The time-consuming and error-prone nature of managing multiple repositories and projects.
  • Ensuring consistency across repositories and projects for compliance and collaboration.
  • The tedious and error-prone nature of managing GitHub manually.
  • The complexity of scaling and automating GitHub management without the right tools and processes.

Terraform has the perfect solution — codify, version, automate, reuse, audit, and release. By integrating GitHub with Terraform, we can manage our GitHub organizations, repositories, branches, teams, projects, and actions more efficiently.

For example, a team leader can use Terraform to grant or revoke access to specific repositories, ensuring compliance and reducing human error. With Terraform, we can use a single configuration file to manage access control for all of our repositories, making it much easier to ensure consistency and security across your organization.

For help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, you can rely on Spacelift instead of using a static pair on your local machine. It supports policy as code, programmatic configuration, context sharing, drift detection, and many more great features right out of the box. One of the things we’re most proud of at Spacelift is the deep integration with everyone’s favorite version control system GitHub. You can check it for free, by creating a trial account.

How to set up Terraform GitHub provider

Before we can start managing GitHub with Terraform, we need to set up the Terraform GitHub provider. To do this, we’ll need to provide our GitHub personal access token and set up the provider configuration.

The following code snippet shows how to set up the GitHub provider in Terraform.

provider "github" {
 token = "your_personal_access_token"
 owner = "your_org_name"
}

resource "github_repository" "example" {
 name        = "repo0088"
 description = "This is my Github repository"
 visibility  = "private"
 auto_init   = true
}

The token attribute is the GitHub account’s personal access token. The owner attribute is the given name of the organization. In my case, the name of my organization is “letsdote-ch”. We can also source these values using environment variables. For this post, the token must have admin: org, delete_repo, and repo permissions.

We will use the same provider details to perform various GitHub management activities with Terraform.

You can also check out how to implement GitLab CI/CD pipeline with Terraform.

Managing GitHub repositories with Terraform

To manage GitHub repositories with Terraform, we can use the github_repository resource. This resource allows us to create, modify, or delete GitHub repositories programmatically.

Creating a new repository

The following code snippet shows how to create a new GitHub repository with Terraform.

resource "github_repository" "example" {
 name        = "repo0088"
 description = "This is my Github repository"
 visibility  = "private"
 auto_init   = true
}

Next, run terraform plan and terraform apply to confirm if this created a new repository on GitHub or not. Below is the terminal output for the apply command.

terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # github_repository.example will be created
  + resource "github_repository" "example" {
      + allow_auto_merge            = false
      + allow_merge_commit          = true
      + allow_rebase_merge          = true
      + allow_squash_merge          = true
      + archived                    = false
      + auto_init                   = true
      + default_branch              = (known after apply)
      + delete_branch_on_merge      = false
      + description                 = "This is my Github repository"
      + etag                        = (known after apply)
      + full_name                   = (known after apply)
      + git_clone_url               = (known after apply)
      + html_url                    = (known after apply)
      + http_clone_url              = (known after apply)
      + id                          = (known after apply)
      + merge_commit_message        = "PR_TITLE"
      + merge_commit_title          = "MERGE_MESSAGE"
      + name                        = "repo0088"
      + node_id                     = (known after apply)
      + private                     = (known after apply)
      + repo_id                     = (known after apply)
      + squash_merge_commit_message = "COMMIT_MESSAGES"
      + squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
      + ssh_clone_url               = (known after apply)
      + svn_url                     = (known after apply)
      + visibility                  = "private"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

github_repository.example: Creating...
github_repository.example: Creation complete after 6s [id=repo0088]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Verify the operation by visiting the organization on GitHub and searching for the “repo0088” repository, as shown in the screenshot below:

search for the repository

Importing existing repositories

Instead of creating a new repository, we can import and manage existing GitHub repositories with Terraform using the terraform import command.

To do this, either select an existing repository from the organization’s GitHub account, or create one for testing purposes. We have created a repository named “repo0099-existing” for the sake of this example.

To import this repository under Terraform management, create the corresponding IaC configuration as shown below.

terraform import github_repository.existing_repo repo0099-existing 
github_repository.existing_repo: Importing from ID "repo0099-existing"...
github_repository.existing_repo: Import prepared!
  Prepared github_repository for import
github_repository.existing_repo: Refreshing state... [id=repo0099-existing]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

As indicated in the console output, we have successfully imported the existing repository from GitHub to Terraform management.

Note: For more details on how to use the import command, refer to Importing Existing Infrastructure into Terraform blog.

Managing GitHub branches with Terraform

To manage GitHub branches with Terraform, use the github_branch and github_branch_protection resources. These resources allow us to create or manage branches and enforce branch protection rules, such as requiring pull request reviews, requiring status checks, and restricting who can push to a branch. 

Creating a new branch

To create a branch for a repository, add the following resource block in the Terraform configuration file. It refers to the repository object name and creates the development branch.

resource "github_branch" "development" {
 repository = github_repository.example.name
 branch     = "development"
}

Run the terraform apply command and check if the branch is successfully created on the target repository.

This is confirmed by the screenshot below:

create new branch

Importing existing branches

We can use the import command to import existing GitHub branches that we want to manage with Terraform.

To do this, first, create a branch in one of the repositories using the GitHub web UI. You can also use this if you are working with existing repositories and branches.

import existing branch

For example, we would like to import the staging branch for repository repo0099-existing.

The overall import process is the same — create the corresponding configuration in Terraform Infrastructure as Code (as shown below) and then run the import command. 

resource "github_branch" "existing_staging" {
 repository = github_repository.existing_repo.name
 branch     = "staging"
}

The following terminal output shows how the import command imports the staging branch of a GitHub repository into Terraform:

terraform import github_branch.existing_staging repo0099-existing:staging
github_branch.existing_staging: Importing from ID "repo0099-existing:staging"...
github_branch.existing_staging: Import prepared!
  Prepared github_branch for import
github_branch.existing_staging: Refreshing state... [id=repo0099-existing:staging]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

Managing GitHub issues with Terraform

In GitHub, an issue is a feature that is used to track enhancements, bugs, or any other tasks within a project. Issues allow users to collaborate with the project contributors. Anyone who has access to the GitHub repos can access and open the GitHub issues.

We can also link one issue with other issues or pull requests. This makes it easy to track down all the different bugs, tasks, and enhancements within a project.

Creating a new GitHub issue

To manage GitHub issues with Terraform, use the github_issue resource. This resource allows us to create, modify, or delete GitHub issues with code. 

The following code snippet shows how to create a new GitHub issue with Terraform:

resource "github_issue" "first_issue" {
 repository = github_repository.example.name
 title = "First Issue"
 body = "This is the first issue."
}

The plan command output on the terminal should highlight that one issue will be added to the selected repository as shown below.

terraform plan
github_repository.existing_repo: Refreshing state... [id=repo0099-existing]
github_repository.example: Refreshing state... [id=repo0088]
github_branch.development: Refreshing state... [id=repo0088:development]
github_branch.existing_staging: Refreshing state... [id=repo0099-existing:staging]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # github_issue.first_issue will be created
  + resource "github_issue" "first_issue" {
      + body       = "This is the first issue."
      + etag       = (known after apply)
      + id         = (known after apply)
      + issue_id   = (known after apply)
      + number     = (known after apply)
      + repository = "repo0088"
      + title      = "First Issue"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Before running the apply command, make sure the ‘issues’ feature is enabled on the target repository. This feature is enabled by navigating to “Settings > General > Features.” The “Issues” checkbox is shown in the screenshot below:

features issues box

We must also update the corresponding resource configuration of the repository in the IaC code.

The resource block for our example repository now has an additional attribute named “has_issues” set as true, as shown below:

resource "github_repository" "example" {
 name        = "repo0088"
 has_issues  = true
 description = "This is my Github repository"
 visibility  = "private"
 auto_init   = true
}

If this is enabled, run the apply command and observe the successful terminal output.

You can verify in the GitHub UI that the issue was successfully created. 

verify issue

Managing GitHub Actions with Terraform

GitHub Actions enable the creation of several automated workflows, which are triggered through several events in a GitHub repository. They contain one or more jobs that perform stepwise individual tasks. So we can use Actions to perform a wide variety of Tasks, such as building applications, running tests, and automated code reviews. GitHub provides a library containing all pre-built Actions that we can use as-is or customize to suit our personal needs.

To manage GitHub Actions with Terraform, use the github_actions_secret resource. This resource allows us to manage the secrets used in GitHub Actions. The following code shows how to create a new Github Actions secret with Terraform:

resource "github_actions_secret" "my_secret" {
 repository      = github_repository.example.name
 secret_name     = "MY_SECRET"
 plaintext_value = "my-secret-value"
}

Run the terraform plan and apply commands to store this secret in the target GitHub repo.

Look at the GitHub UI to see if the secret was successfully created.

github actions secret

Similarly, we can manage other GitHub Action resources using Terraform provider integrations/github.

Note: The integrations/github provider currently does not support any resource for creating the Actions. The workflow for GitHub Actions has to be defined in a separate YAML file (typically named .github.yml). The same file can then be pushed to the repository using null_resource resource and local-exec provisioner.

Read more about managing Terraform with GitHub Actions.

Key points

Terraform is a powerful tool that can simplify the management of GitHub resources like projects, repositories, actions, issues, and branches. With Terraform’s IaC approach, we can create, import, and modify various GitHub resources according to the requirements. Terraform’s declarative syntax can manage the complexity of modern computing.

And don’t forget to explore how Spacelift makes it easy to work with Terraform.

Note: New versions of Terraform will be placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that will expand on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6. OpenTofu retained all the features and functionalities that had made Terraform popular among developers while also introducing improvements and enhancements. OpenTofu is the future of the Terraform ecosystem, and having a truly open-source project to support all your IaC needs is the main priority.

Manage Terraform Better with Spacelift

Build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization and many more.

Start free trial