From ee8e99aec08e70b67198e2dc511c87c98bca9763 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 14 Jul 2026 17:18:18 +0300 Subject: [PATCH 1/5] Ensure that set elements are only considered different if username changes Signed-off-by: Timo Sand --- github/resource_github_team_members.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/github/resource_github_team_members.go b/github/resource_github_team_members.go index e56bf0ac38..63a6899d45 100644 --- a/github/resource_github_team_members.go +++ b/github/resource_github_team_members.go @@ -63,6 +63,10 @@ func resourceGithubTeamMembers() *schema.Resource { Type: schema.TypeSet, Required: true, Description: "List of users that should be members of the team.", + Set: func(v any) int { + username := v.(map[string]any)["username"].(string) + return schema.HashString(strings.ToLower(username)) + }, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "username": { From 3ce6b458dece456818432ff6dfc14f86962eff43 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 14 Jul 2026 17:20:42 +0300 Subject: [PATCH 2/5] Replace diff suppression with statefunc which stores username as lowercase Signed-off-by: Timo Sand --- github/resource_github_team_members.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/github/resource_github_team_members.go b/github/resource_github_team_members.go index 63a6899d45..af659f5121 100644 --- a/github/resource_github_team_members.go +++ b/github/resource_github_team_members.go @@ -64,16 +64,19 @@ func resourceGithubTeamMembers() *schema.Resource { Required: true, Description: "List of users that should be members of the team.", Set: func(v any) int { - username := v.(map[string]any)["username"].(string) + username, _ := v.(map[string]any)["username"].(string) return schema.HashString(strings.ToLower(username)) }, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "username": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: caseInsensitive(), - Description: "User to add to the team.", + Type: schema.TypeString, + Required: true, + StateFunc: func(v any) string { + val, _ := v.(string) + return strings.ToLower(val) + }, + Description: "User to add to the team.", }, "role": { Type: schema.TypeString, From b2a82f468ba35999bb6a0f5c5a85fec6519ac1da Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 14 Jul 2026 21:11:08 +0300 Subject: [PATCH 3/5] Add test for case insensitivity Signed-off-by: Timo Sand --- github/resource_github_team_members_test.go | 64 +++++++++++++++++---- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/github/resource_github_team_members_test.go b/github/resource_github_team_members_test.go index fcb6e10253..47669000c2 100644 --- a/github/resource_github_team_members_test.go +++ b/github/resource_github_team_members_test.go @@ -3,6 +3,7 @@ package github import ( "fmt" "strconv" + "strings" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -18,6 +19,7 @@ func TestAccGithubTeamMembers(t *testing.T) { skipUnlessHasOrgs(t) skipUnlessHasOrgUser1(t) + flippedCaseUsername := flipUsernameCase(testAccConf.testOrgUser1) t.Run("team_by_slug", func(t *testing.T) { t.Parallel() @@ -33,7 +35,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetSlug(), testAccConf.testOrgUser1) +`, team.GetSlug(), flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -71,7 +73,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetSlug(), testAccConf.testOrgUser1) +`, team.GetSlug(), flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -110,7 +112,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetID(), testAccConf.testOrgUser1) +`, team.GetID(), flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -148,7 +150,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetSlug(), testAccConf.testOrgUser1) +`, team.GetSlug(), flippedCaseUsername) configMigrate := fmt.Sprintf(` resource "github_team_members" "test" { @@ -159,7 +161,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetSlug(), testAccConf.testOrgUser1) +`, team.GetSlug(), flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -201,7 +203,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetID(), testAccConf.testOrgUser1) +`, team.GetID(), flippedCaseUsername) configMigrate := fmt.Sprintf(` resource "github_team_members" "test" { @@ -212,7 +214,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetSlug(), testAccConf.testOrgUser1) +`, team.GetSlug(), flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -257,7 +259,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetSlug(), testAccConf.testOrgUser1) +`, team.GetSlug(), flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -296,7 +298,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetSlug(), testAccConf.testOrgUser1) +`, team.GetSlug(), flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -326,7 +328,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, testAccConf.testOrgUser1) +`, flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -364,7 +366,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, team.GetSlug(), testAccConf.testOrgUser1) +`, team.GetSlug(), flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -403,7 +405,7 @@ resource "github_team_members" "test" { role = "maintainer" } } -`, testAccConf.testOrgUser1) +`, flippedCaseUsername) resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -430,4 +432,42 @@ resource "github_team_members" "test" { }, }) }) + + t.Run("is_case_insensitive", func(t *testing.T) { + t.Parallel() + + team := mustCreateTestTeam(t, nil) + + config := fmt.Sprintf(` +resource "github_team_members" "test" { + team_slug = "%s" + + members { + username = "%%s" + role = "maintainer" + } +} +`, team.GetSlug()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessHasOrgs(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(config, flippedCaseUsername), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members"), knownvalue.SetSizeExact(1)), + statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members").AtSliceIndex(0).AtMapKey("username"), knownvalue.StringExact(strings.ToLower(testAccConf.testOrgUser1))), + }, + }, + { + Config: fmt.Sprintf(config, testAccConf.testOrgUser1), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members"), knownvalue.SetSizeExact(1)), + statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members").AtSliceIndex(0).AtMapKey("username"), knownvalue.StringExact(strings.ToLower(testAccConf.testOrgUser1))), + }, + }, + }, + }) + }) } From 8fc4fc092ebdce2a32f9a4948932a819f1b1f1bd Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 14 Jul 2026 21:12:58 +0300 Subject: [PATCH 4/5] re-adds DiffSuppressFunc Signed-off-by: Timo Sand --- github/resource_github_team_members.go | 5 +++-- github/resource_github_team_members_test.go | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/github/resource_github_team_members.go b/github/resource_github_team_members.go index af659f5121..c11aff9a89 100644 --- a/github/resource_github_team_members.go +++ b/github/resource_github_team_members.go @@ -70,8 +70,9 @@ func resourceGithubTeamMembers() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "username": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: caseInsensitive(), StateFunc: func(v any) string { val, _ := v.(string) return strings.ToLower(val) diff --git a/github/resource_github_team_members_test.go b/github/resource_github_team_members_test.go index 47669000c2..c54b63f5ee 100644 --- a/github/resource_github_team_members_test.go +++ b/github/resource_github_team_members_test.go @@ -462,6 +462,11 @@ resource "github_team_members" "test" { }, { Config: fmt.Sprintf(config, testAccConf.testOrgUser1), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("github_team_members.test", plancheck.ResourceActionNoop), + }, + }, ConfigStateChecks: []statecheck.StateCheck{ statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members"), knownvalue.SetSizeExact(1)), statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members").AtSliceIndex(0).AtMapKey("username"), knownvalue.StringExact(strings.ToLower(testAccConf.testOrgUser1))), From a2d55337f2fa788843e37363569acf920b316fdb Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 14 Jul 2026 21:17:27 +0300 Subject: [PATCH 5/5] Adds username comparer to test Signed-off-by: Timo Sand --- github/resource_github_team_members_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/github/resource_github_team_members_test.go b/github/resource_github_team_members_test.go index c54b63f5ee..6cc011f7c7 100644 --- a/github/resource_github_team_members_test.go +++ b/github/resource_github_team_members_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/hashicorp/terraform-plugin-testing/compare" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/knownvalue" "github.com/hashicorp/terraform-plugin-testing/plancheck" @@ -449,6 +450,7 @@ resource "github_team_members" "test" { } `, team.GetSlug()) + usernameIsSameComparer := statecheck.CompareValue(compare.ValuesSame()) resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, @@ -456,6 +458,7 @@ resource "github_team_members" "test" { { Config: fmt.Sprintf(config, flippedCaseUsername), ConfigStateChecks: []statecheck.StateCheck{ + usernameIsSameComparer.AddStateValue("github_team_members.test", tfjsonpath.New("members").AtSliceIndex(0).AtMapKey("username")), statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members"), knownvalue.SetSizeExact(1)), statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members").AtSliceIndex(0).AtMapKey("username"), knownvalue.StringExact(strings.ToLower(testAccConf.testOrgUser1))), }, @@ -468,8 +471,8 @@ resource "github_team_members" "test" { }, }, ConfigStateChecks: []statecheck.StateCheck{ + usernameIsSameComparer.AddStateValue("github_team_members.test", tfjsonpath.New("members").AtSliceIndex(0).AtMapKey("username")), statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members"), knownvalue.SetSizeExact(1)), - statecheck.ExpectKnownValue("github_team_members.test", tfjsonpath.New("members").AtSliceIndex(0).AtMapKey("username"), knownvalue.StringExact(strings.ToLower(testAccConf.testOrgUser1))), }, }, },