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
The "New Pull Request" buttons and the `/pulls/new/{branch}` redirect
build their compare link as `{owner}:{branch}`. If a fork and its parent
share an owner, through ALLOW_FORK_INTO_SAME_OWNER, or after a transfer,
that head resolves back to the base repo, so the link compares the base
against itself and 404s on a branch that only exists in the fork.
Switching to `{owner}/{repo}:{branch}` names the head repo
unambiguously, and it's what the compare page's own links already use.
Also clears the 404 in #37649; the archived-parent half of that report
is separate.
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
## Summary
Replace `url.QueryEscape` with `url.PathEscape` when building
`dist.tarball` in the npm package registry. `QueryEscape` leaves `@`
unescaped, producing `dist.tarball` URLs like `@scope%2Fname` for scoped
packages — which npm clients cannot resolve. `PathEscape` produces the
RFC 3986 path-segment-safe encoding (`%40scope%2Fname`) that the npm
registry URL format requires.
## Reproduction
1. Publish a scoped npm package (`@scope/name@1.0.0`) to a Gitea package
registry.
2. Inspect the `dist.tarball` field in the metadata response.
3. Observe that the package name in the URL is `@scope%2Fname` instead
of `%40scope%2Fname`.
4. `npm install @scope/name` fails because npm rejects the malformed
tarball URL.
## Fix
One-line change in `routers/api/packages/npm/api.go`:
```diff
-Tarball: fmt.Sprintf("%s/%s/-/%s/%s", registryURL, url.QueryEscape(pd.Package.Name), url.PathEscape(pd.Version.Version), url.PathEscape(pd.Files[0].File.LowerName)),
+Tarball: fmt.Sprintf("%s/%s/-/%s/%s", registryURL, url.PathEscape(pd.Package.Name), url.PathEscape(pd.Version.Version), url.PathEscape(pd.Files[0].File.LowerName)),
```
## Tests
- `routers/api/packages/npm/api_test.go`: extended
`TestCreatePackageMetadataResponse` to use `Package.Name: "@scope/test"`
and added an `assert.Equal` on `Dist.Tarball` (per review feedback to
consolidate the test instead of adding a new one).
- `tests/integration/api_packages_npm_test.go`: switched three
`url.QueryEscape(packageName)` to `url.PathEscape(packageName)` to match
the new production encoding (lines 125, 126, 446). The `TestPackageNpm`
assert at line 219 against `pmv.Dist.Tarball` now passes for scoped
packages.
The unit test fails on `main` (excluding the `QueryEscape` →
`PathEscape` swap) and passes with the fix.
## Related
Closes#39060.
## Disclosure
This contribution was prepared with assistance from an AI coding
assistant (limited to language polishing in maintainer-facing messages).
The contributor reviewed and validated all changes, including the test
cases.
---------
Signed-off-by: Dmitriy Chudnyi <dmitriy@chudnyi.com>
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
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`
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 https://github.com/go-gitea/gitea/issues/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>
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 https://github.com/go-gitea/gitea/issues/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>
Require organization ownership before changing repository team
associations when team access is restricted.
---------
Co-authored-by: silverwind <me@silverwind.io>
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>
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>
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>
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#39034
---------
Co-authored-by: bircni <bircni@icloud.com>
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>
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>
Bound gitignore template selections at both web and API request
boundaries before repository initialization.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>