fix: avoid enumerating every public repository in issue search (#38992)

Both issue search endpoints resolve their repository filter with
`SearchRepositoryIDs` and pass the result to the indexer as `RepoIDs`.
They mean
to leave public repositories to the indexer, but
`SearchRepoOptions.AllPublic` is
only read when `OwnerID > 0`, so without an `owner` filter the flag does
nothing
and every public repository is enumerated, without a `LIMIT`, into
`repo_id IN (...)`.

Those IDs are redundant, as `allPublic` is passed to the indexer, which
already
matches every public repository. On a large instance this binds tens of
thousands
of parameters and can fail in the driver, making the endpoint return 500
for every
filter. Admins are worst hit, as `SearchRepositoryCondition` skips their
accessible-repository condition and enumerates the whole table.

Restrict the enumeration to private repositories. The result set is
unchanged, as
the dropped IDs are a subset of what `allPublic` matches.

Both endpoints held copies of this block, so it moves to
`routers/common`.

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Lunny Xiao
2026-08-20 09:29:54 -07:00
committed by GitHub
parent 943f026844
commit 475e51c7e0
5 changed files with 189 additions and 162 deletions
+9
View File
@@ -768,6 +768,15 @@ func PublicRepoUnderPublicOwnerCond() builder.Cond {
)
}
// NotPublicRepoUnderPublicOwnerCond complements PublicRepoUnderPublicOwnerCond. Spelled positively so
// the owner subquery hashes the limited/private minority, not every public user.
func NotPublicRepoUnderPublicOwnerCond() builder.Cond {
return builder.Or(
builder.Eq{"`repository`.is_private": true},
builder.In("`repository`.owner_id", builder.Select("id").From("`user`").Where(builder.Neq{"visibility": structs.VisibleTypePublic})),
)
}
// UserActionsAccessibleOwnerRepoCond selects the repos owned by ownerID whose Actions `user` may read.
// It is used to list an org/user's Actions runs and jobs (see the callers in routers/api/v1/shared).
// - owner_id = ownerID: only that owner's repos.