...

Source file src/edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/policy/predicate/author.go

Documentation: edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/policy/predicate

     1  // Copyright 2018 Palantir Technologies, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package predicate
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"sort"
    21  
    22  	"github.com/pkg/errors"
    23  
    24  	"edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/pull"
    25  
    26  	"edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/policy/common"
    27  )
    28  
    29  type HasAuthorIn struct {
    30  	common.Actors `yaml:",inline"`
    31  }
    32  
    33  var _ Predicate = &HasAuthorIn{}
    34  
    35  func (pred *HasAuthorIn) Evaluate(ctx context.Context, prctx pull.Context) (*common.PredicateResult, error) {
    36  	author := prctx.Author()
    37  
    38  	result, err := pred.IsActor(ctx, prctx, author)
    39  	desc := ""
    40  	if !result {
    41  		desc = fmt.Sprintf("The pull request author %q does not meet the required membership conditions", author)
    42  	}
    43  
    44  	predicateResult := common.PredicateResult{
    45  		Satisfied:       result,
    46  		Description:     desc,
    47  		ValuePhrase:     "authors",
    48  		Values:          []string{author},
    49  		ConditionPhrase: "meet the required membership conditions",
    50  		ConditionsMap: map[string][]string{
    51  			"Organizations": pred.Organizations,
    52  			"Teams":         pred.Teams,
    53  			"Users":         pred.Users,
    54  		},
    55  	}
    56  	return &predicateResult, err
    57  }
    58  
    59  func (pred *HasAuthorIn) Trigger() common.Trigger {
    60  	return common.TriggerStatic
    61  }
    62  
    63  type OnlyHasContributorsIn struct {
    64  	common.Actors `yaml:",inline"`
    65  }
    66  
    67  var _ Predicate = &OnlyHasContributorsIn{}
    68  
    69  func (pred *OnlyHasContributorsIn) Evaluate(ctx context.Context, prctx pull.Context) (*common.PredicateResult, error) {
    70  	commits, err := prctx.Commits()
    71  
    72  	predicateResult := common.PredicateResult{
    73  		ValuePhrase:     "contributors",
    74  		ConditionPhrase: "all meet the required membership conditions",
    75  		ConditionsMap: map[string][]string{
    76  			"Organizations": pred.Organizations,
    77  			"Teams":         pred.Teams,
    78  			"Users":         pred.Users,
    79  		},
    80  	}
    81  
    82  	if err != nil {
    83  		return nil, errors.Wrap(err, "failed to get commits")
    84  	}
    85  
    86  	users := make(map[string]struct{})
    87  	users[prctx.Author()] = struct{}{}
    88  
    89  	for _, c := range commits {
    90  		for _, u := range c.Users() {
    91  			users[u] = struct{}{}
    92  		}
    93  	}
    94  
    95  	userList := make([]string, 0, len(users))
    96  	for user := range users {
    97  		userList = append(userList, user)
    98  	}
    99  	sort.Strings(userList)
   100  
   101  	for _, user := range userList {
   102  		member, err := pred.IsActor(ctx, prctx, user)
   103  		if err != nil {
   104  			return nil, err
   105  		}
   106  		if !member {
   107  			predicateResult.Description = fmt.Sprintf("Contributor %q does not meet the required membership conditions", user)
   108  			predicateResult.Values = []string{user}
   109  			predicateResult.Satisfied = false
   110  			return &predicateResult, nil
   111  		}
   112  	}
   113  	predicateResult.Values = userList
   114  	predicateResult.Satisfied = true
   115  	return &predicateResult, nil
   116  }
   117  
   118  func (pred *OnlyHasContributorsIn) Trigger() common.Trigger {
   119  	return common.TriggerCommit
   120  }
   121  
   122  type HasContributorIn struct {
   123  	common.Actors `yaml:",inline"`
   124  }
   125  
   126  var _ Predicate = &HasContributorIn{}
   127  
   128  func (pred *HasContributorIn) Evaluate(ctx context.Context, prctx pull.Context) (*common.PredicateResult, error) {
   129  	commits, err := prctx.Commits()
   130  
   131  	predicateResult := common.PredicateResult{
   132  		ValuePhrase:     "contributors",
   133  		ConditionPhrase: "meet the required membership conditions ",
   134  		ConditionsMap: map[string][]string{
   135  			"Organizations": pred.Organizations,
   136  			"Teams":         pred.Teams,
   137  			"Users":         pred.Users,
   138  		},
   139  	}
   140  
   141  	if err != nil {
   142  		return nil, errors.Wrap(err, "failed to get commits")
   143  	}
   144  
   145  	users := make(map[string]struct{})
   146  	users[prctx.Author()] = struct{}{}
   147  
   148  	for _, c := range commits {
   149  		for _, u := range c.Users() {
   150  			users[u] = struct{}{}
   151  		}
   152  	}
   153  
   154  	userList := make([]string, 0, len(users))
   155  	for user := range users {
   156  		userList = append(userList, user)
   157  	}
   158  	sort.Strings(userList)
   159  
   160  	for _, user := range userList {
   161  		member, err := pred.IsActor(ctx, prctx, user)
   162  		if err != nil {
   163  			return nil, err
   164  		}
   165  		if member {
   166  			predicateResult.Satisfied = true
   167  			predicateResult.Values = []string{user}
   168  			return &predicateResult, nil
   169  		}
   170  	}
   171  	predicateResult.Description = "No contributors meet the required membership conditions"
   172  	predicateResult.Satisfied = false
   173  	predicateResult.Values = userList
   174  	return &predicateResult, nil
   175  }
   176  
   177  func (pred *HasContributorIn) Trigger() common.Trigger {
   178  	return common.TriggerCommit
   179  }
   180  
   181  type AuthorIsOnlyContributor bool
   182  
   183  var _ Predicate = AuthorIsOnlyContributor(false)
   184  
   185  func (pred AuthorIsOnlyContributor) Evaluate(ctx context.Context, prctx pull.Context) (*common.PredicateResult, error) {
   186  	commits, err := prctx.Commits()
   187  
   188  	predicateResult := common.PredicateResult{
   189  		ValuePhrase:     "authors",
   190  		ConditionPhrase: "meet the condition",
   191  	}
   192  	if pred {
   193  		predicateResult.ConditionValues = []string{"they are the only contributors"}
   194  	} else {
   195  		predicateResult.ConditionValues = []string{"they are not the only contributors"}
   196  	}
   197  
   198  	if err != nil {
   199  		return nil, errors.Wrap(err, "failed to get commits")
   200  	}
   201  
   202  	author := prctx.Author()
   203  	predicateResult.Values = []string{author}
   204  
   205  	for _, c := range commits {
   206  		if c.Author != author || (!c.CommittedViaWeb && c.Committer != author) {
   207  			if pred {
   208  				predicateResult.Description = fmt.Sprintf("Commit %.10s was authored or committed by a different user", c.SHA)
   209  				predicateResult.Satisfied = false
   210  				return &predicateResult, nil
   211  			}
   212  			predicateResult.Satisfied = true
   213  			return &predicateResult, nil
   214  		}
   215  	}
   216  
   217  	if pred {
   218  		predicateResult.Satisfied = true
   219  		return &predicateResult, nil
   220  	}
   221  	predicateResult.Description = fmt.Sprintf("All commits were authored and committed by %s", author)
   222  	predicateResult.Satisfied = false
   223  	return &predicateResult, nil
   224  }
   225  
   226  func (pred AuthorIsOnlyContributor) Trigger() common.Trigger {
   227  	return common.TriggerCommit
   228  }
   229  

View as plain text