sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/cmd/branchprotector/request.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 branchprotection "sigs.k8s.io/prow/pkg/config" 21 "sigs.k8s.io/prow/pkg/github" 22 23 "github.com/sirupsen/logrus" 24 "k8s.io/apimachinery/pkg/util/sets" 25 ) 26 27 // makeRequest renders a branch protection policy into the corresponding GitHub api request. 28 func makeRequest(policy branchprotection.Policy, enableAppsRestrictions bool) github.BranchProtectionRequest { 29 return github.BranchProtectionRequest{ 30 EnforceAdmins: makeAdmins(policy.Admins), 31 RequiredPullRequestReviews: makeReviews(policy.RequiredPullRequestReviews), 32 RequiredStatusChecks: makeChecks(policy.RequiredStatusChecks), 33 Restrictions: makeRestrictions(policy.Restrictions, enableAppsRestrictions), 34 RequiredLinearHistory: makeBool(policy.RequiredLinearHistory), 35 AllowForcePushes: makeBool(policy.AllowForcePushes), 36 AllowDeletions: makeBool(policy.AllowDeletions), 37 } 38 39 } 40 41 // makeAdmins returns true iff *val == true, else false 42 // TODO(skuznets): the API documentation tells us to pass 43 // 44 // `nil` to unset, but that is broken so we need to pass 45 // false. Change back when it's fixed 46 func makeAdmins(val *bool) *bool { 47 if val != nil { 48 return val 49 } 50 no := false 51 return &no 52 } 53 54 // makeBool returns true iff *val == true 55 func makeBool(val *bool) bool { 56 return val != nil && *val 57 } 58 59 // makeChecks renders a ContextPolicy into the corresponding GitHub api object. 60 // 61 // Returns nil when input policy is nil. 62 // Otherwise returns non-nil Contexts (empty if unset) and Strict if Strict is true 63 func makeChecks(cp *branchprotection.ContextPolicy) *github.RequiredStatusChecks { 64 if cp == nil { 65 return nil 66 } 67 return &github.RequiredStatusChecks{ 68 Contexts: append([]string{}, sets.List(sets.New[string](cp.Contexts...))...), 69 Strict: makeBool(cp.Strict), 70 } 71 } 72 73 // makeDismissalRestrictions renders restrictions into the corresponding GitHub api object. 74 // 75 // Returns nil when input restrictions is nil. 76 // Otherwise Teams and Users are both non-nil (empty list if unset). 77 func makeDismissalRestrictions(rp *branchprotection.DismissalRestrictions) *github.DismissalRestrictionsRequest { 78 if rp == nil { 79 return nil 80 } 81 teams := append([]string{}, sets.List(sets.New[string](rp.Teams...))...) 82 users := append([]string{}, sets.List(sets.New[string](rp.Users...))...) 83 return &github.DismissalRestrictionsRequest{ 84 Teams: &teams, 85 Users: &users, 86 } 87 } 88 89 // makeBypassRestrictions renders restrictions into the corresponding GitHub api object. 90 // 91 // Returns nil when input restrictions is nil. 92 // Otherwise Teams and Users are both non-nil (empty list if unset). 93 func makeBypassRestrictions(rp *branchprotection.BypassRestrictions) *github.BypassRestrictionsRequest { 94 if rp == nil { 95 return nil 96 } 97 teams := append([]string{}, sets.List(sets.New[string](rp.Teams...))...) 98 users := append([]string{}, sets.List(sets.New[string](rp.Users...))...) 99 return &github.BypassRestrictionsRequest{ 100 Teams: &teams, 101 Users: &users, 102 } 103 } 104 105 // makeRestrictions renders restrictions into the corresponding GitHub api object. 106 // 107 // Returns nil when input restrictions is nil. 108 // Otherwise Teams and Users are non-nil (empty list if unset). 109 // If enableAppsRestrictions is set Apps behave like Teams and Users, otherwise Apps are nil 110 func makeRestrictions(rp *branchprotection.Restrictions, enableAppsRestrictions bool) *github.RestrictionsRequest { 111 if rp == nil { 112 return nil 113 } 114 // Only set restriction request for apps if feature flag is true 115 // TODO: consider removing feature flag in the future 116 var apps *[]string 117 if enableAppsRestrictions { 118 a := append([]string{}, sets.List(sets.New[string](rp.Apps...))...) 119 apps = &a 120 } 121 teams := append([]string{}, sets.List(sets.New[string](rp.Teams...))...) 122 users := append([]string{}, sets.List(sets.New[string](rp.Users...))...) 123 return &github.RestrictionsRequest{ 124 Apps: apps, 125 Teams: &teams, 126 Users: &users, 127 } 128 } 129 130 // makeReviews renders review policy into the corresponding GitHub api object. 131 // 132 // Returns nil if the policy is nil, or approvals is nil. 133 func makeReviews(rp *branchprotection.ReviewPolicy) *github.RequiredPullRequestReviewsRequest { 134 switch { 135 case rp == nil: 136 return nil 137 case rp.Approvals == nil: 138 logrus.Warn("WARNING: required_pull_request_reviews policy does not specify required_approving_review_count, disabling") 139 return nil 140 } 141 rprr := github.RequiredPullRequestReviewsRequest{ 142 DismissStaleReviews: makeBool(rp.DismissStale), 143 RequireCodeOwnerReviews: makeBool(rp.RequireOwners), 144 RequiredApprovingReviewCount: *rp.Approvals, 145 } 146 if rp.DismissalRestrictions != nil { 147 rprr.DismissalRestrictions = *makeDismissalRestrictions(rp.DismissalRestrictions) 148 } 149 150 if rp.BypassRestrictions != nil { 151 rprr.BypassRestrictions = *makeBypassRestrictions(rp.BypassRestrictions) 152 } 153 return &rprr 154 }