]> source.dussan.org Git - gitea.git/commitdiff
Add block on official review requests branch protection (#13705)
authora1012112796 <1012112796@qq.com>
Sat, 28 Nov 2020 19:30:46 +0000 (03:30 +0800)
committerGitHub <noreply@github.com>
Sat, 28 Nov 2020 19:30:46 +0000 (21:30 +0200)
Signed-off-by: a1012112796 <1012112796@qq.com>
Co-authored-by: Lauris BH <lauris@nix.lv>
14 files changed:
models/branches.go
models/migrations/migrations.go
models/migrations/v160.go [new file with mode: 0644]
modules/auth/repo_form.go
modules/convert/convert.go
modules/structs/repo_branch.go
options/locale/locale_en-US.ini
routers/api/v1/repo/branch.go
routers/repo/issue.go
routers/repo/setting_protected_branch.go
services/pull/merge.go
templates/repo/issue/view_content/pull.tmpl
templates/repo/settings/protected_branch.tmpl
templates/swagger/v1_json.tmpl

index 420a4b663a4e342a3017488a47472b60dbafd649..144767ee9549b560c74b4bfdc293a67a2ba5aeb5 100644 (file)
@@ -21,28 +21,29 @@ import (
 
 // ProtectedBranch struct
 type ProtectedBranch struct {
-       ID                        int64  `xorm:"pk autoincr"`
-       RepoID                    int64  `xorm:"UNIQUE(s)"`
-       BranchName                string `xorm:"UNIQUE(s)"`
-       CanPush                   bool   `xorm:"NOT NULL DEFAULT false"`
-       EnableWhitelist           bool
-       WhitelistUserIDs          []int64  `xorm:"JSON TEXT"`
-       WhitelistTeamIDs          []int64  `xorm:"JSON TEXT"`
-       EnableMergeWhitelist      bool     `xorm:"NOT NULL DEFAULT false"`
-       WhitelistDeployKeys       bool     `xorm:"NOT NULL DEFAULT false"`
-       MergeWhitelistUserIDs     []int64  `xorm:"JSON TEXT"`
-       MergeWhitelistTeamIDs     []int64  `xorm:"JSON TEXT"`
-       EnableStatusCheck         bool     `xorm:"NOT NULL DEFAULT false"`
-       StatusCheckContexts       []string `xorm:"JSON TEXT"`
-       EnableApprovalsWhitelist  bool     `xorm:"NOT NULL DEFAULT false"`
-       ApprovalsWhitelistUserIDs []int64  `xorm:"JSON TEXT"`
-       ApprovalsWhitelistTeamIDs []int64  `xorm:"JSON TEXT"`
-       RequiredApprovals         int64    `xorm:"NOT NULL DEFAULT 0"`
-       BlockOnRejectedReviews    bool     `xorm:"NOT NULL DEFAULT false"`
-       BlockOnOutdatedBranch     bool     `xorm:"NOT NULL DEFAULT false"`
-       DismissStaleApprovals     bool     `xorm:"NOT NULL DEFAULT false"`
-       RequireSignedCommits      bool     `xorm:"NOT NULL DEFAULT false"`
-       ProtectedFilePatterns     string   `xorm:"TEXT"`
+       ID                            int64  `xorm:"pk autoincr"`
+       RepoID                        int64  `xorm:"UNIQUE(s)"`
+       BranchName                    string `xorm:"UNIQUE(s)"`
+       CanPush                       bool   `xorm:"NOT NULL DEFAULT false"`
+       EnableWhitelist               bool
+       WhitelistUserIDs              []int64  `xorm:"JSON TEXT"`
+       WhitelistTeamIDs              []int64  `xorm:"JSON TEXT"`
+       EnableMergeWhitelist          bool     `xorm:"NOT NULL DEFAULT false"`
+       WhitelistDeployKeys           bool     `xorm:"NOT NULL DEFAULT false"`
+       MergeWhitelistUserIDs         []int64  `xorm:"JSON TEXT"`
+       MergeWhitelistTeamIDs         []int64  `xorm:"JSON TEXT"`
+       EnableStatusCheck             bool     `xorm:"NOT NULL DEFAULT false"`
+       StatusCheckContexts           []string `xorm:"JSON TEXT"`
+       EnableApprovalsWhitelist      bool     `xorm:"NOT NULL DEFAULT false"`
+       ApprovalsWhitelistUserIDs     []int64  `xorm:"JSON TEXT"`
+       ApprovalsWhitelistTeamIDs     []int64  `xorm:"JSON TEXT"`
+       RequiredApprovals             int64    `xorm:"NOT NULL DEFAULT 0"`
+       BlockOnRejectedReviews        bool     `xorm:"NOT NULL DEFAULT false"`
+       BlockOnOfficialReviewRequests bool     `xorm:"NOT NULL DEFAULT false"`
+       BlockOnOutdatedBranch         bool     `xorm:"NOT NULL DEFAULT false"`
+       DismissStaleApprovals         bool     `xorm:"NOT NULL DEFAULT false"`
+       RequireSignedCommits          bool     `xorm:"NOT NULL DEFAULT false"`
+       ProtectedFilePatterns         string   `xorm:"TEXT"`
 
        CreatedUnix timeutil.TimeStamp `xorm:"created"`
        UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
@@ -171,13 +172,12 @@ func (protectBranch *ProtectedBranch) GetGrantedApprovalsCount(pr *PullRequest)
 }
 
 // MergeBlockedByRejectedReview returns true if merge is blocked by rejected reviews
-// An official ReviewRequest should also block Merge like Reject
 func (protectBranch *ProtectedBranch) MergeBlockedByRejectedReview(pr *PullRequest) bool {
        if !protectBranch.BlockOnRejectedReviews {
                return false
        }
        rejectExist, err := x.Where("issue_id = ?", pr.IssueID).
-               And("type in ( ?, ?)", ReviewTypeReject, ReviewTypeRequest).
+               And("type = ?", ReviewTypeReject).
                And("official = ?", true).
                Exist(new(Review))
        if err != nil {
@@ -188,6 +188,24 @@ func (protectBranch *ProtectedBranch) MergeBlockedByRejectedReview(pr *PullReque
        return rejectExist
 }
 
+// MergeBlockedByOfficialReviewRequests block merge because of some review request to official reviewer
+// of from official review
+func (protectBranch *ProtectedBranch) MergeBlockedByOfficialReviewRequests(pr *PullRequest) bool {
+       if !protectBranch.BlockOnOfficialReviewRequests {
+               return false
+       }
+       has, err := x.Where("issue_id = ?", pr.IssueID).
+               And("type = ?", ReviewTypeRequest).
+               And("official = ?", true).
+               Exist(new(Review))
+       if err != nil {
+               log.Error("MergeBlockedByOfficialReviewRequests: %v", err)
+               return true
+       }
+
+       return has
+}
+
 // MergeBlockedByOutdatedBranch returns true if merge is blocked by an outdated head branch
 func (protectBranch *ProtectedBranch) MergeBlockedByOutdatedBranch(pr *PullRequest) bool {
        return protectBranch.BlockOnOutdatedBranch && pr.CommitsBehind > 0
index 5a2646474c77fcb6bf3c19fcca3f4aabbbccb691..6b13719b449ab8e826fb3f3e02de0db46e72bffa 100644 (file)
@@ -254,6 +254,8 @@ var migrations = []Migration{
        NewMigration("code comment replies should have the commitID of the review they are replying to", updateCodeCommentReplies),
        // v159 -> v160
        NewMigration("update reactions constraint", updateReactionConstraint),
+       // v160 -> v161
+       NewMigration("Add block on official review requests branch protection", addBlockOnOfficialReviewRequests),
 }
 
 // GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v160.go b/models/migrations/v160.go
new file mode 100644 (file)
index 0000000..e1a4b48
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+       "xorm.io/xorm"
+)
+
+func addBlockOnOfficialReviewRequests(x *xorm.Engine) error {
+       type ProtectedBranch struct {
+               BlockOnOfficialReviewRequests bool `xorm:"NOT NULL DEFAULT false"`
+       }
+
+       return x.Sync2(new(ProtectedBranch))
+}
index 2d6f89b6ed75bcfdb86a7eb0b1fccc3e275e375a..24c2478fa4ef3ac5e4c9a8fb7290f926a5213041 100644 (file)
@@ -178,25 +178,26 @@ func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
 
 // ProtectBranchForm form for changing protected branch settings
 type ProtectBranchForm struct {
-       Protected                bool
-       EnablePush               string
-       WhitelistUsers           string
-       WhitelistTeams           string
-       WhitelistDeployKeys      bool
-       EnableMergeWhitelist     bool
-       MergeWhitelistUsers      string
-       MergeWhitelistTeams      string
-       EnableStatusCheck        bool `xorm:"NOT NULL DEFAULT false"`
-       StatusCheckContexts      []string
-       RequiredApprovals        int64
-       EnableApprovalsWhitelist bool
-       ApprovalsWhitelistUsers  string
-       ApprovalsWhitelistTeams  string
-       BlockOnRejectedReviews   bool
-       BlockOnOutdatedBranch    bool
-       DismissStaleApprovals    bool
-       RequireSignedCommits     bool
-       ProtectedFilePatterns    string
+       Protected                     bool
+       EnablePush                    string
+       WhitelistUsers                string
+       WhitelistTeams                string
+       WhitelistDeployKeys           bool
+       EnableMergeWhitelist          bool
+       MergeWhitelistUsers           string
+       MergeWhitelistTeams           string
+       EnableStatusCheck             bool
+       StatusCheckContexts           []string
+       RequiredApprovals             int64
+       EnableApprovalsWhitelist      bool
+       ApprovalsWhitelistUsers       string
+       ApprovalsWhitelistTeams       string
+       BlockOnRejectedReviews        bool
+       BlockOnOfficialReviewRequests bool
+       BlockOnOutdatedBranch         bool
+       DismissStaleApprovals         bool
+       RequireSignedCommits          bool
+       ProtectedFilePatterns         string
 }
 
 // Validate validates the fields
index 5d056c37954d392f32897c02798e73f4d59c4b34..9b20c683bee273f9fba727a5a628094a572d193c 100644 (file)
@@ -105,28 +105,29 @@ func ToBranchProtection(bp *models.ProtectedBranch) *api.BranchProtection {
        }
 
        return &api.BranchProtection{
-               BranchName:                  bp.BranchName,
-               EnablePush:                  bp.CanPush,
-               EnablePushWhitelist:         bp.EnableWhitelist,
-               PushWhitelistUsernames:      pushWhitelistUsernames,
-               PushWhitelistTeams:          pushWhitelistTeams,
-               PushWhitelistDeployKeys:     bp.WhitelistDeployKeys,
-               EnableMergeWhitelist:        bp.EnableMergeWhitelist,
-               MergeWhitelistUsernames:     mergeWhitelistUsernames,
-               MergeWhitelistTeams:         mergeWhitelistTeams,
-               EnableStatusCheck:           bp.EnableStatusCheck,
-               StatusCheckContexts:         bp.StatusCheckContexts,
-               RequiredApprovals:           bp.RequiredApprovals,
-               EnableApprovalsWhitelist:    bp.EnableApprovalsWhitelist,
-               ApprovalsWhitelistUsernames: approvalsWhitelistUsernames,
-               ApprovalsWhitelistTeams:     approvalsWhitelistTeams,
-               BlockOnRejectedReviews:      bp.BlockOnRejectedReviews,
-               BlockOnOutdatedBranch:       bp.BlockOnOutdatedBranch,
-               DismissStaleApprovals:       bp.DismissStaleApprovals,
-               RequireSignedCommits:        bp.RequireSignedCommits,
-               ProtectedFilePatterns:       bp.ProtectedFilePatterns,
-               Created:                     bp.CreatedUnix.AsTime(),
-               Updated:                     bp.UpdatedUnix.AsTime(),
+               BranchName:                    bp.BranchName,
+               EnablePush:                    bp.CanPush,
+               EnablePushWhitelist:           bp.EnableWhitelist,
+               PushWhitelistUsernames:        pushWhitelistUsernames,
+               PushWhitelistTeams:            pushWhitelistTeams,
+               PushWhitelistDeployKeys:       bp.WhitelistDeployKeys,
+               EnableMergeWhitelist:          bp.EnableMergeWhitelist,
+               MergeWhitelistUsernames:       mergeWhitelistUsernames,
+               MergeWhitelistTeams:           mergeWhitelistTeams,
+               EnableStatusCheck:             bp.EnableStatusCheck,
+               StatusCheckContexts:           bp.StatusCheckContexts,
+               RequiredApprovals:             bp.RequiredApprovals,
+               EnableApprovalsWhitelist:      bp.EnableApprovalsWhitelist,
+               ApprovalsWhitelistUsernames:   approvalsWhitelistUsernames,
+               ApprovalsWhitelistTeams:       approvalsWhitelistTeams,
+               BlockOnRejectedReviews:        bp.BlockOnRejectedReviews,
+               BlockOnOfficialReviewRequests: bp.BlockOnOfficialReviewRequests,
+               BlockOnOutdatedBranch:         bp.BlockOnOutdatedBranch,
+               DismissStaleApprovals:         bp.DismissStaleApprovals,
+               RequireSignedCommits:          bp.RequireSignedCommits,
+               ProtectedFilePatterns:         bp.ProtectedFilePatterns,
+               Created:                       bp.CreatedUnix.AsTime(),
+               Updated:                       bp.UpdatedUnix.AsTime(),
        }
 }
 
index 490c63070a0c8dc044b14a7816cba51972d1c5a5..efb4caecb08277bf103ce03c7725ac11efc7579c 100644 (file)
@@ -23,26 +23,27 @@ type Branch struct {
 
 // BranchProtection represents a branch protection for a repository
 type BranchProtection struct {
-       BranchName                  string   `json:"branch_name"`
-       EnablePush                  bool     `json:"enable_push"`
-       EnablePushWhitelist         bool     `json:"enable_push_whitelist"`
-       PushWhitelistUsernames      []string `json:"push_whitelist_usernames"`
-       PushWhitelistTeams          []string `json:"push_whitelist_teams"`
-       PushWhitelistDeployKeys     bool     `json:"push_whitelist_deploy_keys"`
-       EnableMergeWhitelist        bool     `json:"enable_merge_whitelist"`
-       MergeWhitelistUsernames     []string `json:"merge_whitelist_usernames"`
-       MergeWhitelistTeams         []string `json:"merge_whitelist_teams"`
-       EnableStatusCheck           bool     `json:"enable_status_check"`
-       StatusCheckContexts         []string `json:"status_check_contexts"`
-       RequiredApprovals           int64    `json:"required_approvals"`
-       EnableApprovalsWhitelist    bool     `json:"enable_approvals_whitelist"`
-       ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
-       ApprovalsWhitelistTeams     []string `json:"approvals_whitelist_teams"`
-       BlockOnRejectedReviews      bool     `json:"block_on_rejected_reviews"`
-       BlockOnOutdatedBranch       bool     `json:"block_on_outdated_branch"`
-       DismissStaleApprovals       bool     `json:"dismiss_stale_approvals"`
-       RequireSignedCommits        bool     `json:"require_signed_commits"`
-       ProtectedFilePatterns       string   `json:"protected_file_patterns"`
+       BranchName                    string   `json:"branch_name"`
+       EnablePush                    bool     `json:"enable_push"`
+       EnablePushWhitelist           bool     `json:"enable_push_whitelist"`
+       PushWhitelistUsernames        []string `json:"push_whitelist_usernames"`
+       PushWhitelistTeams            []string `json:"push_whitelist_teams"`
+       PushWhitelistDeployKeys       bool     `json:"push_whitelist_deploy_keys"`
+       EnableMergeWhitelist          bool     `json:"enable_merge_whitelist"`
+       MergeWhitelistUsernames       []string `json:"merge_whitelist_usernames"`
+       MergeWhitelistTeams           []string `json:"merge_whitelist_teams"`
+       EnableStatusCheck             bool     `json:"enable_status_check"`
+       StatusCheckContexts           []string `json:"status_check_contexts"`
+       RequiredApprovals             int64    `json:"required_approvals"`
+       EnableApprovalsWhitelist      bool     `json:"enable_approvals_whitelist"`
+       ApprovalsWhitelistUsernames   []string `json:"approvals_whitelist_username"`
+       ApprovalsWhitelistTeams       []string `json:"approvals_whitelist_teams"`
+       BlockOnRejectedReviews        bool     `json:"block_on_rejected_reviews"`
+       BlockOnOfficialReviewRequests bool     `json:"block_on_official_review_requests"`
+       BlockOnOutdatedBranch         bool     `json:"block_on_outdated_branch"`
+       DismissStaleApprovals         bool     `json:"dismiss_stale_approvals"`
+       RequireSignedCommits          bool     `json:"require_signed_commits"`
+       ProtectedFilePatterns         string   `json:"protected_file_patterns"`
        // swagger:strfmt date-time
        Created time.Time `json:"created_at"`
        // swagger:strfmt date-time
@@ -51,47 +52,49 @@ type BranchProtection struct {
 
 // CreateBranchProtectionOption options for creating a branch protection
 type CreateBranchProtectionOption struct {
-       BranchName                  string   `json:"branch_name"`
-       EnablePush                  bool     `json:"enable_push"`
-       EnablePushWhitelist         bool     `json:"enable_push_whitelist"`
-       PushWhitelistUsernames      []string `json:"push_whitelist_usernames"`
-       PushWhitelistTeams          []string `json:"push_whitelist_teams"`
-       PushWhitelistDeployKeys     bool     `json:"push_whitelist_deploy_keys"`
-       EnableMergeWhitelist        bool     `json:"enable_merge_whitelist"`
-       MergeWhitelistUsernames     []string `json:"merge_whitelist_usernames"`
-       MergeWhitelistTeams         []string `json:"merge_whitelist_teams"`
-       EnableStatusCheck           bool     `json:"enable_status_check"`
-       StatusCheckContexts         []string `json:"status_check_contexts"`
-       RequiredApprovals           int64    `json:"required_approvals"`
-       EnableApprovalsWhitelist    bool     `json:"enable_approvals_whitelist"`
-       ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
-       ApprovalsWhitelistTeams     []string `json:"approvals_whitelist_teams"`
-       BlockOnRejectedReviews      bool     `json:"block_on_rejected_reviews"`
-       BlockOnOutdatedBranch       bool     `json:"block_on_outdated_branch"`
-       DismissStaleApprovals       bool     `json:"dismiss_stale_approvals"`
-       RequireSignedCommits        bool     `json:"require_signed_commits"`
-       ProtectedFilePatterns       string   `json:"protected_file_patterns"`
+       BranchName                    string   `json:"branch_name"`
+       EnablePush                    bool     `json:"enable_push"`
+       EnablePushWhitelist           bool     `json:"enable_push_whitelist"`
+       PushWhitelistUsernames        []string `json:"push_whitelist_usernames"`
+       PushWhitelistTeams            []string `json:"push_whitelist_teams"`
+       PushWhitelistDeployKeys       bool     `json:"push_whitelist_deploy_keys"`
+       EnableMergeWhitelist          bool     `json:"enable_merge_whitelist"`
+       MergeWhitelistUsernames       []string `json:"merge_whitelist_usernames"`
+       MergeWhitelistTeams           []string `json:"merge_whitelist_teams"`
+       EnableStatusCheck             bool     `json:"enable_status_check"`
+       StatusCheckContexts           []string `json:"status_check_contexts"`
+       RequiredApprovals             int64    `json:"required_approvals"`
+       EnableApprovalsWhitelist      bool     `json:"enable_approvals_whitelist"`
+       ApprovalsWhitelistUsernames   []string `json:"approvals_whitelist_username"`
+       ApprovalsWhitelistTeams       []string `json:"approvals_whitelist_teams"`
+       BlockOnRejectedReviews        bool     `json:"block_on_rejected_reviews"`
+       BlockOnOfficialReviewRequests bool     `json:"block_on_official_review_requests"`
+       BlockOnOutdatedBranch         bool     `json:"block_on_outdated_branch"`
+       DismissStaleApprovals         bool     `json:"dismiss_stale_approvals"`
+       RequireSignedCommits          bool     `json:"require_signed_commits"`
+       ProtectedFilePatterns         string   `json:"protected_file_patterns"`
 }
 
 // EditBranchProtectionOption options for editing a branch protection
 type EditBranchProtectionOption struct {
-       EnablePush                  *bool    `json:"enable_push"`
-       EnablePushWhitelist         *bool    `json:"enable_push_whitelist"`
-       PushWhitelistUsernames      []string `json:"push_whitelist_usernames"`
-       PushWhitelistTeams          []string `json:"push_whitelist_teams"`
-       PushWhitelistDeployKeys     *bool    `json:"push_whitelist_deploy_keys"`
-       EnableMergeWhitelist        *bool    `json:"enable_merge_whitelist"`
-       MergeWhitelistUsernames     []string `json:"merge_whitelist_usernames"`
-       MergeWhitelistTeams         []string `json:"merge_whitelist_teams"`
-       EnableStatusCheck           *bool    `json:"enable_status_check"`
-       StatusCheckContexts         []string `json:"status_check_contexts"`
-       RequiredApprovals           *int64   `json:"required_approvals"`
-       EnableApprovalsWhitelist    *bool    `json:"enable_approvals_whitelist"`
-       ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
-       ApprovalsWhitelistTeams     []string `json:"approvals_whitelist_teams"`
-       BlockOnRejectedReviews      *bool    `json:"block_on_rejected_reviews"`
-       BlockOnOutdatedBranch       *bool    `json:"block_on_outdated_branch"`
-       DismissStaleApprovals       *bool    `json:"dismiss_stale_approvals"`
-       RequireSignedCommits        *bool    `json:"require_signed_commits"`
-       ProtectedFilePatterns       *string  `json:"protected_file_patterns"`
+       EnablePush                    *bool    `json:"enable_push"`
+       EnablePushWhitelist           *bool    `json:"enable_push_whitelist"`
+       PushWhitelistUsernames        []string `json:"push_whitelist_usernames"`
+       PushWhitelistTeams            []string `json:"push_whitelist_teams"`
+       PushWhitelistDeployKeys       *bool    `json:"push_whitelist_deploy_keys"`
+       EnableMergeWhitelist          *bool    `json:"enable_merge_whitelist"`
+       MergeWhitelistUsernames       []string `json:"merge_whitelist_usernames"`
+       MergeWhitelistTeams           []string `json:"merge_whitelist_teams"`
+       EnableStatusCheck             *bool    `json:"enable_status_check"`
+       StatusCheckContexts           []string `json:"status_check_contexts"`
+       RequiredApprovals             *int64   `json:"required_approvals"`
+       EnableApprovalsWhitelist      *bool    `json:"enable_approvals_whitelist"`
+       ApprovalsWhitelistUsernames   []string `json:"approvals_whitelist_username"`
+       ApprovalsWhitelistTeams       []string `json:"approvals_whitelist_teams"`
+       BlockOnRejectedReviews        *bool    `json:"block_on_rejected_reviews"`
+       BlockOnOfficialReviewRequests *bool    `json:"block_on_official_review_requests"`
+       BlockOnOutdatedBranch         *bool    `json:"block_on_outdated_branch"`
+       DismissStaleApprovals         *bool    `json:"dismiss_stale_approvals"`
+       RequireSignedCommits          *bool    `json:"require_signed_commits"`
+       ProtectedFilePatterns         *string  `json:"protected_file_patterns"`
 }
index 016211c7f8027a0ffbae7e7dec750045f99f53e2..1500bf73e908429a8a1fc5c0603d9b445e88a354 100644 (file)
@@ -1244,6 +1244,7 @@ pulls.required_status_check_missing = Some required checks are missing.
 pulls.required_status_check_administrator = As an administrator, you may still merge this pull request.
 pulls.blocked_by_approvals = "This Pull Request doesn't have enough approvals yet. %d of %d approvals granted."
 pulls.blocked_by_rejection = "This Pull Request has changes requested by an official reviewer."
+pulls.blocked_by_official_review_requests = "This Pull Request has official review requests."
 pulls.blocked_by_outdated_branch = "This Pull Request is blocked because it's outdated."
 pulls.blocked_by_changed_protected_files_1= "This Pull Request is blocked because it changes a protected file:"
 pulls.blocked_by_changed_protected_files_n= "This Pull Request is blocked because it changes protected files:"
@@ -1707,6 +1708,8 @@ settings.protected_branch_deletion = Disable Branch Protection
 settings.protected_branch_deletion_desc = Disabling branch protection allows users with write permission to push to the branch. Continue?
 settings.block_rejected_reviews = Block merge on rejected reviews
 settings.block_rejected_reviews_desc = Merging will not be possible when changes are requested by official reviewers, even if there are enough approvals.
+settings.block_on_official_review_requests = Block merge on official review requests
+settings.block_on_official_review_requests_desc = Merging will not be possible when it has official review requests, even if there are enough approvals.
 settings.block_outdated_branch = Block merge if pull request is outdated
 settings.block_outdated_branch_desc = Merging will not be possible when head branch is behind base branch.
 settings.default_branch_desc = Select a default repository branch for pull requests and code commits:
index 2b20ab048d0387e8dbf897fa97ca5e5a1494c9a5..9a0a552bad2a385ebf0258509af09f7cdd581c22 100644 (file)
@@ -509,21 +509,22 @@ func CreateBranchProtection(ctx *context.APIContext, form api.CreateBranchProtec
        }
 
        protectBranch = &models.ProtectedBranch{
-               RepoID:                   ctx.Repo.Repository.ID,
-               BranchName:               form.BranchName,
-               CanPush:                  form.EnablePush,
-               EnableWhitelist:          form.EnablePush && form.EnablePushWhitelist,
-               EnableMergeWhitelist:     form.EnableMergeWhitelist,
-               WhitelistDeployKeys:      form.EnablePush && form.EnablePushWhitelist && form.PushWhitelistDeployKeys,
-               EnableStatusCheck:        form.EnableStatusCheck,
-               StatusCheckContexts:      form.StatusCheckContexts,
-               EnableApprovalsWhitelist: form.EnableApprovalsWhitelist,
-               RequiredApprovals:        requiredApprovals,
-               BlockOnRejectedReviews:   form.BlockOnRejectedReviews,
-               DismissStaleApprovals:    form.DismissStaleApprovals,
-               RequireSignedCommits:     form.RequireSignedCommits,
-               ProtectedFilePatterns:    form.ProtectedFilePatterns,
-               BlockOnOutdatedBranch:    form.BlockOnOutdatedBranch,
+               RepoID:                        ctx.Repo.Repository.ID,
+               BranchName:                    form.BranchName,
+               CanPush:                       form.EnablePush,
+               EnableWhitelist:               form.EnablePush && form.EnablePushWhitelist,
+               EnableMergeWhitelist:          form.EnableMergeWhitelist,
+               WhitelistDeployKeys:           form.EnablePush && form.EnablePushWhitelist && form.PushWhitelistDeployKeys,
+               EnableStatusCheck:             form.EnableStatusCheck,
+               StatusCheckContexts:           form.StatusCheckContexts,
+               EnableApprovalsWhitelist:      form.EnableApprovalsWhitelist,
+               RequiredApprovals:             requiredApprovals,
+               BlockOnRejectedReviews:        form.BlockOnRejectedReviews,
+               BlockOnOfficialReviewRequests: form.BlockOnOfficialReviewRequests,
+               DismissStaleApprovals:         form.DismissStaleApprovals,
+               RequireSignedCommits:          form.RequireSignedCommits,
+               ProtectedFilePatterns:         form.ProtectedFilePatterns,
+               BlockOnOutdatedBranch:         form.BlockOnOutdatedBranch,
        }
 
        err = models.UpdateProtectBranch(ctx.Repo.Repository, protectBranch, models.WhitelistOptions{
@@ -652,6 +653,10 @@ func EditBranchProtection(ctx *context.APIContext, form api.EditBranchProtection
                protectBranch.BlockOnRejectedReviews = *form.BlockOnRejectedReviews
        }
 
+       if form.BlockOnOfficialReviewRequests != nil {
+               protectBranch.BlockOnOfficialReviewRequests = *form.BlockOnOfficialReviewRequests
+       }
+
        if form.DismissStaleApprovals != nil {
                protectBranch.DismissStaleApprovals = *form.DismissStaleApprovals
        }
index ded9b3c2086c1df0e011dd022f91011dc15a0ed0..6ebc5d6ecbfbd9d5e7ef11305b4a862fa14c0be6 100644 (file)
@@ -1455,6 +1455,7 @@ func ViewIssue(ctx *context.Context) {
                        cnt := pull.ProtectedBranch.GetGrantedApprovalsCount(pull)
                        ctx.Data["IsBlockedByApprovals"] = !pull.ProtectedBranch.HasEnoughApprovals(pull)
                        ctx.Data["IsBlockedByRejection"] = pull.ProtectedBranch.MergeBlockedByRejectedReview(pull)
+                       ctx.Data["IsBlockedByOfficialReviewRequests"] = pull.ProtectedBranch.MergeBlockedByOfficialReviewRequests(pull)
                        ctx.Data["IsBlockedByOutdatedBranch"] = pull.ProtectedBranch.MergeBlockedByOutdatedBranch(pull)
                        ctx.Data["GrantedApprovals"] = cnt
                        ctx.Data["RequireSigned"] = pull.ProtectedBranch.RequireSignedCommits
index f864e8a75c1f21025eff2589a187ee978799d121..c2e7bc8fac77a2753ec675dd8eff675ceae01dc8 100644 (file)
@@ -246,6 +246,7 @@ func SettingsProtectedBranchPost(ctx *context.Context, f auth.ProtectBranchForm)
                        }
                }
                protectBranch.BlockOnRejectedReviews = f.BlockOnRejectedReviews
+               protectBranch.BlockOnOfficialReviewRequests = f.BlockOnOfficialReviewRequests
                protectBranch.DismissStaleApprovals = f.DismissStaleApprovals
                protectBranch.RequireSignedCommits = f.RequireSignedCommits
                protectBranch.ProtectedFilePatterns = f.ProtectedFilePatterns
index 8e51583e9141bf9b21894dcf2bd90c6d0f528a3b..3d856724cdb191b99c753a3303fe8182f6887406 100644 (file)
@@ -591,6 +591,11 @@ func CheckPRReadyToMerge(pr *models.PullRequest, skipProtectedFilesCheck bool) (
                        Reason: "There are requested changes",
                }
        }
+       if pr.ProtectedBranch.MergeBlockedByOfficialReviewRequests(pr) {
+               return models.ErrNotAllowedToMerge{
+                       Reason: "There are official review requests",
+               }
+       }
 
        if pr.ProtectedBranch.MergeBlockedByOutdatedBranch(pr) {
                return models.ErrNotAllowedToMerge{
index dbecf644d9fc29a9bd0e7ebcbfc92149b5b9272c..9d8ea7ba8aced898454cf8c1b91c574837832e39 100644 (file)
@@ -84,6 +84,7 @@
        {{- else if .IsPullRequestBroken}}red
        {{- else if .IsBlockedByApprovals}}red
        {{- else if .IsBlockedByRejection}}red
+       {{- else if .IsBlockedByOfficialReviewRequests}}red
        {{- else if .IsBlockedByOutdatedBranch}}red
        {{- else if .IsBlockedByChangedProtectedFiles}}red
        {{- else if and .EnableStatusCheck (or .RequiredStatusCheckState.IsFailure .RequiredStatusCheckState.IsError)}}red
                                                <i class="icon icon-octicon">{{svg "octicon-x"}}</i>
                                        {{$.i18n.Tr "repo.pulls.blocked_by_rejection"}}
                                        </div>
+                               {{else if .IsBlockedByOfficialReviewRequests}}
+                                       <div class="item">
+                                               <i class="icon icon-octicon">{{svg "octicon-x"}}</i>
+                                       {{$.i18n.Tr "repo.pulls.blocked_by_official_review_requests"}}
+                                       </div>
                                {{else if .IsBlockedByOutdatedBranch}}
                                        <div class="item">
                                                <i class="icon icon-octicon">{{svg "octicon-x"}}</i>
                                                {{$.i18n.Tr (printf "repo.signing.wont_sign.%s" .WontSignReason) }}
                                        </div>
                                {{end}}
-                               {{$notAllOverridableChecksOk := or .IsBlockedByApprovals .IsBlockedByRejection .IsBlockedByOutdatedBranch .IsBlockedByChangedProtectedFiles (and .EnableStatusCheck (not .RequiredStatusCheckState.IsSuccess))}}
+                               {{$notAllOverridableChecksOk := or .IsBlockedByApprovals .IsBlockedByRejection .IsBlockedByOfficialReviewRequests .IsBlockedByOutdatedBranch .IsBlockedByChangedProtectedFiles (and .EnableStatusCheck (not .RequiredStatusCheckState.IsSuccess))}}
                                {{if and (or $.IsRepoAdmin (not $notAllOverridableChecksOk)) (or (not .AllowMerge) (not .RequireSigned) .WillSign)}}
                                        {{if $notAllOverridableChecksOk}}
                                                <div class="item">
                                {{else if .IsBlockedByRejection}}
                                        <div class="item text red">
                                                {{svg "octicon-x"}}
-                                       {{$.i18n.Tr "repo.pulls.blocked_by_rejection"}}
+                                               {{$.i18n.Tr "repo.pulls.blocked_by_rejection"}}
+                                       </div>
+                               {{else if .IsBlockedByOfficialReviewRequests}}
+                                       <div class="item text red">
+                                               {{svg "octicon-x"}}
+                                               {{$.i18n.Tr "repo.pulls.blocked_by_official_review_requests"}}
                                        </div>
                                {{else if .IsBlockedByOutdatedBranch}}
                                        <div class="item text red">
index 53a978e0684f701ec44b60da4bfc0f5d026c0685..1fbd28d8bd5e453afbfe0f91ef0043b1264231bc 100644 (file)
                                                        <p class="help">{{.i18n.Tr "repo.settings.block_rejected_reviews_desc"}}</p>
                                                </div>
                                        </div>
+                                       <div class="field">
+                                               <div class="ui checkbox">
+                                                       <input name="block_on_official_review_requests" type="checkbox" {{if .Branch.BlockOnOfficialReviewRequests}}checked{{end}}>
+                                                       <label for="block_on_official_review_requests">{{.i18n.Tr "repo.settings.block_on_official_review_requests"}}</label>
+                                                       <p class="help">{{.i18n.Tr "repo.settings.block_on_official_review_requests_desc"}}</p>
+                                               </div>
+                                       </div>
                                        <div class="field">
                                                <div class="ui checkbox">
                                                        <input name="dismiss_stale_approvals" type="checkbox" {{if .Branch.DismissStaleApprovals}}checked{{end}}>
index 8bcfc43d73f75d6f9f4f7d6c221dd63b74fe2a26..b121451ba6a8726f0ac66b15fdfa898ebad9ccd0 100644 (file)
           },
           "x-go-name": "ApprovalsWhitelistUsernames"
         },
+        "block_on_official_review_requests": {
+          "type": "boolean",
+          "x-go-name": "BlockOnOfficialReviewRequests"
+        },
         "block_on_outdated_branch": {
           "type": "boolean",
           "x-go-name": "BlockOnOutdatedBranch"
           },
           "x-go-name": "ApprovalsWhitelistUsernames"
         },
+        "block_on_official_review_requests": {
+          "type": "boolean",
+          "x-go-name": "BlockOnOfficialReviewRequests"
+        },
         "block_on_outdated_branch": {
           "type": "boolean",
           "x-go-name": "BlockOnOutdatedBranch"
           },
           "x-go-name": "ApprovalsWhitelistUsernames"
         },
+        "block_on_official_review_requests": {
+          "type": "boolean",
+          "x-go-name": "BlockOnOfficialReviewRequests"
+        },
         "block_on_outdated_branch": {
           "type": "boolean",
           "x-go-name": "BlockOnOutdatedBranch"