diff --git a/github/resource_github_organization_ruleset.go b/github/resource_github_organization_ruleset.go index 1a8a88817..daede5652 100644 --- a/github/resource_github_organization_ruleset.go +++ b/github/resource_github_organization_ruleset.go @@ -52,14 +52,14 @@ func resourceGithubOrganizationRuleset() *schema.Resource { Schema: map[string]*schema.Schema{ "actor_id": { Type: schema.TypeInt, - Required: true, - Description: "The ID of the actor that can bypass a ruleset. When `actor_type` is `OrganizationAdmin`, this should be set to `1`.", + Optional: true, + Default: nil, + Description: "The ID of the actor that can bypass a ruleset. When `actor_type` is `OrganizationAdmin`, this should be set to `1`. Some resources such as DeployKey do not have an ID and this should be omitted.", }, "actor_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{"RepositoryRole", "Team", "Integration", "OrganizationAdmin"}, false), - Description: "The type of actor that can bypass a ruleset. Can be one of: `RepositoryRole`, `Team`, `Integration`, `OrganizationAdmin`.", + Type: schema.TypeString, + Required: true, + Description: "The type of actor that can bypass a ruleset. See https://docs.github.com/en/rest/orgs/rules for more information", }, "bypass_mode": { Type: schema.TypeString, diff --git a/github/resource_github_organization_ruleset_test.go b/github/resource_github_organization_ruleset_test.go index 3b6530460..d098c1ef3 100644 --- a/github/resource_github_organization_ruleset_test.go +++ b/github/resource_github_organization_ruleset_test.go @@ -295,4 +295,87 @@ func TestGithubOrganizationRulesets(t *testing.T) { }) + t.Run("Creates and updates organization using bypasses", func(t *testing.T) { + + config := fmt.Sprintf(` + resource "github_organization_ruleset" "test" { + name = "test-%s" + target = "branch" + enforcement = "active" + + conditions { + ref_name { + include = ["~ALL"] + exclude = [] + } + } + + rules { + creation = true + update = true + deletion = true + required_linear_history = true + required_signatures = false + pull_request { + required_approving_review_count = 2 + required_review_thread_resolution = true + require_code_owner_review = true + dismiss_stale_reviews_on_push = true + require_last_push_approval = true + } + + bypass_actors { + actor_type = "DeployKey" + bypass_mode = "always" + } + + bypass_actors { + actor_id = 5 + actor_type = "RepositoryRole" + bypass_mode = "always" + } + + bypass_actors { + actor_id = 0 + actor_type = "OrganizationAdmin" + bypass_mode = "always" + } + } + } + `, randomID) + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.0.actor_type", + "0", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.1.actor_type", + "5", + ), + resource.TestCheckResourceAttr( + "github_organization_ruleset.test", "bypass_actors.2.actor_type", + "0", + ), + ) + + 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) + }) + + }) + } diff --git a/github/resource_github_repository_ruleset.go b/github/resource_github_repository_ruleset.go index e5f8cbbf4..a5b4034b1 100644 --- a/github/resource_github_repository_ruleset.go +++ b/github/resource_github_repository_ruleset.go @@ -57,14 +57,15 @@ func resourceGithubRepositoryRuleset() *schema.Resource { Schema: map[string]*schema.Schema{ "actor_id": { Type: schema.TypeInt, - Required: true, - Description: "The ID of the actor that can bypass a ruleset. When `actor_type` is `OrganizationAdmin`, this should be set to `1`.", + Optional: true, + Default: nil, + Description: "The ID of the actor that can bypass a ruleset. When `actor_type` is `OrganizationAdmin`, this should be set to `1`. Some resources such as DeployKey do not have an ID and this should be omitted.", }, "actor_type": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringInSlice([]string{"RepositoryRole", "Team", "Integration", "OrganizationAdmin"}, false), - Description: "The type of actor that can bypass a ruleset. Can be one of: `RepositoryRole`, `Team`, `Integration`, `OrganizationAdmin`.", + ValidateFunc: validation.StringInSlice([]string{"RepositoryRole", "Team", "Integration", "OrganizationAdmin", "DeployKey"}, false), + Description: "The type of actor that can bypass a ruleset. See https://docs.github.com/en/rest/repos/rules for more information.", }, "bypass_mode": { Type: schema.TypeString, diff --git a/github/respository_rules_utils.go b/github/respository_rules_utils.go index 1b798be6d..6a5da6a48 100644 --- a/github/respository_rules_utils.go +++ b/github/respository_rules_utils.go @@ -44,7 +44,11 @@ func expandBypassActors(input []interface{}) []*github.BypassActor { inputMap := v.(map[string]interface{}) actor := &github.BypassActor{} if v, ok := inputMap["actor_id"].(int); ok { - actor.ActorID = github.Int64(int64(v)) + if v == 0 { + actor.ActorID = nil + } else { + actor.ActorID = github.Int64(int64(v)) + } } if v, ok := inputMap["actor_type"].(string); ok { diff --git a/website/docs/r/repository_ruleset.html.markdown b/website/docs/r/repository_ruleset.html.markdown index 2104d5434..2bf7a1f08 100644 --- a/website/docs/r/repository_ruleset.html.markdown +++ b/website/docs/r/repository_ruleset.html.markdown @@ -256,9 +256,9 @@ The `rules` block supports the following: #### bypass_actors #### -* `actor_id` - (Required) (Number) The ID of the actor that can bypass a ruleset. If `actor_type` is `Integration`, `actor_id` is a GitHub App ID. App ID can be obtained by following instructions from the [Get an App API docs](https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#get-an-app) +* `actor_id` - (Number) The ID of the actor that can bypass a ruleset. If `actor_type` is `Integration`, `actor_id` is a GitHub App ID. App ID can be obtained by following instructions from the [Get an App API docs](https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#get-an-app) -* `actor_type` (String) The type of actor that can bypass a ruleset. Can be one of: `RepositoryRole`, `Team`, `Integration`, `OrganizationAdmin`. +* `actor_type` (String) The type of actor that can bypass a ruleset. Can be one of: `RepositoryRole`, `Team`, `Integration`, `OrganizationAdmin`, `DeployKey`. * `bypass_mode` - (Optional) (String) When the specified actor can bypass the ruleset. pull_request means that an actor can only bypass rules on pull requests. Can be one of: `always`, `pull_request`, `exempt`.