22020 Commits

Author SHA1 Message Date
silverwind
3c41728017 test(e2e): assert server-rendered biography after profile update (#40176)
Since Playwright 1.56, a WebKit click on a native submit button can
return before the form navigation starts, so `toHaveValue` passed on the
old page with the value `fill()` just set, and the next step raced the
reload.

Assert the textarea's text instead, its server-rendered default, which
only the reloaded page has.

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-11-09 21:50:27 +00:00
Trung Hehe
06b393e402 feat(ldap): support multiple comma-separated LDAP hosts for failover (#6898) (#40201)
Allows an LDAP auth source to list multiple comma-separated servers in
the Host field so logins continue working when one server is
unreachable. Entries can be plain hosts using the configured Port and
Security Protocol fields or `ldap://`, `ldaps://`, or `ldap+starttls://`
URLs with their own port and protocol (as proposed in
https://github.com/go-gitea/gitea/pull/31649#issuecomment-2505555133),
with TLS protocol consistency enforced so an entry cannot silently
downgrade encryption.

Hosts are tried in order with a 250 ms head start each so an
unresponsive server does not block logins for the full 60 s connect
timeout, and only connection failures fail over to the next host so
failed binds are not retried across servers. Existing single-host
configurations continue to work unchanged without a migration.

Docs: https://gitea.com/gitea/docs/pulls/635
Fixes https://github.com/go-gitea/gitea/issues/6898
/claim #6898

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-09 21:45:12 +00:00
Lunny Xiao
3561478109 fix(projects): move only the dragged card on project boards (#40182)
The board reported every card of the target column on each drag, and the
server wrote all of them into that column. A stale board in another
browser therefore pulled cards moved by someone else back to their old
column.

The client now sends only the dragged issue and its predecessor, and the
server computes the position in one transaction:

- Only the dragged issue changes column, the others are just renumbered.
- A predecessor that is no longer in the column puts the card at the
end.

Added an e2e test.

Fixes https://github.com/go-gitea/gitea/issues/21243
Fixes https://github.com/go-gitea/gitea/issues/32070
Fixes https://github.com/go-gitea/gitea/issues/13498

---
Assisted-by: Codet:claude

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-09 21:39:22 +00:00
Shudhanshu Singh
2d6dca9abb fix(ui): improve user filter dropdown when no remote search is configured (#40296)
On the dashboard issue and pull request pages, author and assignee
filters only accept direct username input since candidate lists across
all accessible repositories cannot be pre-fetched. However, the dropdown
inherited several confusing artifacts from the repository-level user
search:

- Displayed a misleading "Shows a maximum of 30 users" tooltip even
though no remote user list was fetched.
- Used "Search users" as placeholder rather than indicating direct
username input.
- Pressing Enter in the input had no effect, requiring mouse selection.
- Any active username filter was not reflected in the dropdown menu on
open.

This change:
- Only renders the 30-user tooltip when a remote search URL is provided.
- Uses "Filter by username…" as placeholder when no remote search URL
exists.
- Applies the filter on Enter keypress.
- Ensures the active username is displayed and selected when opening the
menu.

Fixes: https://github.com/go-gitea/gitea/issues/40275
Fixes: https://github.com/go-gitea/gitea/issues/33426

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-09 21:34:43 +00:00
Lunny Xiao
bccc90d654 fix(api): lock and unlock issues as the signed-in user, not the repository owner (#40291)
`PUT/DELETE /repos/{owner}/{repo}/issues/{index}/lock` passed
`ctx.ContextUser` as the doer of `LockIssue` / `UnlockIssue`. In the
repo routes that is the owner of the repository, so on a repository of
an organization the lock and unlock timeline comments were created by
the organization instead of the user who did it. The web handler already
uses the signed-in user; this uses `ctx.Doer` as well.

Adds a subtest `DoerOnOrganizationRepo` to the existing
`TestAPILockIssue`: a member of an organization locks and unlocks an
issue of an organization repository, and the comments must be posted by
that member.

Found while testing audit logging of the issue lock events downstream.

_Authored by Codet (Claude)._
2026-11-09 18:00:06 +00:00
wxiaoguang
772f365254 refactor: use RunWithStderr for git commands (#40295)
If the stderr output is not handled, then it needs to use RunWithStderr
to make sure the git error message is included in the returned error.
Otherwise, when the git command fails, the error log won't show useful
information.

Ref:

* #39795 : no useful information in log messages
*
https://github.com/go-gitea/gitea/pull/40160#pullrequestreview-5752720866
2026-11-09 17:59:52 +00:00
bircni
e0b2f3425e fix(actions): run pull_request workflows on the merge commit (#40076)
`pull_request` workflow runs checked out the PR head, so a PR could pass
CI and still break the base branch once merged.

Gitea now maintains `refs/pull/<index>/merge`, a test merge of the head
into the base branch, for open pull requests. It is updated on creation
and mergeability checks and removed on close or merge.

- `pull_request` runs read their workflows from the test merge and
expose it as `github.ref`, `github.sha` and
`github.event.pull_request.merge_commit_sha`. Commit statuses, the API's
`head_sha`, `workflow_run` payloads and `paths` filters stay on the
head.
- Runs fall back to the head when the merge conflicts, the pull request
is closed or git is older than 2.40.
- Hidden refs keep each run's test merge (`refs/gitea/run/<id>`) and
merged commits (`refs/gitea/pull/<index>/merged`) from `git gc`, for
reruns and after the base branch is deleted or force-pushed.

Fixes: https://github.com/go-gitea/gitea/issues/27039
Fixes: https://github.com/go-gitea/gitea/issues/13134
Fixes: https://github.com/go-gitea/gitea/issues/30972
Docs: https://gitea.com/gitea/docs/pulls/617

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-09 12:42:40 +00:00
wxiaoguang
0ab0bfc375 fix: don't log network error in console when loading issue popup (#40288)
* fix #40286

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-09 05:59:03 +00:00
Giteabot
f3354aa902 chore(deps): update dependencies (#40292)
Updates JS, Go, Python and Actions dependencies, including the stylelint
18 and stylelint-config-recommended 19 majors.

- Update clippie to 4.3.1, which fixes copy buttons in browsers without
`ClipboardItem` such as Pale Moon
- Exempt the markup `tt` selectors from the new `selector-no-deprecated`
rule, the sanitizer allows `<tt>`
- Replace the `stylelint-value-no-unknown-custom-properties` plugin with
stylelint's `referenceFiles` and the core `no-unknown-*` rules
- Remove dead dropdown loading icon styles that referenced deleted
keyframes

Fixes: https://github.com/go-gitea/gitea/issues/40287

Assisted-by: Claude Code:claude-opus-5-5

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-09 05:32:54 +00:00
Shudhanshu Singh
7b1cde99d0 perf(charset): skip plain ASCII text when escaping control characters (#39937)
Every line of file, blame, diff and code preview views goes through
`EscapeControlHTML`, which streamed it through a 32 KiB read buffer and
copied every tag and text part. Views render the `EscapeStatus` before
the content, so every caller holds the complete HTML and streaming can't
help. It is now escaped in one pass over the string and returned
unchanged when nothing needs escaping.

- Skip text of printable ASCII, tabs and newlines, such lines return
immediately
- Render markup and wiki pages into a buffer instead of a pipe and
goroutine, and remove `EscapeControlReader`
- Analyze long text parts in windows overlapping by the detection
context, which bounds memory without changing results
- Escape invalid bytes before a tag, they were moved into the tag part
unescaped and could hide a `<math>` tag

| | before | after |
|---|---|---|
| ASCII line | 5.1 µs, 59 allocs | 0.08 µs, 1 alloc |
| line with one `é` | 3.9 µs, 30 allocs | 0.29 µs, 3 allocs |
| 150 KB document | 2.5 ms, 5.6 MB | 0.27 ms, 0.6 KB |

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-11-09 03:42:30 +00:00
GiteaBot
2bbac68f45 [skip ci] Updated translations via Crowdin 2026-11-09 00:36:42 +00:00
silverwind
d715a5ae75 test(api): cover null milestone due_on (#40172)
Removing a milestone deadline with `"due_on": null` was untested, only
`""` was. On release/v28 the null case returned HTTP 500
(https://github.com/go-gitea/gitea/pull/40171). main already handles it,
this adds the case to the existing test so it stays that way.
2026-11-08 20:53:59 +00:00
Lunny Xiao
1554b6c939 feat!: remove repository adopt feature (#40181)
Remove the "adopt unadopted repositories" feature. Adopting assumes a
fixed repository storage path on disk, which makes the storage path hard
to change. It is mostly used once for migrations, and the [Gitea
importer](https://gitea.com/gitea/importer) covers that after the
repositories are moved out of the repository root. The docs are updated
in https://gitea.com/gitea/docs/pulls/639.

- Remove the admin and user adopt pages, the `/admin/unadopted` API
endpoints and the adopt notifier hook
- Remove the `ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES` and
`ALLOW_DELETION_OF_UNADOPTED_REPOSITORIES` settings
- The user "Repositories" settings page only lists the user's
repositories
- Repository files without a database record must now be removed from
disk by the administrator

Assisted-by: Codet:claude

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-08 18:38:23 +00:00
wxiaoguang
3699309edd feat: support jpeg-xl (jxl) (#40283)
Major browsers (Chrome/Firefox/Safari) all support it now,
https://developer.chrome.com/blog/jpeg-xl-in-chrome

* Fix #16629
2026-11-08 15:24:46 +00:00
silverwind
8cb6fb2001 fix: add missing checks to more handlers and services (#40131)
Several code paths skipped checks that their siblings already perform.

- Code comment replies are rejected when they target a review of another
pull request or another user's pending review
- OAuth2 refuses tokens for users who can't sign in, and introspection
reports their tokens and already used refresh tokens as inactive
- AGit proc-receive runs the same pull request permission and wiki
checks as pre-receive
- Repository transfer drops the repository's owner-level scoped workflow
source registrations, and registrations whose source the owner no longer
owns are ignored
- The web editor's base branch copy into a fork and the fork's upstream
divergence info require read access to the base repository
- LFS downloads require sign-in under strict `REQUIRE_SIGNIN_VIEW`, like
git smart HTTP
- Unknown AGit target branches are reported as an unexpected ref again
2026-11-08 09:02:51 +00:00
silverwind
cd92c6a008 fix: paste copied code as text, not as a markdown table (#40053)
Copying lines from a diff, file view, blame, code search or code preview
and pasting them into a comment on Gitea or GitHub produced a markdown
table with escaped pipes and stripped indentation. Both use
`@github/paste-markdown`, which converts copied HTML tables unless they
carry `data-paste-markdown-skip`, as GitHub's own code tables do.
Gitea's code tables now set it too.

The test is a bit more complicated because of a upstream bug which
causes `paste-markdown` to insert pasted content twice, once
https://github.com/github/paste-markdown/pull/128 is merged and
released, the negative assertion could be removed.

---------

Signed-off-by: silverwind <me@silverwind.io>
2026-11-08 09:01:50 +00:00
GiteaBot
edebfaa125 [skip ci] Updated translations via Crowdin 2026-11-08 00:36:44 +00:00
silverwind
bd8fd71bc1 enhance(theme): derive theme colors with color-mix and unify shades (#40113)
Derive theme colors from a few base colors with `color-mix(in srgb, …)`
and make the colorful palette coherent, so custom themes that import a
Gitea theme can override a base color and get matching shades.

- Every `-light`, `-dark-1` and `-dark-2` shade follows one rule for all
hues, fixing dark orange shades copied from the light theme, black
shades that barely moved and neon tints
- Base colors move at most 4 OKLab units toward a common lightness, the
median in dark and red in light, yellow stays unchanged
- Text, secondary, console, message, surface and alpha colors derive
from their own base, alpha variants now match their names
- Added and removed diff colors share one lightness per level in all
themes, including colorblind ones
- Chart.js and the external render iframe resolve `color-mix()` values
to hex through `getComputedStyle`
- Remove unused `secondary-dark-12`, `-13`, `shadow-opaque` and
`workflow-edge-hover`

Fixes: https://github.com/go-gitea/gitea/issues/30160

<img width="880" alt="Components with the largest color changes, dark
and light, before and after"
src="https://github.com/user-attachments/assets/a9d27636-e3bb-46fa-a3ac-3fec33fd9806"
/>
<img width="880" alt="All theme colors per family, before and after,
unchanged ones dimmed"
src="https://github.com/user-attachments/assets/9977dde3-0749-4926-b110-18c0dc31d632"
/>

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-11-07 23:39:15 +00:00
Sandiyo Christan
c54ec52f0f fix(auth): limit failed TOTP attempts per account (#39993)
Gitea accepted unlimited wrong TOTP passcodes, so anyone holding an
account's password could enumerate the 6-digit code in minutes. This
allows 5 failed attempts per account, then refuses TOTP until 15 minutes
after the last one.

- The count lives in the cache, and the global lock spans the check,
validation and counting, so new sessions and concurrent requests cannot
widen it. With Redis, both are shared across instances
- Applies to every TOTP check: the web 2FA page, account recovery and
Basic auth with `X-Gitea-OTP` (API, git, packages)
- Only wrong or replayed passcodes count, server errors do not
- Scratch codes and WebAuthn stay usable as the recovery path while
locked
- Failures log `Failed authentication attempt for <user> from <ip>`,
which the fail2ban filter already matches

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-11-07 23:01:49 +00:00
silverwind
51879941dc enhance: improve commit and compare link rendering (#40154)
Commit, compare and SHA links render the SHA in code with the rest of
the URL after it, and links to other repositories get an `owner/repo@`
prefix like references do.

- Abbreviated SHAs, branch compares and `<url>` autolinks now render as
commit links
- Pull request commit URLs no longer break into an issue reference plus
stray text
- Only routes that take a SHA are shortened, so file and API URLs stay
plain

Replaces https://github.com/go-gitea/gitea/pull/36725

<img width="620" alt="Commit links before and after"
src="https://github.com/user-attachments/assets/5919c8a0-94e3-4148-ad11-6944bf790572"
/>
2026-11-07 22:43:07 +00:00
William Desportes
87a703819b fix(queue): bump levelqueue to v0.5.0 and remove workarounds (#40219)
levelqueue v0.5.1 fixes this upstream
(https://gitea.com/lunny/levelqueue/pulls/8), so this now only bumps the
dependency.

A push wrote "high" before the payload, so an interrupted push left an
id counted with no key. `LPop` then returned `ErrNotFound` without
advancing "low" and the wrapper retried forever: nothing popped, no
worker started, later items unreachable. All were only fixable by
clearing the queue, losing the backlog:
- https://github.com/go-gitea/gitea/issues/32006 — mail, 0 workers
- https://github.com/go-gitea/gitea/issues/28919 — mirror, "already in
queue"
- https://github.com/go-gitea/gitea/issues/33862 — archives hanging
- https://github.com/go-gitea/gitea/issues/33882 — self-healing request

v0.5.1 writes counter and payload in one batch, moves the counters past
missing keys, and repairs leftover unique-queue set entries, so affected
instances recover on their next pop.

No test: the behaviour lives in the dependency, which covers it in its
own `recover_test.go`.

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-11-07 22:26:53 +00:00
silverwind
e09813f472 docs: update AGENTS.md (#40270)
Some useful rules from my past experiences, feel free to suggest more.
Dark theme screenshots is subjective of course, but I prefer them.

---------

Signed-off-by: silverwind <me@silverwind.io>
2026-11-07 16:09:25 +00:00
Lazizbek Ergashev
884884308d fix(pull): don't add a timeline entry for pending API reviews (#40260)
Pending reviews created through the API went through `SubmitReview`,
which added a timeline entry and sent notifications before the review
was submitted, so submitting it later showed the review twice.

- Pending reviews skip the timeline entry and notifications until
submitted, like on GitHub
- `CreatePullReview` rejects comments without a `path` or a positive
line with 422, like GitHub
- Already duplicated reviews stay as they are

Fixes https://github.com/go-gitea/gitea/issues/40259

Assisted-by: Claude Code:claude-opus-5-5

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-07 14:19:50 +00:00
Renox
462ab3801a fix(web): don't block README images with REQUIRE_SIGNIN_VIEW = expensive (#40264)
Relax expensive endpoint list, then README can render its images.

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-07 13:34:01 +00:00
Mitrahsoft
3aca9c8fb7 enhance(actions): create commit status for workflow_dispatch runs (#39961)
Runs triggered by `workflow_dispatch` never created a commit status, so
the commit showed no sign that a workflow ran on it.

- Post the status on the run's commit, e.g. `ci / e2e
(workflow_dispatch)`. `schedule` runs stay unchanged.
- These statuses don't count for pull requests. They don't show in a
PR's checks and can't satisfy or fail its required checks, even through
broad globs like `ci / e2e*`.

Closes https://github.com/go-gitea/gitea/issues/39639

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-07 12:55:19 +00:00
Basavaraj S m
4f69599981 fix(repo): do not reuse pull mirror credentials for a new host (#39991)
Changing a pull mirror address with an empty password field carried the
stored credentials over to the new address. The password is write-only,
so a repo admin who did not set up the mirror could send the owner's
token to a host they control, or pull another repository on the same
host that the token can read.

Stored credentials are now reused only when the address is unchanged,
like a changed username already drops the stored password. The API
cannot change the address and push mirrors never reuse credentials, so
both are unaffected.

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-07 12:35:10 +00:00
TheFox0x7
dd4672607b chore: add report requirements (#40262)
Explicitly require version, reproduction and settings

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: silverwind <me@silverwind.io>
2026-11-07 12:09:23 +00:00
wxiaoguang
a165fdb63c refactor: lazy init global regexp variables (#40269)
Gitea binary is an all-in-one program.

It doesn't make sense to compile dozens or even hundreds of regexps for
git hook sub commands.
2026-11-07 11:56:56 +00:00
Trung Hehe
6bc92f464a fix(org): enforce unique team names in the database (#40228)
Concurrent requests could create teams with the same name in one
organization, because only the service checked the name. Editing such a
team, or renaming a team to a taken name, then failed with a 500.

- Add a unique index on `team (org_id, lower_name)`. Migration 368
renames every duplicate except the oldest to a free `<name>-<n>` and
logs each rename. IDs, members, repositories and permissions are kept,
but lookups by the old name (CODEOWNERS, group-to-team sync, mentions,
URLs) now reach only the kept team.
- Team writes report a name rejected by the index as
`ErrTeamAlreadyExist`, so duplicates, concurrent ones included, return
409 from `POST /orgs/{org}/teams` (previously 422) and `PATCH
/teams/{id}`, and a form error in the web UI.

Fixes https://github.com/go-gitea/gitea/issues/39632

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-07 11:16:11 +00:00
silverwind
baccc2d7cd fix: truncate strings on character boundaries (#40267)
Byte slicing like `t.Description[:255]` can split a multi-byte character
and store invalid UTF-8. Team descriptions were also cut to 255 bytes
although their `MaxSize(255)` validation allows 255 characters.

Team descriptions now truncate by runes. Signup user agents, Actions log
lines and access log request IDs use `util.TruncateStringBytes`, which
now returns short strings untouched.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-07 11:15:28 +00:00
Michael Lopez
5d9bfa1e14 feat(packages): add private Terraform module registry (#38040)
Adds a Terraform module registry package type implementing the [module
registry
protocol](https://developer.hashicorp.com/terraform/internals/module-registry-protocol),
so `terraform init` and Terragrunt `tfr://` can resolve modules from
Gitea:

```hcl
module "vpc" {
  source  = "gitea.example.com/owner/vpc/aws"
  version = "~> 1.0"
}
```

- Modules are uploaded with `PUT
/api/packages/-/terraform/modules/{owner}/{name}/{provider}/{version}`
as a `.tar.gz` with the module at its root, stored verbatim and
immutable.
- `X-Terraform-Get` is a short-lived signed URL because Terraform sends
no credentials when downloading the archive.
- The package page shows install snippets, README, the root module's
inputs, outputs and providers, and `modules/*` submodules.
- Metadata is read by a small in-tree HCL scanner instead of
`hashicorp/hcl/v2`, which would add 5 modules and ~1.4 MB to the binary.

Docs: https://gitea.com/gitea/docs/pulls/433

---------

Signed-off-by: Michael Lopez <mickael.lopez@gmail.com>
Co-authored-by: TheFox0x7 <thefox0x7@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-11-07 10:45:05 +00:00
Wei-Lun Li
7efb5c055f fix(markup): recognize issue references next to CJK punctuation (#40097)
Issue references next to non-ASCII characters, common in Chinese and
Japanese text, are ignored: `修复#1`, `(#2)` or `Closes #3,` create no
link or cross reference.

Like on GitHub, any non-ASCII character may now precede `#123`, `!123`
or `owner/repo#123`, and anything but a word character may follow it.
Dead trailing-space handling in the reference and mention search is
removed.

I used Claude Code to write this change.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-07 10:14:47 +00:00
silverwind
b23c70d439 fix: add missing checks to several handlers and services (#40120)
Several code paths skipped checks their siblings perform, or cleaned up
more than they validated.

- Official team review requests now count, and removing one no longer
marks an unrelated review official
- Release edits only delete files of validated attachments
- Rejected container uploads no longer delete an existing blob
- Attachment removal only removes the uploader's own pending uploads
- OpenID sign-in checks the allow and block lists against the normalized
identifier
- HTTP git access is rejected while a repository is being created, like
SSH

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-07 09:43:39 +00:00
Mitrahsoft
b6c291f87a fix(api): honor branch protection force push and allowlist options on create and edit (#39990)
The branch protection API handled push and force push options
inconsistently. Create dropped force push unless push was enabled, and
edit ignored allowlist fields unless their parent was set to true in the
same request.

- Create treats force push independently of push, like edit and the web
UI. Enforcement is unchanged.
- Edit applies `enable_push_whitelist`, `enable_force_push_allowlist`
and both deploy key flags against the rule's resulting state, like the
deletion fields. `{"enable_push_whitelist": false}` now disables the
whitelist instead of being ignored.
- Documents that `enable_force_push_allowlist` requires
`enable_force_push` on create.

Fixes https://github.com/go-gitea/gitea/issues/35121

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-07 09:34:21 +00:00
Zettat123
c74f2f9216 fix(repo): mark repository as non-empty before git push returns (#40102)
The post-receive hook syncs pushed branches to the database, but
`is_empty` and the default branch of an empty repository were only
updated later by the `push_update` queue. Until then the API treated the
repository as empty (branch list `null`, `GET /branches/{branch}` 500),
and the queue overwrote the default branch chosen by the hook or set via
the API.

`SyncBranchesToDB` now initializes an empty repository and repairs a
default branch missing in git in its locked transaction, so the state is
final when `git push` returns. The push queue and web file edits retry
it while the repository is still empty.

- The default branch is the configured one if it exists, else `main`,
else `master`, else the first branch by name, like GitLab. HEAD follows
it.
- A first push of several branches no longer depends on push order. The
push that initializes a repository still prints no pull request hints,
like GitHub.

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-07 03:20:25 +00:00
GiteaBot
b8b270bac9 [skip ci] Updated translations via Crowdin 2026-11-07 00:31:59 +00:00
Alan Hsu
df4544a58b fix(web): handle TypeCastError when building form validation messages (#40212)
Fixes https://github.com/go-gitea/gitea/issues/40210

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-06 23:27:06 +00:00
silverwind
ede9ec3e10 fix: stop discarding file close and test setup errors (#39987)
- Fix
https://github.com/go-gitea/gitea/security/quality/rules/go%2Funhandled-writable-file-close,
ignored close errors hide failed flushes, which could lose rotated logs
and truncate authorized_keys
- Fix `TestProjects` fixture reset, from
https://github.com/go-gitea/gitea/security/quality/ai-findings,
`TruncateBeans` rejected the table names and the ignored error let the
test run against fixture data
2026-11-06 20:45:17 +00:00
silverwind
24700dca2a test(e2e): retry clipboard reads rejected by Firefox (#40155)
The Firefox mermaid e2e test fails intermittently with `Clipboard read
operation is not allowed.`, for example in
https://github.com/go-gitea/gitea/actions/runs/41281998298/job/124776072700.

Firefox rejects `readText()` when it overlaps the page's still pending
clipboard write, and `expect.poll` does not retry errors thrown by its
callback, so one overlapping read fails the test.
https://github.com/go-gitea/gitea/pull/39838 only removed the paste
prompt, not this rejection.

- A new `assertClipboardText` helper treats a rejected read as a
mismatch so it is polled again
- The bot token copy test had the same race and uses it too

_Written by Claude (Opus 5.5)._
2026-11-06 20:44:00 +00:00
silverwind
7e18e81c7d refactor: remove duplicated and dead Go code (#40244)
Pure refactors with no behavior change, mostly reusing existing helpers
and dropping duplicated or dead code. Net −222 lines.

- Reuse existing helpers instead of inlined copies: `getIssueIndex`,
`NewLabel`, `ToCommitUser`, `GetPackageFileDescriptors`,
`util.SplitTrimSpace`
- Merge copy-pasted blocks in review comment deletion, project deletion
and the pre/post-receive hook templates
- Drop dead code: an error `toStringKeys` never returned, impossible
`bytes.Buffer` write errors, redundant nil-map branches, a `base64`
wrapper
- Use stdlib where it fits: `strings.Cut`, `bytes.IndexAny`,
`cmp.Compare`, `min`/`max`, `slices.Concat`, map lookups instead of key
scans
2026-11-06 11:59:49 +00:00
Shivansh Garg
a5201dc427 feat(release): allow setting a release as the latest (#40214)
Gitea picks the latest release by commit date, while GitHub keeps an
explicit pointer, so repositories migrated from GitHub could show a
different latest release than their source. Fixes
https://github.com/go-gitea/gitea/issues/35273.

- Add a "Set as Latest Release" checkbox and GitHub's `make_latest` API
option. Without them, the newest stable release by commit date stays the
latest.
- Migrations from GitHub and Gitea carry over the source's latest
release.
- Migrated releases are dated by their commit like native ones, and
equally dated ones keep the source's order.

<img width="355" height="122" alt="Set as Latest Release checkbox"
src="https://github.com/user-attachments/assets/d35f5324-7ae0-4e9f-b73c-d3c90496fb00"
/>

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-06 08:23:13 +00:00
Lazizbek Ergashev
98c937170f fix(repo): reject unparsable required approvals in branch protection (#40213)
Saving a branch protection rule with a "Required approvals" value that
can't be parsed as an integer (like `99999999999999999999` or `abc`)
showed the success message and stored 0, because the binding error was
never checked. The form now uses `form-fetch-action` with
`GetFetchActionForm`, so invalid input is rejected and nothing is saved.
Dev mode still answers unparsable numbers with a 500 until
`TypeCastError` gets a message, see
https://github.com/go-gitea/gitea/pull/40212.

- Validation errors show on the page and highlight the offending field,
keeping the form input
- Negative approvals are rejected before any rule lookup, and the input
gets `min="0"`

Fixes https://github.com/go-gitea/gitea/issues/40211

Assisted-by: Claude Code:claude-opus-5-5

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-06 08:08:20 +00:00
silverwind
09922e4ae1 ci: update giteabot to v1.5.1, label conflict-free backports (#40247)
Bump `giteabot` to
[`v1.5.1`](https://github.com/go-gitea/giteabot/releases/tag/v1.5.1) to
label PRs with a `backport/<version>` label that would cherry-pick
cleanly onto the latest release branch with `backport/conflict-free`.

The backport workflow's concurrency group is now per ref, so release
branch pushes can't cancel a pending backport run from `main`.

_Written by Claude (Opus 5.5)._
2026-11-06 07:55:55 +00:00
Basavaraj S m
8d14c9af20 fix(pull): enforce user blocks on pull request reviews (#40194)
Code review never checked user blocks, so a user blocked by the poster
or repository owner could still post reviews, code comments and replies
through the web, API and email.

- `CreateCodeComment` and `SubmitReview` now check blocks, with the repo
admin exemption issue comments have.
- Official reviewers blocked only by the author can still review, so an
author can't keep a maintainer from requesting changes.
- Review requests are handled in
https://github.com/go-gitea/gitea/pull/39296.

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-06 07:31:58 +00:00
silverwind
87ebf3b1ba feat(auth)!: remove support for obsolete OpenID 2.0 draft (#40231)
Remove OpenID 2.0 authentication. The spec is an obsolete draft, major
providers dropped it years ago, and the code keeps needing security
fixes like https://github.com/go-gitea/gitea/pull/39642. OpenID Connect
and OAuth2 are unaffected. Docs: https://gitea.com/gitea/docs/pulls/633.

- The `[openid]` settings, OpenID sign-in, sign-up and account
association are gone
- A migration drops the `user_open_id` table with all user OpenID URIs
- Accounts registered via OpenID have a random password and regain
access via password reset

Fixes: https://github.com/go-gitea/gitea/issues/1310
Fixes: https://github.com/go-gitea/gitea/issues/3521
2026-11-06 07:21:19 +00:00
wxiaoguang
fd98ab5472 enhance(codeowners): support section / glob / file view display / skip review request (#40243)
Document: https://gitea.com/gitea/docs/pulls/634 ([doc PR
preview](955ae7d75c/docs/usage/repository/code-owners.md))

1. If the pattern starts with `*` or contains `/*`, use our glob package
to parse it as glob to regexp
* Make it easier to use. Otherwise it's really ugly to keep writing a
lot of backslash escapes
2. Add GitLab-style "section" support
   * Fix #28926

```codeowners
[Section] @user
*.js
```

3. Add our annotation support, at the moment only need to support
review-request=true/false
    * Fix #40241

```codeowners
## review-request=false # this is global

*.js $user ## review-request=true # this is line-level

[Section] @user ## review-request=true # this is section-level
*.md
```

4. Add GitHub/GitLab-style "show codeowner when viewing a file"
    * Fix #28137
2026-11-06 07:19:51 +00:00
silverwind
0d59b737aa fix: upgrade Alpine base packages in Docker images (#40252)
The `alpine:3.24` base image lags behind fixes published to the Alpine
repository.

Both images now run `apk upgrade` before `apk add`. Packages from `apk
add` are already current, so this only affects the preinstalled base
packages.

_Written by Claude (Opus 5.5)._
2026-11-06 07:19:07 +00:00
Giteabot
917badaae6 fix(deps): update module github.com/andybalholm/brotli to v1.2.7 [security] (#40246)
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[github.com/andybalholm/brotli](https://redirect.github.com/andybalholm/brotli)
| `v1.2.1` → `v1.2.7` |
![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fandybalholm%2fbrotli/v1.2.7?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fandybalholm%2fbrotli/v1.2.1/v1.2.7?slim=true)
|

---

### Excessive memory allocation when decompressing crafted streams in
github.com/andybalholm/brotli
BIT-brotli-2026-111497 / BIT-dotnet-2026-111497 /
BIT-dotnet-sdk-2026-111497 / BIT-node-2026-111497 /
BIT-node-min-2026-111497 / BIT-powershell-2026-111497 /
[CVE-2026-111497](https://nvd.nist.gov/vuln/detail/CVE-2026-111497) /
[GHSA-9v8h-qqgm-4m35](https://redirect.github.com/advisories/GHSA-9v8h-qqgm-4m35)
/
[GHSA-c9gr-gmg4-2vqv](https://redirect.github.com/advisories/GHSA-c9gr-gmg4-2vqv)
/ [GO-2026-6888](https://pkg.go.dev/vuln/GO-2026-6888) / PYSEC-2026-4322
/ PYSEC-2026-4323

<details>
<summary>More information</summary>

#### Details
In github.com/andybalholm/brotli before v1.2.7, the decompressor
allocates memory for Huffman tables and block-type trees on every
meta-block header without bounding the cumulative allocations relative
to the input size. A small crafted brotli stream containing many empty
meta-blocks with new Huffman trees can trigger hundreds of megabytes of
allocations per kilobyte of input, leading to denial of service.

#### Severity
Unknown

#### References
-
[https://github.com/andybalholm/brotli/security/advisories/GHSA-c9gr-gmg4-2vqv](https://redirect.github.com/andybalholm/brotli/security/advisories/GHSA-c9gr-gmg4-2vqv)
-
[33c2a98842)
-
[https://github.com/andybalholm/brotli/releases/tag/v1.2.7](https://redirect.github.com/andybalholm/brotli/releases/tag/v1.2.7)
-
[0ed4268a44)

This data is provided by
[OSV](https://osv.dev/vulnerability/GO-2026-6888) and the [Go
Vulnerability Database](https://redirect.github.com/golang/vulndb)
([CC-BY 4.0](https://redirect.github.com/golang/vulndb#license)).
</details>

---

### Release Notes

<details>
<summary>andybalholm/brotli (github.com/andybalholm/brotli)</summary>

###
[`v1.2.7`](https://redirect.github.com/andybalholm/brotli/compare/v1.2.6...v1.2.7)

[Compare
Source](https://redirect.github.com/andybalholm/brotli/compare/v1.2.6...v1.2.7)

###
[`v1.2.6`](https://redirect.github.com/andybalholm/brotli/compare/v1.2.5...v1.2.6)

[Compare
Source](https://redirect.github.com/andybalholm/brotli/compare/v1.2.5...v1.2.6)

###
[`v1.2.5`](https://redirect.github.com/andybalholm/brotli/compare/v1.2.4...v1.2.5)

[Compare
Source](https://redirect.github.com/andybalholm/brotli/compare/v1.2.4...v1.2.5)

###
[`v1.2.4`](https://redirect.github.com/andybalholm/brotli/compare/v1.2.3...v1.2.4)

[Compare
Source](https://redirect.github.com/andybalholm/brotli/compare/v1.2.3...v1.2.4)

###
[`v1.2.3`](https://redirect.github.com/andybalholm/brotli/compare/v1.2.2...v1.2.3)

[Compare
Source](https://redirect.github.com/andybalholm/brotli/compare/v1.2.2...v1.2.3)

###
[`v1.2.2`](https://redirect.github.com/andybalholm/brotli/compare/v1.2.1...v1.2.2)

[Compare
Source](https://redirect.github.com/andybalholm/brotli/compare/v1.2.1...v1.2.2)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend Renovate
CLI](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xOTAuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjE5MC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2026-11-06 01:55:15 +00:00
Lazizbek Ergashev
288d54951e fix(perm): keep read access for restricted collaborators on public repos (#40234)
Adding a restricted user as a read collaborator to a public repo gave
them no access when the owner isn't fully public, like a limited org.
Restricted users get no default read there, and `RecalculateUserAccess`
dropped their read access row.

- `RecalculateUserAccess` now keeps the same read rows as
`refreshAccesses`, on org-owned repos and for restricted users.
- Re-saving an unchanged collaborator permission recalculates access,
repairing collaborators affected before this fix.

Fixes https://github.com/go-gitea/gitea/issues/40233

Assisted-by: Claude Code:claude-opus-5-5

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-05 23:48:55 +00:00
silverwind
b81b50be55 fix(build): pass # test patterns to go test -run unchanged (#39977)
The `test-backend#` and `test-integration#` targets rewrote every `.`
into `/`, because GNU make pattern rules never match goals containing
`/`. That broke regexes like `make 'test-backend#TestA.*'`, which
silently selected subtests instead.

Static pattern rules built from the goals accept `/` directly, so the
pattern reaches `go test -run` unchanged. Subtests are now selected like
`make 'test-backend#TestA/sub'`, on GNU make 3.81 and 4.x.
2026-11-05 23:44:33 +00:00