Add DEFAULT_TITLE_SOURCE setting for pull request title default behavior (#37465)

Adds a new `DEFAULT_TITLE_SOURCE` option under
`[repository.pull-request]` with three values:

- `first-commit` (default): uses the oldest commit summary, current
behavior since v1.26
- `auto`: normalizes branch name as title for multi-commit PRs (just
like GitHub), use commit summary for single-commit PRs

Closes: #37463
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
Co-authored-by: Nicolas <bircni@icloud.com>
This commit is contained in:
0xGREG
2026-04-28 23:33:20 +02:00
committed by GitHub
parent deec2b0929
commit 0ba862cb97
4 changed files with 106 additions and 19 deletions
+41 -4
View File
@@ -13,6 +13,7 @@ import (
"path/filepath"
"sort"
"strings"
"unicode"
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
@@ -349,13 +350,46 @@ func parseCompareInfo(ctx *context.Context) (*git_service.CompareInfo, error) {
return &compareInfo, nil
}
func prepareNewPullRequestTitleContent(ci *git_service.CompareInfo, commits []*git_model.SignCommitWithStatuses) (title, content string) {
title = ci.HeadRef.ShortName()
// autoTitleFromBranchName humanizes a branch name into a PR title.
func autoTitleFromBranchName(name string) string {
var buf strings.Builder
var prevIsSpace bool
runes := []rune(name)
for i, r := range runes {
isSpace := unicode.IsSpace(r)
if r == '-' || r == '_' || isSpace {
if !prevIsSpace {
buf.WriteRune(' ')
}
prevIsSpace = true
continue
}
if !prevIsSpace && unicode.IsUpper(r) {
needSpace := i > 0 && unicode.IsLower(runes[i-1]) || i < len(runes)-1 && unicode.IsLower(runes[i+1])
if needSpace {
buf.WriteRune(' ')
}
}
buf.WriteRune(unicode.ToLower(r))
prevIsSpace = isSpace
}
out := strings.TrimSpace(buf.String())
if out == "" {
return out
}
outRunes := []rune(out)
outRunes[0] = unicode.ToUpper(outRunes[0])
return string(outRunes)
}
if len(commits) > 0 {
func prepareNewPullRequestTitleContent(ci *git_service.CompareInfo, commits []*git_model.SignCommitWithStatuses, defaultTitleSource string) (title, content string) {
useFirstCommitAsTitle := len(commits) == 1 || (defaultTitleSource == setting.RepoPRTitleSourceFirstCommit && len(commits) > 0)
if useFirstCommitAsTitle {
// the "commits" are from "ShowPrettyFormatLogToList", which is ordered from newest to oldest, here take the oldest one
c := commits[len(commits)-1]
title = strings.TrimSpace(c.UserCommit.Summary())
} else {
title = autoTitleFromBranchName(ci.HeadRef.ShortName())
}
if len(commits) == 1 {
@@ -491,7 +525,10 @@ func prepareCompareDiff(ctx *context.Context, ci *git_service.CompareInfo, white
ctx.Data["Commits"] = commits
ctx.Data["CommitCount"] = len(commits)
ctx.Data["title"], ctx.Data["content"] = prepareNewPullRequestTitleContent(ci, commits)
ctx.Data["title"], ctx.Data["content"] = prepareNewPullRequestTitleContent(ci, commits, setting.Repository.PullRequest.DefaultTitleSource)
ctx.Data["Username"] = ci.HeadRepo.OwnerName
ctx.Data["Reponame"] = ci.HeadRepo.Name
setCompareContext(ctx, beforeCommit, headCommit, ci.HeadRepo.OwnerName, repo.Name)
return false