perf(pr): read the pull request template with one request

Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
bircni committed 2026-10-18 17:17:51 +02:00
1 parent 5f878c86ed
commit 0b7e2f01b0
3 files changed
+79 -21

No files matched your search

+34 -11
View File
@@ -15,6 +15,7 @@ import (
"slices"
"strconv"
"strings"
"sync"
"time"
gitea "gitea.dev/sdk"
@@ -474,20 +475,42 @@ var pullTemplatePaths = []string{
const maxPullTemplateBytes = 1 << 20
// Template returns the first pull request template found at ref, or "" when the repository has none.
// All paths are probed concurrently; the result is decided in priority order, so a failure is
// reported only when every higher-priority path is missing.
func (s Pulls) Template(ctx context.Context, ref string) (string, error) {
for _, path := range pullTemplatePaths {
file, err := repoCall(ctx, s.Client, s.Repository, func(ctx context.Context, c *gitea.Client, owner, name string) (io.ReadCloser, *gitea.Response, error) {
return c.Repositories.GetFileReader(ctx, owner, name, ref, path)
type probe struct {
content string
missing bool
err error
}
probes := make([]probe, len(pullTemplatePaths))
var wg sync.WaitGroup
for i, path := range pullTemplatePaths {
wg.Go(func() {
probes[i].content, probes[i].missing, probes[i].err = s.templateAt(ctx, ref, path)
})
if err != nil {
if IsNotFound(err) {
continue
}
return "", err
}
wg.Wait()
for _, p := range probes {
if !p.missing {
return p.content, p.err
}
data, err := io.ReadAll(io.LimitReader(file, maxPullTemplateBytes))
_ = file.Close()
return string(data), err
}
return "", nil
}
// templateAt reads one template path; missing reports a 404.
func (s Pulls) templateAt(ctx context.Context, ref, path string) (content string, missing bool, err error) {
file, err := repoCall(ctx, s.Client, s.Repository, func(ctx context.Context, c *gitea.Client, owner, name string) (io.ReadCloser, *gitea.Response, error) {
return c.Repositories.GetFileReader(ctx, owner, name, ref, path)
})
if err != nil {
if IsNotFound(err) {
return "", true, nil
}
return "", false, err
}
data, err := io.ReadAll(io.LimitReader(file, maxPullTemplateBytes))
_ = file.Close()
return string(data), false, err
}