func handle()

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
}