diff --git a/github/resource_github_branch_protection.go b/github/resource_github_branch_protection.go index ed2d24b300..211c4419cd 100644 --- a/github/resource_github_branch_protection.go +++ b/github/resource_github_branch_protection.go @@ -91,6 +91,10 @@ func resourceGithubBranchProtection() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + "require_code_owner_reviews": { + Type: schema.TypeBool, + Optional: true, + }, }, }, }, @@ -187,6 +191,14 @@ func resourceGithubBranchProtectionUpdate(d *schema.ResourceData, meta interface if err != nil { return err } + + if protectionRequest.RequiredPullRequestReviews == nil { + _, err = client.Repositories.RemovePullRequestReviewEnforcement(context.TODO(), meta.(*Organization).name, r, b) + if err != nil { + return err + } + } + d.SetId(buildTwoPartID(&r, &b)) return resourceGithubBranchProtectionRead(d, meta) @@ -268,9 +280,10 @@ func flattenRequiredPullRequestReviews(d *schema.ResourceData, protection *githu if err := d.Set("required_pull_request_reviews", []interface{}{ map[string]interface{}{ - "dismiss_stale_reviews": rprr.DismissStaleReviews, - "dismissal_users": schema.NewSet(schema.HashString, users), - "dismissal_teams": schema.NewSet(schema.HashString, teams), + "dismiss_stale_reviews": rprr.DismissStaleReviews, + "dismissal_users": schema.NewSet(schema.HashString, users), + "dismissal_teams": schema.NewSet(schema.HashString, teams), + "require_code_owner_reviews": rprr.RequireCodeOwnerReviews, }, }); err != nil { return err @@ -363,6 +376,7 @@ func expandRequiredPullRequestReviews(d *schema.ResourceData) (*github.PullReque rprr.DismissalRestrictionsRequest = drr rprr.DismissStaleReviews = m["dismiss_stale_reviews"].(bool) + rprr.RequireCodeOwnerReviews = m["require_code_owner_reviews"].(bool) } return rprr, nil diff --git a/github/resource_github_branch_protection_test.go b/github/resource_github_branch_protection_test.go index 58560b459e..08feebdf17 100644 --- a/github/resource_github_branch_protection_test.go +++ b/github/resource_github_branch_protection_test.go @@ -29,7 +29,7 @@ func TestAccGithubBranchProtection_basic(t *testing.T) { testAccCheckGithubProtectedBranchExists("github_branch_protection.master", repoName+":master", &protection), testAccCheckGithubBranchProtectionRequiredStatusChecks(&protection, true, []string{"github/foo"}), testAccCheckGithubBranchProtectionRestrictions(&protection, []string{testUser}, []string{}), - testAccCheckGithubBranchProtectionPullRequestReviews(&protection, true, []string{testUser}, []string{}), + testAccCheckGithubBranchProtectionPullRequestReviews(&protection, true, []string{testUser}, []string{}, true), resource.TestCheckResourceAttr("github_branch_protection.master", "repository", repoName), resource.TestCheckResourceAttr("github_branch_protection.master", "branch", "master"), resource.TestCheckResourceAttr("github_branch_protection.master", "enforce_admins", "true"), @@ -38,6 +38,7 @@ func TestAccGithubBranchProtection_basic(t *testing.T) { resource.TestCheckResourceAttr("github_branch_protection.master", "required_pull_request_reviews.0.dismiss_stale_reviews", "true"), resource.TestCheckResourceAttr("github_branch_protection.master", "required_pull_request_reviews.0.dismissal_users.#", "1"), resource.TestCheckResourceAttr("github_branch_protection.master", "required_pull_request_reviews.0.dismissal_teams.#", "0"), + resource.TestCheckResourceAttr("github_branch_protection.master", "required_pull_request_reviews.0.require_code_owner_reviews", "true"), resource.TestCheckResourceAttr("github_branch_protection.master", "restrictions.0.users.#", "1"), resource.TestCheckResourceAttr("github_branch_protection.master", "restrictions.0.teams.#", "0"), ), @@ -180,7 +181,7 @@ func testAccCheckGithubBranchProtectionRestrictions(protection *github.Protectio } } -func testAccCheckGithubBranchProtectionPullRequestReviews(protection *github.Protection, expectedStale bool, expectedUsers, expectedTeams []string) resource.TestCheckFunc { +func testAccCheckGithubBranchProtectionPullRequestReviews(protection *github.Protection, expectedStale bool, expectedUsers, expectedTeams []string, expectedCodeOwners bool) resource.TestCheckFunc { return func(s *terraform.State) error { reviews := protection.RequiredPullRequestReviews if reviews == nil { @@ -207,6 +208,10 @@ func testAccCheckGithubBranchProtectionPullRequestReviews(protection *github.Pro return fmt.Errorf("diff %q: (-got +want)\n%s", "dismissal_teams", diff) } + if reviews.RequireCodeOwnerReviews != expectedCodeOwners { + return fmt.Errorf("Expected `require_code_owner_reviews` to be %t, got %t", expectedCodeOwners, reviews.RequireCodeOwnerReviews) + } + return nil } } @@ -278,6 +283,7 @@ resource "github_branch_protection" "master" { required_pull_request_reviews { dismiss_stale_reviews = true dismissal_users = ["%s"] + require_code_owner_reviews = true } restrictions { diff --git a/website/docs/r/branch_protection.html.markdown b/website/docs/r/branch_protection.html.markdown index 60a8fafd29..065226f00a 100644 --- a/website/docs/r/branch_protection.html.markdown +++ b/website/docs/r/branch_protection.html.markdown @@ -66,6 +66,7 @@ The following arguments are supported: * `dismiss_stale_reviews`: (Optional) Dismiss approved reviews automatically when a new commit is pushed. Defaults to `false`. * `dismissal_users`: (Optional) The list of user logins with dismissal access * `dismissal_teams`: (Optional) The list of team slugs with dismissal access +* `require_code_owner_reviews`: (Optional) Require an approved review in pull requests including files with a designated code owner. Defaults to `false`. ### Restrictions @@ -82,4 +83,4 @@ Github Branch Protection can be imported using an id made up of `repository:bran ``` $ terraform import github_branch_protection.terraform terraform:master -``` \ No newline at end of file +```