Commit Graph

904 Commits

Author SHA1 Message Date
bircni
42eb7945d1 fix: Fix issue target branch selection for non-collaborators (#36916) (#38164)
Backport #36916 

This PR fixes a bug in the UI that prevented non-collaborator users (the
issue poster or creator) from setting the target branch (ref) of an
issue. The backend API already supports this, but the UI was rigidly
disabling the dropdown based only on collaborator status.

Changes:
- Enable the branch selector for the issue poster and during new issue
creation.
- Fix a typo (.IsIssueWriter -> .IsIssuePoster) that was preventing the
reference update URL from being correctly set for posters.

Co-authored-by: fwag <30782430+fwag@users.noreply.github.com>
2026-06-19 18:16:02 +02:00
bircni
6fb96fcfdf fix: allow git clone of private repos with anonymous code access (#38074) (#38146)
Backport #38074

## Summary

Fixes #38062.

Private repositories with a code unit configured for **anonymous read
access** (Settings → Public Access → Code: anonymous view) could not be
cloned without credentials. The git HTTP auth gate (`httpBase`) only
bypassed authentication for non-private repos, ignoring the per-unit
anonymous access setting entirely.

- Check anonymous permissions via
`access_model.GetDoerRepoPermission(ctx, repo, nil)` + `CanAccess`
before requiring auth on pull operations, so the per-unit
`AnonymousAccessMode` is respected through the existing permission model
- This also correctly handles `setting.Repository.ForcePrivate` (which
the naive direct-field check would have missed)
- Push (receive-pack) and `RequireSignInViewStrict` continue to require
credentials as before

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-06-17 21:21:05 +00:00
bircni
99f8b3d9a1 fix: Various security fixes (#38103) (#38151)
Backport #38103

- Enforce org visibility on organization label read endpoints (private
org labels no longer leak to non-members).
- Block fork sync (`merge-upstream`) when the base repo is no longer
readable (stops pulling commits after a parent goes private).
- Remove `REVERSE_PROXY_LIMIT` / `REVERSE_PROXY_TRUSTED_PROXIES` from
the Docker `app.ini` templates (the `= *` default allowed
`X-WEBAUTH-USER` impersonation; reverse-proxy auth is now opt-in and
admin-configured).
- Enforce single-use TOTP passcodes across web login, password-reset,
and Basic-Auth `X-Gitea-OTP` (fixes a TOCTOU race and a stateless
replay).
- Re-check branch write permission for every ref in a push (the
pre-receive hook cached the first ref's result, letting a per-branch
maintainer-edit grant escalate to full repo write).

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-06-17 20:49:59 +00:00
Lunny Xiao
f6e2ca4388 fix(auth): ignore stale OIDC external login links to organizations (#37875) (#38141)
Backport #37875

This fixes an OIDC sign-in edge case where a stale `external_login_user`
record can still point to an organization or a deleted user.

In that situation, Gitea may keep resolving the external login to the
wrong account during sign-in. For affected instances, this matches the
behavior reported in #36439 and #37812, where a user signing in with
OIDC/Entra ID could appear as an organization, or hit a 404 after that
organization was removed.

- validate the user resolved from `external_login_user` during
OAuth2/OIDC login
- ignore stale links when the linked user no longer exists
- ignore stale links when the linked user is not an individual user
- remove the stale external login row so the sign-in flow can relink the
external account to the correct user

- Fixes #37812
- Related to #36439

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
Co-authored-by: bircni <bircni@icloud.com>
2026-06-17 20:19:24 +00:00
bircni
5facdcc7fd fix: Various sec fixes (#38108) (#38147)
Backport #38108

- Enforce repository token scope on RSS/Atom feed endpoints so a PAT
without repo scope can no longer read private repo commit data.
- Block HTTP redirects during repository migration clones to prevent
SSRF reaching internal addresses via an attacker-controlled redirect.
- Redact the notification subject after repo access is revoked so
private issue/PR metadata is no longer leaked through the notification
API.

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-06-17 21:43:22 +02:00
Lunny Xiao
bb4cccc6e9 fix: parse HEAD ref (#38119)
backport #38088
2026-06-14 19:52:44 +00:00
bircni
98cc15b307 fix(api): nil pointer panic when filtering tracked times by a non-existent user (#38112) (#38115)
Backport #38112

## Problem

`GET /repos/{owner}/{repo}/times` and `GET
/repos/{owner}/{repo}/issues/{index}/times` crash with a nil pointer
dereference when the `user` query filter names a user that does not
exist.

## Root cause

In `ListTrackedTimes` and `ListTrackedTimesByRepository`, the
`IsErrUserNotExist` branch sends the 404 but is missing a `return`, so
execution falls through to `opts.UserID = user.ID` with a nil `user`.

---------

Co-authored-by: Pycub <iamsokhandan@gmail.com>
2026-06-14 20:06:04 +02:00
Giteabot
4751adf42d feat(api): add Link header in ListForks (#38052) (#38063)
Backport #38052
Fixes #38051.

Signed-off-by: Eugenio Paolantonio <eugenio.paolantonio@suse.com>
Co-authored-by: Eugenio Paolantonio <me@medesimo.eu>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-06-12 18:21:46 +00:00
Giteabot
e107498f3b fix(actions)!: require merged PR to bypass fork PR approval gate (#38010) (#38041)
Backport #38010 by @bircni

`ifNeedApproval` in `services/actions/notifier_helper.go` decided
whether a
fork PR's workflow run had to wait for maintainer approval. The bypass
clause
counted any prior `approved_by > 0` run for `(repo_id,
trigger_user_id)`, so
the very first Approve-and-run click on a contributor's fork PR
permanently
trusted that user for every future fork PR in the same repository —
including
PRs whose only change is the workflow YAML itself.

Approving a workflow *run* is not the same as merging *code*. This
change
aligns the gate with GitHub Actions' first-time-contributor model: trust
is
granted only after the user has had a pull request merged in the repo.

## Behavior change

- **Before**: one approval = permanent trust for that user in that repo.
- **After**: every fork PR is gated until the contributor has at least
one
  merged PR in the repo.

Existing already-approved runs and merged PRs continue to work; only the
trust criterion for *future* fork PRs changes. Maintainers who rely on
the
implicit "approve once" trust will see the approval banner reappear
until
they merge a PR from that contributor.

---------

Signed-off-by: bircni <bircni@icloud.com>
Co-authored-by: bircni <bircni@icloud.com>
2026-06-09 15:53:42 +02:00
Giteabot
8bf445e86a fix(actions): reject workflow_dispatch for workflows without that trigger (#37660) (#37895)
Backport #37660 by @jorgeortiz85

## Summary

Fixes #37528

This PR makes the workflow dispatch API reject workflows that do not
declare `workflow_dispatch`. Previously, `POST
/repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches` could
create an `ActionRun` for a workflow that only declared another event
such as `push`.

The service now validates that the target workflow has a
`workflow_dispatch` trigger before inserting the run. The API maps that
validation failure to `422 Unprocessable Entity`, matching existing
validation failures in this handler.

The regression test creates a push-only workflow, dispatches it through
the public API, asserts the `workflow_dispatch` validation message, and
verifies that no run was inserted.

## Testing

- `go test ./services/actions`
- `TAGS="sqlite sqlite_unlock_notify" make
test-integration#TestWorkflowDispatchPublicApiRequiresWorkflowDispatchTrigger`
- `TAGS="sqlite sqlite_unlock_notify" make
test-integration#TestWorkflowDispatchPublicApi`

## Disclosure

Developed with assistance from OpenAI Codex.

Co-authored-by: Jorge Ortiz <jorge.ortiz@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
2026-05-29 05:09:08 +02:00
Giteabot
094eeee365 fix(actions): ack re-sent UpdateLog finalize idempotently (#37885) (#37892)
Backport #37885 by @silverwind

Fixes https://github.com/go-gitea/gitea/issues/37871, full backwards and
forwards compatible with runners.

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-05-28 03:52:50 +00:00
Nicolas
a859221a62 fix(pull): handle empty pull request files view to allow reviews (#37783) (#37785)
Backport #37783

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-05-19 18:45:18 +00:00
Lunny Xiao
a34eac5ef4 fix: Unify public-only token filtering in API queries and repo access checks (#37118) (#37773)
backport #37118 

This PR closes remaining `public-only` token gaps in the API by making
the restriction apply consistently across repository, organization,
activity, notification, and authenticated `/api/v1/user/...` routes.

Previously, `public-only` tokens were still able to:
- receive private results from some list/search/self endpoints,
- access repository data through ID-based lookups,
- and reach several authenticated self routes that should remain
unavailable for public-only access.

This change treats `public-only` as a cross-cutting visibility boundary:
- list/search endpoints now filter private resources consistently,
- repository lookups enforce the same restriction even when addressed
indirectly,
- and self routes that inherently expose or mutate private account state
now reject `public-only` tokens.

---
Generated by a coding agent with Codex 5.2

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Nicolas <bircni@icloud.com>
2026-05-19 15:38:51 +00:00
Giteabot
6d2b02dac1 fix(permissions): Fix reading permission (#37769) (#37781) 2026-05-19 17:06:09 +02:00
Giteabot
9c0ad8291b fix: Add missed token scope checking (#37735) (#37757)
Backport #37735 by @lunny

Follow #37698

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-05-18 06:59:33 +00:00
Giteabot
58597cc30a fix: Allow direct commits for unprotected files with push restrictions (#37657) (#37756)
Backport #37657 by @bircni

Fixes an issue where users could not commit changes on a file which is
unprotected.

Fixes #37655

Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 06:11:19 +00:00
Lunny Xiao
86cc3e8783 fix(oauth): bind token exchanges to the original client request (#37704) (#37740)
Backport #37704 

This PR hardens OAuth token exchange validation by binding exchanged
credentials to the client and redirect URI that originally obtained
them.

What it changes:

- reject refresh token exchanges when the refresh token belongs to a
different OAuth application
- reject authorization code exchanges when the `redirect_uri` in the
token request differs from the `redirect_uri` stored with the
authorization code
- add integration coverage for:
  - authorization code exchange with a mismatched redirect URI
- refresh token reuse across two different dynamically created OAuth
applications

Why:

OAuth authorization codes and refresh tokens must remain bound to the
client context that originally received them. Without those checks:
- a valid authorization code can be redeemed against a different
registered redirect URI of the same client
- a refresh token can be replayed by a different OAuth client

---------

Co-authored-by: Nicolas <bircni@icloud.com>
2026-05-17 22:17:33 +02:00
Zettat123
1d7b84922f fix(actions): wrong assumption that run id always >= job id (#37737) (#37742)
Backport #37737

Fix #37734

Follow up #37008

The `jobNum >= runNum` check is useless. Removed it to support `job_id <
run_id`
2026-05-17 08:42:20 +02:00
Giteabot
2965b0c08a fix(web): enforce token scopes on raw, media, and attachment downloads (#37698) (#37733) 2026-05-16 18:18:44 +02:00
Giteabot
ab0d52b4c7 fix(auth): set User-Agent on avatar fetch and sync avatar on link-account register (#37564) (#37588) (#37726)
Backport #37588 by @pandareen

## Summary

Fixes
[go-gitea/gitea#37564](https://github.com/go-gitea/gitea/issues/37564):
when an OIDC provider returns a `picture` claim, Gitea is supposed to
download that image as the user's avatar (if `[oauth2_client]
UPDATE_AVATAR = true`). Two latent bugs prevented this from working
consistently:

1. **Default Go User-Agent rejected by some image hosts.**
`oauth2UpdateAvatarIfNeed` used `http.Get`, which sends `User-Agent:
Go-http-client/1.1`. Hosts like `upload.wikimedia.org` reject that UA
with `403`, and every error path silently returned, so the user was left
with an identicon and **no log line** to diagnose the issue.
2. **Link-account *register* path skipped avatar sync.** First-time OIDC
sign-ins where auto-registration is disabled (or required a
username/password retype) go through `LinkAccountPostRegister`, which
created the user but never called `oauth2SignInSync`. So the avatar /
full name / SSH keys from the IdP were dropped on the floor for those
users, even though the existing-account-link path (`oauth2LinkAccount`)
and the auto-register path (`handleOAuth2SignIn`) both already did the
sync.

## Changes

- `routers/web/auth/oauth.go` — `oauth2UpdateAvatarIfNeed` now uses
`http.NewRequest` + `http.DefaultClient.Do`, sets `User-Agent: Gitea
<version>`, and logs every failure path at `Warn` (invalid URL, fetch
error, non-200, body read error, oversize body, upload error). No silent
failures.
- `routers/web/auth/linkaccount.go` — `LinkAccountPostRegister` now
calls `oauth2SignInSync` after a successful user creation, mirroring the
auto-register and link-existing-account flows.
- `tests/integration/oauth_avatar_test.go` — new
`TestOAuth2AvatarFromPicture` integration test with five sub-cases:
- `AutoRegister_FetchesAvatarFromPictureWithGiteaUA` — happy path,
asserts `use_custom_avatar=true`, an avatar hash is set, exactly one
HTTP request was made, and the request carried a `Gitea ` UA. The mock
server enforces the UA prefix to mirror real-world hosts that reject
Go's default UA.
- `AutoRegister_NonOK_DoesNotUpdateAvatar` — server returns 403; user's
avatar must remain unset.
- `AutoRegister_EmptyPicture_NoFetch` — empty `picture` claim must not
trigger any HTTP request.
- `AutoRegister_UpdateAvatarFalse_NoFetch` — `UPDATE_AVATAR=false` must
not trigger any HTTP request.
- `LinkAccountRegister_FetchesAvatarFromPicture` — guards the
`linkaccount.go` fix; without the new `oauth2SignInSync` call this
assertion fails.

## Test plan

- [x] `go test -tags 'sqlite sqlite_unlock_notify' -run
'^TestOAuth2AvatarFromPicture$' ./tests/integration/ -v` — 5/5 sub-tests
pass.
- [x] Manual: log in as a Keycloak user with `picture` claim pointing at
`https://avatars.githubusercontent.com/u/9919?v=4` — Gitea avatar is
replaced with the GitHub picture.
- [x] Manual: same flow with `https://upload.wikimedia.org/...` —
request now succeeds (or returns a clearly logged `Warn` line if
rate-limited with `429`); previously it silently 403'd.
- [x] Manual: `UPDATE_AVATAR=false` — user keeps the identicon, no
outbound request in container logs.
- [ ] Reviewer: please double-check that no other call sites of
`oauth2UpdateAvatarIfNeed` rely on the old `http.Get` behaviour.

## Related

- Upstream issue: go-gitea/gitea#37564
--------------------------------------------


AI Editor was used in this PR

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: pandareen <7270563+pandareen@users.noreply.github.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
2026-05-16 14:15:53 +00:00
Giteabot
519b8d6d88 fix(security): enforce wiki git writes and LFS token access at request time (#37695) (#37714)
Backport #37695 by @lunny

This PR fixes two permission-checking gaps in Git and LFS request
handling.

## What it changes

- keep wiki Git HTTP pushes on the normal write-permission path, even
when proc-receive support is enabled
- revalidate LFS bearer token requests against the current user state
and current repository permissions before allowing access
- add regression coverage for unauthorized wiki HTTP pushes
- add LFS tests for blocked users, revoked repository access, read-only
upload attempts, and valid write access

## Why

- wiki repositories should not inherit the relaxed refs/for handling
used for normal code repositories
- LFS authorization tokens should not remain usable after a user is
disabled or loses repository access

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-05-16 06:58:28 +00:00
wxiaoguang
1d5163133b fix(repo): /generate must sync the branch table for the new repo (#37693) (#37712)
Backport #37693
2026-05-16 01:54:48 +08:00
Giteabot
28729ef7e3 fix(actions): run TransferLogs on UpdateLog{Rows:[], NoMore:true} (#37631) (#37687)
Backport #37631 by @silverwind

`UpdateLog` short-circuits on `len(Rows)==0` before honoring `NoMore`,
so a final empty `UpdateLog{NoMore:true}` never runs `TransferLogs`. The
task's `dbfs_data` rows are then never moved to log storage and never
deleted.

The bug has been latent since the original Actions implementation,
`act_runner` versions after
[runner#819](https://gitea.com/gitea/runner/pulls/819) trip it
deterministically.

Fix: let `NoMore=true` with no new rows fall through to `TransferLogs`.
Bail when the runner has outrun the server (`Index > ack`) even with
`NoMore`, since archiving a log with a gap is worse than retrying.
Always call `WriteLogs` so `offset==0` bootstraps an empty DBFS file in
the no-output case (otherwise `TransferLogs` would fail at `dbfs.Open`).

Fixes: https://github.com/go-gitea/gitea/issues/37623
Ref: [runner#952](https://gitea.com/gitea/runner/pulls/952)
Ref: [runner#950](https://gitea.com/gitea/runner/pulls/950)

---
This PR was written with the help of Claude Opus 4.7

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
2026-05-13 06:58:28 +00:00
silverwind
57dd9f5bab fix(deps): update dependency mermaid to v11.15.0 [security], add e2e test (#37665)
Backport of #37662.

---
This PR was written with the help of Claude Opus 4.7

---------

Co-authored-by: Giteabot <teabot@gitea.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
2026-05-12 08:37:33 +02:00
Giteabot
5eaa0bc603 fix(packages): Add label for private and internal package and fix composor package source permission check (#37610) (#37643)
Backport #37610 by @lunny

- Add permission checks for Composer package source links

- Add private/internal visibility labels for packages, similar to
repository visibility labels

<img width="969" height="571" alt="image"
src="https://github.com/user-attachments/assets/8a8ec3a0-bfbd-4dd6-b45b-58eda5db1a2d"
/>

- Add a link to change package visibility

<img width="1309" height="208" alt="image"
src="https://github.com/user-attachments/assets/3fa82b23-4c63-4a5e-b3f0-d37a103231ee"
/>

- Update link package descriptions

<img width="1308" height="265" alt="image"
src="https://github.com/user-attachments/assets/2c80b50e-5ffe-4d96-aedd-aa15964c4e05"
/>

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-05-11 10:36:07 -07:00
Nicolas
a55be951e3 Compare dropdown fails when selecting branch with no common merge-base (#37470) (#37472)
## Summary

- handle compare requests where base and head refs have no common merge
base without returning 500
- keep the compare branch selectors usable and show a clear warning
message
- add regression coverage for unrelated-history compare selection and
merge-base error detection

Fixes #37469 



Manuel Backport of: https://github.com/go-gitea/gitea/pull/37470

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-05-08 19:08:36 +00:00
Giteabot
65f3feaa84 fix: treat email addresses case-insensitively (#37600) (#37611) 2026-05-08 18:32:25 +00:00
Giteabot
677ab982bf fix(git): Fix smart http request scope bug (#37583) (#37605)
Backport #37583 by @lunny

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-05-08 09:14:41 -07:00
Giteabot
eeb4d8ffa2 fix(packages): use file names for generic web downloads (#37514) (#37520)
Backport #37514 

Fixes #37511.

Signed-off-by: cyphercodes <cyphercodes@users.noreply.github.com>
Co-authored-by: Rayan Salhab <r.salhab@aiyexpertsolutions.com>
Co-authored-by: cyphercodes <cyphercodes@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-05-03 11:24:02 -07:00
Giteabot
dd78d87dcd fix: merge autodetect can't close other PRs but only the last one when multiple PRs are pushed at once (#37512) (#37516)
Backport #37512

Fixes #37510.

Co-authored-by: Jason Learst <jason@jasonlearst.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-05-03 01:15:56 -07:00
Giteabot
5632abff9e Fix review submission from single-commit PR view (#37475) (#37485)
Backport #37475 by @cyphercodes

Fixes #37415.

Pin the review submission form action to the canonical PR files route

Co-authored-by: Rayan Salhab <r.salhab@aiyexpertsolutions.com>
Co-authored-by: cyphercodes <cyphercodes@users.noreply.github.com>
Co-authored-by: Hermes Agent (OpenAI GPT-5.5) <noreply@nousresearch.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-29 21:34:37 +02:00
wxiaoguang
fb3c1b031d Add CurrentURL template variable back (#37444) (#37449)
Backport #37444
2026-04-27 21:05:24 +08:00
silverwind
64d12024d6 Stabilize e2e logout propagation test (#37408)
Backport of #37403 to `release/v1.26`.

The `events › logout propagation` e2e test was racing the SSE connection
setup: if page2's SharedWorker had not finished registering its
messenger by the time page1 triggered logout, the event was silently
dropped and page2 stayed on the authenticated page.

Wait 500ms after verifying page2 is signed in, before triggering the
logout from page1, so the SharedWorker has time to register. Comment
points at a cleaner future fix (expose a ready attribute on the page)
that will also work for the planned WebSocket SharedWorker.

---
This PR was written with the help of Claude Opus 4.7

Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
2026-04-25 00:20:09 +08:00
Giteabot
fc9dfe0e56 fix: use TriggerEvent instead of Event in workflow runs API response for scheduled runs (#37288) (#37360)
Backport #37288 by @KalashThakare

## Summary

Fixes #37252

The `/api/v1/repos/{owner}/{repo}/actions/runs` endpoint was returning
`event: "push"` for workflow runs triggered by `schedule:` (cron),
instead
of `event: "schedule"`.

## Root Cause

`ActionRun` has two separate fields:
- `Event` — the workflow registration event (e.g. `push`, set when the
workflow file was first pushed)
- `TriggerEvent` — the actual event that triggered the run (e.g.
`schedule`)

`ToActionWorkflowRun` in `services/convert/action.go` was serializing
`run.Event` into the API response instead of `run.TriggerEvent`, causing
scheduled runs to be indistinguishable from push events via the API.

This was already asymmetric — the tasks/jobs API correctly used
`TriggerEvent`.

## Fix

Changed `ToActionWorkflowRun` to use `run.TriggerEvent` for the `event`
field in the API response, consistent with how the jobs API works.

## Before

`event: "push"` returned for all scheduled runs:

<img width="1112" height="191" alt="Screenshot 2026-04-19 115642"
src="https://github.com/user-attachments/assets/c0a169f5-bbd9-4f5d-9474-e4c3795110e4"
/>

## After

`event: "schedule"` correctly returned for scheduled runs:

<img width="890" height="166" alt="Screenshot 2026-04-19 121723"
src="https://github.com/user-attachments/assets/860e99ac-0935-4a43-86a1-7b60f8113480"
/>


## Testing

- Added unit test `TestToActionWorkflowRun_UsesTriggerEvent` in
  `services/convert/action_test.go` that explicitly verifies the API
  returns `TriggerEvent` and not `Event` for a scheduled run.
- Manually verified via the API against a live Gitea instance with a
  `cron: "* * * * *"` workflow.

Co-authored-by: Kalash Thakare ☯︎ <kalashthakare898@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
2026-04-22 18:39:10 +02:00
Giteabot
fc4296a21a Fix URL related escaping for oauth2 (#37334) (#37340)
Backport #37334 by wxiaoguang

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-21 17:11:19 +00:00
Giteabot
657ea10cf1 When the requested arch rpm is missing fall back to noarch (#37236) (#37339)
Backport #37236 by chethenry

This fixes: https://github.com/go-gitea/gitea/issues/37235

It uses the same changeset alpine packages got in:
https://github.com/go-gitea/gitea/issues/26691

Co-authored-by: chethenry <henry@visionlink.org>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-21 16:27:01 +00:00
Giteabot
ef096b0f90 fix(oauth): Error on auth sources with spaces (#37327) (#37332)
Backport #37327 by @prettysunflower

Nyallo~

In pull request #36901, a change is made so that the link to
authentication sources is now escaped with the QueryEscape filter.
https://github.com/go-gitea/gitea/pull/36901/changes#diff-34c39c9736a8b62e293c0c0b24c4b5b8c1c792790018c5809f9ff2cbc12b16b1R4

The problem is that [QueryEscape replace spaces with the `+`
character](https://cs.opensource.google/go/go/+/refs/tags/go1.26.2:src/net/url/url.go;l=234;drc=917949cc1d16c652cb09ba369718f45e5d814d8f),
and this is not unescaped when a user tries to log in with an
authentication source that contains a space, which throws an error.

This commit fixes that by unescaping the provider name in the URL.

---

Example of the error, on my instance, when I try to log in with
`prettysunflower's auth`
```
2026/04/21 00:11:41 routers/web/auth/oauth.go:42:SignInOAuth() [E] SignIn: oauth2 source not found, name: "prettysunflower's+auth"
	/go/src/code.gitea.io/gitea/routers/web/auth/oauth.go:42 (0x2cfa5c5)
	/usr/local/go/src/reflect/value.go:586 (0x51e245)
	/usr/local/go/src/reflect/value.go:369 (0x51d0f8)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:181 (0x1a6aaf6)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:188 (0x1a6ab65)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:188 (0x1a6ab65)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:188 (0x1a6ab65)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/services/context/context.go:217 (0x2df1b23)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:145 (0x1a6afb5)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/pkg/mod/gitea.com/go-chi/session@v0.0.0-20251124165456-68e0254e989e/session.go:258 (0x197eb82)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:145 (0x1a6afb5)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/chain.go:31 (0x1a61d05)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/mux.go:479 (0x1a64fae)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/mux.go:73 (0x1a628c2)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/mux.go:321 (0x1a6421a)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/chain.go:31 (0x1a61d05)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/mux.go:479 (0x1a64fae)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/middleware/get_head.go:37 (0x2c33a67)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:145 (0x1a6afb5)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/mux.go:73 (0x1a628c2)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/mux.go:321 (0x1a6421a)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/routers/common/maintenancemode.go:50 (0x2b752da)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:145 (0x1a6afb5)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/chain.go:31 (0x1a61d05)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/mux.go:479 (0x1a64fae)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/routing/logger_manager.go:124 (0x127d1ec)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:145 (0x1a6afb5)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/pkg/mod/github.com/chi-middleware/proxy@v1.1.1/middleware.go:37 (0x2b76acf)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:145 (0x1a6afb5)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/routers/common/middleware.go:89 (0x2b78cd6)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:145 (0x1a6afb5)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/routers/common/middleware.go:104 (0x2b7890f)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/src/code.gitea.io/gitea/modules/web/handler.go:145 (0x1a6afb5)
	/usr/local/go/src/net/http/server.go:2286 (0x94dc88)
	/go/pkg/mod/github.com/go-chi/chi/v5@v5.2.5/mux.go:90 (0x1a62881)
	/go/src/code.gitea.io/gitea/modules/web/router.go:286 (0x1a6d2a2)
	/go/src/code.gitea.io/gitea/modules/web/router.go:221 (0x1a6cbc6)
	/usr/local/go/src/net/http/server.go:3311 (0x96e36d)
	/usr/local/go/src/net/http/server.go:2073 (0x94bd6f)
	/usr/local/go/src/runtime/asm_amd64.s:1771 (0x49af20)
```

Signed-off-by: prettysunflower <me@prettysunflower.moe>
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: prettysunflower <me@prettysunflower.moe>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-04-21 08:33:46 +00:00
Giteabot
82613a40a0 Fix container auth for public instance (#37290) (#37294)
Backport #37290 by wxiaoguang

Fix #37289

Don't tell container client that the instance needs basic auth if the
public access is available.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-19 13:23:12 +00:00
wxiaoguang
1412009d0a Frontend iframe renderer framework: 3D models, OpenAPI (#37233) (#37273)
Backport

* #37233
* #37272

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-04-18 16:02:18 +08:00
wxiaoguang
145898b358 Swift registry metadata: preserve more JSON fields and accept empty metadata (#37254) (#37261)
Backport #37254

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
2026-04-17 23:36:48 +02:00
Giteabot
b191cf7e77 Fix user ssh key exporting and tests (#37256) (#37258)
Backport #37256 by wxiaoguang

1. Make sure OmitEmail won't panic
2. SSH principal keys are not for signing or authentication

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-18 03:13:41 +08:00
wxiaoguang
3b253e06a3 Fix corrupted JSON caused by goccy library (#37214) (#37220)
Backport #37214

The only conflict is go.mod

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-04-14 17:24:39 +00:00
Giteabot
789a3d3a4d fix(api): handle fork-only commits in compare API (#37185) (#37199)
Backport #37185 by @Mohit25022005

Fix 500 error when comparing branches across fork repositories

## Problem

The compare API returns a 500 Internal Server Error when comparing
branches where the head commit exists only in the fork repository.

## Cause

The API was using the base repository's GitRepo and repository context
when converting commits. This fails when the commit does not exist in
the base repository, resulting in a "fatal: bad object" error.

## Solution

Use the head repository and HeadGitRepo when available to ensure commits
are resolved in the correct repository context.

## Result

* Fixes "fatal: bad object" error
* Enables proper comparison between base and fork repositories
* Prevents 500 Internal Server Error

Fixes #37168

Co-authored-by: Mohit Swarnkar <mohitswarnkar13@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-13 18:01:44 +00:00
Giteabot
7a7376dfc8 Implement logout redirection for reverse proxy auth setups (#36085) (#37171)
Backport #36085 by @eliroca

When authentication is handled externally by a reverse proxy SSO
provider, users can be redirected to an external logout URL or relative
path defined on the reverse proxy.

Co-authored-by: Elisei Roca <eroca@suse.de>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-10 16:49:55 +00:00
silverwind
d0a39bc3a4 Replace rollup-plugin-license with rolldown-license-plugin (#37130) (#37158)
Backport #37130. Only one merge conflict in lockfile.

---
This PR was written with the help of Claude Opus 4.6

Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
2026-04-10 10:47:11 +00:00
Rohan Guliani
1b200dc3da Add support for RPM Errata (updateinfo.xml) (#37125)
Resolves https://github.com/go-gitea/gitea/issues/37124

This PR adds support for RPM Errata (security advisories, bugfixes, and
enhancements) to Gitea's built-in RPM registry.

---------

Signed-off-by: Rohan Guliani <rohansguliani@google.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-08 00:39:53 +08:00
TheFox0x7
ff777cd2ad Add terraform state registry (#36710)
Adds terraform/opentofu state registry with locking. Implements: https://github.com/go-gitea/gitea/issues/33644. I also checked [encrypted state](https://opentofu.org/docs/language/state/encryption), it works out of the box.

Docs PR: https://gitea.com/gitea/docs/pulls/357

---------

Co-authored-by: Andras Elso <elso.andras@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-06 13:41:17 -07:00
Lunny Xiao
e47c6135dd Add gpg signing for merge rebase and update by rebase (#36701)
Fix #36685 

--- 

Generated by a coding agent with Codex 5.2 LLM.
2026-04-05 13:37:35 -07:00
TheFox0x7
ca51b4f875 Move package settings to package instead of being tied to version (#37026)
Unties settings page from package version and adds button to delete the
package version
Settings page now allows for deletion of entire package and it's
versions as opposed to a single version

Adds an API endpoint to delete the entire package with all versions from
registry

fixes: https://github.com/go-gitea/gitea/issues/36904

Co-Authored-By: gemini-3-flash

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
2026-04-06 03:51:51 +08:00
silverwind
a8938115d4 Merge some standalone Vite entries into index.js (#37085)
Keep `swagger` and `external-render-helper` as a standalone entries for
external render.

- Move `devtest.ts` to `modules/` as init functions
- Make external renders correctly load its helper JS and Gitea's current theme
- Make external render iframe inherit Gitea's iframe's background color to avoid flicker
- Add e2e tests for external render and OpenAPI iframe

---------

Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-04-05 19:13:34 +00:00