-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
Allow configuring default PR base branch (fixes #36412) #36425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 7 commits
10047b6
e52f187
9d5b6b4
668575e
c026345
8b7728b
32d1eee
e7363d5
3647385
9ecc21c
79b1ac5
c035282
1e7b108
4712e38
c3dd9c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| // Copyright 2026 The Gitea Authors. All rights reserved. | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| package repo | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "strings" | ||
|
|
||
| "code.gitea.io/gitea/models/db" | ||
| "code.gitea.io/gitea/models/unit" | ||
| "code.gitea.io/gitea/modules/util" | ||
| ) | ||
|
|
||
| // ErrDefaultPRBaseBranchNotExist represents an error that branch with such name does not exist. | ||
| type ErrDefaultPRBaseBranchNotExist struct { | ||
| RepoID int64 | ||
| BranchName string | ||
| } | ||
|
|
||
| // IsErrDefaultPRBaseBranchNotExist checks if an error is an ErrDefaultPRBaseBranchNotExist. | ||
| func IsErrDefaultPRBaseBranchNotExist(err error) bool { | ||
| _, ok := err.(ErrDefaultPRBaseBranchNotExist) | ||
| return ok | ||
| } | ||
|
|
||
| func (err ErrDefaultPRBaseBranchNotExist) Error() string { | ||
| return fmt.Sprintf("default PR base branch does not exist [repo_id: %d name: %s]", err.RepoID, err.BranchName) | ||
| } | ||
|
|
||
| func (err ErrDefaultPRBaseBranchNotExist) Unwrap() error { | ||
| return util.ErrNotExist | ||
| } | ||
|
|
||
| // GetDefaultPRBaseBranchSetting returns the configured base branch for new pull requests. | ||
| // It returns an empty string when unset or pull requests are disabled. | ||
| func (repo *Repository) GetDefaultPRBaseBranchSetting(ctx context.Context) string { | ||
| prUnit, err := repo.GetUnit(ctx, unit.TypePullRequests) | ||
| if err != nil { | ||
| return "" | ||
| } | ||
| cfg := prUnit.PullRequestsConfig() | ||
| if cfg == nil { | ||
| return "" | ||
| } | ||
| return strings.TrimSpace(cfg.DefaultPRBaseBranch) | ||
tototomate123 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| // GetDefaultPRBaseBranch returns the preferred base branch for new pull requests. | ||
| // It falls back to the repository default branch when unset or invalid. | ||
| func (repo *Repository) GetDefaultPRBaseBranch(ctx context.Context) string { | ||
| preferred := repo.GetDefaultPRBaseBranchSetting(ctx) | ||
| if preferred != "" { | ||
| exists, err := isBranchNameExists(ctx, repo.ID, preferred) | ||
| if err == nil && exists { | ||
| return preferred | ||
| } | ||
| } | ||
| return repo.DefaultBranch | ||
| } | ||
|
|
||
| // ValidateDefaultPRBaseBranch checks whether a preferred base branch is valid. | ||
| func (repo *Repository) ValidateDefaultPRBaseBranch(ctx context.Context, branch string) error { | ||
| branch = strings.TrimSpace(branch) | ||
| if branch == "" { | ||
| return nil | ||
| } | ||
|
|
||
| exists, err := isBranchNameExists(ctx, repo.ID, branch) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if !exists { | ||
| return ErrDefaultPRBaseBranchNotExist{ | ||
| RepoID: repo.ID, | ||
| BranchName: branch, | ||
| } | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func isBranchNameExists(ctx context.Context, repoID int64, branchName string) (bool, error) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aren't there some similar functions?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's |
||
| type branch struct { | ||
| IsDeleted bool `xorm:"is_deleted"` | ||
| } | ||
| var b branch | ||
| has, err := db.GetEngine(ctx). | ||
| Where("repo_id = ?", repoID). | ||
| And("name = ?", branchName). | ||
| Get(&b) | ||
| if err != nil { | ||
| return false, err | ||
| } | ||
| if !has { | ||
| return false, nil | ||
| } | ||
| return !b.IsDeleted, nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // Copyright 2026 The Gitea Authors. All rights reserved. | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| package repo | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "code.gitea.io/gitea/models/unit" | ||
| "code.gitea.io/gitea/models/unittest" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| ) | ||
|
|
||
| func TestDefaultPRBaseBranchSelection(t *testing.T) { | ||
| assert.NoError(t, unittest.PrepareTestDatabase()) | ||
|
|
||
| ctx := t.Context() | ||
| repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 1}) | ||
|
|
||
| assert.Equal(t, repo.DefaultBranch, repo.GetDefaultPRBaseBranch(ctx)) | ||
|
|
||
| repo.Units = nil | ||
| prUnit, err := repo.GetUnit(ctx, unit.TypePullRequests) | ||
| assert.NoError(t, err) | ||
| prConfig := prUnit.PullRequestsConfig() | ||
| prConfig.DefaultPRBaseBranch = "branch2" | ||
| prUnit.Config = prConfig | ||
| assert.NoError(t, UpdateRepoUnit(ctx, prUnit)) | ||
| repo.Units = nil | ||
| assert.Equal(t, "branch2", repo.GetDefaultPRBaseBranch(ctx)) | ||
|
|
||
| err = repo.ValidateDefaultPRBaseBranch(ctx, "does-not-exist") | ||
| assert.True(t, IsErrDefaultPRBaseBranchNotExist(err)) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -247,7 +247,7 @@ func ParseCompareInfo(ctx *context.Context) *git_service.CompareInfo { | |
| } | ||
|
|
||
| // 4 get base and head refs | ||
| baseRefName := util.IfZero(compareReq.BaseOriRef, baseRepo.DefaultBranch) | ||
| baseRefName := util.IfZero(compareReq.BaseOriRef, baseRepo.GetDefaultPRBaseBranch(ctx)) | ||
|
||
| headRefName := util.IfZero(compareReq.HeadOriRef, headRepo.DefaultBranch) | ||
|
|
||
| baseRef := ctx.Repo.GitRepo.UnstableGuessRefByShortName(baseRefName) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.