Add bypass allowlist for branch protection#36514
Add bypass allowlist for branch protection#36514bircni wants to merge 25 commits intogo-gitea:mainfrom
Conversation
03c404c to
36d1fbf
Compare
There was a problem hiding this comment.
Pull request overview
This pull request introduces a "Bypass Protection Allowlist" feature for branch protection rules, allowing specific users and teams to bypass branch protection checks (required approvals, status checks, and protected files) without requiring full administrator privileges. This addresses the need for "Merge Masters" or "Technical Leads" who need bypass capabilities while following the Principle of Least Privilege.
Changes:
- Added database columns
EnableBypassAllowlist,BypassAllowlistUserIDs, andBypassAllowlistTeamIDsto theProtectedBranchmodel with migration v326 - Implemented
CanBypassBranchProtectionhelper function that checks both admin privileges and allowlist membership - Extended API endpoints and Swagger documentation to support bypass allowlist configuration
- Updated branch protection settings UI to allow configuration of bypass users and teams
- Modified pull request merge box to display appropriate messages for bypass-capable users
- Applied bypass logic in pre-receive hooks and merge checks to allow allowlisted users to override unmet requirements
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| models/migrations/v1_26/v326.go | Migration adding three new columns to ProtectedBranch table for bypass allowlist feature |
| models/migrations/migrations.go | Registers the new migration v326 |
| models/git/protected_branch.go | Adds bypass allowlist fields to ProtectedBranch model and implements CanBypassBranchProtection function |
| models/git/protected_branch_test.go | Unit tests for CanBypassBranchProtection covering various scenarios |
| modules/structs/repo_branch.go | Extends API structs (BranchProtection, CreateBranchProtectionOption, EditBranchProtectionOption) with bypass allowlist fields |
| routers/api/v1/repo/branch.go | Updates API endpoints to handle bypass allowlist users and teams during branch protection creation and editing |
| routers/web/repo/setting/protected_branch.go | Handles bypass allowlist data in web UI forms for branch protection settings |
| routers/web/repo/issue_view.go | Sets template data for bypass permissions to control merge button visibility and messages |
| routers/private/hook_pre_receive.go | Applies bypass logic in pre-receive hook to allow bypass users to push despite protection checks |
| services/pull/check.go | Uses CanBypassBranchProtection in merge checks instead of admin-only check, updates comment |
| services/pull/check_test.go | Removes redundant queue.Has() checks that could cause test flakiness |
| services/forms/repo_form.go | Adds bypass allowlist fields to ProtectBranchForm |
| services/convert/convert.go | Converts bypass allowlist IDs to usernames/team names for API responses |
| templates/repo/settings/protected_branch.tmpl | UI form for configuring bypass allowlist users and teams |
| templates/repo/issue/view_content/pull_merge_box.tmpl | Displays context-appropriate message when bypass user can force merge |
| templates/swagger/v1_json.tmpl | Swagger documentation for bypass allowlist fields in API |
| options/locale/locale_en-US.json | Locale strings for bypass allowlist UI elements and messages |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
36d1fbf to
da1f775
Compare
ReviewI reviewed the full diff. The overall structure follows existing patterns well (model fields, migration, API plumbing, settings UI, template). A few observations: 1. Breaking behavior change in pre-receive hookThe original if ctx.userPerm.IsAdmin() {
return
}The new code replaces this with This is arguably more correct behavior (closing an inconsistency), but it is a breaking change for existing setups and should be called out explicitly in the PR description and release notes. 2. Unrelated test change in
|
|
What do we do about point 1? Is it worth calling out a breaking change? I think not as it's probably too obscure of a feature. |
|
I would not call it breaking but idk |
|
Ok, please address points 3 and 4 if you can. |
|
both are already done - I think |
|
any screenshot of the added ui? |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
fixed |
|
Fix merge conflicts please and show a screenshot of the added UI. |
03d5b44 to
b108b00
Compare
|
@silverwind Done - here a screenshot |
|
Updated so no conflicts |
|
Also added a test which I somehow forgot back then :-( |
0831502 to
96f4123
Compare
| cacheKey := fmt.Sprintf("%d:%d:%v", user.ID, protectBranch.RepoID, protectBranch.BypassAllowlistTeamIDs) | ||
| in, err := cache.GetWithContextCache(ctx, cachegroup.BypassAllowlist, cacheKey, func(ctx context.Context, _ string) (bool, error) { | ||
| return organization.IsUserInTeams(ctx, user.ID, protectBranch.BypassAllowlistTeamIDs) | ||
| }) |




still respected.
message for bypass-capable users.
protected files when force-merging.
Fixes #36476