22039 Commits
Author SHA1 Message Date
Lunny Xiaoandsilverwind e867cfbf0d fix(repo): rank exact repository name matches first (#39038)
The quick repository switcher orders results alphabetically, so a
repository whose name exactly matches the query can appear below names
that merely contain it.

- Rank exact repository name matches first when no explicit sort order
is requested
- For "owner/repo" queries, rank the exact pair first, then the owner's
other repositories
- Match the owner of "owner/repo" queries case-insensitively, mixed-case
owners were missed

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-11 19:01:43 +00:00
Shivansh Gargandwxiaoguang aa073fb1be fix(web): avoid compare output route collisions (#40307)
Allow compare refs named diff or patch to use the normal compare page
while preserving explicit .diff and .patch downloads.

Compare refs ending in diff or patch were incorrectly matched as raw
.diff/.patch routes. This caused normal compare pages such as
main...diff and main...patch to return an empty or invalid response.

The route matching is now constrained so valid raw diff/patch downloads
continue working while branches named diff or patch use the normal
compare page.

Assisted-by: Agent:GPT-5.6 Luna

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

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-11 17:53:39 +00:00
wxiaoguangandsilverwind b3422c0920 refactor: clean up error system (#40328)
1. `ctx.ServerError("LogMessage", err)` is very messy and useless. When
the log is printed, it already contains the caller's file and line
number
2. `ctx.NotFound(nil)` and `ctx.NotFound(err)` were abused a lot, now
only `ctx.NotFound()`

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-11 17:07:57 +00:00
Shudhanshu Singh a61ef7aa14 fix(markup): keep list items on separate lines in quote replies (#40329)
Keep each list item on its own line when quoting a comment. Items
containing bold text or links could run together in the reply editor,
breaking the quoted list.
2026-11-11 12:55:13 +00:00
silverwind 03fc2bdcc8 fix(repo): require the unit in AccessibleRepositoryCondition (#40059)
`AccessibleRepositoryCondition(user, unitType)` now requires the repo to
have the requested unit enabled and not globally disabled, consistent
with the per-repo permission checks. This affects code search, Actions
run listings, LFS object reuse, recently pushed branches and org project
milestones.

Written by Claude.
2026-11-11 12:55:04 +00:00
silverwind 6eb5efb6bb fix(ui): consistent spacing between labels (#40261)
The issue reference popup showed its labels without any spacing, and the
other label lists each used their own gap, with wrapped rows spaced
differently from columns.

`.labels-list` is now a wrapping flex list with `--gap-inline` by
default, giving the popup, issue sidebar and project cards equal gaps in
both directions. Lists inline with text, in issue list titles and
timeline events, stay inline so their labels still wrap one by one.

<img width="600" alt="Issue reference popup, issue sidebar and issue
list labels, before and after"
src="https://github.com/user-attachments/assets/fc4f0b9e-2b9d-4060-a2fb-c1bd3b7391db"
/>
2026-11-11 10:33:15 +00:00
GiteaBot c62bcf19f6 [skip ci] Updated translations via Crowdin 2026-11-11 00:33:48 +00:00
silverwind d399f844e6 test: fix the login tab order e2e test in macOS WebKit (#40316)
The login tab order test fails in WebKit on macOS, so `make test-e2e`
fails locally on every Mac. CI on Linux is unaffected.

- macOS WebKit moves Tab focus only between text fields, plus buttons
and checkboxes when the system keyboard navigation setting is on, and
never to links, like Safari. Option+Tab reaches every element there and
acts as Tab in Linux WebKit, so the test presses Alt+Tab in WebKit.
- Headless WebKit applies the username `autofocus` late, which pulled
focus back from the password field. The test now waits for the autofocus
first, which also covers it.

Follow-up to https://github.com/go-gitea/gitea/pull/40081

Assisted-by: Claude Code:claude-opus-5-5
2026-11-10 20:07:28 +00:00
Shudhanshu Singhandsilverwind db23b5a192 fix(api): keep webhook settings that are omitted in an edit request (#40282)
`PATCH .../hooks/{id}` previously reset webhook events to push-only and
cleared the branch filter and authorization header whenever they were
not included in the payload. Disabling a hook with `{"active": false}`
silently destroyed its configuration.

`BranchFilter` and `AuthorizationHeader` are now pointers so omitted
fields remain untouched, while empty strings can still be passed to
clear them explicitly.

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-10 19:26:22 +00:00
Gaurav Dubeyandsilverwind d5ce1cad7f fix(indexer): reindex issues when their projects change (#40299)
With the bleve, elasticsearch or meilisearch issue indexer, a keyword
search filtered by project matched issues by the projects they had when
they were last indexed, so newly added issues were missing and removed
ones still showed up.

- Reindex an issue when its projects change, using `IssueChangeProjects`
from https://github.com/go-gitea/gitea/pull/30205.
- Reindex the issues of a deleted project, so the "No project" filter
finds them again.

Entries that are already stale are corrected on the issue's next change
or an index rebuild.

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

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

---
🤖 Opened with [Superhuman](https://github.com/gaurav0107/superhuman), an
open-source contribution agent.

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-10 19:26:12 +00:00
Giteabot a61ad4876a chore(deps): update go toolchain directive to v1.27.4 (#40315)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [go](https://go.dev/)
([source](https://redirect.github.com/golang/go)) | toolchain | patch |
`1.27.3` → `1.27.4` |

---

### 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:eyJjcmVhdGVkSW5WZXIiOiI0NC4yMTAuMCIsInVwZGF0ZWRJblZlciI6IjQ0LjIxMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
2026-11-10 18:08:53 +00:00
silverwind f5a54d6169 chore(css): remove dead CSS (#40314)
Remove CSS rules that no longer match anything because earlier changes
removed or restructured the markup they styled.

- Fomantic card styles, unused since the migrate page and profile card
moved off cards
- List item image, table cell and grid column width rules whose last
users are gone
- Dashboard filter menu and actions panel button overrides

Assisted-by: Claude Code:claude-opus-5-5
2026-11-10 17:35:57 +00:00
Yonghun Shin 2ef5b7623b fix(packages): generic package deletion ignores terraform state lock and latest version (#40302)
`IsLocked` and `IsLatest` in `services/packages/terraform/state.go`
return early when the package **is** a terraform state (`==` instead of
`!=`), so the `OnBeforeRemovePackageAll` /
`OnBeforeRemovePackageVersion` guards never fire. As a result, deleting
through the generic package API (`DELETE
/api/v1/packages/{owner}/terraform/{name}[/{version}]`) or the web UI
ignores the state lock and allows removing the latest state version,
while the terraform state endpoints reject both.

Changes:

- Flip the type check in `IsLocked` and `IsLatest`.
- `DeleteState` (terraform state `DELETE` endpoint) relied on the bug:
after checking the lock it removed every version one by one with
`RemovePackageVersion`, including the latest. With the guard fixed, it
failed with 500 partway through and left a half-deleted state (the
existing `TestPackageTerraform` subtests catch this). It now calls
`RemovePackage`, which checks the lock and deletes everything in one
transaction.
- The generic package delete API used `APIErrorInternal` for every
error, so the guard errors became 500. It now uses `APIErrorAuto`, which
returns 422 for these.
- Added a `GenericPackageAPI` subtest to `TestPackageTerraform`:
deleting an older version works, deleting the latest version or a locked
state returns 422, and deleting an unlocked state works. It fails on
current `main`.

Tested locally with `go test -run '^TestPackage' ./tests/integration`
(SQLite): all pass.

AI disclosure: I used an AI assistant (Claude) to find the bug, trace
the code paths, and draft the change and this description. I reviewed
the change and ran the tests myself.

Signed-off-by: choam2426 <choam2426@gmail.com>
2026-11-10 17:10:59 +00:00
Gaurav Dubeyandsilverwind 1fcb6b4cd6 fix(packages): rebuild repository index after removing a package (#40306)
Deleting a package or a package version from the web UI, the admin panel
or `DELETE /api/v1/packages/...` removed the database rows but never
rebuilt the Debian, Alpine, RPM or Arch repository index, so clients
kept seeing the deleted version until something else triggered a
rebuild. Only the registries' own delete endpoints and the cleanup task
rebuilt it.

https://github.com/go-gitea/gitea/pull/22810 was closed in favor of
`OnBeforeRemovePackageVersion`, but that hook runs before the version is
gone, so it can't refresh the index. This adds an `OnAfterRemovePackage`
hook and rebuilds the owner's repository files there, the same way the
cleanup task does.

Deleting the last RPM of a group also removed the repodata of all other
groups of the owner. Now only the emptied group's files are removed.

Fixes: https://github.com/go-gitea/gitea/issues/32830
Fixes: https://github.com/go-gitea/gitea/issues/40304
Fixes: https://github.com/go-gitea/gitea/issues/40305

---
🤖 Opened with [Superhuman](https://github.com/gaurav0107/superhuman), an
open-source contribution agent.

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-10 16:29:39 +00:00
wxiaoguangandsilverwind d1d702bea9 refactor: user error system (#40308)
Introduce "FlashErrorAuto" for "XxxErrorAuto" family and simplify the
error handling logic.

* Use ErrorUnwrapForHTML for web error messages 
* Use ErrorUnwrapForUser for api error messages
* Make Flash message can take up to about 3000 bytes

Next step: completely refactor "ctx.ServerError"

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-10 16:29:36 +00:00
Toniandwxiaoguang 518e08c2c7 fix: discard stale markdown preview and diff responses (#40289)
Preview and diff tabs render whichever response arrives last, so a slow
earlier request can overwrite the result of a newer click. Introduce
ExclusiveFetch class to handle duplicate requests.

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

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-10 14:22:53 +00:00
Basavaraj S mandsilverwind 25c5b6ab37 fix(issues): hide commit references the viewer cannot read (#40216)
Pushing a commit whose message mentions `owner/repo#1` adds a
"referenced this issue from a commit" event to that issue, with the
commit subject and a link into the pushed repository. The event never
recorded that repository, so a commit in a private repository
referencing a public issue showed its subject and repository path to
anonymous visitors of the issue page and the timeline API.

- The event now records the pushed repository in `RefRepoID`, and is
only shown to viewers who can read that repository's code, including the
issue's own. Older events have no recorded source and stay as they are.
- As on GitHub, the event stays attributed to the repository the commit
was first pushed to, even after the commit reaches another repository,
and is removed when that repository is deleted.

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-11-10 06:13:50 +00:00
Shivansh Gargandwxiaoguang 640cd615c4 feat: restrict pull/issue creation on access basis (#40069)
Adds a repository-level **"Restrict to collaborators"** option under the
Issues and Pull Request unit settings. When enabled, only users with
collaborator access to the base repository (owner, team members, or
explicit collaborators) can open issues or pull requests against it.

Public repositories often need to be visible/cloneable by everyone, but
owners may want to limit who can open pull requests (e.g. restrict to an
internal team while still keeping the code public)

* Fixes: https://github.com/go-gitea/gitea/issues/40015
* Fixes: https://github.com/go-gitea/gitea/issues/31890
* Fixes: https://github.com/go-gitea/gitea/issues/28021
* Fixes: https://github.com/go-gitea/gitea/issues/14801

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-11-10 00:53:49 +00:00
GiteaBot c01f93b5a7 [skip ci] Updated translations via Crowdin 2026-11-10 00:32:42 +00:00
silverwindandLunny Xiao 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 Heheandsilverwind 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 Xiaoandsilverwind 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 Singhandwxiaoguang 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
bircniandsilverwind 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
Giteabotandsilverwind 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
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 Xiaoandsilverwind 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
silverwindandLunny Xiao 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
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
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 Ergashevandsilverwind 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
Renoxandwxiaoguang 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
Mitrahsoftandsilverwind 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 mandsilverwind 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
TheFox0x7andsilverwind 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 Heheandsilverwind 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
silverwindandwxiaoguang 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
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