githubterraforminfrastructure-as-codeopentofu

When importing an existing repo to github_repository, how do you fix Schrödinger's repo?


Background

My estate-repos repo,

Goal: Import manually created repos

I am attempting to import a repo that I (sadly) created manually before I built estate-repos, into estate-repos.

Expectation

import {
  to = module.github_repository["estate-config"].github_repository.repo
  id = "evoteum/estate-config"
}

This should result in the existing repo being successfully imported into tofu management.

Reality

With the import block in place, tofu apply returns the following error;

 module.github_repository["estate-config"].github_repository.repo: Refreshing state... [id=evoteum/estate-config]
╷
│ Error: Cannot import non-existent remote object
│ 
│ While attempting to import an existing object to
│ "module.github_repository[\"estate-config\"].github_repository.repo", the
│ provider detected that no object exists with the given id. Only
│ pre-existing objects can be imported; check that the id is correct and that
│ it is associated with the provider's configured region or endpoint, or use
│ "tofu apply" to create a new remote object for this resource.
╵

If I remove the import block, tofu apply returns,

 module.github_repository["estate-config"].github_repository.repo: Creating...
╷
│ Error: POST https://api.github.com/orgs/evoteum/repos: 422 Repository creation failed. [{Resource:Repository Field:name Code:custom Message:name already exists on this account}]
│ 
│   with module.github_repository["estate-config"].github_repository.repo,
│   on .terraform/modules/github_repository/github/repo/main.tofu line 11, in resource "github_repository" "repo":
│   11: resource "github_repository" "repo" {
│ 
╵
Error: OpenTofu exited with code 1.
Error: Process completed with exit code 1.

Furthermore, both the gh CLI and the API confirm that the repo is available.

Setup

module.github_repository[".github"].github_branch.main
module.github_repository[".github"].github_branch_default.main
module.github_repository[".github"].github_repository.repo
module.github_repository[".github"].github_repository_file.readme
module.github_repository["discussions"].github_branch.main
module.github_repository["discussions"].github_branch_default.main
module.github_repository["discussions"].github_repository.repo
module.github_repository["discussions"].github_repository_file.readme
module.github_repository["estate-reusable-workflows"].github_branch.main
module.github_repository["estate-reusable-workflows"].github_branch_default.main
module.github_repository["estate-reusable-workflows"].github_repository.repo
module.github_repository["estate-reusable-workflows"].github_repository_file.readme
module.github_repository["evoteum.github.io"].github_branch.main
module.github_repository["evoteum.github.io"].github_branch_default.main
module.github_repository["evoteum.github.io"].github_repository.repo
module.github_repository["evoteum.github.io"].github_repository_file.readme
module.github_repository["planzoco"].github_branch.main
module.github_repository["planzoco"].github_branch_default.main
module.github_repository["planzoco"].github_repository.repo
module.github_repository["planzoco"].github_repository_file.readme
module.github_repository["testy-mctestface"].github_branch.main
module.github_repository["testy-mctestface"].github_branch_default.main
module.github_repository["testy-mctestface"].github_repository.repo
module.github_repository["testy-mctestface"].github_repository_file.readme

Question

Since we have confirmed that the API is aware that repo does exist, so why is the GitHub Terraform provider saying that it both does and does not exist? What am I doing wrong?


Solution

  • When you import to the github_repository you need to use the name. https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository#import

    Repositories can be imported using the name

    In your repos file your names are just the repo name, but in your import your prefixing it with owner. but your PAT token will already be associated with that and likely its getting prefixed so your import becomes evoteum/evoteum/estate-config

    I have been able to reproduce this issue with

    resource "github_repository" "repo" {
      name = "killercoda"
    }
    
    import {
      id = "cdsre/killercoda"
      to = github_repository.repo
    }
    
    
    $ terraform apply
    github_repository.repo: Preparing import... [id=cdsre/killercoda]
    github_repository.repo: Refreshing state... [id=cdsre/killercoda]
    ╷
    │ Error: Cannot import non-existent remote object
    │
    │ While attempting to import an existing object to "github_repository.repo", the provider detected that no object exists with the given id. Only pre-existing objects can be imported; check that the id  
    │ is correct and that it is associated with the provider's configured region or endpoint, or use "terraform apply" to create a new remote object for this resource.
    ╵
    

    When I remove my user prefix from the id in the import

    
    github_repository.repo: Importing... [id=killercoda]
    github_repository.repo: Import complete [id=killercoda]
    github_repository.repo: Modifying... [id=killercoda]
    github_repository.repo: Modifications complete after 2s [id=killercoda]
    
    Apply complete! Resources: 1 imported, 0 added, 1 changed, 0 destroyed.
    

    Edit I have checked in the github terraform provider source code and can see this is exactly whats occuring https://github.com/integrations/terraform-provider-github/blob/main/github/resource_github_repository.go#L628

    func resourceGithubRepositoryRead(d *schema.ResourceData, meta interface{}) error {
        client := meta.(*Owner).v3client
    
        owner := meta.(*Owner).name
        repoName := d.Id()
    ...
    ...
    
        repo, resp, err := client.Repositories.Get(ctx, owner, repoName)