Skip to content

Commit

Permalink
Merge pull request integrations#26 from terraform-providers/b-migrate…
Browse files Browse the repository at this point in the history
…-enforce-admins

r/github_branch_protection: Support enforce_admins, update branch protection
  • Loading branch information
grubernaut authored Jul 5, 2017
2 parents 9414c84 + e794c50 commit b291aeb
Show file tree
Hide file tree
Showing 12 changed files with 1,429 additions and 126 deletions.
289 changes: 209 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,21 @@ 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",
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
return true
},
},
"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 +68,29 @@ 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",
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
return true
},
},
"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 +101,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 +157,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 +203,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

0 comments on commit b291aeb

Please sign in to comment.