in prow/plugins/verify-owners/verify-owners.go [208:365]
func handle(ghc githubClient, gc git.ClientFactory, roc repoownersClient, log *logrus.Entry, pr *github.PullRequest, info info, bannedLabels []string, triggerConfig plugins.Trigger, skipTrustedUserCheck bool, cp commentPruner, resolver ownersconfig.Resolver) error {
org := info.org
repo := info.repo
number := info.number
filenames := resolver(org, repo)
wrongOwnersFiles := map[string]messageWithLine{}
// Get changes.
changes, err := ghc.GetPullRequestChanges(org, repo, number)
if err != nil {
return fmt.Errorf("error getting PR changes: %w", err)
}
// List modified OWNERS files.
var modifiedOwnersFiles []github.PullRequestChange
for _, change := range changes {
if filepath.Base(change.Filename) == filenames.Owners && change.Status != github.PullRequestFileRemoved {
modifiedOwnersFiles = append(modifiedOwnersFiles, change)
}
}
// Check if the OWNERS_ALIASES file was modified.
var modifiedOwnerAliasesFile github.PullRequestChange
var ownerAliasesModified bool
for _, change := range changes {
if change.Filename == filenames.OwnersAliases {
modifiedOwnerAliasesFile = change
ownerAliasesModified = true
break
}
}
issueLabels, err := ghc.GetIssueLabels(org, repo, number)
if err != nil {
return err
}
hasInvalidOwnersLabel := github.HasLabel(labels.InvalidOwners, issueLabels)
if len(modifiedOwnersFiles) == 0 && !ownerAliasesModified && !hasInvalidOwnersLabel {
return nil
}
// Clone the repo, checkout the PR.
r, err := gc.ClientFor(org, repo)
if err != nil {
return err
}
defer func() {
if err := r.Clean(); err != nil {
log.WithError(err).Error("Error cleaning up repo.")
}
}()
if err := r.Config("user.name", "prow"); err != nil {
return err
}
if err := r.Config("user.email", "prow@localhost"); err != nil {
return err
}
if err := r.Config("commit.gpgsign", "false"); err != nil {
log.WithError(err).Errorf("Cannot set gpgsign=false in gitconfig: %v", err)
}
if err := r.MergeAndCheckout(pr.Base.Ref, string(github.MergeMerge), pr.Head.SHA); err != nil {
return err
}
// If OWNERS_ALIASES file exists, get all aliases.
// If the file was modified, check for non trusted users in the newly added owners.
nonTrustedUsers, trustedUsers, repoAliases, err := nonTrustedUsersInOwnersAliases(ghc, log, triggerConfig, org, repo, r.Directory(), modifiedOwnerAliasesFile.Patch, ownerAliasesModified, skipTrustedUserCheck, filenames)
if err != nil {
return err
}
// Check if OWNERS files have the correct config and if they do,
// check if all newly added owners are trusted users.
oc, err := roc.LoadRepoOwners(org, repo, pr.Base.Ref)
if err != nil {
return fmt.Errorf("error loading RepoOwners: %w", err)
}
for _, c := range modifiedOwnersFiles {
path := filepath.Join(r.Directory(), c.Filename)
msg, owners := parseOwnersFile(oc, path, c, log, bannedLabels, filenames)
if msg != nil {
wrongOwnersFiles[c.Filename] = *msg
continue
}
if !skipTrustedUserCheck {
nonTrustedUsers, err = nonTrustedUsersInOwners(ghc, log, triggerConfig, org, repo, c.Patch, c.Filename, owners, nonTrustedUsers, trustedUsers, repoAliases)
if err != nil {
return err
}
}
}
if len(wrongOwnersFiles) > 0 {
s := "s"
if len(wrongOwnersFiles) == 1 {
s = ""
}
if !hasInvalidOwnersLabel {
if err := ghc.AddLabel(org, repo, number, labels.InvalidOwners); err != nil {
return err
}
}
log.Debugf("Creating a review for %d %s file%s.", len(wrongOwnersFiles), filenames.Owners, s)
var comments []github.DraftReviewComment
for errFile, err := range wrongOwnersFiles {
comments = append(comments, github.DraftReviewComment{
Path: errFile,
Body: err.message,
Position: err.line,
})
}
// Make the review body.
response := fmt.Sprintf("%d invalid %s file%s", len(wrongOwnersFiles), filenames.Owners, s)
draftReview := github.DraftReview{
Body: plugins.FormatResponseRaw(pr.Body, pr.HTMLURL, pr.User.Login, response),
Action: github.Comment,
Comments: comments,
}
if pr.Head.SHA != "" {
draftReview.CommitSHA = pr.Head.SHA
}
err := ghc.CreateReview(org, repo, number, draftReview)
if err != nil {
return fmt.Errorf("error creating a review for invalid %s file%s: %w", filenames.Owners, s, err)
}
}
if len(nonTrustedUsers) > 0 {
if !hasInvalidOwnersLabel {
if err := ghc.AddLabel(org, repo, number, labels.InvalidOwners); err != nil {
return err
}
}
// prune old comments before adding a new one
cp.PruneComments(func(comment github.IssueComment) bool {
return strings.Contains(comment.Body, fmt.Sprintf(untrustedResponseFormat, filenames.Owners, triggerConfig.JoinOrgURL, org))
})
if err := ghc.CreateComment(org, repo, number, markdownFriendlyComment(org, triggerConfig.JoinOrgURL, nonTrustedUsers, filenames)); err != nil {
log.WithError(err).Errorf("Could not create comment for listing non-collaborators in %s files", filenames.Owners)
}
}
if len(wrongOwnersFiles) == 0 && len(nonTrustedUsers) == 0 {
// Don't bother checking if it has the label...it's a race, and we'll have
// to handle failure due to not being labeled anyway.
if err := ghc.RemoveLabel(org, repo, number, labels.InvalidOwners); err != nil {
return fmt.Errorf("failed removing %s label: %w", labels.InvalidOwners, err)
}
cp.PruneComments(func(comment github.IssueComment) bool {
return strings.Contains(comment.Body, fmt.Sprintf(untrustedResponseFormat, filenames.Owners, triggerConfig.JoinOrgURL, org))
})
}
return nil
}