integrations / integrations/terraform-provider-github
[BUG] github_team_members: pending team members are re-added on every plan
- Dominant language
- Go
- Stars
- 1.2k
- Forks
- 1k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 8
Description
> This was filed at the request of this GitHub user, using Claude Code. The investigation and
> wording are Claude's; I have read the whole thing and verified the source links, the API
> behaviour and the version details before filing.
### Expected Behavior
After adding a user to `github_team_members` who has not yet accepted their organization
invitation, a subsequent plan should be empty. The apply already did what was asked: GitHub
records a pending team membership and sends the user a team-scoped invitation.
### Actual Behavior
Every plan proposes adding the same user again, indefinitely, until they accept the invitation
or it expires after 7 days. With a steady stream of new members, the diff is never empty.
Read and write disagree about what a team member is. The write in `resourceGithubTeamMembers`
uses `AddTeamMembershipBySlug`, which creates a pending membership:
https://github.com/integrations/terraform-provider-github/blob/main/github/resource_github_team_members.go#L394
The read in `getTeamMembers` uses the GraphQL `team.members(membership: IMMEDIATE)` connection,
which returns only members who have accepted:
https://github.com/integrations/terraform-provider-github/blob/main/github/resource_github_team_members.go#L291
So the pending membership is created, is invisible to the next read, and is planned again.
This looks like a side effect of #3497. Moving the read to GraphQL fixed the child-team problem,
and `IMMEDIATE` is the right filter for that, but the REST endpoint it replaced had the same
blind spot, so I don't think this ever worked — the GraphQL move just makes it the only
remaining gap.
`GET /orgs/{org}/teams/{team_slug}/invitations` returns the pending invitations for a team and
would let the read union them in:
https://docs.github.com/en/rest/teams/members#list-pending-team-invitations
Worth noting that `updateTeamMembers` builds its removal set from the same `getTeamMembers` call,
so a pending member is currently never a removal candidate either. That looks like the same root
cause as #307, and fixing the read would cover both.
I'd be happy to send a PR if you agree with the approach and with `IMMEDIATE` being kept.
### Terraform Version
Terraform v1.15.8, provider integrations/github v6.13.0
### GitHub Installation Type
GitHub.com (Enterprise Cloud)
### Affected Resource(s)
- `github_team_members`
### Terraform Configuration Files
```hcl
resource "github_team_members" "example" {
team_id = github_team.example.id
members {
username = "a-user-who-has-not-accepted-yet"
role = "member"
}
}
```
### Steps to Reproduce
1. `terraform apply` with a member who is not yet in the organization. The user is invited.
2. Before they accept, run `terraform plan` again.
3. The same member is proposed for addition. Repeat as often as you like.
### Debug Output
```
~ resource "github_team_members" "main" {
+ members {
+ role = "member"
+ username = "REDACTED"
}
}
Plan: 0 to add, 11 to change, 0 to destroy
```
Contributor guide
Assessment
This issue has not been assessed yet.