From a42b848f4bcf387b67eccb36d081242b1859111b Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sat, 25 Apr 2026 20:57:01 +0300 Subject: [PATCH 1/3] Update Read to combine Invites and Collaborator users This is to prevent drift when external users have not accepted invites yet. Signed-off-by: Timo Sand --- .../resource_github_repository_collaborators.go | 9 +++++---- ...ource_github_repository_collaborators_test.go | 16 ++++++++-------- github/util_user.go | 4 ---- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/github/resource_github_repository_collaborators.go b/github/resource_github_repository_collaborators.go index ece5141927..dcd45b38c1 100644 --- a/github/resource_github_repository_collaborators.go +++ b/github/resource_github_repository_collaborators.go @@ -255,10 +255,6 @@ func resourceGithubRepositoryCollaboratorsRead(ctx context.Context, d *schema.Re return diag.FromErr(err) } - if err := d.Set("user", ghUsers.flatten()); err != nil { - return diag.FromErr(err) - } - if isOrg { ghTeams, err := listTeamCollaborators(ctx, client, owner, repoName, inTeams, inIgnoreTeams) if err != nil { @@ -280,6 +276,11 @@ func resourceGithubRepositoryCollaboratorsRead(ctx context.Context, d *schema.Re return diag.FromErr(err) } + combinedUsersAndInvitations := slices.Concat(ghUsers, ghInvitations) + if err := d.Set("user", combinedUsersAndInvitations.flatten()); err != nil { + return diag.FromErr(err) + } + if err = d.Set("invitation_ids", ghInvitations.flattenInvitations()); err != nil { return diag.FromErr(err) } diff --git a/github/resource_github_repository_collaborators_test.go b/github/resource_github_repository_collaborators_test.go index 62eb917734..3f05d246f8 100644 --- a/github/resource_github_repository_collaborators_test.go +++ b/github/resource_github_repository_collaborators_test.go @@ -57,7 +57,7 @@ resource "github_repository_collaborators" "test" { } `, repoName, teamName0, teamName1, collaboratorUser) - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -118,14 +118,14 @@ resource "github_repository_collaborators" "test" { } `, repoName, testAccConf.testExternalUser) - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { skipUnauthenticated(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ { Config: config, ConfigStateChecks: []statecheck.StateCheck{ - statecheck.ExpectKnownValue("github_repository_collaborators.test", tfjsonpath.New("user"), knownvalue.SetSizeExact(0)), + statecheck.ExpectKnownValue("github_repository_collaborators.test", tfjsonpath.New("user"), knownvalue.SetSizeExact(1)), statecheck.ExpectKnownValue("github_repository_collaborators.test", tfjsonpath.New("team"), knownvalue.SetSizeExact(0)), statecheck.ExpectKnownValue("github_repository_collaborators.test", tfjsonpath.New("invitation_ids"), knownvalue.MapSizeExact(1)), }, @@ -196,7 +196,7 @@ resource "github_repository_collaborators" "test" { } `, configPre) - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -270,7 +270,7 @@ resource "github_repository_collaborators" "test" { } `, configPre) - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { skipUnauthenticated(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -336,7 +336,7 @@ resource "github_repository_collaborators" "test" { } `, configPre) - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -397,7 +397,7 @@ resource "github_repository_collaborators" "test" { } `, configPre) - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -451,7 +451,7 @@ resource "github_repository_collaborators" "test" { } `, repoName, teamName) - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ diff --git a/github/util_user.go b/github/util_user.go index 5f4b5aeddc..132bd887fe 100644 --- a/github/util_user.go +++ b/github/util_user.go @@ -21,10 +21,6 @@ func (u userCollaborator) flatten() any { "permission": u.permission, } - if u.invitationID != nil { - m["invitation_id"] = *u.invitationID - } - return m } From 1dbf8a468e44c5f1a52f038c1a69f68032739567 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sat, 25 Apr 2026 20:58:14 +0300 Subject: [PATCH 2/3] Improve DEBUG logging of repo collaborators Signed-off-by: Timo Sand --- ...esource_github_repository_collaborators.go | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/github/resource_github_repository_collaborators.go b/github/resource_github_repository_collaborators.go index dcd45b38c1..1190883c29 100644 --- a/github/resource_github_repository_collaborators.go +++ b/github/resource_github_repository_collaborators.go @@ -117,6 +117,7 @@ func resourceGithubRepositoryCollaborators() *schema.Resource { } func resourceGithubRepositoryCollaboratorsDiff(ctx context.Context, d *schema.ResourceDiff, m any) error { + tflog.Debug(ctx, "Diffing user collaborators") if d.HasChange("user") { users := d.Get("user").(*schema.Set).List() seen := make(map[string]any) @@ -181,6 +182,11 @@ func resourceGithubRepositoryCollaboratorsCreate(ctx context.Context, d *schema. teams := d.Get("team").(*schema.Set).List() ignoreTeams := d.Get("ignore_team").(*schema.Set).List() + tflog.Debug(ctx, "Creating repository collaborators", map[string]any{ + "users": users, + "teams": teams, + "ignoreTeams": ignoreTeams, + }) inUsers, err := getUserCollaborators(users) if err != nil { return diag.FromErr(err) @@ -226,6 +232,7 @@ func resourceGithubRepositoryCollaboratorsCreate(ctx context.Context, d *schema. } func resourceGithubRepositoryCollaboratorsRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + tflog.Debug(ctx, "Reading repository collaborators") meta, _ := m.(*Owner) client := meta.v3client owner := meta.name @@ -289,6 +296,7 @@ func resourceGithubRepositoryCollaboratorsRead(ctx context.Context, d *schema.Re } func resourceGithubRepositoryCollaboratorsUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + tflog.Debug(ctx, "Updating repository collaborators") meta, _ := m.(*Owner) client := meta.v3client owner := meta.name @@ -334,6 +342,7 @@ func resourceGithubRepositoryCollaboratorsUpdate(ctx context.Context, d *schema. } func resourceGithubRepositoryCollaboratorsDelete(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + tflog.Debug(ctx, "Deleting repository collaborators") meta, _ := m.(*Owner) client := meta.v3client owner := meta.name @@ -365,6 +374,7 @@ func resourceGithubRepositoryCollaboratorsDelete(ctx context.Context, d *schema. } func resourceGithubRepositoryCollaboratorsImport(ctx context.Context, d *schema.ResourceData, m any) ([]*schema.ResourceData, error) { + tflog.Debug(ctx, "Importing repository collaborators") meta := m.(*Owner) client := meta.v3client owner := meta.name @@ -497,7 +507,10 @@ func getTeamIdentity(d any) (teamIdentity, error) { func listUserCollaborators(ctx context.Context, client *github.Client, owner, repoName string) (userCollaborators, error) { col := make([]userCollaborator, 0) - + tflog.Debug(ctx, "Listing user collaborators", map[string]any{ + "owner": owner, + "repoName": repoName, + }) affiliations := []string{"direct", "outside"} for _, affiliation := range affiliations { opt := &github.ListCollaboratorsOptions{ @@ -634,6 +647,14 @@ func updateUserCollaboratorsAndInvites(ctx context.Context, client *github.Clien lookup[inUser.login] = inUser } + tflog.Debug(ctx, "Updating user collaborators and invitations", map[string]any{ + "repoName": repoName, + "inUsers": inUsers, + "lookup": lookup, + "seen": seen, + "remove": remove, + }) + ghUsers, err := listUserCollaborators(ctx, client, owner, repoName) if err != nil { return nil, err From 4e71b07177479be7c91718d80d6e8db9f034ff31 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 28 Apr 2026 12:20:08 +0300 Subject: [PATCH 3/3] Revert `ParallelTest` changes Signed-off-by: Timo Sand --- ...esource_github_repository_collaborators_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/github/resource_github_repository_collaborators_test.go b/github/resource_github_repository_collaborators_test.go index 3f05d246f8..c49d5a06b1 100644 --- a/github/resource_github_repository_collaborators_test.go +++ b/github/resource_github_repository_collaborators_test.go @@ -57,7 +57,7 @@ resource "github_repository_collaborators" "test" { } `, repoName, teamName0, teamName1, collaboratorUser) - resource.ParallelTest(t, resource.TestCase{ + resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -118,7 +118,7 @@ resource "github_repository_collaborators" "test" { } `, repoName, testAccConf.testExternalUser) - resource.ParallelTest(t, resource.TestCase{ + resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnauthenticated(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -196,7 +196,7 @@ resource "github_repository_collaborators" "test" { } `, configPre) - resource.ParallelTest(t, resource.TestCase{ + resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -270,7 +270,7 @@ resource "github_repository_collaborators" "test" { } `, configPre) - resource.ParallelTest(t, resource.TestCase{ + resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnauthenticated(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -336,7 +336,7 @@ resource "github_repository_collaborators" "test" { } `, configPre) - resource.ParallelTest(t, resource.TestCase{ + resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -397,7 +397,7 @@ resource "github_repository_collaborators" "test" { } `, configPre) - resource.ParallelTest(t, resource.TestCase{ + resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ @@ -451,7 +451,7 @@ resource "github_repository_collaborators" "test" { } `, repoName, teamName) - resource.ParallelTest(t, resource.TestCase{ + resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{