`git commit --message=` passes the merge message as a single argument,
which Linux caps at 128 KiB and Windows at 32 KiB for the whole command
line. Long messages failed with `argument list too long` and the merge
box toast showed the raw HTML 500 page.
Pass the message via `--file=-` on stdin instead, and answer
fetch-action requests with JSON on server errors so the toast shows the
error text. Limits merge commit messages to 512KB which could be
extended or made configurable later.
Fixes: https://github.com/go-gitea/gitea/issues/39261
Fixes: https://github.com/go-gitea/gitea/issues/30276
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Follow-up to https://github.com/go-gitea/gitea/pull/38966. Replaces the
unreleased `POST /admin/users/{username}/convert-type` endpoint with a
`type` field on `PATCH /admin/users/{username}`.
Adds first-class bot accounts (`UserTypeBot`): local, password-less
users for automation that authenticate only with access tokens.
1. Admin UI: create bots, filter users by type, manage a bot's access
tokens, convert between user and bot
2. API: `POST /admin/users/{username}/convert-type`, and user objects
gain a GitHub-compatible `type` (`User`, `Organization`, `Bot`)
3. CLI: `gitea admin user change-type`, `--user-type` accepts `User` or
`Bot` case-insensitively
4. Converting keeps the password, 2FA, OAuth2 grants and access tokens,
and since sign-in rejects bots, converting back restores the account.
Only local, non-admin accounts can be converted, and conversions are
audited
5. Session, reverse proxy, SSPI, external source and password reset
sign-in reject non-individual users, so a bot never gets an interactive
session
6. Bots receive no notifications or emails
Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: joestump <joe@joestump.net>
Co-authored-by: Joe Stump <joe@stu.mp>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Deploy keys only work over SSH. A deploy token is their counterpart for HTTPS: a repository scoped credential, used as the password of a Git request, with read or read and write access. It covers Git operations and LFS, and can be regenerated in place.
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Claude Mythos <noreply@anthropic.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
With SIGNING_FORMAT = ssh the OpenPGP verification path builds its
GPGSettings from the instance signing key but leaves the format empty,
so it runs `gpg -a --export` on an SSH public key path. Depending on the
local gpg setup that either exports nothing, so an OpenPGP signed commit
reports gpg.error.generate_hash instead of a missing key, or it fails
outright and logs an export error for every such commit.
Both guards are needed. The first covers SIGNING_KEY set to a path with
SIGNING_FORMAT=ssh; the second covers the shipped default
SIGNING_KEY=default, where the format comes from git's own gpg.format
and never gets reconciled with the hardcoded "openpgp". Drop either one
and a working config goes back to broken.
Also raise minimum git version to 2.18 which was already required before this change.
Fixes: https://github.com/go-gitea/gitea/issues/37452
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Bot co-authors like `dependabot[bot]` render as one long string with the
email inside the name, and never get truncated, so they overflow the
column.
Co-author idents are parsed with `net/mail`, but a git ident isn't an
email address. `mail.ParseAddress` rejects the whole value when the name
holds characters RFC 5322 reserves, like a `[bot]` suffix or a comma, so
the error branch keeps the raw trailer as the display name and throws
the address away. No address means no `mailto:` link, and the anchor is
what `.avatar-stack-names` truncates.
So parse the angle-addr ourselves when `net/mail` won't take it.
Splitting on the last `<` is safe because git strips angle brackets from
idents. The bare-name branch gets the class too.
Fixes https://github.com/go-gitea/gitea/issues/38949
Follow-up to https://github.com/go-gitea/gitea/pull/39068, which
disabled `modernize` entirely.
- re-enable `modernize`, with only the new `embedlit` rule disabled. It
flattens embedded struct literals across ~145 files, and orphans imports
in 6 of them that the fixer does not remove
- apply the rest of the suite: `errors.AsType`, `reflect.TypeAssert`,
`strings.Cut`, and dropping the legacy import comment
- use the new stdlib `uuid` package, `github.com/google/uuid` becomes
indirect
- use `strings.CutLast` in place of manual `LastIndex` slicing in label
scopes, email domains and the diff tree list
- take the header lint skip dirs from the `go.mod` `ignore` directive
and skip dot-directories, instead of hardcoding the list
Assisted-by: Claude Code:claude-opus-5
Only made some necessary changes:
1. remove `GOEXPERIMENT`, only use jsonv2
1. `make fmt`
* `SigningKey` and `Signature` were affected due to some bugs in the
toolchain, so rewrote them
1. remove or fix fragile magic numbers and strings
* the outputs of image/gzip/zlib packages are different
1. update "nolint" comments for the changed lint behaviors
1. add `tls.MLKEM1024`
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>
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>
Bound gitignore template selections at both web and API request
boundaries before repository initialization.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
### 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>