1116 Commits
Author SHA1 Message Date
bircniandsilverwind ba4f8fa246 enhance(pull)!: add per-repository default squash merge commit message (#39816)
Adds a repository setting for the default squash merge commit message
body with GitHub's options `PR_BODY`, `COMMIT_MESSAGES` and `BLANK`,
also settable via `squash_merge_commit_message` in the API. The commit
title stays the pull request title.

1. Breaking: API squash merges without `merge_message_field` now get the
same default message as the web merge box instead of a title-only
commit, which affects clients sending only `Do` like Renovate. An empty
value keeps title-only.
2. Breaking: `[repository.pull-request] DEFAULT_SQUASH_MERGE_MESSAGE`
replaces `POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES`, which still
works as a deprecated fallback. Repositories store the default when
created or next saved.
3. Deprecated app.ini keys now migrate through one table instead of
per-loader fallbacks, which also fixes the ignored `[mailer] CERT_FILE`
and `KEY_FILE` fallbacks. Deprecation warnings no longer claim a removal
version.

<img width="1891" height="571" alt="grafik"
src="https://github.com/user-attachments/assets/0fdcde13-1f11-4156-b598-d80eb0d04cbe"
/>

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-10-19 09:15:41 +00:00
silverwindandwxiaoguang 5264304a34 refactor: carry the API token on the doer (#39690)
The token a request authenticated with now lives on the doer, so
permission and visibility checks apply its scope from the doer alone.
Replaces https://github.com/go-gitea/gitea/pull/39167, following
https://github.com/go-gitea/gitea/pull/39167#issuecomment-6063839619.

1. Public-only tokens get 404 instead of 403 for hidden users, orgs and
repos, like GitHub.
2. Org ownership, site admin, repo and org creation, generation and
transfer endpoints reject public-only tokens.
3. API pull request responses set `head.repo` to `null` and
`head.repo_id` to `-1` when the caller cannot see the head repository.
4. Public-only tokens see org memberships like anonymous callers, so
concealed members stay hidden.
5. Site admin access in activity feeds, follower lists, org members,
Actions run lists and packages needs a session or an `all`-scoped token.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-19 00:34:01 +00:00
ae17c14cff fix: add missing checks to several handlers and models (#39839)
Several handlers and model helpers skipped checks that their siblings
already perform.

- Only match principal keys when looking up SSH certificate principals
- Return no attachments for an unsaved issue instead of every issue-less
one
- Reject issue and comment attachments when adding release attachments
- Share one permission check for editing, deleting and reacting to issue
content and for comment attachments between the web UI and the API,
refusing them on locked issues for users who can't write
- Reject issue edits, deletion and label changes in archived
repositories via the API
- Apply cross-origin protection to the repository topics endpoint
- Return 404 for the repositories tab of individual users and respect
profile visibility for the heatmap

Fixes: https://github.com/go-gitea/gitea/issues/39226
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: bircni <bircni@icloud.com>
2026-10-18 06:29:49 -07:00
silverwind 1031e34987 test: run integration tests on random ports and speed up slow tests (#39842)
Integration test processes now get their own work directory, config file
and random ports, so several runs can execute in parallel on one
machine. The slowest tests also lose fixed sleeps and needlessly
expensive setup, with their assertions kept.

- Batch PostgreSQL sequence resets, the main per-test fixture cost there
- Cheap hashing params in hash and OAuth2 fixture tests, full-cost
vectors stay
- Single fetch for negative Actions runner assertions instead of 1s
polls
- Queue flushes and backdated timestamps instead of sleeps
- In-memory SQLite test journal, tmpfs for PostgreSQL in CI
- E2E instance writes SSH keys into its work directory instead of
`~/.ssh/authorized_keys`
2026-10-18 12:56:04 +00:00
Max P. a4908d4af4 enhance(actions): add OIDC workload identity support (#39052)
Adds OpenID Connect workload identity to Gitea Actions: jobs declaring
`id-token: write` can request short-lived tokens to authenticate to
cloud providers and other services without stored secrets. Tokens follow
GitHub's format, so clients like `@actions/core` and existing trust
policies carry over.

- Issuer at `/api/actions/oidc` with discovery and JWKS, signed with a
dedicated RS256 key
- GitHub's claims, including `workflow_ref`, `job_workflow_ref` and the
immutable `repo:owner@id/repo@id:ref:...` subject
- `id-token: write` or `write-all` grant it, default permissions and
fork pull requests never get it, owner and repository maximum
permissions can disable it
- Reusable workflows record the exact ref they were loaded from, and
dispatch rejects refs that only resolve through a same-named tag
- Generated signing keys are written atomically, and generated ES384 and
ES512 OAuth2 keys use their own curves instead of P-256
- `github.ref_type` is `branch` for pull request runs, like on GitHub

Fixes https://github.com/go-gitea/gitea/issues/26383
Fixes https://github.com/go-gitea/gitea/issues/33681
Docs: https://gitea.com/gitea/docs/pulls/526
Assisted-by: ChatGPT:gpt-5.6-sol, Claude Code:claude-opus-5-5
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-10-18 07:08:55 +00:00
Mitrahsoftandwxiaoguang efb0b34395 fix(packages): list highest CRAN version in PACKAGES index (#39793)
Fixes https://github.com/go-gitea/gitea/issues/35728

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-17 06:48:48 +00:00
42b1f95261 fix: optimize packages upload memory (#39366)
Bound the memory used when parsing uploaded packages, so instances with
low memory limits survive non-standard packages.

1. Metadata files are read through a size-limited reader, archives
themselves stay unbounded so large payloads keep working
2. zstd decoding caps the window at 128 MiB, the zstd CLI default
3. RPM headers go through a first-party reader with rpmlib's size and
array count limits that allocates only what the upload contains, until
https://github.com/sassoftware/go-rpmutils/pull/44 is released. Signing
still verifies the payload digest, and its signature header matches
rpmsign's byte for byte
4. Swift and NuGet read the zip entry they size-checked, a duplicate
name could stand in for it before
5. Terraform states check `LIMIT_SIZE_TERRAFORM_STATE` before parsing,
NuGet symbol PDBs share a 256 MiB budget
6. Oversized container configs are rejected instead of stored without
metadata, invalid Vagrant boxes answer 400 instead of 500

Signed-off-by: techknowlogick <git@tklk.dev>
Co-authored-by: techknowlogick <git@tklk.dev>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: techknowlogick <techknowlogick@gitea.com>
2026-10-17 06:10:04 +00:00
Mitrahsoftandwxiaoguang 6b252ca3a9 fix(pull): don't auto-detect empty pull requests as manually merged (#39807)
With "Autodetect manual merge" enabled, an empty pull request (one with
no commits of its own, for example opened to discuss a branch) was
closed as manually merged as soon as it was checked. Its head commit is
already an ancestor of the base branch, so the detection took the
"fast-forwarded" path and recorded the head itself as the merge commit,
even though nothing was merged.

Detection now skips a PR whose head commit is its merge base, the same
condition Gitea already uses to show a PR as "already included in the
target branch". Real manual merges are still detected, including when
the base branch and the PR branch are pushed together.

The merge base is refreshed on recheck, so a fast-forward manual merge
whose merge base was already refreshed to the head is not detected
either. This only misses a detection and never closes a PR wrongly;
telling the two apart would need a value stored at PR creation.

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

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-16 08:29:25 -07:00
wxiaoguang 222136ee71 refactor: clean up pull request comment related code and template dict (#39789)
1. drop comment.commit_id
2. refactor templates, remove `dict "." .` from templates
2026-10-15 23:09:41 +00:00
Zettat123 919116568f fix(actions): fix schedule cleanup and default branch switch (#39740)
Cancelling running schedule runs has not worked since
https://github.com/go-gitea/gitea/pull/35767: callers pass a branch name
like `main`, while schedule runs store the full ref like
`refs/heads/main`. Disabling Actions, archiving the repository or
changing the default branch left them running.

Fixing the ref alone would also cancel them on every push to the default
branch, which GitHub does not do, and whenever the Actions setting is
saved, so those paths now only replace the schedules.

Changing or renaming the default branch deleted the schedules without
registering the new branch's ones
(https://github.com/go-gitea/gitea/pull/28691), so they stopped until
the next push, and the API path kept the old ones. Both now switch the
schedules to the new default branch, since scheduled workflows only run
on the default branch.
2026-10-14 19:34:46 +00:00
wxiaoguang ccc9b928fe refactor: issue comment context menu and buttons (#39771)
1. Support show "Quote reply" shortcut in help menu, fix the TODO
2. Help #36862 to reuse existing "issue/comment context menu"
2026-10-14 12:07:31 +00:00
b015cd67e2 feat(repo): allow deleting protected branches (#39243)
This adds a Branch Deletion setting with three modes: disabled by
default, anyone with push access, or a restricted user/team/deploy-key
allowlist. The policy applies to Git pushes, API/UI deletion, and
post-merge cleanup; the default branch and the pull request target
branch remain undeletable.

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

---------

Co-authored-by: Enoque Duarte <12515551+enoquefcd@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-14 07:19:49 +00:00
wxiaoguang c6e2513570 refactor: migrate protected branch fields into one json column and support system users (#39735)
1. migrate protected branch fields into one json column
2. use the dropdown list for push/force-push user selection, and Actions
user can be added into the list now.
2026-10-13 00:40:21 +00:00
Shivansh Gargandwxiaoguang f270534e83 fix: validate "scope" for OAuth2, "state" for OpenID (#39642)
1. Fixes: https://github.com/go-gitea/gitea/issues/39641
* The OAuth2 authorize/grant endpoint accepted and persisted arbitrary
scope strings without validation, unlike personal access token creation
which rejects unknown scopes. Normalize and validate form.Scope before
creating or updating a grant, ignore invalid scopes
* `// TODO: at the moment invalid tokens are treated as "all" to avoid
breaking 1.22 behavior` is fixed.
2. To avoid CSRF attack for OpenID endpoint, add a state check

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-12 20:57:41 +00:00
bircniandwxiaoguang 8a9e8c4e8c fix(actions): harden log cursor, activity type and actor filter handling (#39721)
Fixes a few Actions bugs where user input or nondeterminism caused
failures:

- The job log view indexed task steps with the client-supplied cursor
step without a bounds check, so an out-of-range value panicked and
returned a 500.
- Workflow activity type filters (`types:`) were compiled with
`glob.MustCompile`, so an invalid pattern in a workflow file panicked
during event detection. Invalid patterns now simply don't match.
- Listing workflow runs with an unknown `actor` returned a 500; it now
returns 404.
- The v4 artifact `ListArtifacts` response was built by ranging over a
map, so its order changed between calls. It now follows database order.
- The error from marshalling a workflow job when inserting run jobs was
silently ignored.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-10 19:52:23 +00:00
321d3ec104 refactor(actions): pass secret and variable scope as a struct (#39719)
Secret and variable functions took an adjacent `ownerID, repoID int64`
pair, so swapping the two compiled and only failed at runtime. They now
take a `BelongingScope` value instead.

`BelongingScope` also replaces the "drop OwnerID when RepoID is set"
step that `InsertEncryptedSecret` and `InsertVariable` each implemented
separately

No behaviour change. It also makes adding another scope dimension, such
as the environment ID in https://github.com/go-gitea/gitea/pull/38149, a
one-field change.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
2026-10-10 18:21:28 +00:00
Jspringandwxiaoguang 39ae5d6e6b test(api): refactor organization repository listing testing code (#39699)
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-09 12:11:47 +00:00
Shivansh Garg c0a8eb8e74 fix: OIDC discovery advertises unsupported id_token response_type (#39498)
The OIDC discovery document at `/.well-known/openid-configuration`
advertised `id_token` in `response_types_supported`, but
`/login/oauth/authorize` only implements the authorization code flow and
rejects any other response_type with `unsupported_response_type`. This
mismatch caused OIDC client libraries that rely on discovery to attempt
the implicit flow and fail silently.

This removes `id_token` from `response_types_supported` so discovery
matches actual server behavior, and adds an integration test asserting
`response_type=id_token` is rejected consistently.

Fixes #39482.
2026-10-08 18:10:54 +00:00
Roland Singerandwxiaoguang a0b9ce05c4 fix: go get fails with GO_GET_CLONE_URL_PROTOCOL=ssh on the default SSH port (#39674)
Go rejects scp-style addresses like `git@host:owner/repo.git` in the
go-import meta tag because they have no URL scheme, so
GO_GET_CLONE_URL_PROTOCOL=ssh did not work with the default SSH port
unless USE_COMPAT_SSH_URI was set. Always use the ssh:// form for
go-get.

When DISABLE_HTTP_GIT is enabled, the https clone URL can never work, so
GO_GET_CLONE_URL_PROTOCOL now defaults to ssh in that case.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-08 08:52:24 +00:00
wxiaoguang cc623c5f2f refactor: clean up git migration forms (#39672)
Only extracted shared code, removed unnecessary code, and use
form-fetch-action to replace RenderWithErrDeprecated, slightly
refactored JS to use data-global-init

Nothing else is changed, although there are still many problems.

Written by AI

Diff with hiding spaces:
https://github.com/go-gitea/gitea/pull/39672/changes?w=1
2026-10-08 10:36:08 +02:00
wxiaoguang 26475404d4 fix: show "merge" form for empty PR (#39640)
fix #39637
2026-10-06 17:28:28 +00:00
dziulatexandwxiaoguang 1264072754 fix(pull): refresh commits behind when an AGit pull request is updated (#39613)
Fixes #39598

The AGit update path in `services/agit` moved `refs/pull/N/head` without
recomputing commits_behind.

The AGit update path now calls `syncCommitDivergence` in
`UpdateRefForAgit`, the same as AGit PR creation (`NewPullRequest`)
already does.

---------

Signed-off-by: dziulatex <paweldziurasoftware@yahoo.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-06 07:21:43 +00:00
d16b20b972 feat(user): allow renaming security keys (webauthn/passkey) (#39413)
Closes https://github.com/go-gitea/gitea/issues/39287

Security key nicknames could only be set at registration, so a skipped
nickname left an auto-generated hex name until the key was
re-registered. Each key now has a Rename button opening a dialog with
the current nickname. A nickname used by another of the user's keys
(case-insensitive) or a blank nickname is rejected. Renames are recorded
as `user:webauth:rename` audit events.

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-05 19:12:22 +02:00
wxiaoguang b0d5a63e7a fix: migrate broken team authorize access mode (#39579)
* fix:  #39571
* ref: https://github.com/go-gitea/gitea/pull/38938#pullrequestreview-4945228548
* fix the bug in `assignTeamPermissionUnits` which can result in wrong team access

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-05 09:03:34 +00:00
silverwind fc44404843 test: keep integration ssh independent of user ssh config (#39600)
The SSH integration tests read the user's `~/.ssh/config`, so options
like `ControlMaster` reused a connection authenticated with another
test's key and the tests failed with "Cannot find key". Pass `-F none`
so ssh reads no config files.
2026-10-05 05:25:54 +00:00
silverwind eb4468ff4e enhance!: raise minimum git version to 2.34 (#39565)
Raise the minimum git version to 2.34, the version in Ubuntu 22.04,
Debian 12 and RHEL 8 ship newer, and remove the fallbacks it makes
obsolete.

- Always enable AGit
- Use `diff --skip-to` and `apply -3` unconditionally
- Set the default branch of new repos and wikis via `git init
--initial-branch`
- Detect rebase conflicts via `REBASE_HEAD`
2026-10-04 16:26:14 +08:00
Zettat123 4bebd86285 fix(user): restore organizations tab on user profile (#39577)
Fixes #39572

The shared user cards template calls the User-only `IsTypeBot` method.
The profile organizations tab passed `*organization.Organization` values
to that template, so `/{username}?tab=organizations` returned a 500
error.

Organizations are now converted to Users before rendering.
2026-10-04 15:30:04 +08:00
cca466caae fix(api): allow bots with pending password changes (#39551)
Allow bot accounts to use the API when a legacy password-change flag is
set, since bots cannot complete the interactive password-change flow.
Preserve password-change enforcement for human accounts and restrictions
for inactive or prohibited accounts.

Fixes: https://github.com/go-gitea/gitea/issues/39542
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-10-03 17:22:07 +00:00
okxintandsilverwind ab1979bcfb fix(api): normalize all API due dates to end of day (#38677)
Due dates set through the API were stored inconsistently. The create
endpoints kept the raw timestamp, issue and pull request edits used end
of day in the client's offset, and only the deadline and milestone edit
endpoints normalized to end of day in the server's UI timezone like the
web UI does. All API due dates now go through
`ParseAPIDeadlineToEndOfDay`.

Editing a pull request with `unset_due_date: false` and no `due_date`
dereferenced a nil pointer and returned 500. It now shares the issue
edit logic and returns 400.

Related to https://github.com/go-gitea/gitea/issues/37620, which is
about the web sidebar and isn't fixed here.

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-10-03 11:59:43 +00:00
silverwindandwxiaoguang ad38b60983 refactor!: remove go-git backend (#39487)
Removes the go-git backend so every build uses the git CLI backend. Its
Windows performance advantage is gone, it lacks SHA-256 support, and it
breaks repositories on Windows.

The performance changes moved to
https://github.com/go-gitea/gitea/pull/39526.

Fixes https://github.com/go-gitea/gitea/issues/38359
Fixes https://github.com/go-gitea/gitea/issues/34694

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-03 10:04:24 +00:00
457510fa09 fix: use READ_COMMITTED_SNAPSHOT on MSSQL (#39512)
MSSQL's default READ COMMITTED makes reads wait on writers, so the
runner pickup deadlocks with concurrent claims, flaking
`TestCreateTaskForRunnerConcurrentClaim`.

- Enable `READ_COMMITTED_SNAPSHOT` on MSSQL so it reads like PostgreSQL
and MySQL
- Read the pickup cursor before claiming, a lost claim could skip
waiting jobs
- Add tests that fail without consistent READ COMMITTED

Performance: Writes on MSSQL now also store the previous row version in
tempdb, the same versioning cost PostgreSQL and MySQL always pay, and
Azure SQL enables it by default. Reads no longer block on writers, and a
32-runner pickup stress test ran 2.5x faster with it.

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
2026-10-03 15:25:47 +08:00
silverwind 2baa5a16f8 enhance(citation): render citations server-side (#39373)
Replace citation-js with a Go port of ruby-cff, which GitHub uses for
"Cite this repository", rendering APA and BibTeX server-side and
dropping about 770KB of JS. Output matches GitHub on 1568 of 1571
real-world files, the rest are improvements over GitHub.

- `CITATION.cff` wins over `CITATION.bib`, matched case-insensitively
and through symlinks
- `CITATION.bib` is offered as-is, without APA

Signed-off-by: silverwind <me@silverwind.io>
2026-10-03 02:28:34 +00:00
6dad3ad43d refactor: only update sync status columns when syncing push mirror (#39517)
`UpdatePushMirror` used `AllCols()`, so a sync could overwrite columns
changed concurrently (e.g. `interval`) with stale values. It now updates
only `last_update` and `last_error`, and is renamed to
`UpdatePushMirrorSyncStatus` to match.

Co-authored-by: Giteabot <teabot@gitea.io>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 5) <noreply@anthropic.com>
2026-10-02 19:28:51 +00:00
silverwindandwxiaoguang cf89ecd887 refactor!: move go-chi/session into Gitea (#39504)
The `gitea.com/go-chi/session` package only exists for Gitea, so it
moves into `modules/session` to fix its bugs directly. Fixes the flake
in
https://github.com/go-gitea/gitea/actions/runs/36726154500/job/109923538400.

- Sessions are only written back when changed, so a read-only request
can't revert a concurrent change or restore a logged-out session, like
https://github.com/go-macaron/session/commit/ae808a4a4660c802965c834299ab08f167effd12
- The session cookie is only set once a session holds data
- Every backend refreshes the expiry on load and file sessions are
written atomically
- Also fix  https://github.com/go-gitea/gitea/issues/36176

## ⚠️ BREAKING ⚠️

* the `mysql`, `postgres`, `couchbase` and `memcache` session providers
are removed, use `file`, `db` or `redis` instead
* login-related cookies are renamed to `gitea_session` and
`gitea_remember`, if you'd like to use the old names, set `COOKIE_NAME`
and `COOKIE_REMEMBER_NAME` in app.ini

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-02 21:08:14 +02:00
silverwindandwxiaoguang 873efed5a6 refactor: move go-chi/captcha into Gitea (#39529)
The `gitea.com/go-chi/captcha` package only exists for Gitea,
so it moves into `modules/imagecaptcha`.

- Reloading an expired challenge shows a new image instead of a broken one
- Every answer is consumed on its first check
- OpenID registration stops after a failed captcha

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-02 22:21:41 +08:00
wxiaoguang 9b5c87a6b6 fix: trace git command correctly (#39520)
Help  #39410
2026-10-01 10:01:45 +00:00
silverwindandwxiaoguang 51b93d1d27 enhance(packages/npm): improve npm client compatibility (#39434)
Aligns the npm registry with what npm, pnpm and yarn expect:

1. Raise the publish body cap from
https://github.com/go-gitea/gitea/pull/37890 to 256 MiB like npmjs,
larger bodies get 413
2. Pick the tarball attachment by name, `npm publish --provenance`
failed at random
3. Store and serve `libc`, so mismatched glibc/musl optional binaries
are skipped
4. Treat root `*.gyp` files as an install script, like npm does
5. Always serve a `latest` dist-tag, yarn and pnpm fail without it
6. Take top-level metadata from `latest` and drop the per-version readme
7. Serve tarballs at the npmjs path `/<name>/-/<file>`, former URLs keep
working
8. Add ETag revalidation for metadata, `npm ping` and `npm whoami`

Tested with npm 12.1, pnpm 12.4, yarn 1.22 and yarn 4.18.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-01 07:50:47 +00:00
a71c5c94c5 fix(actions): reject jobs without runs-on (#39480)
Align job and `runs-on` validation with github.com, as implemented by
the parser in https://github.com/actions/runner. A job without `runs-on`
could be claimed by any runner, so a job meant for a container could run
on the host.

- Jobs without `runs-on` fail with `Required property is missing:
runs-on`, called workflows included
- Unknown job keys and callers (`uses:`) mixed with steps-only keys like
`runs-on` are rejected
- Empty, null and nested `runs-on` values are rejected
- A `runs-on` evaluating to such a value fails only that job
- Called workflows are validated at run creation, an invalid one fails
the run as an invalid workflow file
- Zero labels (`runs-on: []` or `{}`) never match a runner, including
jobs queued before upgrading

<img width="960" alt="image"
src="https://github.com/user-attachments/assets/e746ce5a-b711-4e8b-aab8-81336ff53d86"
/>

**Behavior Change:** workflows that omit `runs-on`, use unknown job keys
or mix `uses` with `runs-on` stop running until fixed.

---------

Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-09-30 21:42:07 -06:00
silverwindandbircni 8936303510 fix: add missing checks to several API and web handlers (#39501)
Several handlers skipped checks that their sibling routes or settings already enforce. This brings them in line.

- Push mirror API honors `DISABLE_NEW_PUSH` and checks the caller's permission
- Media API serves small files with the usual content headers
- Issue attachment API ignores comment attachments
- Push-to-create respects `FORCE_PRIVATE`
- Profile feeds and follow actions respect `ENABLE_FEED` and owner visibility
- Tag delete route refuses release tags
- Refresh token grant only accepts refresh tokens
- Gitea migrations bound the source's page size

Co-authored-by: bircni <bircni@icloud.com>
2026-09-30 20:25:14 +02:00
Zettat123 3d085dbaf1 feat(admin): show and filter users by authentication source (#38900) 2026-09-30 11:28:35 -06:00
wxiaoguang cc95f141f8 fix: npm route (#39488) 2026-09-30 19:49:50 +08:00
1b1274486c fix(git)!: use internal proxy for all git operations (#39426)
Introduces gitproxy module which spawns a small forward proxy as scanner
for git calls
Replaces hostmatcher with matchlist which supports port rules
Deprecates ALLOWED_DOMAINS/BLOCKED_DOMAINS and ALLOW_LOCALNETWORKS
settings in migration in favor of full names we have in security
configs.
Removes `external` preset in favor of lax/strict modes, strict mode
requiring explicit ports if they aren't standard http/s ones.

Breaking changes:
- `external` preset no longer works as deny rule. To enforce that, use
`strict` mode and allow ranges to connect to
- Wildcards are no longer accepted in IP addresses
- `*` is no longer allowed as entry in lists
- domain rules now use curl like syntax `*.example.com` matching
subdomains but not `example.com`, `example.com` matching itself and all
subdomains. `example.*` is not a valid rule
- In the default `lax` mode, `[security] ALLOWED_HOST_LIST` no longer
restricts public hosts, set `EGRESS_MODE = strict` to keep an exclusive
list. A startup warning flags this
- Invalid list entries are logged at startup, invalid
`BLOCKED_HOST_LIST`/`BLOCKED_DOMAINS` entries stop it

Docs: https://gitea.com/gitea/docs/pulls/557
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-09-29 14:43:36 +02:00
Stochastic 6bb74ed65d fix(actions): preserve admitted jobs and runs in their concurrency group (#39461) 2026-09-29 04:36:33 +00:00
silverwind 9e7b302bd3 enhance(actions): add pending job status and align job statuses with GitHub (#39376) 2026-09-27 18:30:42 +00:00
bircniandsilverwind f44e64be81 fix(actions): harden fork pull request run approval (#39399)
Fixes several gaps in the approval of fork pull request runs:

1. Approving a run that was cancelled while awaiting approval revived
its cancelled jobs. Such a run is no longer treated as awaiting approval
by the merge box, run page, approve actions and API, and rerunning it
approves it.
2. Approval no longer revives jobs cancelled while the run was pending,
no longer lets two jobs sharing a concurrency group cancel each other,
and re-emits the run so jobs needing a cancelled job get resolved.
3. An unapproved run applies its workflow-level concurrency only once
approved.
4. For workflows from the pull request, both the event actor and the
pull request author must be trusted to skip approval. Workflows from the
default branch, like `issue_comment`, still only check the actor.

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-09-26 22:52:19 +00:00
wxiaoguang ea91028028 fix: PR merge (#39442)
* Revert the behavior introduced by #30805
* Now the PR status is still managed in Gitea's code where the operation
is triggerred but not in post-receive hook
* Fix #39254 and many more related bugs.
    * Fix #39124

```
// MarkAsMerged sets a pull request to merged and closes the corresponding issue
// To make sure the pull request is marked as merged correctly, the caller uses multiple-stage operations:
//  1. Create a temp repo from base, merge the head into the temp repo, and get the merged commit ID and timestamp,
//  2. The merged commit ID and related information are stored into pull request
//  3. Push the merged commit to the base repo
//  4. Call MarkAsMerged to mark the pull request as merged and do post-processing (notification, close issues, etc)
//
// If failure occurs in step 1/2/3: the pull request is still open, the base repo is not changed, the doer can start a new merge.
// If failure occurs in step 4: the pull request can be marked as merged by the merged commit ID stored in it later.
```
2026-09-26 17:38:42 +00:00
dcef88a233 fix(api): allow pending-inline-comment-only reviews (#39433)
Prior to this change, the API rejected reviews without a summary
comment, even if it had pending inline comments. This differs from the
web UI, which accepts such reviews. The affected endpoints are:

1. Submitting via POST /repos/{owner}/{repo}/pulls/{index}/reviews/{id}.
2. Creating via POST /repos/{owner}/{repo}/pulls/{index}/reviews, both
when finishing an existing pending review and when creating a new
pending review.

The endpoints ran their own emptiness check, which ignored comments
already in a pending review. The fix drops it for comment and pending
reviews and relies on the model's check, which counts them, as the web
UI does.

A review with neither a body nor inline comments remains invalid.

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: bircni <bircni@icloud.com>
2026-09-26 16:51:55 +00:00
3875db1974 feat(actions): add build queue view (#38585)
Adds a read-only Actions job queue: running jobs first, then waiting
jobs in the order a runner picks them up. It is shown instance-wide in
the admin Actions section with owner, repository and status filters, and
per repository in the Actions tab. Both lists refresh in place.

Pending work is currently only visible per repository and newest-first,
so nothing shows what is queued, in which order, or what occupies the
runners. Reordering the queue will be proposed separately.

A migration adds indexes for the runner pickup query and
repository-scoped status lookups.

* Fix #34198

<img width="1345" height="451" alt="image"
src="https://github.com/user-attachments/assets/7d52ff76-81b4-44e8-b583-d7d89c9dffcd"
/>
<img width="1809" height="1134" alt="image"
src="https://github.com/user-attachments/assets/4d56c0cb-bae7-4ce2-8f3c-75163b2bc7f4"
/>

---------

Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-09-26 08:01:41 +00:00
5a56e118e4 feat(actions): Add artifact preview in Actions run view (#36754)
Closes https://github.com/go-gitea/gitea/issues/33579.

Adds browser previews for Actions artifacts. Selecting an artifact opens
its file browser; selecting a file renders it in the same tab. The ZIP
download remains available separately.

Previews require sign-in and read access to the run. Text, image and PDF
files are supported; rendered HTML and JavaScript run in a sandboxed
frame and are labeled as automatically generated. The frame loads files
from a signed link that expires after an hour, because its requests
carry no session cookie. `[actions] ARTIFACT_PREVIEW_MAX_SIZE` limits
total previewable artifact size (`0` disables previews; `-1` removes the
limit); individual files also follow `[ui] MAX_DISPLAY_FILE_SIZE`.

<img width="1803" height="913" alt="image"
src="https://github.com/user-attachments/assets/a38fd704-2244-44fa-9181-c695ecbe0276"
/>

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

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
2026-09-26 07:42:36 +00:00
Zettat123andsilverwind a15f032026 fix(actions): evaluate job-level if: before concurrency check (#39437)
Gitea doesn't evaluate a job's `if:` before checking the job's
concurrency group, which causes a job that should have been skipped to
incorrectly cancel other jobs in the same concurrency group.

This PR makes Gitea decide `if:` for every job before it becomes
waiting, including jobs without `needs` at insertion, on approval and on
rerun. A skipped job therefore no longer takes part in job concurrency
or holds a max-parallel slot, and a reusable caller whose `if:` is false
is no longer expanded on approval or rerun. An invalid `if:` skips the
job with an error summary.

After this PR, Gitea decides all jobs' `if:` expressions and sends `if:
always()` to the runner, so the runner no longer needs to evaluate a
job's `if:` again ([gitea/runner
`run_context.go`](https://gitea.com/gitea/runner/src/commit/81add274599355ec1838b6ebe45804890d40bab9/act/runner/run_context.go#L1195)).

---------

Co-authored-by: silverwind <me@silverwind.io>
2026-09-26 09:01:21 +02:00