diff --git a/github/resource_github_organization_ruleset_test.go b/github/resource_github_organization_ruleset_test.go index d098c1ef3d..f70a9ad564 100644 --- a/github/resource_github_organization_ruleset_test.go +++ b/github/resource_github_organization_ruleset_test.go @@ -303,6 +303,23 @@ func TestGithubOrganizationRulesets(t *testing.T) { target = "branch" enforcement = "active" + bypass_actors { + actor_type = "DeployKey" + bypass_mode = "always" + } + + bypass_actors { + actor_id = 5 + actor_type = "RepositoryRole" + bypass_mode = "always" + } + + bypass_actors { + actor_id = 1 + actor_type = "OrganizationAdmin" + bypass_mode = "always" + } + conditions { ref_name { include = ["~ALL"] @@ -323,39 +340,147 @@ func TestGithubOrganizationRulesets(t *testing.T) { dismiss_stale_reviews_on_push = true require_last_push_approval = true } + } + } + `, randomID) - bypass_actors { - actor_type = "DeployKey" - bypass_mode = "always" - } + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.#", + "3", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.0.actor_type", + "DeployKey", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.0.bypass_mode", + "always", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.1.actor_id", + "5", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.1.actor_type", + "RepositoryRole", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.1.bypass_mode", + "always", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.2.actor_id", + "1", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.2.actor_type", + "OrganizationAdmin", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.2.bypass_mode", + "always", + ), + ) - bypass_actors { - actor_id = 5 - actor_type = "RepositoryRole" - bypass_mode = "always" - } + 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("with an enterprise account", func(t *testing.T) { + testCase(t, enterprise) + }) + + }) + + t.Run("Creates organization ruleset with all bypass_modes", func(t *testing.T) { - bypass_actors { - actor_id = 0 - actor_type = "OrganizationAdmin" - bypass_mode = "always" + config := fmt.Sprintf(` + resource "github_organization_ruleset" "test" { + name = "test-bypass-modes-%s" + target = "branch" + enforcement = "active" + + bypass_actors { + actor_id = 1 + actor_type = "OrganizationAdmin" + bypass_mode = "always" + } + + bypass_actors { + actor_id = 5 + actor_type = "RepositoryRole" + bypass_mode = "pull_request" + } + + bypass_actors { + actor_id = 2 + actor_type = "RepositoryRole" + bypass_mode = "exempt" + } + + conditions { + ref_name { + include = ["~ALL"] + exclude = [] } } + + rules { + creation = true + } } `, randomID) check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.#", + "3", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.0.actor_id", + "1", + ), resource.TestCheckResourceAttr( "github_organization_ruleset.test", "bypass_actors.0.actor_type", - "0", + "OrganizationAdmin", ), resource.TestCheckResourceAttr( - "github_organization_ruleset.test", "bypass_actors.1.actor_type", + "github_organization_ruleset.test", "bypass_actors.0.bypass_mode", + "always", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.1.actor_id", "5", ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.1.actor_type", + "RepositoryRole", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.1.bypass_mode", + "pull_request", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.2.actor_id", + "2", + ), resource.TestCheckResourceAttr( "github_organization_ruleset.test", "bypass_actors.2.actor_type", - "0", + "RepositoryRole", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.2.bypass_mode", + "exempt", ), ) @@ -378,4 +503,76 @@ func TestGithubOrganizationRulesets(t *testing.T) { }) + t.Run("Updates organization ruleset bypass_mode without error", func(t *testing.T) { + + config := fmt.Sprintf(` + resource "github_organization_ruleset" "test" { + name = "test-bypass-update-%s" + target = "branch" + enforcement = "active" + + bypass_actors { + actor_id = 1 + actor_type = "OrganizationAdmin" + bypass_mode = "always" + } + + conditions { + ref_name { + include = ["~ALL"] + exclude = [] + } + } + + rules { + creation = true + } + } + `, randomID) + + configUpdated := strings.Replace( + config, + `bypass_mode = "always"`, + `bypass_mode = "exempt"`, + 1, + ) + + checks := map[string]resource.TestCheckFunc{ + "before": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.0.bypass_mode", + "always", + ), + ), + "after": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.0.bypass_mode", + "exempt", + ), + ), + } + + 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: checks["before"], + }, + { + Config: configUpdated, + Check: checks["after"], + }, + }, + }) + } + + t.Run("with an enterprise account", func(t *testing.T) { + testCase(t, enterprise) + }) + + }) + } diff --git a/github/resource_github_repository_ruleset_test.go b/github/resource_github_repository_ruleset_test.go index 2ff1efc040..0c6570b870 100644 --- a/github/resource_github_repository_ruleset_test.go +++ b/github/resource_github_repository_ruleset_test.go @@ -675,6 +675,346 @@ func TestGithubRepositoryRulesets(t *testing.T) { }) + t.Run("Creates repository ruleset with all bypass_modes", func(t *testing.T) { + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "tf-acc-test-bypass-modes-%s" + description = "Terraform acceptance tests %[1]s" + auto_init = true + } + + resource "github_team" "test_always" { + name = "tf-acc-test-team-always-%[1]s" + description = "Terraform acc test team for always bypass" + } + + resource "github_team" "test_pull_request" { + name = "tf-acc-test-team-pr-%[1]s" + description = "Terraform acc test team for pull_request bypass" + } + + resource "github_team" "test_exempt" { + name = "tf-acc-test-team-exempt-%[1]s" + description = "Terraform acc test team for exempt bypass" + } + + resource "github_repository_ruleset" "test" { + name = "test-bypass-modes" + repository = github_repository.test.id + target = "branch" + enforcement = "active" + + bypass_actors { + actor_id = github_team.test_always.id + actor_type = "Team" + bypass_mode = "always" + } + + bypass_actors { + actor_id = github_team.test_pull_request.id + actor_type = "Team" + bypass_mode = "pull_request" + } + + bypass_actors { + actor_id = github_team.test_exempt.id + actor_type = "Team" + bypass_mode = "exempt" + } + + conditions { + ref_name { + include = ["~ALL"] + exclude = [] + } + } + + rules { + creation = true + } + } + `, randomID) + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.#", + "3", + ), + resource.TestCheckResourceAttrSet( + "github_repository_ruleset.test", "bypass_actors.0.actor_id", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.0.bypass_mode", + "always", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.0.actor_type", + "Team", + ), + resource.TestCheckResourceAttrSet( + "github_repository_ruleset.test", "bypass_actors.1.actor_id", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.1.bypass_mode", + "pull_request", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.1.actor_type", + "Team", + ), + resource.TestCheckResourceAttrSet( + "github_repository_ruleset.test", "bypass_actors.2.actor_id", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.2.bypass_mode", + "exempt", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.2.actor_type", + "Team", + ), + ) + + 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("with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + + t.Run("with an individual account", func(t *testing.T) { + t.Skip("bypass actors require organization resources") + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + + }) + + t.Run("Updates bypass_mode without error", func(t *testing.T) { + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "tf-acc-test-bypass-update-%s" + description = "Terraform acceptance tests %[1]s" + auto_init = true + } + + resource "github_team" "test" { + name = "tf-acc-test-team-update-%[1]s" + description = "Terraform acc test team" + } + + resource "github_repository_ruleset" "test" { + name = "test-bypass-update" + repository = github_repository.test.id + target = "branch" + enforcement = "active" + + bypass_actors { + actor_id = github_team.test.id + actor_type = "Team" + bypass_mode = "always" + } + + conditions { + ref_name { + include = ["~ALL"] + exclude = [] + } + } + + rules { + creation = true + } + } + `, randomID) + + configUpdated := strings.Replace( + config, + `bypass_mode = "always"`, + `bypass_mode = "exempt"`, + 1, + ) + + checks := map[string]resource.TestCheckFunc{ + "before": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.0.bypass_mode", + "always", + ), + ), + "after": resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.0.bypass_mode", + "exempt", + ), + ), + } + + 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: checks["before"], + }, + { + Config: configUpdated, + Check: checks["after"], + }, + }, + }) + } + + t.Run("with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + + t.Run("with an individual account", func(t *testing.T) { + t.Skip("bypass actors require organization resources") + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + + }) + + t.Run("Creates repository ruleset with different actor types and bypass modes", func(t *testing.T) { + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "tf-acc-test-actor-types-%s" + description = "Terraform acceptance tests %[1]s" + auto_init = true + } + + resource "github_team" "test" { + name = "tf-acc-test-team-actor-%[1]s" + description = "Terraform acc test team" + } + + resource "github_repository_ruleset" "test" { + name = "test-actor-types" + repository = github_repository.test.id + target = "branch" + enforcement = "active" + + bypass_actors { + actor_id = github_team.test.id + actor_type = "Team" + bypass_mode = "always" + } + + bypass_actors { + actor_id = 5 + actor_type = "RepositoryRole" + bypass_mode = "pull_request" + } + + bypass_actors { + actor_id = 1 + actor_type = "OrganizationAdmin" + bypass_mode = "exempt" + } + + conditions { + ref_name { + include = ["~ALL"] + exclude = [] + } + } + + rules { + creation = true + } + } + `, randomID) + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.#", + "3", + ), + resource.TestCheckResourceAttrSet( + "github_repository_ruleset.test", "bypass_actors.0.actor_id", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.0.actor_type", + "Team", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.0.bypass_mode", + "always", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.1.actor_id", + "5", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.1.actor_type", + "RepositoryRole", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.1.bypass_mode", + "pull_request", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.2.actor_id", + "1", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.2.actor_type", + "OrganizationAdmin", + ), + resource.TestCheckResourceAttr( + "github_repository_ruleset.test", "bypass_actors.2.bypass_mode", + "exempt", + ), + ) + + 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("with an anonymous account", func(t *testing.T) { + t.Skip("anonymous account not supported for this operation") + }) + + t.Run("with an individual account", func(t *testing.T) { + t.Skip("bypass actors require organization resources") + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + + }) + } func importRepositoryRulesetByResourcePaths(repoLogicalName, rulesetLogicalName string) resource.ImportStateIdFunc {