Import existing GitHub repositories into Terraform state

This blog post is a basic introduction to importing an existing GitHub repository into Terraform local backend.

By using the -generate-config-out flag when running terraform plan, we can leverage Terraform’ experimental code generation feature and produce an ouput file containing the repository resource definition in HCL format.

Create root module

Create a folder to store module code.

[~] mkdir ~/gh_repo_module
[~] cd ~/gh_repo_module

Add the files below.

Github provider configuration

provider "github" {
  owner = "my-github-user"
  token = "XXXXXXXXXXXXXXXXXXXXXXXXXXX"
}

Import configuration file

Include an import block, specifying:

  • resource type and label (to)
  • identifier of the existing resource (id)

The following is a sample import block for:

  • resource type -> github_respository
  • label -> github_repo
  • identifier (name of existing target repo to import) -> my-github-repo
import {
  to = github_repository.github_repo
  id = "my-github-repo"
}

Run module

Run terraform init.

[~/gh_repo_module]-> terraform init

Run terraform plan, with parameter -generate-config-out=<outputfile>, to instruct Terraform to generate an output HCL resource definition.

In the example below, outputfile = generated.tf.

[~/gh_repo_module]-> terraform plan -generate-config-out=generated.tf
Terraform will perform the following actions:

  # github_repository.github_repo will be imported
  # (config will be generated)
    resource "github_repository" "github_repo" {
        allow_auto_merge            = false
        allow_merge_commit          = true
        allow_rebase_merge          = true
        allow_squash_merge          = true
        allow_update_branch         = false
        archived                    = false
        auto_init                   = false
        default_branch              = "main"
        delete_branch_on_merge      = false
        etag                        = "W/\"**********\""
        full_name                   = "******/my-github-repo"
        git_clone_url               = "git://github.com/******/my-github-repo.git"
        has_discussions             = false
        has_downloads               = true
        has_issues                  = true
        has_projects                = true
        has_wiki                    = true
        html_url                    = "https://github.com/******/my-github-repo"
        http_clone_url              = "https://github.com/******/my-github-repo.git"
        id                          = "my-github-repo"
        is_template                 = false
        merge_commit_message        = "PR_TITLE"
        merge_commit_title          = "MERGE_MESSAGE"
        name                        = "my-github-repo"
        node_id                     = "******"
        private                     = true
        repo_id                     = *******
        squash_merge_commit_message = "COMMIT_MESSAGES"
        squash_merge_commit_title   = "COMMIT_OR_PR_TITLE"
        ssh_clone_url               = "git@github.com:******/my-github-repo.git"
        svn_url                     = "https://github.com/******/my-github-repo"
        topics                      = []
        visibility                  = "*****"
        vulnerability_alerts        = false
        web_commit_signoff_required = false

        security_and_analysis {
            secret_scanning {
                status = "disabled"
            }
            secret_scanning_push_protection {
                status = "disabled"
            }
        }
    }

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

Run terraform apply to import the repository into local backend.

[~/gh_repo_module]-> terraform apply

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.github_repo: Importing... [id=my-github-repo]
   github_repository.github_repo: Import complete [id=my-github-repo]

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

Quick confirmation to check resource exists in backend state file.

[~/gh_repo_module]-> terraform state list

github_repository.github_repo

Review generated HCL file for target resource

Our generated.tf file is shown below:

# __generated__ by Terraform
# Please review these resources and move them into your main configuration files.

# __generated__ by Terraform from "my-github-repo"
resource "github_repository" "github_repo" {
  allow_auto_merge                        = false
  allow_merge_commit                      = true
  allow_rebase_merge                      = true
  allow_squash_merge                      = true
  allow_update_branch                     = false
  archive_on_destroy                      = null
  archived                                = false
  auto_init                               = false
  delete_branch_on_merge                  = false
  description                             = null
  gitignore_template                      = null
  has_discussions                         = false
  has_downloads                           = true
  has_issues                              = true
  has_projects                            = true
  has_wiki                                = true
  homepage_url                            = null
  ignore_vulnerability_alerts_during_read = null
  is_template                             = false
  license_template                        = null
  merge_commit_message                    = "PR_TITLE"
  merge_commit_title                      = "MERGE_MESSAGE"
  name                                    = "my-github-repo"
  squash_merge_commit_message             = "COMMIT_MESSAGES"
  squash_merge_commit_title               = "COMMIT_OR_PR_TITLE"
  topics                                  = []
  visibility                              = "******"
  vulnerability_alerts                    = false
  web_commit_signoff_required             = false
  security_and_analysis {
    secret_scanning {
      status = "disabled"
    }
    secret_scanning_push_protection {
      status = "disabled"
    }
  }
}

Converting to other formats

We can transform the generated file into popular output formats, such as YAML or JSON.

JSON

Use hcl2json to produce JSON output.

[~/gh_repo_module]-> hcl2json generated.tf
{
    "resource": {
        "github_repository": {
            "github_repo": [
                {
                    "allow_auto_merge": false,
                    "allow_merge_commit": true,
                    "allow_rebase_merge": true,
                    "allow_squash_merge": true,
                    "allow_update_branch": false,
...
...
    }
}

YAML

Pipe the JSON output to yq to transform to YAML.

[~/gh_repo_module]-> hcl2json generated.tf | yq -P
resource:
  github_repository:
    github_repo:
      - allow_auto_merge: false
        allow_merge_commit: true
        allow_rebase_merge: true
        allow_squash_merge: true
        allow_update_branch: false
        ...
        ...