Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/github_branch_protection: Support enforce_admins, update branch protection #26

Merged
merged 2 commits into from
Jul 5, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
283 changes: 203 additions & 80 deletions github/resource_github_branch_protection.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package github
import (
"context"
"errors"
"fmt"
"net/http"

"github.com/google/go-github/github"
Expand Down Expand Up @@ -37,17 +38,18 @@ func resourceGithubBranchProtection() *schema.Resource {
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"include_admins": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Type: schema.TypeBool,
Optional: true,
Default: false,
Deprecated: "Use enforce_admins instead",
},
"strict": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"contexts": {
Type: schema.TypeList,
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
Expand All @@ -63,10 +65,26 @@ func resourceGithubBranchProtection() *schema.Resource {
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"include_admins": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Deprecated: "Use enforce_admins instead",
},
"dismiss_stale_reviews": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"dismissal_users": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"dismissal_teams": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
Expand All @@ -77,18 +95,23 @@ func resourceGithubBranchProtection() *schema.Resource {
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"users": {
Type: schema.TypeList,
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"teams": {
Type: schema.TypeList,
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
"enforce_admins": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
}
}
Expand Down Expand Up @@ -128,54 +151,18 @@ func resourceGithubBranchProtectionRead(d *schema.ResourceData, meta interface{}

d.Set("repository", r)
d.Set("branch", b)
d.Set("enforce_admins", githubProtection.EnforceAdmins.Enabled)

rsc := githubProtection.RequiredStatusChecks
if rsc != nil {
d.Set("required_status_checks", []interface{}{
map[string]interface{}{
"include_admins": rsc.IncludeAdmins,
"strict": rsc.Strict,
"contexts": rsc.Contexts,
},
})
} else {
d.Set("required_status_checks", []interface{}{})
if err := flattenRequiredStatusChecks(d, githubProtection); err != nil {
return fmt.Errorf("Error setting required_status_checks: %v", err)
}

rprr := githubProtection.RequiredPullRequestReviews
if rprr != nil {
d.Set("required_pull_request_reviews", []interface{}{
map[string]interface{}{
"include_admins": rprr.IncludeAdmins,
},
})
} else {
d.Set("required_pull_request_reviews", []interface{}{})
if err := flattenRequiredPullRequestReviews(d, githubProtection); err != nil {
return fmt.Errorf("Error setting required_pull_request_reviews: %v", err)
}

restrictions := githubProtection.Restrictions
if restrictions != nil {
var userLogins []string
for _, u := range restrictions.Users {
if u.Login != nil {
userLogins = append(userLogins, *u.Login)
}
}
var teamSlugs []string
for _, t := range restrictions.Teams {
if t.Slug != nil {
teamSlugs = append(teamSlugs, *t.Slug)
}
}

d.Set("restrictions", []interface{}{
map[string]interface{}{
"users": userLogins,
"teams": teamSlugs,
},
})
} else {
d.Set("restrictions", []interface{}{})
if err := flattenRestrictions(d, githubProtection); err != nil {
return fmt.Errorf("Error setting restrictions: %v", err)
}

return nil
Expand Down Expand Up @@ -210,74 +197,210 @@ func resourceGithubBranchProtectionDelete(d *schema.ResourceData, meta interface
func buildProtectionRequest(d *schema.ResourceData) (*github.ProtectionRequest, error) {
protectionRequest := new(github.ProtectionRequest)

rsc, err := expandRequiredStatusChecks(d)
if err != nil {
return nil, err
}
protectionRequest.RequiredStatusChecks = rsc

rprr, err := expandRequiredPullRequestReviews(d)
if err != nil {
return nil, err
}
protectionRequest.RequiredPullRequestReviews = rprr

res, err := expandRestrictions(d)
if err != nil {
return nil, err
}
protectionRequest.Restrictions = res

protectionRequest.EnforceAdmins = d.Get("enforce_admins").(bool)

return protectionRequest, nil
}

func flattenRequiredStatusChecks(d *schema.ResourceData, protection *github.Protection) error {
rsc := protection.RequiredStatusChecks
if rsc != nil {
contexts := make([]interface{}, 0, len(rsc.Contexts))
for _, c := range rsc.Contexts {
contexts = append(contexts, c)
}

if err := d.Set("required_status_checks", []interface{}{
map[string]interface{}{
"strict": rsc.Strict,
"contexts": schema.NewSet(schema.HashString, contexts),
},
}); err != nil {
return err
}
} else {
d.Set("required_status_checks", []interface{}{})
}

return nil
}

func flattenRequiredPullRequestReviews(d *schema.ResourceData, protection *github.Protection) error {
rprr := protection.RequiredPullRequestReviews
if rprr != nil {
users := make([]interface{}, 0, len(rprr.DismissalRestrictions.Users))
for _, u := range rprr.DismissalRestrictions.Users {
if u.Login != nil {
users = append(users, *u.Login)
}
}

teams := make([]interface{}, 0, len(rprr.DismissalRestrictions.Teams))
for _, t := range rprr.DismissalRestrictions.Teams {
if t.Slug != nil {
teams = append(teams, *t.Slug)
}
}

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),
},
}); err != nil {
return err
}
} else {
d.Set("required_pull_request_reviews", []interface{}{})
}

return nil
}

func flattenRestrictions(d *schema.ResourceData, protection *github.Protection) error {
restrictions := protection.Restrictions
if restrictions != nil {
users := make([]interface{}, 0, len(restrictions.Users))
for _, u := range restrictions.Users {
if u.Login != nil {
users = append(users, *u.Login)
}
}

teams := make([]interface{}, 0, len(restrictions.Teams))
for _, t := range restrictions.Teams {
if t.Slug != nil {
teams = append(teams, *t.Slug)
}
}

if err := d.Set("restrictions", []interface{}{
map[string]interface{}{
"users": schema.NewSet(schema.HashString, users),
"teams": schema.NewSet(schema.HashString, teams),
},
}); err != nil {
return fmt.Errorf("Error setting restrictions: %v", err)
}
} else {
d.Set("restrictions", []interface{}{})
}

return nil
}

func expandRequiredStatusChecks(d *schema.ResourceData) (*github.RequiredStatusChecks, error) {
if v, ok := d.GetOk("required_status_checks"); ok {
vL := v.([]interface{})
if len(vL) > 1 {
return nil, errors.New("cannot specify required_status_checks more than one time")
}
rsc := new(github.RequiredStatusChecks)

for _, v := range vL {
// List can only have one item, safe to early return here
if v == nil {
return nil, nil
}
m := v.(map[string]interface{})

rsc := new(github.RequiredStatusChecks)
rsc.IncludeAdmins = m["include_admins"].(bool)
rsc.Strict = m["strict"].(bool)

rsc.Contexts = []string{}
if contexts, ok := m["contexts"].([]interface{}); ok {
for _, c := range contexts {
rsc.Contexts = append(rsc.Contexts, c.(string))
}
}

protectionRequest.RequiredStatusChecks = rsc
contexts := expandNestedSet(m, "contexts")
rsc.Contexts = contexts
}
return rsc, nil
}

return nil, nil
}

func expandRequiredPullRequestReviews(d *schema.ResourceData) (*github.PullRequestReviewsEnforcementRequest, error) {
if v, ok := d.GetOk("required_pull_request_reviews"); ok {
vL := v.([]interface{})
if len(vL) > 1 {
return nil, errors.New("cannot specify required_pull_request_reviews more than one time")
}

rprr := new(github.PullRequestReviewsEnforcementRequest)
drr := new(github.DismissalRestrictionsRequest)

for _, v := range vL {
// List can only have one item, safe to early return here
if v == nil {
return nil, nil
}
m := v.(map[string]interface{})

rprr := new(github.RequiredPullRequestReviews)
rprr.IncludeAdmins = m["include_admins"].(bool)
users := expandNestedSet(m, "dismissal_users")
drr.Users = users
teams := expandNestedSet(m, "dismissal_teams")
drr.Teams = teams

protectionRequest.RequiredPullRequestReviews = rprr
rprr.DismissalRestrictionsRequest = drr
rprr.DismissStaleReviews = m["dismiss_stale_reviews"].(bool)
}

return rprr, nil
}

return nil, nil
}

func expandRestrictions(d *schema.ResourceData) (*github.BranchRestrictionsRequest, error) {
if v, ok := d.GetOk("restrictions"); ok {
vL := v.([]interface{})
if len(vL) > 1 {
return nil, errors.New("cannot specify restrictions more than one time")
}
restrictions := new(github.BranchRestrictionsRequest)

for _, v := range vL {
// Restrictions only have set attributes nested, need to return nil values for these.
// The API won't initialize these as nil
if v == nil {
restrictions.Users = []string{}
restrictions.Teams = []string{}
return restrictions, nil
}
m := v.(map[string]interface{})

restrictions := new(github.BranchRestrictionsRequest)

restrictions.Users = []string{}
if users, ok := m["users"].([]interface{}); ok {
for _, u := range users {
restrictions.Users = append(restrictions.Users, u.(string))
}
}
users := expandNestedSet(m, "users")
restrictions.Users = users
teams := expandNestedSet(m, "teams")
restrictions.Teams = teams
}
return restrictions, nil
}

restrictions.Teams = []string{}
if teams, ok := m["teams"].([]interface{}); ok {
for _, t := range teams {
restrictions.Teams = append(restrictions.Teams, t.(string))
}
}
return nil, nil
}

protectionRequest.Restrictions = restrictions
func expandNestedSet(m map[string]interface{}, target string) []string {
res := []string{}
if v, ok := m[target]; ok {
vL := v.(*schema.Set).List()
for _, v := range vL {
res = append(res, v.(string))
}
}

return protectionRequest, nil
return res
}
Loading