Skip to content

enhance(ui): forced colors mode enhancements - #38991

Merged
silverwind merged 5 commits into
go-gitea:mainfrom
silverwind:forced-colors
Aug 20, 2026
Merged

enhance(ui): forced colors mode enhancements#38991
silverwind merged 5 commits into
go-gitea:mainfrom
silverwind:forced-colors

Conversation

@silverwind

@silverwind silverwind commented Aug 19, 2026

Copy link
Copy Markdown
Member

Improve various UI elements while in forced color mode. Tested in Firefox and Chrome, untestable in Safari as it does not implement forced color mode currently.

Before and after screenshots from Chrome's color emulation mode:

dark-BEFORE dark-AFTER chromium-light-BEFORE chromium-light-AFTER

Forced colors replaces author colors with the user's palette, which left
checked and indeterminate checkboxes identical to unchecked ones, made
toggle switches disappear entirely, and stripped the fill from labels,
progress bars and branch divergence bars.

Restore each state with system colors, keeping every rule inside the
media query so normal rendering is untouched.

Assisted-by: Claude Code:claude-opus-5
@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Aug 19, 2026
Comment thread web_src/css/modules/checkbox.css Outdated
Signed-off-by: silverwind <me@silverwind.io>
Comment thread web_src/css/modules/label.css Outdated
Signed-off-by: silverwind <me@silverwind.io>
Comment thread web_src/css/base.css Outdated
Signed-off-by: silverwind <me@silverwind.io>
@silverwind silverwind changed the title fix: make form controls visible in forced colors mode fix(ui): forced colors mode enhancements Aug 19, 2026
@github-actions github-actions Bot added the topic/ui Change the appearance of the Gitea UI label Aug 19, 2026
@silverwind silverwind changed the title fix(ui): forced colors mode enhancements enhance(ui): forced colors mode enhancements Aug 19, 2026
@github-actions github-actions Bot added type/enhancement An improvement of existing functionality and removed type/bug labels Aug 19, 2026
@GiteaBot GiteaBot added lgtm/need 1 This PR needs approval from one additional maintainer to be merged. and removed lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. labels Aug 20, 2026
@GiteaBot GiteaBot added lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. and removed lgtm/need 1 This PR needs approval from one additional maintainer to be merged. labels Aug 20, 2026
@silverwind
silverwind enabled auto-merge (squash) August 20, 2026 05:03
@silverwind silverwind added the reviewed/wait-merge This pull request is part of the merge queue. It will be merged soon. label Aug 20, 2026
@silverwind
silverwind merged commit 8f7eb9f into go-gitea:main Aug 20, 2026
23 checks passed
@silverwind
silverwind deleted the forced-colors branch August 20, 2026 05:12
@GiteaBot GiteaBot added this to the 28.0.0 milestone Aug 20, 2026
@GiteaBot GiteaBot removed the reviewed/wait-merge This pull request is part of the merge queue. It will be merged soon. label Aug 20, 2026
zjjhot added a commit to zjjhot/gitea that referenced this pull request Aug 20, 2026
* 'main' of https://github.com/go-gitea/gitea: (29 commits)
  fix(actions): Fix how jobs in matrixes are grouped (go-gitea#38980)
  enhance(ui): forced colors mode enhancements (go-gitea#38991)
  fix: resolve YAML anchors and aliases in Actions workflows (go-gitea#38984)
  [skip ci] Updated translations via Crowdin
  fix(lfs): ensure lock listing paginates with a total order (go-gitea#38850)
  fix: resolve actions commit status permission per repository (go-gitea#38977)
  chore(deps): update dependency go to v1.26.7 (go-gitea#38987)
  chore: form binding trim space (go-gitea#38978)
  fix: honor environment variables during install (go-gitea#38974)
  refactor: http request binding (go-gitea#38971)
  [skip ci] Updated translations via Crowdin
  enhance(ui): tint toast backgrounds by level (go-gitea#38919)
  ci: improve caching (go-gitea#38958)
  refactor: private endpoints (go-gitea#38964)
  fix: grant limited-org unit read access to authenticated non-members (go-gitea#38871)
  fix: allow anonymous theme switching when REQUIRE_SIGNIN_VIEW is set (go-gitea#38956)
  [skip ci] Updated translations via Crowdin
  fix(actions): drop wrapper span around the action status icon (go-gitea#38957)
  test: run frontend unit tests in browsers (go-gitea#38860)
  chore(maintainers): add wingsallen as maintainer (go-gitea#38913)
  ...

# Conflicts:
#	MAINTAINERS
zjjhot added a commit to zjjhot/gitea that referenced this pull request Aug 20, 2026
* main: (29 commits)
  fix(actions): Fix how jobs in matrixes are grouped (go-gitea#38980)
  enhance(ui): forced colors mode enhancements (go-gitea#38991)
  fix: resolve YAML anchors and aliases in Actions workflows (go-gitea#38984)
  [skip ci] Updated translations via Crowdin
  fix(lfs): ensure lock listing paginates with a total order (go-gitea#38850)
  fix: resolve actions commit status permission per repository (go-gitea#38977)
  chore(deps): update dependency go to v1.26.7 (go-gitea#38987)
  chore: form binding trim space (go-gitea#38978)
  fix: honor environment variables during install (go-gitea#38974)
  refactor: http request binding (go-gitea#38971)
  [skip ci] Updated translations via Crowdin
  enhance(ui): tint toast backgrounds by level (go-gitea#38919)
  ci: improve caching (go-gitea#38958)
  refactor: private endpoints (go-gitea#38964)
  fix: grant limited-org unit read access to authenticated non-members (go-gitea#38871)
  fix: allow anonymous theme switching when REQUIRE_SIGNIN_VIEW is set (go-gitea#38956)
  [skip ci] Updated translations via Crowdin
  fix(actions): drop wrapper span around the action status icon (go-gitea#38957)
  test: run frontend unit tests in browsers (go-gitea#38860)
  chore(maintainers): add wingsallen as maintainer (go-gitea#38913)
  ...
silverwind added a commit to ToastyTheBot/gitea that referenced this pull request Aug 20, 2026
* origin/main:
  fix(actions): show "Complete job" logs when the last step is skipped (go-gitea#38939)
  fix: avoid enumerating every public repository in issue search (go-gitea#38992)
  refactor: deploy key and private route handlers (go-gitea#38999)
  chore: update eslint and stylelint configs and re-sync `modern-normalize` (go-gitea#38982)
  enhance: use browser's locale to detect week's first day for the contribution map (go-gitea#38995)
  fix(actions): Fix how jobs in matrixes are grouped (go-gitea#38980)
  enhance(ui): forced colors mode enhancements (go-gitea#38991)
  fix: resolve YAML anchors and aliases in Actions workflows (go-gitea#38984)
  [skip ci] Updated translations via Crowdin
  fix(lfs): ensure lock listing paginates with a total order (go-gitea#38850)
  fix: resolve actions commit status permission per repository (go-gitea#38977)
  chore(deps): update dependency go to v1.26.7 (go-gitea#38987)

# Conflicts:
#	models/asymkey/deploy_key.go
#	routers/api/v1/repo/key.go
#	routers/web/repo/setting/deploy_key.go
#	services/asymkey/deploy_key.go
#	services/convert/convert.go
#	templates/repo/settings/deploy_keys.tmpl
silverwind added a commit to silverwind/gitea that referenced this pull request Aug 21, 2026
* origin/main: (1064 commits)
  fix(actions): enforce fork pull request trust boundaries (go-gitea#39005)
  fix(git): restrict hook permissions (go-gitea#39008)
  fix(api): enforce repository creation token authorization (go-gitea#39007)
  fix(api): enforce public-only scope for compare heads (go-gitea#39006)
  fix(repo): hide repositories of hidden owners (go-gitea#39009)
  [skip ci] Updated translations via Crowdin
  fix(actions): allow larger scheduled workflows (go-gitea#38985)
  fix(actions): show "Complete job" logs when the last step is skipped (go-gitea#38939)
  fix: avoid enumerating every public repository in issue search (go-gitea#38992)
  refactor: deploy key and private route handlers (go-gitea#38999)
  chore: update eslint and stylelint configs and re-sync `modern-normalize` (go-gitea#38982)
  enhance: use browser's locale to detect week's first day for the contribution map (go-gitea#38995)
  fix(actions): Fix how jobs in matrixes are grouped (go-gitea#38980)
  enhance(ui): forced colors mode enhancements (go-gitea#38991)
  fix: resolve YAML anchors and aliases in Actions workflows (go-gitea#38984)
  [skip ci] Updated translations via Crowdin
  fix(lfs): ensure lock listing paginates with a total order (go-gitea#38850)
  fix: resolve actions commit status permission per repository (go-gitea#38977)
  chore(deps): update dependency go to v1.26.7 (go-gitea#38987)
  chore: form binding trim space (go-gitea#38978)
  ...

# Conflicts:
#	modelmigration/migrations.go
#	modelmigration/v1_26/v326.go
#	modelmigration/v1_26/v326_test.go
#	models/fixtures/release.yml
#	services/convert/release.go
#	services/release/release.go
#	templates/repo/home_sidebar_bottom.tmpl
joestump-agent added a commit to joestump/gitea that referenced this pull request Aug 24, 2026
* refactor: private endpoints (go-gitea#38964)

1. remove dead code (SetDefaultBranch)
2. remove useless and unsafe code (AddLogger)

* ci: improve caching (go-gitea#38958)

- only `cache-seeder` writes caches, every other workflow restores.
Saves were being rejected once the repo went over its cache budget,
leaving main's caches stale and PR runs building cold
- seed the pnpm store and uv caches next to the go ones, so PRs
warm-start on them rather than installing from scratch
- prune keeps a single generation per key, including across go versions,
where a toolchain bump leaves the previous build cache unusable.
Reclaims ~2.6 GB immediately
- prune runs every 6h instead of daily and trims to 6 GB, since CodeQL
writes ~200 MB per push to main from outside this repo's workflows
- pull requests and release branches no longer write pnpm, uv and binfmt
caches, whose ref-scoped copies are never read again

---------

Signed-off-by: silverwind <me@silverwind.io>

* enhance(ui): tint toast backgrounds by level (go-gitea#38919)

Toasts now use the same tinted backgrounds and borders as the flash
messages, replacing the solid full-color style. The first commit reverts
go-gitea#38842, the second re-applies it
with tinting.

---------

Co-authored-by: silverwind <me@silverwind.io>

* [skip ci] Updated translations via Crowdin

* refactor: http request binding (go-gitea#38971)

Better than before, still not good enough (more work can be done in the
future)

And add the missing error handling in the PrivateContext "bind"
middleware.

By the way, picked some "TrimSpace" changes from "fix: trim whitespace
from SMTP address and port - go-gitea#38934" (fix go-gitea#38926)

* fix: honor environment variables during install (go-gitea#38974)

Environment variables must be applied to the "install form" config
before the config values are used.

Fixes go-gitea#38911

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* chore: form binding trim space (go-gitea#38978)

Use "binding:TrimSpace" instead of fragile IsEmptyString

And fix a bug in locale's `HasKey`: it should also try the default
language if current language doesn't have the translation key, a new
test is added.

* ui

* refactor: share access token scope parsing between admin and user handlers

Extract the duplicated "scope-*" form parsing into
auth.AccessTokenScopeFromForm and use it from both the user-facing
ApplicationsPost and the new admin bot-token handler.

* fix(auth): block bot and organization accounts from interactive sign-in

Bot accounts are meant for token-based automation only, but the
reverse-proxy and external-source (LDAP/SMTP/PAM) auth paths resolved
users by name/email without checking the user type. A bot whose name or
email matched a proxy header or external identity could obtain an
interactive session.

Guard reverse-proxy auth and the UserSignIn external-source fallback so
only individual users may sign in interactively, matching the existing
local-password and OAuth2 behavior. Add regression tests covering both.

Assisted-by: Claude:claude-opus-4-8

* feat: convert users between individual and bot via UI, API and CLI

Allow a site admin to convert an existing account between the individual
and bot types. Only individual <-> bot is permitted; organizations and
reserved types are rejected.

When converting to a bot the account becomes a local, token-only account:
password, auth source and persisted sessions are cleared, OAuth2
applications/grants and external login links are removed, while access
tokens and owned content (repositories, org membership, ...) are kept.

Exposed through the admin Edit User page (User Type dropdown), the API
(POST /admin/users/{username}/convert-type) and the CLI
(gitea admin user change-type), all backed by user_service.ConvertUserType.
The CLI user-type parsing is shared with "user create".

Assisted-by: Claude:claude-opus-4-8

* docs: add bot user design document

Document the bot account model: definition, the no-interactive-sign-in
guarantee across all auth paths, the capability matrix, and the
individual <-> bot conversion rules with every side effect spelled out.

Assisted-by: Claude:claude-opus-4-8

* fix: harden bot account creation, conversion and token management

- reject and clear passwords when creating a bot via the admin UI, so
  bots stay passwordless like the CLI and edit-user paths already enforce
- wrap the individual->bot credential teardown in a transaction so a
  mid-sequence failure cannot leave a half-converted account
- guard DeleteBotToken so the admin bot-token route only acts on bots

Assisted-by: Claude Code:claude-opus-4-8

* refactor

* fix lint

* fixes

* fix(admin): block impersonation of bot users

Bot accounts are non-interactive: converting a user to a bot strips its
password and auth source so it can never sign in. Impersonation sets the
session UID directly, bypassing credentials entirely, which would hand out
a session that signing in could never produce.

Guard the handler and hide the button on the admin user view page.

Assisted-by: Claude:claude-opus-5

* feat(admin): add user type filter to the admin user list

The admin user list mixes individuals, bots, reserved and remote accounts
with no way to narrow them down. Add a "User Type" dropdown that filters to
individuals or bots; unfiltered behaviour is unchanged.

* adress comments

* adress comments

* cleanup

* adress feedback

* cleanup

* review: address remaining feedback on bot-account PR

- Replace the new RenderWithErrDeprecated call for the bot-admin error
  with a flash message and redirect, per reviewer request to not add
  more usages of the deprecated helper.
- Drop the unit TestImpersonateUser duplicate and cover bot
  impersonation rejection in the TestAdminBotUser integration test.
- Update TestConvertUserTypeRejectsNonConvertibleTarget to expect 400,
  matching APIErrorAuto's current mapping of invalid-argument errors.

Pick-up of go-gitea#38181 by bircni, whose authorship is
preserved via the merged commits.

💘 Generated with Crush

Assisted-by: Crush:glm-5.3

* test(activities): cover org-branch bot skip in repo transfer notifications

The organization path of CreateRepoTransferNotification skips bot members and notifies the rest by their real user id, but had no test coverage.

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

* docs: restore and expand the bot user design document

Reinstates the design doc removed during the original review, with the sign-in enforcement matrix and conversion side-effects corrected to match the current implementation (renamed error, SSPI/session/OpenID handling, kept vs cleared artifacts).

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

* cleanup

* fix: repair tests after rebase onto new form-binding API

* chore(deps): update dependency go to v1.26.7 (go-gitea#38987)

* fix: resolve actions commit status permission per repository (go-gitea#38977)

Various pages did not display the correct action run list tooltips. Fix
those tooltips like here on the `/pulls` page:

`ctx.Repo.Permission` is the zero value outside a repository route, so
on `/pulls`, `/issues`, `/notifications/subscriptions` and the dashboard
repo list the commit status "Details" link was always stripped. The live
job status is looked up from that target URL, so running checks also
rendered as a static pending dot instead of a spinner.

Resolve the Actions unit permission per repository instead.

Also drops the releases page's gate on *loading* statuses, which hid
external CI results from anyone without Actions read; it now loads them
and hides only the URL, like every other page.

Co-authored-by: bircni <bircni@icloud.com>

* fix(lfs): ensure lock listing paginates with a total order (go-gitea#38850)

`GetLFSLockByRepoID` applies `LIMIT`/`OFFSET` to a query with no `ORDER
BY`. The order of such a query is unspecified (according to the SQL
standard), so the resulting queryset might be inconsistent.

These locks AFAIK are never updated, so in practice the order is
insertion-based, but that's not guaranteed.

* fix: use checked type assertions in handleAdminCreateUserError

* [skip ci] Updated translations via Crowdin

* fix: resolve YAML anchors and aliases in Actions workflows (go-gitea#38984)

Workflows using YAML anchors are rejected as invalid, because a workflow
is split into one document per job and an alias whose anchor lands in
another job's document no longer resolves.

Aliases are now expanded once, right after the workflow is parsed and
before anything reads or splits it, bounded like GitHub's parser so
nested aliases cannot expand without limit. Merge keys stay unsupported,
as they are upstream.

Fixes go-gitea#38983
Signed-off-by: silverwind <me@silverwind.io>

* enhance(ui): forced colors mode enhancements (go-gitea#38991)

Improve various UI elements while in [forced color
mode](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/forced-colors).

* fix(actions): Fix how jobs in matrixes are grouped (go-gitea#38980)

The workflow graph decided which job rows belonged to the same matrix by
parsing display names: it stripped a trailing `" (...)"` off `name` and
grouped rows sharing the prefix. That guesses at a string the user
controls, and it fails both ways. `jobparser` only appends the `
(<combination>)` suffix when `name:` contains no `${{ }}`, so a leg
named `E2E on ${{ matrix.browser }}` never grouped, while two unrelated
jobs `build (fast)` and `build (slow)` folded into one bogus matrix
panel.

Matrix legs already have a real identity: expansion clones one row per
combination, all sharing the workflow's `JobID` and differing only in
`Name`. Group on that instead, so a matrix is whatever the backend says
it is. Matrix expansion state is keyed on the graph node id for the same
reason.

Closes go-gitea#38975, though that
report's own example already groups on main, since `explicit (${{
matrix.leg }})` interpolates to a name that still ends in a suffix. The
interpolated shapes above are the broken ones.

Assisted-by: Claude Code:claude-opus-5
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: silverwind <me@silverwind.io>

* enhance: use browser's locale to detect week's first day for the contribution map (go-gitea#38995)

fix go-gitea#6058

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: silverwind <me@silverwind.io>

* chore: update eslint and stylelint configs and re-sync `modern-normalize` (go-gitea#38982)

- update the vendored `modern-normalize` to v3.0.1
- require descriptions for lint disables in TS and CSS, same as we
already have in Go.
- disable core rules covered by `regexp/*` and `unicorn/*`, and ones
that cannot fire
- stop applying vitest rules to the playwright files in `tests/e2e`
- enable 7 stylelint rules, mostly `no-unknown` and `no-invalid` checks
- drop 2 unnecessary vendor prefixes (safari v17+, chrome v120+)
- look up ids via `querySelector` with `CSS.escape` instead of
`getElementById`
- remove stale doc about `@ts-expect-error`, it's forbidden
- misc dev doc fixes

Every declaration that `modern-normalize` v3 removes was checked against
chromium, webkit and firefox defaults first. The `hr` color and the
`:-moz-focusring` outline are kept as documented deviations, dropping
those does change rendering.

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* refactor: deploy key and private route handlers (go-gitea#38999)

clean up legacy code, fix various bugs:

* add missing "return"

* fix: avoid enumerating every public repository in issue search (go-gitea#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>

* fix(actions): show "Complete job" logs when the last step is skipped (go-gitea#38939)

`FullSteps` only gave the synthetic "Complete job" step the remaining
log range when the last step that had run was also the final step of the
job. A skipped step does not count as having run, so any job ending in a
skipped step left the post step with an empty range: its logs were
stored but never rendered, and the duration showed as `0s`.

Reproducible with any job whose last step is skipped, which is common
for failure notifications:

```yaml
steps:
  - run: echo hello
  - run: echo never
    if: failure()
```

The gate now checks whether the final step is done, which preserves the
behaviour from go-gitea#29926 of showing
the post step as waiting while steps are still pending.
--> Regression from go-gitea#29926

---------

Signed-off-by: bircni <bircni@icloud.com>

* fix(actions): allow larger scheduled workflows (go-gitea#38985)

MySQL stores `action_schedule.content` as `BLOB`, limiting scheduled
workflow definitions to 65,535 bytes. Oversized workflows fail schedule
refresh and can also suppress default-branch push handling.

Store scheduled workflow content as `LONGBLOB`, migrate existing MySQL
columns, and cover the migration by persisting 65,536 bytes.

Fixes go-gitea#38613

* [skip ci] Updated translations via Crowdin

* fix(repo): hide repositories of hidden owners (go-gitea#39009)

Exclude public repositories owned by hidden individual accounts from
broad repository listings, while preserving visibility through explicit
access and ownership.

_Assisted-by: Codex:GPT-5_

* fix(api): enforce public-only scope for compare heads (go-gitea#39006)

Enforce public-only token scope for repositories resolved as compare
heads.

_Assisted-by: Codex:GPT-5_

* fix(api): enforce repository creation token authorization (go-gitea#39007)

Reject public-only tokens for repository migrations and require
repository scope for canonical organization repository creation. This
aligns both routes with the existing token authorization boundaries.

_Assisted-by: Codex:GPT-5_

* fix(git): restrict hook permissions (go-gitea#39008)

Create delegate hook files and directories without group or other write
access, including correcting existing hook directories.

_Assisted-by: Codex:GPT-5_

* fix(actions): enforce fork pull request trust boundaries (go-gitea#39005)

Preserve fork pull request restrictions across review-triggered
workflows, reusable workflow access, job scheduling, and filtered
workflow statuses.

This prevents untrusted fork workflow content from bypassing approval,
accessing private reusable workflows, or satisfying protected status
checks.


_Assisted-by: Codex:GPT-5_

* fix(packages): bound Alpine metadata entries (go-gitea#39026)

* fix(packages): limit Maven checksum uploads (go-gitea#39028)

Bound checksum uploads to the maximum usable digest length before
buffering their content.

* fix(packages): limit Swift package manifests (go-gitea#39025)

Bound the number and aggregate size of Swift manifests retained from an
uploaded archive.

* fix(migrations): bound OneDev version responses (go-gitea#39024)

Limit OneDev version responses before parsing so a remote server cannot
make a migration retain an unbounded response.

* fix: make local queue PopItem can be notified (go-gitea#39011)

* fix(migrations): cancel GitLab version probes (go-gitea#39023)

Bind the GitLab version probe to the migration context so a cancelled
migration does not remain blocked on a remote response.

* enhance: add permalinks to pull request reviews (go-gitea#38849)

1. Make review threads linkable via `#pullrequestreview-<reviewID>`
2. Improve CSS so username and timestamp go colored on hover.
3. CSS cleanup, remove dead rules, nonexistant class name, make `.suppressed` actually do what it says in the doc above.

* feat(api): list all packages for site administrators (go-gitea#38968)

Add `GET /admin/packages` so site administrators can review packages
across every owner without querying each owner separately.

It returns the same package version representation as `GET
/packages/{owner}` and supports `page`, `limit`, `type`, and `q`
filters.

---
Assisted by Codet(DeepSeek)

---------

Signed-off-by: bircni <bircni@icloud.com>
Signed-off-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* fix(api): hide limited users from restricted viewers (go-gitea#39004)

Use the canonical profile-visibility check for user API content and
prevent restricted users from enumerating public repositories owned by
limited users.

This keeps feeds, heatmaps, keys, and issue search consistent with
profile visibility.

---------

Co-authored-by: silverwind <me@silverwind.io>

* fix(release): separate publication time from the release date (go-gitea#36761)

`published_at` was an alias for `created_at`, so a release created from
an existing tag reported that tag's commit date as its publication time,
and drafts reported one despite never having been published. It is now
stored separately, set when a release is published and null for drafts.

`created_at` in turn means the date of the commit the release points at,
matching what GitHub documents it to be, and the latest release is
selected by it again. Publishing a release for an old commit no longer
takes over the latest badge, and a tag created in the web UI is dated
the same way as one pushed from the CLI.

Fixes go-gitea#11206
Fixes go-gitea#38714
Fixes go-gitea#31789

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(base): correct natural sort of numbers with leading zeros (go-gitea#38163)

### Description

`NaturalSortCompare` (`modules/base/natural_sort.go`) compares two
numeric run parts by **raw string length**:

```go
if len(part1) != len(part2) {
    return len(part1) - len(part2)
}
```

"Longer digit string = larger number" only holds without leading zeros.
With zero-padded numbers the comparison inverts:

- `file0001` vs `file2` → claims `file0001 > file2`, but `1 < 2`
- `a08` vs `a9` → claims `a08 > a9`, but `8 < 9`

This affects any natural-ordered listing where zero-padded and shorter
unpadded numbers mix (branch/tag/file names, etc.).

### Fix

Strip leading zeros before comparing digit-count magnitude; on equal
magnitude fall back to collation, then to the original length so fewer
leading zeros sort first. Added a small `naturalSortTrimZeros` helper
(keeps one char so `"000"` → `"0"`).

Signed-off-by: Seonghyun Hong <s3onghyun.hong@gmail.com>
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* fix(repo): limit gitignore template selections (go-gitea#39027)

Bound gitignore template selections at both web and API request
boundaries before repository initialization.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* build(release): use native golang toolchain for official release builds (go-gitea#37828)

Official releases are built by Golang toolchain with CGO disabled.

For packagers who need to cross-compile with CGO, use "build" target
with proper TAGS/LDFLAGS/CGO_CFLAGS to make "$(EXECUTABLE)" target run
the "go build" command.

By the way, drop i386 arch support

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* test: speed up tests, fix transaction bug (go-gitea#39030)

Speed up tests: `make test-backend` 103s to 37s, `make test-integration`
908s to 852s.

Most of it is a detached system notice insert blocking on the SQLite
write lock until the busy timeout expired, and `ExternalServiceHTTP`
re-probing on every call with an untimed `http.Get`.

- fixed one correctness bug with nested transactions: files were deleted
while the outer transaction was open, so a later failure could roll the
database back with the files gone
- git push branch counts were far above the hook batch size
- Fix makefile dependencies so running tests and lint work in fresh
worktrees.

---------

Co-authored-by: Giteabot <teabot@gitea.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* fix: drop queued job updates for deleted runs instead of requeueing forever (go-gitea#39037)

When a repository is deleted while one of its Actions runs still has a
pending job update in the emitter queue, `checkJobsByRunID` returns an
error because the run no longer exists. The queue handler in
`jobEmitterQueueHandler` treats every error as unhandled and requeues
the item, creating an infinite retry loop that fills the log with error
messages.

### Changes

1. **`services/actions/job_emitter.go`** — swap the `!exist`/`err` check
order so a database error is reported first, then treat a non-existent
run as handled (nil error). The queue consumer drops the item instead of
requeueing it.

2. **`services/actions/job_emitter_test.go`** — add
`Test_checkJobsByRunID_DeletedRunIsHandled`, which verifies that a
deleted run produces nil (handled, not requeued).

### Related issue

Fixes go-gitea#39034

---------

Co-authored-by: bircni <bircni@icloud.com>

* fix(actions): verify raw artifact signatures first (go-gitea#39049)

Validate raw-artifact signatures before resolving the requested
artifact.

---------

Co-authored-by: silverwind <me@silverwind.io>

* fix(markup): enforce same-repository issue access (go-gitea#39045)

Enforce Issues and Pull Requests access for references within the
current repository.

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* fix(repo): preserve transfer recipient collaboration (go-gitea#39042)

Remove temporary recipient access after a transfer ends while preserving
existing collaboration.

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* feat(actions)!: add RUN_RETENTION_DAYS to delete old action runs (go-gitea#38855)

Gitea keeps completed Actions runs forever. Artifacts and logs expire on
their own schedule, but the run rows never go away, so `action_run` and
its child tables grow without bound.

Adds `RUN_RETENTION_DAYS` to delete completed runs along with their
jobs, tasks and anything the earlier expiries left behind. It defaults
to 400 days, matching how long GitHub keeps run history browsable. A
dedicated `cleanup_action_runs` cron task performs the cleanup, so
admins can schedule it separately from the nightly artifact and log
sweep.

`0` now means "keep forever" for all three retention settings, where
`LOG_RETENTION_DAYS` and `ARTIFACT_RETENTION_DAYS` previously took it
literally and deleted everything at the next sweep.

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

----

## ⚠️ BREAKING ⚠️

`RUN_RETENTION_DAYS` defaults to 400, so completed runs older than that
are deleted when the cron task next runs at midnight. Set
`RUN_RETENTION_DAYS = 0` before upgrading to keep all runs.

---------

Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>

* [skip ci] Updated translations via Crowdin

* review: address silverwind and copilot feedback on bot-account PR

- Fix notification.go: UserID used loop index instead of users[i].ID (Copilot)
- Add comment explaining login_type "0" = LoginNoType (silverwind)
- Rename j- prefix to js- for consistency with project convention (silverwind)
- Add specific case for ErrUserTypeCanNotConvert before generic ErrInvalidArgument (Copilot)
- Add locale key for the new error message

* fix(org): hide limited organizations from restricted users (go-gitea#39047)

Do not expose limited organization memberships to restricted viewers.

---------

Co-authored-by: silverwind <me@silverwind.io>

* fix(repo): require organization owners for team access (go-gitea#39046)

Require organization ownership before changing repository team
associations when team access is restricted.

---------

Co-authored-by: silverwind <me@silverwind.io>

* fix(actions): enforce workflow badge token scope (go-gitea#39044)

Apply repository token-scope and public-only checks to workflow badges.

---------

Co-authored-by: silverwind <me@silverwind.io>

* fix(api): enforce organization listing token scope (go-gitea#39041)

Enforce organization token scope before listing organizations and retain
public-only filtering.

---------

Co-authored-by: silverwind <me@silverwind.io>

* fix(packages): restrict limited owner package access (go-gitea#39043)

Apply restricted-viewer visibility rules when resolving package access.

---------

Co-authored-by: silverwind <me@silverwind.io>

* fix(db): make paginated database reads always require "order" option (go-gitea#39017)


Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* fix(auth): record last sign-in on reverse proxy login (go-gitea#38672)

Reverse proxy and SSPI logins establish a session but never recorded
`last_login_unix`, so those users stayed "Never Signed-In" in admin.

The write is folded into the language update that `handleSignIn` already
does, so it stays at one query and only runs when a session is
established.

Fixes go-gitea#7836

---------

Co-authored-by: roman s <roman.sukach@dust-labs.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* feat(diff): Add search and extension filter to diff sidebar (go-gitea#37068)

Adds a search box and a file-extension filter to the pull request diff
sidebar, so reviewers can narrow a large diff down to the files they
care about.

Both filters apply to the file tree and to the diff itself. The
extension menu follows GitHub: extensions sorted alphabetically,
dotfiles and extension-less files in their own buckets, and the
selection kept in the same `file-filters[]` query parameter, so a
filtered view is shareable and survives a reload.

The menu can list every extension in a diff, so `createTippy` gains an
opt-in `limitSizeToViewport` option that caps a popup to the space left
in the viewport and scrolls its content. Popups that do not ask for it
are unchanged.

Closes go-gitea#27256
Signed-off-by: silverwind <me@silverwind.io>
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>

* refactor: prefix admin user form classes with js- for grepability

Rename .non-bot, .local, .non-local → .js-non-bot, .js-local,
.js-non-local across common.ts, new.tmpl, and edit.tmpl per
silverwind's request for consistency with project convention.

---------

Signed-off-by: silverwind <me@silverwind.io>
Signed-off-by: bircni <bircni@icloud.com>
Signed-off-by: Lunny Xiao <xiaolunwen@gmail.com>
Signed-off-by: Seonghyun Hong <s3onghyun.hong@gmail.com>
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: GiteaBot <teabot@gitea.io>
Co-authored-by: APZN <129354802+jsk1004ha@users.noreply.github.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: joestump-agent <joestump-agent@users.noreply.github.com>
Co-authored-by: joestump-agent <agent@stump.wtf>
Co-authored-by: Iaroslav <viralpraxis@evilmartians.com>
Co-authored-by: bn-zr <174343671+bn-zr@users.noreply.github.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Julian Scholle <Julian.scholle@googlemail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: SEONGHYUN HONG <s3onghyun.hong@gmail.com>
Co-authored-by: water <672684719@qq.com>
Co-authored-by: Federico A. Corazza <20555025+facorazza@users.noreply.github.com>
Co-authored-by: roman.s <55788842+majorissuerep@users.noreply.github.com>
Co-authored-by: roman s <roman.sukach@dust-labs.com>
Co-authored-by: McMichalK <michal.krela@monstercouch.com>
Co-authored-by: Copilot <copilot@github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. topic/ui Change the appearance of the Gitea UI type/enhancement An improvement of existing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants