Skip to content

Commit 8f21815

Browse files
jpraetdelvh
authored andcommitted
Add branch protection setting for ignoring stale approvals (go-gitea#28498)
Fixes go-gitea#27114. * In Gitea 1.12 (go-gitea#9532), a "dismiss stale approvals" branch protection setting was introduced, for ignoring stale reviews when verifying the approval count of a pull request. * In Gitea 1.14 (go-gitea#12674), the "dismiss review" feature was added. * This caused confusion with users (go-gitea#25858), as "dismiss" now means 2 different things. * In Gitea 1.20 (go-gitea#25882), the behavior of the "dismiss stale approvals" branch protection was modified to actually dismiss the stale review. For some users this new behavior of dismissing the stale reviews is not desirable. So this PR reintroduces the old behavior as a new "ignore stale approvals" branch protection setting. --------- Co-authored-by: delvh <dev.lh@web.de>
1 parent 20b02d8 commit 8f21815

File tree

12 files changed

+53
-2
lines changed

12 files changed

+53
-2
lines changed

models/git/protected_branch.go

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type ProtectedBranch struct {
5454
BlockOnOfficialReviewRequests bool `xorm:"NOT NULL DEFAULT false"`
5555
BlockOnOutdatedBranch bool `xorm:"NOT NULL DEFAULT false"`
5656
DismissStaleApprovals bool `xorm:"NOT NULL DEFAULT false"`
57+
IgnoreStaleApprovals bool `xorm:"NOT NULL DEFAULT false"`
5758
RequireSignedCommits bool `xorm:"NOT NULL DEFAULT false"`
5859
ProtectedFilePatterns string `xorm:"TEXT"`
5960
UnprotectedFilePatterns string `xorm:"TEXT"`

models/issues/pull.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ func GetGrantedApprovalsCount(ctx context.Context, protectBranch *git_model.Prot
801801
And("type = ?", ReviewTypeApprove).
802802
And("official = ?", true).
803803
And("dismissed = ?", false)
804-
if protectBranch.DismissStaleApprovals {
804+
if protectBranch.IgnoreStaleApprovals {
805805
sess = sess.And("stale = ?", false)
806806
}
807807
approvals, err := sess.Count(new(Review))

models/migrations/v1_22/v284.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_22 //nolint
5+
import (
6+
"xorm.io/xorm"
7+
)
8+
9+
func AddIgnoreStaleApprovalsColumnToProtectedBranchTable(x *xorm.Engine) error {
10+
type ProtectedBranch struct {
11+
IgnoreStaleApprovals bool `xorm:"NOT NULL DEFAULT false"`
12+
}
13+
return x.Sync(new(ProtectedBranch))
14+
}

modules/structs/repo_branch.go

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type BranchProtection struct {
4343
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
4444
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
4545
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
46+
IgnoreStaleApprovals bool `json:"ignore_stale_approvals"`
4647
RequireSignedCommits bool `json:"require_signed_commits"`
4748
ProtectedFilePatterns string `json:"protected_file_patterns"`
4849
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
@@ -75,6 +76,7 @@ type CreateBranchProtectionOption struct {
7576
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
7677
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
7778
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
79+
IgnoreStaleApprovals bool `json:"ignore_stale_approvals"`
7880
RequireSignedCommits bool `json:"require_signed_commits"`
7981
ProtectedFilePatterns string `json:"protected_file_patterns"`
8082
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
@@ -100,6 +102,7 @@ type EditBranchProtectionOption struct {
100102
BlockOnOfficialReviewRequests *bool `json:"block_on_official_review_requests"`
101103
BlockOnOutdatedBranch *bool `json:"block_on_outdated_branch"`
102104
DismissStaleApprovals *bool `json:"dismiss_stale_approvals"`
105+
IgnoreStaleApprovals *bool `json:"ignore_stale_approvals"`
103106
RequireSignedCommits *bool `json:"require_signed_commits"`
104107
ProtectedFilePatterns *string `json:"protected_file_patterns"`
105108
UnprotectedFilePatterns *string `json:"unprotected_file_patterns"`

options/locale/locale_en-US.ini

+2
Original file line numberDiff line numberDiff line change
@@ -2315,6 +2315,8 @@ settings.protect_approvals_whitelist_users = Whitelisted reviewers:
23152315
settings.protect_approvals_whitelist_teams = Whitelisted teams for reviews:
23162316
settings.dismiss_stale_approvals = Dismiss stale approvals
23172317
settings.dismiss_stale_approvals_desc = When new commits that change the content of the pull request are pushed to the branch, old approvals will be dismissed.
2318+
settings.ignore_stale_approvals = Ignore stale approvals
2319+
settings.ignore_stale_approvals_desc = Do not count approvals that were made on older commits (stale reviews) towards how many approvals the PR has. Irrelevant if stale reviews are already dismissed.
23182320
settings.require_signed_commits = Require Signed Commits
23192321
settings.require_signed_commits_desc = Reject pushes to this branch if they are unsigned or unverifiable.
23202322
settings.protect_branch_name_pattern = Protected Branch Name Pattern

routers/api/v1/repo/branch.go

+5
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ func CreateBranchProtection(ctx *context.APIContext) {
615615
BlockOnRejectedReviews: form.BlockOnRejectedReviews,
616616
BlockOnOfficialReviewRequests: form.BlockOnOfficialReviewRequests,
617617
DismissStaleApprovals: form.DismissStaleApprovals,
618+
IgnoreStaleApprovals: form.IgnoreStaleApprovals,
618619
RequireSignedCommits: form.RequireSignedCommits,
619620
ProtectedFilePatterns: form.ProtectedFilePatterns,
620621
UnprotectedFilePatterns: form.UnprotectedFilePatterns,
@@ -786,6 +787,10 @@ func EditBranchProtection(ctx *context.APIContext) {
786787
protectBranch.DismissStaleApprovals = *form.DismissStaleApprovals
787788
}
788789

790+
if form.IgnoreStaleApprovals != nil {
791+
protectBranch.IgnoreStaleApprovals = *form.IgnoreStaleApprovals
792+
}
793+
789794
if form.RequireSignedCommits != nil {
790795
protectBranch.RequireSignedCommits = *form.RequireSignedCommits
791796
}

routers/web/repo/setting/protected_branch.go

+1
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ func SettingsProtectedBranchPost(ctx *context.Context) {
228228
protectBranch.BlockOnRejectedReviews = f.BlockOnRejectedReviews
229229
protectBranch.BlockOnOfficialReviewRequests = f.BlockOnOfficialReviewRequests
230230
protectBranch.DismissStaleApprovals = f.DismissStaleApprovals
231+
protectBranch.IgnoreStaleApprovals = f.IgnoreStaleApprovals
231232
protectBranch.RequireSignedCommits = f.RequireSignedCommits
232233
protectBranch.ProtectedFilePatterns = f.ProtectedFilePatterns
233234
protectBranch.UnprotectedFilePatterns = f.UnprotectedFilePatterns

services/convert/convert.go

+1
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch) *api
158158
BlockOnOfficialReviewRequests: bp.BlockOnOfficialReviewRequests,
159159
BlockOnOutdatedBranch: bp.BlockOnOutdatedBranch,
160160
DismissStaleApprovals: bp.DismissStaleApprovals,
161+
IgnoreStaleApprovals: bp.IgnoreStaleApprovals,
161162
RequireSignedCommits: bp.RequireSignedCommits,
162163
ProtectedFilePatterns: bp.ProtectedFilePatterns,
163164
UnprotectedFilePatterns: bp.UnprotectedFilePatterns,

services/forms/repo_form.go

+1
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ type ProtectBranchForm struct {
212212
BlockOnOfficialReviewRequests bool
213213
BlockOnOutdatedBranch bool
214214
DismissStaleApprovals bool
215+
IgnoreStaleApprovals bool
215216
RequireSignedCommits bool
216217
ProtectedFilePatterns string
217218
UnprotectedFilePatterns string

templates/repo/settings/protected_branch.tmpl

+8-1
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,18 @@
144144
</div>
145145
<div class="field">
146146
<div class="ui checkbox">
147-
<input name="dismiss_stale_approvals" type="checkbox" {{if .Rule.DismissStaleApprovals}}checked{{end}}>
147+
<input id="dismiss_stale_approvals" name="dismiss_stale_approvals" type="checkbox" {{if .Rule.DismissStaleApprovals}}checked{{end}}>
148148
<label>{{ctx.Locale.Tr "repo.settings.dismiss_stale_approvals"}}</label>
149149
<p class="help">{{ctx.Locale.Tr "repo.settings.dismiss_stale_approvals_desc"}}</p>
150150
</div>
151151
</div>
152+
<div id="ignore_stale_approvals_box" class="field {{if .Rule.DismissStaleApprovals}}disabled{{end}}">
153+
<div class="ui checkbox">
154+
<input id="ignore_stale_approvals" name="ignore_stale_approvals" type="checkbox" {{if .Rule.IgnoreStaleApprovals}}checked{{end}}>
155+
<label>{{ctx.Locale.Tr "repo.settings.ignore_stale_approvals"}}</label>
156+
<p class="help">{{ctx.Locale.Tr "repo.settings.ignore_stale_approvals_desc"}}</p>
157+
</div>
158+
</div>
152159
<div class="grouped fields">
153160
<div class="field">
154161
<div class="ui checkbox">

templates/swagger/v1_json.tmpl

+12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web_src/js/features/repo-settings.js

+4
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ export function initRepoSettingBranches() {
8282
const $target = $($(this).attr('data-target'));
8383
if (this.checked) $target.addClass('disabled'); // only disable, do not auto enable
8484
});
85+
$('#dismiss_stale_approvals').on('change', function () {
86+
const $target = $('#ignore_stale_approvals_box');
87+
$target.toggleClass('disabled', this.checked);
88+
});
8589

8690
// show the `Matched` mark for the status checks that match the pattern
8791
const markMatchedStatusChecks = () => {

0 commit comments

Comments
 (0)