Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion github/resource_github_team_members.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package github

import (
"context"
"errors"
"log"
"net/http"
"reflect"
"strconv"
"strings"

"github.com/google/go-github/v88/github"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/shurcooL/githubv4"
Expand Down Expand Up @@ -187,6 +190,11 @@ func resourceGithubTeamMembersRead(ctx context.Context, d *schema.ResourceData,

teamSlug, err := getTeamSlug(ctx, meta, teamIdString)
if err != nil {
if ghErr, ok := errors.AsType[*github.ErrorResponse](err); ok && ghErr.Response.StatusCode == http.StatusNotFound {
tflog.Info(ctx, "Team no longer exists, removing from state", map[string]any{"team_id": teamIdString})
d.SetId("")
return nil
}
return diag.FromErr(err)
}

Expand All @@ -201,7 +209,8 @@ func resourceGithubTeamMembersRead(ctx context.Context, d *schema.ResourceData,
var q struct {
Organization struct {
Team struct {
Members struct {
DatabaseId int
Members struct {
Edges []struct {
Node struct {
Login string
Expand Down Expand Up @@ -229,6 +238,12 @@ func resourceGithubTeamMembersRead(ctx context.Context, d *schema.ResourceData,
return diag.FromErr(err)
}

if q.Organization.Team.DatabaseId == 0 {
tflog.Info(ctx, "Team no longer exists, removing from state", map[string]any{"team_id": teamIdString})
d.SetId("")
return nil
}

// Add all members to the list
for _, member := range q.Organization.Team.Members.Edges {
teamMembersAndMaintainers = append(teamMembersAndMaintainers, map[string]any{
Expand Down Expand Up @@ -257,6 +272,10 @@ func resourceGithubTeamMembersDelete(ctx context.Context, d *schema.ResourceData
teamIdString := d.Get("team_id").(string)
teamId, err := getTeamID(ctx, meta, teamIdString)
if err != nil {
if ghErr, ok := errors.AsType[*github.ErrorResponse](err); ok && ghErr.Response.StatusCode == http.StatusNotFound {
tflog.Info(ctx, "Team no longer exists, skipping member deletion", map[string]any{"team_id": teamIdString})
return nil
}
return diag.FromErr(err)
}

Expand All @@ -270,6 +289,10 @@ func resourceGithubTeamMembersDelete(ctx context.Context, d *schema.ResourceData

_, err = client.Teams.RemoveTeamMembershipByID(ctx, orgId, teamId, username)
if err != nil {
if ghErr, ok := errors.AsType[*github.ErrorResponse](err); ok && ghErr.Response.StatusCode == http.StatusNotFound {
tflog.Info(ctx, "Team no longer exists, skipping remaining member deletions", map[string]any{"team_id": teamIdString})
return nil
}
return diag.FromErr(err)
}
Comment thread
nitinjain999 marked this conversation as resolved.
}
Expand Down
49 changes: 49 additions & 0 deletions github/resource_github_team_members_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,55 @@ resource "github_team_members" "test" {
},
})
})

t.Run("succeeds when parent team is deleted out-of-band before destroy", func(t *testing.T) {
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
teamName := fmt.Sprintf("%steam-members-%s", testResourcePrefix, randomID)

config := fmt.Sprintf(`
resource "github_team" "test" {
name = "%s"
}

resource "github_team_members" "test" {
team_id = github_team.test.id

members {
username = "%s"
role = "maintainer"
}
}
`, teamName, testAccConf.testOrgUser)

resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessHasOrgs(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Comment thread
nitinjain999 marked this conversation as resolved.
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("github_team_members.test", "members.#", "1"),
),
},
{
// Delete the team out-of-band so it is gone before Terraform runs its destroy.
// The github_team_members delete should no-op instead of returning a 404 error.
PreConfig: func() {
meta, err := getTestMeta()
if err != nil {
t.Fatal(err.Error())
}
ctx := context.Background()
if _, err := meta.v3client.Teams.DeleteTeamBySlug(ctx, meta.name, teamName); err != nil {
t.Fatalf("failed to delete team out-of-band: %s", err)
}
},
Config: config,
Destroy: true,
},
},
})
})
}

func testAccCheckGithubTeamMembersDestroy(s *terraform.State) error {
Expand Down