diff options
author | David Svantesson <davidsvantesson@gmail.com> | 2020-01-11 08:29:34 +0100 |
---|---|---|
committer | techknowlogick <techknowlogick@gitea.io> | 2020-01-11 02:29:34 -0500 |
commit | 32fb813133c74ddc3af1964e81fff72fea4f24f1 (patch) | |
tree | 31eec446f12e448d7cf398db43620606e9704ff1 /services/pull/merge.go | |
parent | 4d06d10dbafe7cfd404889b636d8e243058ee96f (diff) | |
download | gitea-32fb813133c74ddc3af1964e81fff72fea4f24f1.tar.gz gitea-32fb813133c74ddc3af1964e81fff72fea4f24f1.zip |
Allow repo admin to merge PR regardless of review status (#9611)
* Allow repo admin to merge even if review is not ok.
Diffstat (limited to 'services/pull/merge.go')
-rw-r--r-- | services/pull/merge.go | 67 |
1 files changed, 62 insertions, 5 deletions
diff --git a/services/pull/merge.go b/services/pull/merge.go index 7aec7cef3e..e825c3fdd1 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -30,6 +30,7 @@ import ( ) // Merge merges pull request to base repository. +// Caller should check PR is ready to be merged (review and status checks) // FIXME: add repoWorkingPull make sure two merges does not happen at same time. func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repository, mergeStyle models.MergeStyle, message string) (err error) { binVersion, err := git.BinVersion() @@ -53,11 +54,6 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor } prConfig := prUnit.PullRequestsConfig() - if err := pr.CheckUserAllowedToMerge(doer); err != nil { - log.Error("CheckUserAllowedToMerge(%v): %v", doer, err) - return fmt.Errorf("CheckUserAllowedToMerge: %v", err) - } - // Check if merge style is correct and allowed if !prConfig.IsMergeStyleAllowed(mergeStyle) { return models.ErrInvalidMergeStyle{ID: pr.BaseRepo.ID, Style: mergeStyle} @@ -473,3 +469,64 @@ func getDiffTree(repoPath, baseBranch, headBranch string) (string, error) { return out.String(), nil } + +// IsUserAllowedToMerge check if user is allowed to merge PR with given permissions and branch protections +func IsUserAllowedToMerge(pr *models.PullRequest, p models.Permission, user *models.User) (bool, error) { + if p.IsAdmin() { + return true, nil + } + if !p.CanWrite(models.UnitTypeCode) { + return false, nil + } + + err := pr.LoadProtectedBranch() + if err != nil { + return false, err + } + + if pr.ProtectedBranch == nil || pr.ProtectedBranch.IsUserMergeWhitelisted(user.ID) { + return true, nil + } + + return false, nil +} + +// CheckPRReadyToMerge checks whether the PR is ready to be merged (reviews and status checks) +func CheckPRReadyToMerge(pr *models.PullRequest) (err error) { + if pr.BaseRepo == nil { + if err = pr.GetBaseRepo(); err != nil { + return fmt.Errorf("GetBaseRepo: %v", err) + } + } + if pr.ProtectedBranch == nil { + if err = pr.LoadProtectedBranch(); err != nil { + return fmt.Errorf("LoadProtectedBranch: %v", err) + } + if pr.ProtectedBranch == nil { + return nil + } + } + + isPass, err := IsPullCommitStatusPass(pr) + if err != nil { + return err + } + if !isPass { + return models.ErrNotAllowedToMerge{ + Reason: "Not all required status checks successful", + } + } + + if enoughApprovals := pr.ProtectedBranch.HasEnoughApprovals(pr); !enoughApprovals { + return models.ErrNotAllowedToMerge{ + Reason: "Does not have enough approvals", + } + } + if rejected := pr.ProtectedBranch.MergeBlockedByRejectedReview(pr); rejected { + return models.ErrNotAllowedToMerge{ + Reason: "There are requested changes", + } + } + + return nil +} |