diff --git a/github/resource_github_organization_settings.go b/github/resource_github_organization_settings.go index 7eddd96b9..1222edb2a 100644 --- a/github/resource_github_organization_settings.go +++ b/github/resource_github_organization_settings.go @@ -172,6 +172,101 @@ func resourceGithubOrganizationSettings() *schema.Resource { } } +// buildOrganizationSettings creates a github.Organization struct with only the fields that are explicitly configured +func buildOrganizationSettings(d *schema.ResourceData, isEnterprise bool) *github.Organization { + settings := &github.Organization{} + + // Required field + if billingEmail, ok := d.GetOk("billing_email"); ok { + settings.BillingEmail = github.String(billingEmail.(string)) + } + + // Optional string fields - only set if explicitly configured + if company, ok := d.GetOk("company"); ok { + settings.Company = github.String(company.(string)) + } + if email, ok := d.GetOk("email"); ok { + settings.Email = github.String(email.(string)) + } + if twitterUsername, ok := d.GetOk("twitter_username"); ok { + settings.TwitterUsername = github.String(twitterUsername.(string)) + } + if location, ok := d.GetOk("location"); ok { + settings.Location = github.String(location.(string)) + } + if name, ok := d.GetOk("name"); ok { + settings.Name = github.String(name.(string)) + } + if description, ok := d.GetOk("description"); ok { + settings.Description = github.String(description.(string)) + } + if blog, ok := d.GetOk("blog"); ok { + settings.Blog = github.String(blog.(string)) + } + + // Boolean fields - only set if explicitly configured + if hasOrgProjects, ok := d.GetOk("has_organization_projects"); ok { + settings.HasOrganizationProjects = github.Bool(hasOrgProjects.(bool)) + } + if hasRepoProjects, ok := d.GetOk("has_repository_projects"); ok { + settings.HasRepositoryProjects = github.Bool(hasRepoProjects.(bool)) + } + if defaultRepoPermission, ok := d.GetOk("default_repository_permission"); ok { + settings.DefaultRepoPermission = github.String(defaultRepoPermission.(string)) + } + if membersCanCreateRepos, ok := d.GetOk("members_can_create_repositories"); ok { + settings.MembersCanCreateRepos = github.Bool(membersCanCreateRepos.(bool)) + } + if _, exists := d.GetOkExists("members_can_create_private_repositories"); exists { + settings.MembersCanCreatePrivateRepos = github.Bool(d.Get("members_can_create_private_repositories").(bool)) + } + if membersCanCreatePublicRepos, ok := d.GetOk("members_can_create_public_repositories"); ok { + settings.MembersCanCreatePublicRepos = github.Bool(membersCanCreatePublicRepos.(bool)) + } + if membersCanCreatePages, ok := d.GetOk("members_can_create_pages"); ok { + settings.MembersCanCreatePages = github.Bool(membersCanCreatePages.(bool)) + } + if membersCanCreatePublicPages, ok := d.GetOk("members_can_create_public_pages"); ok { + settings.MembersCanCreatePublicPages = github.Bool(membersCanCreatePublicPages.(bool)) + } + if membersCanCreatePrivatePages, ok := d.GetOk("members_can_create_private_pages"); ok { + settings.MembersCanCreatePrivatePages = github.Bool(membersCanCreatePrivatePages.(bool)) + } + if membersCanForkPrivateRepos, ok := d.GetOk("members_can_fork_private_repositories"); ok { + settings.MembersCanForkPrivateRepos = github.Bool(membersCanForkPrivateRepos.(bool)) + } + if webCommitSignoffRequired, ok := d.GetOk("web_commit_signoff_required"); ok { + settings.WebCommitSignoffRequired = github.Bool(webCommitSignoffRequired.(bool)) + } + if advancedSecurityEnabled, ok := d.GetOk("advanced_security_enabled_for_new_repositories"); ok { + settings.AdvancedSecurityEnabledForNewRepos = github.Bool(advancedSecurityEnabled.(bool)) + } + if dependabotAlertsEnabled, ok := d.GetOk("dependabot_alerts_enabled_for_new_repositories"); ok { + settings.DependabotAlertsEnabledForNewRepos = github.Bool(dependabotAlertsEnabled.(bool)) + } + if dependabotSecurityUpdatesEnabled, ok := d.GetOk("dependabot_security_updates_enabled_for_new_repositories"); ok { + settings.DependabotSecurityUpdatesEnabledForNewRepos = github.Bool(dependabotSecurityUpdatesEnabled.(bool)) + } + if dependencyGraphEnabled, ok := d.GetOk("dependency_graph_enabled_for_new_repositories"); ok { + settings.DependencyGraphEnabledForNewRepos = github.Bool(dependencyGraphEnabled.(bool)) + } + if secretScanningEnabled, ok := d.GetOk("secret_scanning_enabled_for_new_repositories"); ok { + settings.SecretScanningEnabledForNewRepos = github.Bool(secretScanningEnabled.(bool)) + } + if secretScanningPushProtectionEnabled, ok := d.GetOk("secret_scanning_push_protection_enabled_for_new_repositories"); ok { + settings.SecretScanningPushProtectionEnabledForNewRepos = github.Bool(secretScanningPushProtectionEnabled.(bool)) + } + + // Enterprise-specific field + if isEnterprise { + if _, exists := d.GetOkExists("members_can_create_internal_repositories"); exists { + settings.MembersCanCreateInternalRepos = github.Bool(d.Get("members_can_create_internal_repositories").(bool)) + } + } + + return settings +} + func resourceGithubOrganizationSettingsCreateOrUpdate(d *schema.ResourceData, meta interface{}) error { err := checkOrganization(meta) if err != nil { @@ -181,120 +276,21 @@ func resourceGithubOrganizationSettingsCreateOrUpdate(d *schema.ResourceData, me ctx := context.WithValue(context.Background(), ctxId, d.Id()) org := meta.(*Owner).name - settings := github.Organization{ - BillingEmail: github.String(d.Get("billing_email").(string)), - Company: github.String(d.Get("company").(string)), - Email: github.String(d.Get("email").(string)), - TwitterUsername: github.String(d.Get("twitter_username").(string)), - Location: github.String(d.Get("location").(string)), - Name: github.String(d.Get("name").(string)), - Description: github.String(d.Get("description").(string)), - HasOrganizationProjects: github.Bool(d.Get("has_organization_projects").(bool)), - HasRepositoryProjects: github.Bool(d.Get("has_repository_projects").(bool)), - DefaultRepoPermission: github.String(d.Get("default_repository_permission").(string)), - MembersCanCreateRepos: github.Bool(d.Get("members_can_create_repositories").(bool)), - MembersCanCreatePrivateRepos: github.Bool(d.Get("members_can_create_private_repositories").(bool)), - MembersCanCreatePublicRepos: github.Bool(d.Get("members_can_create_public_repositories").(bool)), - MembersCanCreatePages: github.Bool(d.Get("members_can_create_pages").(bool)), - MembersCanCreatePublicPages: github.Bool(d.Get("members_can_create_public_pages").(bool)), - MembersCanCreatePrivatePages: github.Bool(d.Get("members_can_create_private_pages").(bool)), - MembersCanForkPrivateRepos: github.Bool(d.Get("members_can_fork_private_repositories").(bool)), - WebCommitSignoffRequired: github.Bool(d.Get("web_commit_signoff_required").(bool)), - Blog: github.String(d.Get("blog").(string)), - AdvancedSecurityEnabledForNewRepos: github.Bool(d.Get("advanced_security_enabled_for_new_repositories").(bool)), - DependabotAlertsEnabledForNewRepos: github.Bool(d.Get("dependabot_alerts_enabled_for_new_repositories").(bool)), - DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(d.Get("dependabot_security_updates_enabled_for_new_repositories").(bool)), - DependencyGraphEnabledForNewRepos: github.Bool(d.Get("dependency_graph_enabled_for_new_repositories").(bool)), - SecretScanningEnabledForNewRepos: github.Bool(d.Get("secret_scanning_enabled_for_new_repositories").(bool)), - SecretScanningPushProtectionEnabledForNewRepos: github.Bool(d.Get("secret_scanning_push_protection_enabled_for_new_repositories").(bool)), - } - - enterpriseSettings := github.Organization{ - BillingEmail: github.String(d.Get("billing_email").(string)), - Company: github.String(d.Get("company").(string)), - Email: github.String(d.Get("email").(string)), - TwitterUsername: github.String(d.Get("twitter_username").(string)), - Location: github.String(d.Get("location").(string)), - Name: github.String(d.Get("name").(string)), - Description: github.String(d.Get("description").(string)), - HasOrganizationProjects: github.Bool(d.Get("has_organization_projects").(bool)), - HasRepositoryProjects: github.Bool(d.Get("has_repository_projects").(bool)), - DefaultRepoPermission: github.String(d.Get("default_repository_permission").(string)), - MembersCanCreateRepos: github.Bool(d.Get("members_can_create_repositories").(bool)), - MembersCanCreateInternalRepos: github.Bool(d.Get("members_can_create_internal_repositories").(bool)), - MembersCanCreatePrivateRepos: github.Bool(d.Get("members_can_create_private_repositories").(bool)), - MembersCanCreatePublicRepos: github.Bool(d.Get("members_can_create_public_repositories").(bool)), - MembersCanCreatePages: github.Bool(d.Get("members_can_create_pages").(bool)), - MembersCanCreatePublicPages: github.Bool(d.Get("members_can_create_public_pages").(bool)), - MembersCanCreatePrivatePages: github.Bool(d.Get("members_can_create_private_pages").(bool)), - MembersCanForkPrivateRepos: github.Bool(d.Get("members_can_fork_private_repositories").(bool)), - WebCommitSignoffRequired: github.Bool(d.Get("web_commit_signoff_required").(bool)), - Blog: github.String(d.Get("blog").(string)), - AdvancedSecurityEnabledForNewRepos: github.Bool(d.Get("advanced_security_enabled_for_new_repositories").(bool)), - DependabotAlertsEnabledForNewRepos: github.Bool(d.Get("dependabot_alerts_enabled_for_new_repositories").(bool)), - DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(d.Get("dependabot_security_updates_enabled_for_new_repositories").(bool)), - DependencyGraphEnabledForNewRepos: github.Bool(d.Get("dependency_graph_enabled_for_new_repositories").(bool)), - SecretScanningEnabledForNewRepos: github.Bool(d.Get("secret_scanning_enabled_for_new_repositories").(bool)), - SecretScanningPushProtectionEnabledForNewRepos: github.Bool(d.Get("secret_scanning_push_protection_enabled_for_new_repositories").(bool)), + orgInfo, _, err := client.Organizations.Get(ctx, org) + if err != nil { + return err } - enterpriseSettingsNoFork := github.Organization{ - BillingEmail: github.String(d.Get("billing_email").(string)), - Company: github.String(d.Get("company").(string)), - Email: github.String(d.Get("email").(string)), - TwitterUsername: github.String(d.Get("twitter_username").(string)), - Location: github.String(d.Get("location").(string)), - Name: github.String(d.Get("name").(string)), - Description: github.String(d.Get("description").(string)), - HasOrganizationProjects: github.Bool(d.Get("has_organization_projects").(bool)), - HasRepositoryProjects: github.Bool(d.Get("has_repository_projects").(bool)), - DefaultRepoPermission: github.String(d.Get("default_repository_permission").(string)), - MembersCanCreateRepos: github.Bool(d.Get("members_can_create_repositories").(bool)), - MembersCanCreateInternalRepos: github.Bool(d.Get("members_can_create_internal_repositories").(bool)), - MembersCanCreatePrivateRepos: github.Bool(d.Get("members_can_create_private_repositories").(bool)), - MembersCanCreatePublicRepos: github.Bool(d.Get("members_can_create_public_repositories").(bool)), - MembersCanCreatePages: github.Bool(d.Get("members_can_create_pages").(bool)), - MembersCanCreatePublicPages: github.Bool(d.Get("members_can_create_public_pages").(bool)), - MembersCanCreatePrivatePages: github.Bool(d.Get("members_can_create_private_pages").(bool)), - WebCommitSignoffRequired: github.Bool(d.Get("web_commit_signoff_required").(bool)), - Blog: github.String(d.Get("blog").(string)), - AdvancedSecurityEnabledForNewRepos: github.Bool(d.Get("advanced_security_enabled_for_new_repositories").(bool)), - DependabotAlertsEnabledForNewRepos: github.Bool(d.Get("dependabot_alerts_enabled_for_new_repositories").(bool)), - DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(d.Get("dependabot_security_updates_enabled_for_new_repositories").(bool)), - DependencyGraphEnabledForNewRepos: github.Bool(d.Get("dependency_graph_enabled_for_new_repositories").(bool)), - SecretScanningEnabledForNewRepos: github.Bool(d.Get("secret_scanning_enabled_for_new_repositories").(bool)), - SecretScanningPushProtectionEnabledForNewRepos: github.Bool(d.Get("secret_scanning_push_protection_enabled_for_new_repositories").(bool)), - } + // Build settings using helper function + isEnterprise := orgInfo.GetPlan().GetName() == "enterprise" + settings := buildOrganizationSettings(d, isEnterprise) - orgPlan, _, err := client.Organizations.Edit(ctx, org, nil) + orgSettings, _, err := client.Organizations.Edit(ctx, org, settings) if err != nil { return err } - - if orgPlan.GetPlan().GetName() == "enterprise" { - if _, ok := d.GetOk("members_can_fork_private_repositories"); !ok { - orgSettings, _, err := client.Organizations.Edit(ctx, org, &enterpriseSettingsNoFork) - if err != nil { - return err - } - id := strconv.FormatInt(orgSettings.GetID(), 10) - d.SetId(id) - } else if _, ok := d.GetOk("members_can_fork_private_repositories"); ok { - orgSettings, _, err := client.Organizations.Edit(ctx, org, &enterpriseSettings) - if err != nil { - return err - } - id := strconv.FormatInt(orgSettings.GetID(), 10) - d.SetId(id) - } - } else { - orgSettings, _, err := client.Organizations.Edit(ctx, org, &settings) - if err != nil { - return err - } - id := strconv.FormatInt(orgSettings.GetID(), 10) - d.SetId(id) - } + id := strconv.FormatInt(orgSettings.GetID(), 10) + d.SetId(id) return resourceGithubOrganizationSettingsRead(d, meta) } @@ -404,115 +400,29 @@ func resourceGithubOrganizationSettingsDelete(d *schema.ResourceData, meta inter ctx := context.WithValue(context.Background(), ctxId, d.Id()) org := meta.(*Owner).name - // This will set org settings to default values - settings := github.Organization{ - BillingEmail: github.String("email@example.com"), - Company: github.String(""), - Email: github.String(""), - TwitterUsername: github.String(""), - Location: github.String(""), - Name: github.String(""), - Description: github.String(""), - HasOrganizationProjects: github.Bool(true), - HasRepositoryProjects: github.Bool(true), - DefaultRepoPermission: github.String("read"), - MembersCanCreateRepos: github.Bool(true), - MembersCanCreatePrivateRepos: github.Bool(true), - MembersCanCreatePublicRepos: github.Bool(true), - MembersCanCreatePages: github.Bool(false), - MembersCanCreatePublicPages: github.Bool(true), - MembersCanCreatePrivatePages: github.Bool(true), - MembersCanForkPrivateRepos: github.Bool(false), - WebCommitSignoffRequired: github.Bool(false), - Blog: github.String(""), - AdvancedSecurityEnabledForNewRepos: github.Bool(false), - DependabotAlertsEnabledForNewRepos: github.Bool(false), - DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(false), - DependencyGraphEnabledForNewRepos: github.Bool(false), - SecretScanningEnabledForNewRepos: github.Bool(false), - SecretScanningPushProtectionEnabledForNewRepos: github.Bool(false), + log.Printf("[DEBUG] Reverting Organization Settings to default values: %s", org) + + // Get organization info to determine if it's enterprise + orgInfo, _, err := client.Organizations.Get(ctx, org) + if err != nil { + return err } - enterpriseSettings := github.Organization{ - BillingEmail: github.String("email@example.com"), - Company: github.String(""), - Email: github.String(""), - TwitterUsername: github.String(""), - Location: github.String(""), - Name: github.String(""), - Description: github.String(""), - HasOrganizationProjects: github.Bool(true), - HasRepositoryProjects: github.Bool(true), - DefaultRepoPermission: github.String("read"), - MembersCanCreateRepos: github.Bool(true), - MembersCanCreatePrivateRepos: github.Bool(true), - MembersCanCreateInternalRepos: github.Bool(true), - MembersCanCreatePublicRepos: github.Bool(true), - MembersCanCreatePages: github.Bool(false), - MembersCanCreatePublicPages: github.Bool(true), - MembersCanCreatePrivatePages: github.Bool(true), - MembersCanForkPrivateRepos: github.Bool(false), - WebCommitSignoffRequired: github.Bool(false), - Blog: github.String(""), - AdvancedSecurityEnabledForNewRepos: github.Bool(false), - DependabotAlertsEnabledForNewRepos: github.Bool(false), - DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(false), - DependencyGraphEnabledForNewRepos: github.Bool(false), - SecretScanningEnabledForNewRepos: github.Bool(false), - SecretScanningPushProtectionEnabledForNewRepos: github.Bool(false), + // Build minimal settings with only required fields + isEnterprise := orgInfo.GetPlan().GetName() == "enterprise" + defaultSettings := &github.Organization{ + BillingEmail: github.String("email@example.com"), } - enterpriseSettingsNoFork := github.Organization{ - BillingEmail: github.String("email@example.com"), - Company: github.String(""), - Email: github.String(""), - TwitterUsername: github.String(""), - Location: github.String(""), - Name: github.String(""), - Description: github.String(""), - HasOrganizationProjects: github.Bool(true), - HasRepositoryProjects: github.Bool(true), - DefaultRepoPermission: github.String("read"), - MembersCanCreateRepos: github.Bool(true), - MembersCanCreatePrivateRepos: github.Bool(true), - MembersCanCreateInternalRepos: github.Bool(true), - MembersCanCreatePublicRepos: github.Bool(true), - MembersCanCreatePages: github.Bool(false), - MembersCanCreatePublicPages: github.Bool(true), - MembersCanCreatePrivatePages: github.Bool(true), - WebCommitSignoffRequired: github.Bool(false), - Blog: github.String(""), - AdvancedSecurityEnabledForNewRepos: github.Bool(false), - DependabotAlertsEnabledForNewRepos: github.Bool(false), - DependabotSecurityUpdatesEnabledForNewRepos: github.Bool(false), - DependencyGraphEnabledForNewRepos: github.Bool(false), - SecretScanningEnabledForNewRepos: github.Bool(false), - SecretScanningPushProtectionEnabledForNewRepos: github.Bool(false), + // Only add enterprise-specific fields if it's an enterprise org + if isEnterprise { + defaultSettings.MembersCanCreateInternalRepos = github.Bool(true) } - log.Printf("[DEBUG] Reverting Organization Settings to default values: %s", org) - orgPlan, _, err := client.Organizations.Edit(ctx, org, nil) + _, _, err = client.Organizations.Edit(ctx, org, defaultSettings) if err != nil { return err } - if orgPlan.GetPlan().GetName() == "enterprise" { - if _, ok := d.GetOk("members_can_fork_private_repositories"); !ok { - _, _, err := client.Organizations.Edit(ctx, org, &enterpriseSettingsNoFork) - if err != nil { - return err - } - } else if _, ok := d.GetOk("members_can_fork_private_repositories"); ok { - _, _, err := client.Organizations.Edit(ctx, org, &enterpriseSettings) - if err != nil { - return err - } - } - } else { - _, _, err := client.Organizations.Edit(ctx, org, &settings) - if err != nil { - return err - } - } return nil } diff --git a/github/resource_github_organization_settings_test.go b/github/resource_github_organization_settings_test.go index c0b6a8b20..115a396fb 100644 --- a/github/resource_github_organization_settings_test.go +++ b/github/resource_github_organization_settings_test.go @@ -180,4 +180,580 @@ func TestAccGithubOrganizationSettings(t *testing.T) { testCase(t, organization) }) }) + + t.Run("handles boolean false values correctly", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + members_can_create_private_repositories = false + members_can_create_internal_repositories = false + members_can_fork_private_repositories = false + web_commit_signoff_required = false + advanced_security_enabled_for_new_repositories = false + dependabot_alerts_enabled_for_new_repositories = false + dependabot_security_updates_enabled_for_new_repositories = false + dependency_graph_enabled_for_new_repositories = false + secret_scanning_enabled_for_new_repositories = false + secret_scanning_push_protection_enabled_for_new_repositories = false + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "billing_email", "test@example.com", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "members_can_create_private_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "members_can_create_internal_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "members_can_fork_private_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "web_commit_signoff_required", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "advanced_security_enabled_for_new_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "dependabot_alerts_enabled_for_new_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "dependabot_security_updates_enabled_for_new_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "dependency_graph_enabled_for_new_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "secret_scanning_enabled_for_new_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "secret_scanning_push_protection_enabled_for_new_repositories", "false", + ), + ) + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + }) + } + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) + + t.Run("handles mixed boolean values correctly", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + members_can_create_private_repositories = false + members_can_create_internal_repositories = true + members_can_fork_private_repositories = false + web_commit_signoff_required = true + advanced_security_enabled_for_new_repositories = false + dependabot_alerts_enabled_for_new_repositories = true + dependabot_security_updates_enabled_for_new_repositories = false + dependency_graph_enabled_for_new_repositories = true + secret_scanning_enabled_for_new_repositories = false + secret_scanning_push_protection_enabled_for_new_repositories = true + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "billing_email", "test@example.com", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "members_can_create_private_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "members_can_create_internal_repositories", "true", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "members_can_fork_private_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "web_commit_signoff_required", "true", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "advanced_security_enabled_for_new_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "dependabot_alerts_enabled_for_new_repositories", "true", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "dependabot_security_updates_enabled_for_new_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "dependency_graph_enabled_for_new_repositories", "true", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "secret_scanning_enabled_for_new_repositories", "false", + ), + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "secret_scanning_push_protection_enabled_for_new_repositories", "true", + ), + ) + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + }) + } + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) + + t.Run("handles minimal configuration without errors", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_settings.test", + "billing_email", "test@example.com", + ), + ) + testCase := func(t *testing.T, mode string) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, mode) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + }) + } + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) + + t.Run("comprehensive parameter testing", func(t *testing.T) { + t.Run("test all string fields", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + company = "Test Company" + email = "contact@test.com" + twitter_username = "testorg" + location = "Test City, Country" + name = "Test Organization" + description = "Test organization description" + blog = "https://test.com/blog" + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("github_organization_settings.test", "billing_email", "test@example.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "company", "Test Company"), + resource.TestCheckResourceAttr("github_organization_settings.test", "email", "contact@test.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "twitter_username", "testorg"), + resource.TestCheckResourceAttr("github_organization_settings.test", "location", "Test City, Country"), + resource.TestCheckResourceAttr("github_organization_settings.test", "name", "Test Organization"), + resource.TestCheckResourceAttr("github_organization_settings.test", "description", "Test organization description"), + resource.TestCheckResourceAttr("github_organization_settings.test", "blog", "https://test.com/blog"), + ) + + testCase := resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, organization) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + } + + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + resource.Test(t, testCase) + }) + }) + + t.Run("test all security boolean fields", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + advanced_security_enabled_for_new_repositories = true + dependabot_alerts_enabled_for_new_repositories = true + dependabot_security_updates_enabled_for_new_repositories = true + dependency_graph_enabled_for_new_repositories = true + secret_scanning_enabled_for_new_repositories = true + secret_scanning_push_protection_enabled_for_new_repositories = true + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("github_organization_settings.test", "billing_email", "test@example.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "advanced_security_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "dependabot_alerts_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "dependabot_security_updates_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "dependency_graph_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "secret_scanning_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "secret_scanning_push_protection_enabled_for_new_repositories", "true"), + ) + + testCase := resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, organization) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + } + + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + resource.Test(t, testCase) + }) + }) + + t.Run("test repository creation fields", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + members_can_create_private_repositories = true + members_can_create_internal_repositories = true + members_can_create_pages = true + members_can_create_public_pages = true + members_can_create_private_pages = true + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("github_organization_settings.test", "billing_email", "test@example.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_private_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_internal_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_pages", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_public_pages", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_private_pages", "true"), + ) + + testCase := resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, organization) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + } + + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + resource.Test(t, testCase) + }) + }) + + t.Run("test other boolean fields", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + web_commit_signoff_required = true + has_organization_projects = true + has_repository_projects = true + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("github_organization_settings.test", "billing_email", "test@example.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "web_commit_signoff_required", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "has_organization_projects", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "has_repository_projects", "true"), + ) + + testCase := resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, organization) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + } + + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + resource.Test(t, testCase) + }) + }) + + t.Run("test enum fields", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + default_repository_permission = "write" + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("github_organization_settings.test", "billing_email", "test@example.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "default_repository_permission", "write"), + ) + + testCase := resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, organization) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + } + + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + resource.Test(t, testCase) + }) + }) + + t.Run("test comprehensive configuration", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + company = "Test Company" + email = "contact@test.com" + twitter_username = "testorg" + location = "Test City, Country" + name = "Test Organization" + description = "Test organization description" + blog = "https://test.com/blog" + + advanced_security_enabled_for_new_repositories = true + dependabot_alerts_enabled_for_new_repositories = true + dependabot_security_updates_enabled_for_new_repositories = true + dependency_graph_enabled_for_new_repositories = true + secret_scanning_enabled_for_new_repositories = true + secret_scanning_push_protection_enabled_for_new_repositories = true + + members_can_create_private_repositories = true + members_can_create_internal_repositories = true + members_can_create_pages = true + members_can_create_public_pages = true + members_can_create_private_pages = true + + web_commit_signoff_required = true + default_repository_permission = "write" + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("github_organization_settings.test", "billing_email", "test@example.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "company", "Test Company"), + resource.TestCheckResourceAttr("github_organization_settings.test", "email", "contact@test.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "twitter_username", "testorg"), + resource.TestCheckResourceAttr("github_organization_settings.test", "location", "Test City, Country"), + resource.TestCheckResourceAttr("github_organization_settings.test", "name", "Test Organization"), + resource.TestCheckResourceAttr("github_organization_settings.test", "description", "Test organization description"), + resource.TestCheckResourceAttr("github_organization_settings.test", "blog", "https://test.com/blog"), + resource.TestCheckResourceAttr("github_organization_settings.test", "advanced_security_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "dependabot_alerts_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "dependabot_security_updates_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "dependency_graph_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "secret_scanning_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "secret_scanning_push_protection_enabled_for_new_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_private_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_internal_repositories", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_pages", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_public_pages", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_private_pages", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "web_commit_signoff_required", "true"), + resource.TestCheckResourceAttr("github_organization_settings.test", "default_repository_permission", "write"), + ) + + testCase := resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, organization) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + } + + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + resource.Test(t, testCase) + }) + }) + + t.Run("test boolean false values for all fields", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + advanced_security_enabled_for_new_repositories = false + dependabot_alerts_enabled_for_new_repositories = false + dependabot_security_updates_enabled_for_new_repositories = false + dependency_graph_enabled_for_new_repositories = false + secret_scanning_enabled_for_new_repositories = false + secret_scanning_push_protection_enabled_for_new_repositories = false + members_can_create_private_repositories = false + members_can_create_internal_repositories = false + members_can_create_pages = false + members_can_create_public_pages = false + members_can_create_private_pages = false + web_commit_signoff_required = false + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("github_organization_settings.test", "billing_email", "test@example.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "advanced_security_enabled_for_new_repositories", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "dependabot_alerts_enabled_for_new_repositories", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "dependabot_security_updates_enabled_for_new_repositories", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "dependency_graph_enabled_for_new_repositories", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "secret_scanning_enabled_for_new_repositories", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "secret_scanning_push_protection_enabled_for_new_repositories", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_private_repositories", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_internal_repositories", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_pages", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_public_pages", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "members_can_create_private_pages", "false"), + resource.TestCheckResourceAttr("github_organization_settings.test", "web_commit_signoff_required", "false"), + ) + + testCase := resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, organization) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + } + + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + resource.Test(t, testCase) + }) + }) + + t.Run("test enum field variations", func(t *testing.T) { + config := ` + resource "github_organization_settings" "test" { + billing_email = "test@example.com" + default_repository_permission = "admin" + }` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("github_organization_settings.test", "billing_email", "test@example.com"), + resource.TestCheckResourceAttr("github_organization_settings.test", "default_repository_permission", "admin"), + ) + + testCase := resource.TestCase{ + PreCheck: func() { skipUnlessMode(t, organization) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + } + + t.Run("run with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + t.Run("run with an individual account", func(t *testing.T) { + t.Skip("individual account not supported for this operation") + }) + t.Run("run with an organization account", func(t *testing.T) { + resource.Test(t, testCase) + }) + }) + }) }