integrations / integrations/terraform-provider-github
github_repository Read doesn't refresh id/name after an out-of-band rename (unlike Create/Update)
- Dominant language
- Go
- Stars
- 1.2k
- Forks
- 1k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 8
Description
## Terraform Version
1.5.7 (and later, unaffected by TF core version)
## Provider Version
v6.11.1 (confirmed still present at v6.13.0, the latest release as of this report)
## Affected Resource(s)
- github_repository
## Terraform Configuration Files
N/A — reproduces on any `github_repository` resource that is renamed out-of-band (i.e. `name` changes on an already-applied resource) between two `terraform apply`/`terraform plan -refresh-only` runs.
## Expected Behavior
After a rename, `terraform refresh`/`plan` should observe the *actual current* repository name and either report no diff (if the config's `name` already matches) or a correct diff.
## Actual Behavior
`resourceGithubRepositoryRead` (`github/resource_github_repository.go`) does:
```go
repoName := d.Id()
...
repo, resp, err := client.Repositories.Get(ctx, owner, repoName)
...
_ = d.Set("name", repoName)
```
`client.Repositories.Get` succeeds even when `repoName` is the *old* name, because the GitHub API transparently redirects a renamed repository's old-name lookup to the current one — `repo` in the response correctly reflects the new name (`repo.GetName()`), and every other field is set from that response (`repo.GetDescription()`, `repo.GetFullName()`, etc.). But `name` is set from the pre-read `repoName` local variable instead of `repo.GetName()`, so it never reflects the actual current name. `Read` also never calls `d.SetId(...)`, so the resource's ID likewise never advances past the original name.
By contrast, both `resourceGithubRepositoryCreate` and `resourceGithubRepositoryUpdate` correctly call `d.SetId(repo.GetName())` after their respective API calls (Update even has a comment noting exactly this hazard: "It's possible that `repo.GetName()` is different from `repoName` if the repository is renamed"). That same handling was never applied to Read.
Practical impact for consumers that track external identity by ID/name (e.g. Crossplane's upjet-based providers, which re-derive their external-name annotation from the Terraform ID on every reconcile): once a repository is renamed, `Read` keeps reporting the pre-rename name indefinitely, and any control loop that treats that as authoritative will keep trying to "correct" the live repository back to its old name.
## Steps to Reproduce
1. `terraform apply` a `github_repository` resource, e.g. `name = "foo"`.
2. Rename the repository out-of-band (GitHub UI, or `gh repo rename bar -R owner/foo`), so the live repo is now `owner/bar` but the Terraform ID in state is still `foo`.
3. `terraform plan -refresh-only` (or any `Read`/`RefreshWithoutUpgrade` invocation using the stale ID).
4. Observe: the read succeeds (via GitHub's redirect), but the refreshed `name` attribute (and the resource's ID) still shows `foo`, not `bar`.
## Suggested fix
In `resourceGithubRepositoryRead`, immediately after the `client.Repositories.Get` call:
```go
d.SetId(repo.GetName())
...
_ = d.Set("name", repo.GetName())
```
mirroring the existing `Create`/`Update` handling.
Contributor guide
Research direction
Read resourceGithubRepositoryRead in github/resource_github_repository.go first, then compare its name and ID handling with Create and Update. Verify completion by reproducing an out-of-band rename and confirming refresh observes repo.GetName() for both the name attribute and resource ID.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github, go, terraform
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100