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  }