Automated update of the generated runner reference pages from gitea/runner (main for the develop docs, the newest stable tag for every documented series), opened by the "update runner reference" scheduled workflow.
---------
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/555
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@astrojs/starlight](https://starlight.astro.build) ([source](https://github.com/withastro/starlight/tree/HEAD/packages/starlight)) | [`0.42.0` → `0.42.1`](https://renovatebot.com/diffs/npm/@astrojs%2fstarlight/0.42.0/0.42.1) |  |  |
| [pnpm](https://github.com/pnpm/pnpm/tree/main/pnpm) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm/npm/pnpm)) | [`12.4.0` → `12.4.2`](https://renovatebot.com/diffs/npm/pnpm/12.4.0/12.4.2) |  |  |
| [yaml](https://eemeli.org/yaml/) ([source](https://github.com/eemeli/yaml)) | [`2.9.0` → `2.9.1`](https://renovatebot.com/diffs/npm/yaml/2.9.0/2.9.1) |  |  |
---
### Release Notes
<details>
<summary>withastro/starlight (@​astrojs/starlight)</summary>
### [`v0.42.1`](https://github.com/withastro/starlight/blob/HEAD/packages/starlight/CHANGELOG.md#0421)
[Compare Source](https://github.com/withastro/starlight/compare/@astrojs/[email protected]...@astrojs/[email protected])
##### Patch Changes
- [#​4198](https://github.com/withastro/starlight/pull/4198) [`96a44d4`](https://github.com/withastro/starlight/commit/96a44d4f296b512febc6e631a587103ec5297872) Thanks [@​mayank99](https://github.com/mayank99)! - Removes the `popover` attribute from the sidebar pane on desktop viewports. This ensures the desktop sidebar doesn't stay in a "hidden" popover visibility state.
</details>
<details>
<summary>pnpm/pnpm (pnpm)</summary>
### [`v12.4.2`](https://github.com/pnpm/pnpm/releases/tag/v12.4.2): pnpm 12.4.2
[Compare Source](https://github.com/pnpm/pnpm/compare/v12.4.1...v12.4.2)
pnpm 12.4.2 includes security fixes for executable shims and GitHub Actions links, more reliable installs, faster peer dependency checks in workspaces, and Python lockfiles that work across compatible targets.
#### Patch Changes
##### Security
- Dependency executables can no longer take over another package's POSIX bin shim through its shell helpers. Reinstall dependencies to replace existing shims [#​14837](https://github.com/pnpm/pnpm/issues/14837).
On Cygwin, MSYS2, and WSL, shims still use `PATH` for Windows path conversion, so dependency executables can still redirect them there.
- GitHub Actions homepage links no longer expose server credentials. GitHub server URLs now require HTTPS, with HTTP allowed only for loopback hosts.
##### Installing packages
- pnpm no longer crashes at startup on FreeBSD and other Unix-like platforms. Platforms other than Windows and macOS use `~/.local/share/pnpm/store` by default [#​14859](https://github.com/pnpm/pnpm/issues/14859).
- `pnpm install` on Windows no longer fails with `ERR_PNPM_PACKAGE_MANAGER_REMOVE_MODULES_DIR` when clearing `node_modules` containing linked dependencies, such as when changing `nodeLinker` [#​14790](https://github.com/pnpm/pnpm/issues/14790).
- `pnpm install <pkg>` now accepts `--prod` and `--dev`, including `--prod=false` [#​14868](https://github.com/pnpm/pnpm/issues/14868).
- `pnpm install` and `pnpm update` now honor `--ignore-workspace` in nested projects excluded from the surrounding workspace. The flag also skips that workspace's settings during the `packageManager` check [#​14809](https://github.com/pnpm/pnpm/issues/14809).
- `pnpm install` on macOS no longer reuses stale files for `file:` tarball or git-hosted tarball dependencies.
- `pnpm install` in a single-project directory now detects `package.json` edits made while the previous install was finishing [#​14890](https://github.com/pnpm/pnpm/issues/14890).
- `pnpm install --frozen-lockfile` now removes packages no longer reachable from any project in `pnpm-lock.yaml`. This also prevents repeated lifecycle script execution and unnecessary installs before `pnpm run` and `pnpm exec` with `verifyDepsBeforeRun` [#​14891](https://github.com/pnpm/pnpm/issues/14891).
##### Resolving and updating dependencies
- Node.js runtime resolution now reports network failures from unofficial-builds.nodejs.org. These failures previously omitted musl builds from `pnpm-lock.yaml`, making its contents depend on network access [#​14813](https://github.com/pnpm/pnpm/issues/14813).
- `pnpm install` now rejects invalid `peerDependencies` specifiers with `ERR_PNPM_INVALID_PEER_DEPENDENCY_SPECIFICATION`. A value such as `"foo": "[email protected]"` previously created a broken directory link [#​14791](https://github.com/pnpm/pnpm/issues/14791).
- `pnpm deploy` now writes plain registry versions in the deployed `package.json`, without peer dependency suffixes. The lockfile retains peer bindings, and npm aliases retain their target package names [#​14873](https://github.com/pnpm/pnpm/issues/14873).
- `pnpm add <git repository>` now names repositories without a `package.json` as `@owner/repo`, allowing dependencies on equally named repositories from different owners [#​14870](https://github.com/pnpm/pnpm/issues/14870).
- Peer dependency resolution now deduplicates packages whose child dependency resolves an optional peer in only some workspace projects, such as `next` with `styled-jsx`'s optional `babel-plugin-macros` peer [#​14800](https://github.com/pnpm/pnpm/issues/14800).
- `pnpm update` now settles the lockfile in one run when an upgrade removes the package providing an optional peer dependency [#​14895](https://github.com/pnpm/pnpm/issues/14895).
- `pnpm update --no-save` now preserves override-applied specifiers for dependencies it is not updating, preventing subsequent frozen installs from failing with `ERR_PNPM_OUTDATED_LOCKFILE` [#​14836](https://github.com/pnpm/pnpm/issues/14836).
- `pnpm update --no-save` now succeeds under `minimumReleaseAgeStrict` when every resolved version is old enough [#​14835](https://github.com/pnpm/pnpm/issues/14835).
##### Performance
- Workspace installs and `pnpm peers check` are faster when projects depend on each other, fixing a slowdown introduced in 12.3.0. Unmet peer dependencies of workspace packages are now reported only under projects that link them directly [#​14906](https://github.com/pnpm/pnpm/issues/14906).
- Hoisted installs use less memory when packages are cached. Frozen-lockfile hoisted installs on macOS are also faster when reusable package directories are cached.
##### Python projects
- `pnpm install --frozen-lockfile` now reuses `pylock.toml` across compatible Python targets, including after kernel updates. Reuse requires unchanged requirements, index, and `requires-python`, compatible wheels, and a locked dependency graph matching the target's markers [#​14843](https://github.com/pnpm/pnpm/issues/14843).
The lockfile's `environments` marker now includes only the interpreter version and marker variables used by the dependency graph. Without `--frozen-lockfile`, pnpm warns and resolves again when the locked graph no longer matches the target.
- Python resolution no longer fails on malformed `Requires-Python` values, such as the trailing comma in `openpyxl` 3.0.x. pnpm treats these releases as declaring no interpreter range [#​14910](https://github.com/pnpm/pnpm/issues/14910).
- `pnpm add pypi:...` now rejects unsupported `--save-prefix` values before editing the manifest or resolving dependencies.
##### Workspaces and scripts
- Scripts listed in `syncInjectedDepsAfterScripts` no longer fail with `ERR_PNPM_INJECTED_DEPS_SYNC_READ_DIR` when the lockfile contains an injected package copy that no project depends on.
- `shellEmulator` now expands `${VAR}`, `${VAR:-default}`, and `${VAR:+alternative}` in scripts [#​14814](https://github.com/pnpm/pnpm/issues/14814).
- Cargo and Python project discovery now honors `!` exclusions in `pnpm-workspace.yaml` `packages`, skipping both parsing and generated source configuration for excluded projects [#​14844](https://github.com/pnpm/pnpm/issues/14844).
- `pnpm --filter "./packages/{app,lib}"` now selects either alternative. Brace alternatives can nest, span path separators, and combine with other wildcards.
- GitHub Actions updates now stop if an action reference changes during version resolution, and preserve unrelated workflow edits.
##### CLI and output
- `pn`, `pnpx`, and `pnx` now run the pnpm installed alongside them, even when that directory is absent from `PATH` or another pnpm comes first [#​14803](https://github.com/pnpm/pnpm/issues/14803).
- `pnpm --version` now reports failures to install or record a project's pinned pnpm, then prints the running CLI's version. It also honors `--store-dir` and `--store` [#​14831](https://github.com/pnpm/pnpm/issues/14831).
- `pnpm self-update` no longer reinstalls the active version when it was installed by the standalone installation script [#​14823](https://github.com/pnpm/pnpm/issues/14823).
- `pnpm t` and `pnpm tst` work again as aliases for `pnpm test`.
- `pnpm sbom` now emits valid repository URLs in CycloneDX `externalReferences[].url` and SPDX `homepage`. Shorthands such as `vercel/ms` become `git+https` URLs, embedded credentials are removed, and invalid repository values are omitted [#​14773](https://github.com/pnpm/pnpm/issues/14773).
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
### [`v12.4.1`](https://github.com/pnpm/pnpm/releases/tag/v12.4.1): pnpm 12.4.1
[Compare Source](https://github.com/pnpm/pnpm/compare/v12.4.0...v12.4.1)
pnpm 12.4.1 fixes installs that failed on filesystems refusing hard links or clones, on Android, and under `nodeLinker: hoisted`. Repeat installs are faster.
#### Patch Changes
##### Installing packages
- `pnpm install` no longer fails with `Operation not permitted` when the filesystem refuses a hard link or a copy-on-write clone [#​14722](https://github.com/pnpm/pnpm/issues/14722). Under `packageImportMethod: auto` and `clone-or-copy`, pnpm copies the file instead. EdenFS checkouts, which have no hard links, and rootless containers, which refuse the clone syscall, both hit this. An explicit `packageImportMethod: hardlink` or `clone` still reports the error.
pnpm also copies a package file whose store entry has reached the filesystem's limit on names for one file, 1024 on NTFS and 65000 on ext4. Such a file failed the install under `packageImportMethod: hardlink`, and under `auto` it stopped pnpm hard linking for the rest of the install.
- `pnpm install` no longer writes a package file through a symlink left at the path it is importing to. Copying such a file overwrote whatever the link pointed at, and created that file when the link pointed nowhere. An executable package file also made the link's target executable.
- Fixed `pnpm install` and `pnpm dlx` on Android. Registry requests crashed because pnpm found no system CA certificates, so pnpm uses bundled ones there [#​14777](https://github.com/pnpm/pnpm/issues/14777). Imports also failed with "Permission denied" on filesystems that deny hard links and reflinks, and now fall back to copying [#​14780](https://github.com/pnpm/pnpm/issues/14780).
- `pnpm install` no longer fails with "Invalid cross-device link" while preserving a package's nested `node_modules` directory during a Docker build [#​14758](https://github.com/pnpm/pnpm/issues/14758).
- `pnpm install` no longer fails on a package tarball that carries a file at the archive root, such as the `._*` entries macOS `tar` adds [#​14701](https://github.com/pnpm/pnpm/issues/14701). The file is installed at the root of the package.
A `file:` tarball packed without the usual `package/` directory is now recorded under the name and version from its own `package.json`. It was recorded under the alias the dependency was given, at version 0.0.0.
- Under `nodeLinker: hoisted`, `pnpm install` no longer re-imports packages that are already in place. A repeat install replaced the whole `node_modules` tree and reported `Packages: +N`. A package is still imported when its directory is missing, when its `package.json` no longer carries the installed version, when it is a `file:` dependency, and when it is patched. Lifecycle scripts no longer run again for a package left in place, and `pnpm rebuild` and a change to `allowBuilds` still reach it.
- `pnpm install` now runs a dependency's build scripts again when its side-effects cache entry has no files to restore [#​14717](https://github.com/pnpm/pnpm/issues/14717). Such builds were skipped and nothing was put in their place, so a script whose whole effect lands outside its own package directory, such as a git hook installer, never took effect. pnpm no longer publishes empty artifacts to the shared side-effects cache either.
##### Resolving and linking dependencies
- `pnpm install`, `pnpm add`, and `pnpm dedupe` now apply `ignoredOptionalDependencies` [#​14729](https://github.com/pnpm/pnpm/issues/14729). Matching optional dependencies are left out of the lockfile and are not installed. pnpm 12 installed them whenever it resolved dependencies from scratch.
- `pnpm install` no longer links a transitive dependency to a workspace package when `linkWorkspacePackages` is `true` and the dependency is declared with a plain version range [#​14781](https://github.com/pnpm/pnpm/issues/14781). Enabling `preferWorkspacePackages` does not change this. Set `linkWorkspacePackages: deep` to link them.
- `pnpm install` no longer leaves dangling dependency links in workspace packages located above the workspace root [#​14726](https://github.com/pnpm/pnpm/issues/14726).
- `pnpm install` and `pnpm add` no longer leave a dangling symlink in `node_modules` when a project starts depending directly on a package that the lockfile holds only as a transitive dependency with resolved peer dependencies [#​14714](https://github.com/pnpm/pnpm/issues/14714).
- `pnpm dedupe` now keeps a compatible auto-installed peer when another workspace project depends on a newer major [#​14697](https://github.com/pnpm/pnpm/issues/14697). Repeated runs alternated between compatible and incompatible peer versions.
- `pnpm peers check` no longer reports a peer dependency declared as `workspace:^`, `workspace:~`, or a bare `workspace:` as unmet [#​14770](https://github.com/pnpm/pnpm/issues/14770). pnpm reported these as unmet whatever version the linked workspace project supplied.
##### Performance
- Sped up repeat installs [#​14540](https://github.com/pnpm/pnpm/issues/14540). pnpm checks the store's files only for the packages it links into `node_modules`, instead of every package in the lockfile. Creating the command shims in `node_modules/.bin` makes about 1,500 fewer filesystem calls in a 76 project workspace. Installs that use the global virtual store read their slot paths from the cache directory instead of deriving them every time. Verifying a large lockfile also allocates less memory.
- Sped up `pnpm install` in Cargo workspaces with many member crates. Repeated installs reuse verified Cargo checksum metadata.
- Installing several packages from the same Git repository and commit now downloads the source once per install [#​14725](https://github.com/pnpm/pnpm/issues/14725). Each package still runs its prepare scripts in its own copy of the checkout.
##### Running scripts and tasks
- pnpm now passes Ctrl+C on to the script or command it started and waits for it to shut down [#​14723](https://github.com/pnpm/pnpm/issues/14723). pnpm exited first, so a script that was still writing landed on the shell prompt.
- `pnpm run "/pattern/" --no-bail` now lets every matched script finish after one of them fails [#​14718](https://github.com/pnpm/pnpm/issues/14718). The command exits with `ERR_PNPM_RUN_FAILED`, and its message lists the scripts that failed in the order they were selected.
- `pnpm pipeline` no longer fails on a project that tracks a symlink, such as a `CLAUDE.md` pointing at `AGENTS.md` [#​14692](https://github.com/pnpm/pnpm/issues/14692). Changing a symlinked input's target invalidates that task's cache, and `pnpm pipeline --no-cache` no longer hashes task inputs.
##### Commands
- `pnpm add -g`, `pnpm update -g`, and `pnpm remove -g` no longer change global bins or install directories after reading only part of an installed package group [#​13796](https://github.com/pnpm/pnpm/issues/13796). If any declared package manifest is missing, malformed, or unreadable, pnpm now fails before it activates or removes anything and leaves the existing global installation intact.
- `pnpm dedupe` now processes every workspace project by default, including workspaces that keep a separate lockfile per project [#​14732](https://github.com/pnpm/pnpm/issues/14732). Workspace filters select which projects it processes, and `--fail-if-no-match` exits with an error when no project matches.
- `pnpm update <name>@​<version>` now keeps the range operator the manifest declares [#​14745](https://github.com/pnpm/pnpm/issues/14745). Running `pnpm update [email protected]` on `"react": "^19.2.8"` writes `"react": "^19.3.0"`. A `jsr:` entry keeps its `jsr:` prefix, and a plain `pnpm update` now moves a `jsr:` range the way it moves an npm range.
- `pnpm --filter` directory selectors now support `?` wildcards and character classes such as `[ab]`. A `*` or `?` wildcard no longer selects a directory whose name starts with a dot, as on pnpm 11.
- `pnpm deploy --legacy` now prefers the dependency versions pinned in the source workspace lockfile when they still satisfy the deployed project's range [#​13857](https://github.com/pnpm/pnpm/issues/13857).
- `pnpm sbom` now leaves out a package's author field when the manifest author name is empty or contains only whitespace [#​14685](https://github.com/pnpm/pnpm/issues/14685). In a filtered or split workspace run, only a project with no `author` field inherits the workspace root's author.
`pnpm sbom --sbom-format spdx` now writes `creationInfo.created` with whole seconds, such as `2026-09-08T10:38:21Z` [#​14684](https://github.com/pnpm/pnpm/issues/14684). The fractional seconds it carried were rejected by strict SPDX consumers.
##### Configuration
- The `updateConfig` pnpmfile hook now receives the resolved configuration, including settings that came from `.npmrc`, the command line, or a default [#​14676](https://github.com/pnpm/pnpm/issues/14676). Scoped registries are reported under `registriesByScope`, and a hook may rewrite that map to change where packages are fetched from. Registry credentials are reported under `configByUri`, as pnpm 11 reports them. An unset setting is left out rather than reported as `null`.
- `pnpm audit --fix` and the `minimumReleaseAgeStrict` approval prompt now keep the comments in `minimumReleaseAgeExclude` when they append an entry to it in `pnpm-workspace.yaml`. The rest of the list is left as written, and the `trustPolicyExcludePrune` and `minimumReleaseAgeExcludePrune` cleanups keep the comments of the entries they retain.
`pnpm install` and `pnpm dedupe` now run those cleanups too [#​14759](https://github.com/pnpm/pnpm/issues/14759). Only `pnpm add`, `pnpm update`, and `pnpm remove` pruned the entries that the freshly written lockfile no longer resolves.
- `pnpm config set --global node-download-mirrors` no longer rejects the key [#​13611](https://github.com/pnpm/pnpm/issues/13611). The global config file already accepted `nodeDownloadMirrors`, but the command refused to write it.
- `NO_PROXY` entries that start with a dot, such as `.npmjs.org`, now bypass the proxy for the domain and its subdomains [#​14686](https://github.com/pnpm/pnpm/issues/14686).
- pnpm no longer creates a project `pnpm-lock.yaml` when `devEngines.packageManager.onFail` is `download` and lockfile writing is off through `lockfile: false` or `--no-lockfile` [#​14728](https://github.com/pnpm/pnpm/issues/14728). pnpm still switches to the pinned version.
- pnpm now writes `node_modules/.package-map.json` only when `nodeExperimentalPackageMap` is enabled. Nothing reads the file without that setting, and an install that stops writing the map removes the one a previous install left.
##### Windows
- `pnpm pipeline` no longer fails with intermittent access denied errors when concurrent tasks save their cache entries on Windows.
- Windows filesystem operations now retry permission errors for up to one second [#​14682](https://github.com/pnpm/pnpm/issues/14682). A permanent permission error delayed the failure by a minute. Sharing and lock violations keep their one minute retry budget.
##### Messages and output
- pnpm now warns when the root `package.json` declares a non-empty `workspaces` array and the project has no `pnpm-workspace.yaml` [#​2255](https://github.com/pnpm/pnpm/issues/2255). Such an install linked no project and said nothing about why.
- `ERR_PNPM_PACKAGE_MANAGER_REMOVE_MODULES_DIR` now names the file or directory in `node_modules` that pnpm could not clean up. It reported only the underlying OS error, such as "Access is denied (os error 5)".
- `pnpm --help` no longer describes pnpm as experimental.
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
</details>
<details>
<summary>eemeli/yaml (yaml)</summary>
### [`v2.9.1`](https://github.com/eemeli/yaml/releases/tag/v2.9.1)
[Compare Source](https://github.com/eemeli/yaml/compare/v2.9.0...v2.9.1)
- Limit recursive merge aliases ([#​685](https://github.com/eemeli/yaml/issues/685), [#​713](https://github.com/eemeli/yaml/issues/713))
- Simplify line unfolding during quoted string parsing ([#​714](https://github.com/eemeli/yaml/issues/714))
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
<!-- cloudflare-preview --> Preview: https://pr-554.docs-gitea-com.pages.dev
Reviewed-on: https://gitea.com/gitea/docs/pulls/554
Reviewed-by: silverwind <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
Fixes https://github.com/go-gitea/gitea/issues/39310
The docker install pages tell readers to use `:nightly` / `:nightless-rootless` for the latest development version, but those tags are no longer published — the registry only carries `main-nightly` and `main-nightly-rootless` (plus the per-release-branch `1.x-nightly` tags):
```
$ curl -s https://docker.gitea.com/v2/gitea/tags/list?n=1000 | tr ',' '\n' | grep -E '"(main-)?nightly(-rootless)?"'
"main-nightly"
"main-nightly-rootless"
```
Anyone who followed the rootless page has been pinned to an image that has not been rebuilt since 2025-08-23.
Changes:
- point the docker and rootless docker install pages at `:main-nightly` / `:main-nightly-rootless`, in English and in the zh-cn/zh-tw translations
- use `1.27-nightly` instead of the long gone `1.16-nightly` as the release branch example (the oldest one still published is `1.19-nightly`)
- fix the zh-cn/zh-tw claim that `:latest` installs a development version, and mention the nightly tags there the way the English page does
- render `@dockerVersion@` as `main-nightly` for the next version, so the compose snippets on the unreleased docs no longer reference `gitea:nightly`
Not touched: the 1.22–1.26 versioned docs carry the same stale tag, but those versions are already out of maintenance — happy to include them if preferred.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- cloudflare-preview --> Preview: https://pr-550.docs-gitea-com.pages.dev
---------
Co-authored-by: bircni <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/550
Reviewed-by: silverwind <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
Several cron tasks in the cheat sheet listed `ENABLE_SUCCESS_NOTICE` or `NO_SUCCESS_NOTICE`. Gitea reads neither, only `NOTICE_ON_SUCCESS`. `NO_SUCCESS_NOTICE` was removed in https://github.com/go-gitea/gitea/pull/19221.
1. Replace both dead keys with `NOTICE_ON_SUCCESS` (default `false`).
2. Fix "Notice if not success" descriptions, which inverted the key's meaning.
3. List the key for `cleanup_hook_task_table`, `cleanup_actions`, `cleanup_action_runs` and `gc_lfs`, which honor it but omitted it.
Matches https://github.com/go-gitea/gitea/pull/39352.
Written by Claude.
Reviewed-on: https://gitea.com/gitea/docs/pulls/552
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
Two unrelated but small fixes, closes#258 and closes#32.
**The reference does not name its types (#258)**
Since the api reference is rendered from the openapi 3.0 document, a field of type `ReviewStateType` is rendered as the bare string enum the `$ref` points at: starlight-openapi dereferences everything and the schema has no `title`, so the name of the type is nowhere on the page. Searching the current reference for `ReviewStateType` returns nothing, which is what the issue reports (the plugin also has no route for `components/schemas`, so there is no page per type either).
`normalizeSchema()` now titles every named schema of an openapi 3.0 document with its own name, which the plugin renders next to the type of a field:
- before: `state` · `string` · Allowed values: APPROVED …
- after: `state` · `ReviewStateType` · `string` · Allowed values: APPROVED …
The go doc comments start with the name of the type, so the description would repeat it ("ChangeFilesOptions — ChangeFilesOptions options for creating …"); a leading `<name> ` is stripped from the description.
For the record, how the three generations of documents describe that type:
| Versions | Type name | Allowed values |
| --- | --- | --- |
| 1.22 – 1.25 (swagger, `ReviewStateType` definition without `enum`) | shown | missing |
| 1.26 – 1.27 (swagger, enum inlined upstream) | missing | shown |
| 1.27, next (openapi 3.0, with this change) | shown | shown |
The released swagger documents are frozen, so 1.22 – 1.26 keep what they have; from 1.27 on the reference answers the question the issue asks.
**Gmail needs an app password (#32)**
The configuration in the guide is still correct after Google turned off password-only access, because it already asks for an app password. What was missing is why there is no alternative: Gitea's mailer authenticates with `CRAM-MD5`, `PLAIN` or `LOGIN` and has no XOAUTH2, so "Sign in with Google" is not an option. Added that, together with the two things people run into — an app password needs 2-step verification and a Workspace administrator can disable app passwords for the domain — and the `587` + `smtp+starttls` variant.
Verified by building the api and the next docs: the type names show up on the operation pages, the descriptions are not duplicated, and 1.26 and older are unchanged. `pnpm check` passes.
<!-- cloudflare-preview --> Preview: https://pr-541.docs-gitea-com.pages.dev
---------
Co-authored-by: bircni <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/541
Reviewed-by: bircni <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
Closes#243.
The `sha` of the contents API is compared against the ID of the blob the commit has at that path, and for a file tracked by Git LFS that blob is the pointer file. Sending the `lfs_oid` or a checksum of the file content fails with `sha does not match`, and nothing in the documentation said so.
Adds a section to the LFS page: use the `sha` from `GET /repos/{owner}/{repo}/contents/{filepath}`, not `lfs_oid`, and note that the API does turn the content into an LFS object by itself when `.gitattributes` tracks the path (`modifyFile()` stores the object and commits the pointer), so nothing else has to be done differently.
The swagger comments upstream are being fixed in https://github.com/go-gitea/gitea/pull/38915, which will reach `/api/next/` through the scheduled job and the released reference with 1.28. The documents of 1.22 – 1.27 are frozen, so the guide is the only place where readers of the current release can find it.
<!-- cloudflare-preview --> Preview: https://pr-542.docs-gitea-com.pages.dev
Reviewed-on: https://gitea.com/gitea/docs/pulls/542
Reviewed-by: bircni <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
Automated update of static/swagger-latest.json and static/openapi3-latest.json from the gitea main branch, opened by the "update api spec files" scheduled workflow.
Reviewed-on: https://gitea.com/gitea/docs/pulls/531
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
## Summary
Adds Sealos to the cloud-provider installation page for the current and next
Gitea documentation.
## Why
Sealos provides a public, community-maintained one-click Gitea template. The
entry fits alongside the existing Cloudron, Linode, alwaysdata, and Exoscale
options.
## Proposed files
- `docs/installation/on-cloud-provider.md`
- `versioned_docs/version-1.27/installation/on-cloud-provider.md`
## Validation
- Sealos App Store: https://sealos.io/products/app-store/gitea
- Template source: https://github.com/labring-actions/templates/tree/kb-0.9/template/gitea
- Gitea image: `docker.gitea.com/gitea:1.27.0-rootless`
- Live deployment validated on 2026-07-24
- Verified administrator initialization, login, repository creation, commits,
issues, release uploads, persistence, and S3 upload, read, and delete flows
## Maintenance
I maintain the Sealos template and can update the documentation when its
deployment path changes. Deployment-specific support is handled in the
[Sealos templates repository](https://github.com/labring-actions/templates/issues).
## AI assistance
This proposal was prepared with OpenAI Codex assistance. I reviewed the
deployment evidence and proposed content and will personally handle review
feedback.
---------
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/525
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: yangchuansheng <[email protected]>
Automated update of the generated runner reference pages from gitea/runner (main for the develop docs, the newest stable tag for every documented series), opened by the "update runner reference" scheduled workflow.
Reviewed-on: https://gitea.com/gitea/docs/pulls/528
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
Automated update of static/swagger-latest.json and static/openapi3-latest.json from the gitea main branch, opened by the "update api spec files" scheduled workflow.
Reviewed-on: https://gitea.com/gitea/docs/pulls/522
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
The docs site is served by Cloudflare Pages now, so the AWS deployment path is redundant.
- Drop the AWS CLI installation step.
- Drop the `configure-aws-credentials` step and the `aws s3 sync` + CloudFront invalidation step.
- Keep only the Cloudflare Pages deploy, and simplify the `_headers` / `_redirects` comment since it no longer needs to explain S3 ordering.
The AWS_* secrets are no longer used by this workflow and can be removed from the repository settings.
Reviewed-on: https://gitea.com/gitea/docs/pulls/518
Reviewed-by: silverwind <[email protected]>
Automated update of static/swagger-latest.json and static/openapi3-latest.json from the gitea main branch, opened by the "update api spec files" scheduled workflow.
Reviewed-on: https://gitea.com/gitea/docs/pulls/519
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
The `checks` workflow deploys a Cloudflare Pages preview to the `pr-<number>` branch of the `docs-gitea-com` project for every pull request, but nothing ever removed it. Closed and merged pull requests therefore keep an alias and a growing list of deployments around.
This adds a `cleanup preview` workflow that runs when a pull request is closed (merged or not), lists the deployments of the project through the Cloudflare API and deletes the ones whose trigger branch is `pr-<number>`. `force=true` is used so the deployment the branch alias points at is removed as well.
Pull requests from forks do not receive the secrets, so the cleanup is skipped there, exactly like the preview deployment itself.
---------
Co-authored-by: bircni <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/517
Reviewed-by: bircni <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
Five documentation fixes that do not depend on anything upstream.
**PostgreSQL version in the docker guide** (closes#224)
The compose example pinned `postgres:14`, the oldest version Gitea still tests against, and PostgreSQL does not upgrade its data directory on its own, so every new deployment that copies the example is one major upgrade behind from day one. The example now uses `postgres:18`, with a note about why the major version is pinned and a pointer to the supported range.
**SELinux** (closes#211)
`setcap 'cap_net_bind_service=+ep'` is what the docs suggest for binding to a port below 1024, but it is denied under SELinux depending on the label of the binary, and it is lost on every upgrade because the capability lives in an extended attribute of the file. A new page describes granting the capability through the systemd unit instead (`AmbientCapabilities`, plus `PrivateUsers=false` when the sandboxing gets in the way), the `semanage fcontext` / `restorecon` labels for the binary and the data directory, and how to read the denials with `ausearch` and `audit2allow`. It is linked from the binary and source installation pages and from the `gitea web` notes.
**OAuth2 and OpenID Connect** (closes#106)
The authentication page documented LDAP, PAM, SMTP, FreeIPA, SPNEGO and the reverse proxy, but not that Gitea can log users in against an external OAuth2 or OpenID Connect provider, which made it look like the only OAuth2 support is Gitea acting as the provider. The new section covers the fields of the authentication source, the callback URL to register at the provider, the group and claim mappings, and the `[oauth2_client]` settings, and separates it from the older OpenID 2.0 sign-in.
**IIS reverse proxy** (closes#39)
Application Request Routing rewrites the host of the `Location` header back to the internal one while "Reverse rewrite host in response headers" is on, which sends the browser to `127.0.0.1:3000` after a sign-in. The IIS section now says to turn it off and where the setting lives.
**ACME in containers** (closes#292)
`ACME_DIRECTORY` defaults to the relative path `https`, which is resolved against the working directory of the process. In the official image that is `/app/gitea`, outside the `/data` volume, so a recreated container asks the CA for a new certificate and runs into the Let's Encrypt limit of 5 certificates per week for the same domains. The HTTPS page now warns about it and shows an absolute path inside the volume; the cheat sheet entry points at the warning. The default itself is being changed in https://github.com/go-gitea/gitea/pull/35851, the note stays useful for every released version.
Only `docs/` is touched, the released versions keep their content.
<!-- cloudflare-preview --> Preview: https://pr-513.docs-gitea-com.pages.dev
Reviewed-on: https://gitea.com/gitea/docs/pulls/513
Reviewed-by: bircni <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
Closes#37.
Gitea generates an OpenAPI 3.0 document since 1.27 (`templates/swagger/v1_openapi3_json.tmpl`, renamed to `templates/swagger/v1-openapi3.generated.json` on main, served by an instance at `/openapi3.v1.json`), but this site never picked it up and still published Swagger 2.0 only. That is what the issue is about: code generators such as `openapi-python-client` reject the document with "You may be trying to use a Swagger document; this is not supported by this project".
**What this does**
- `update_api_docs.sh` downloads the OpenAPI 3.0 document next to the Swagger 2.0 one, rewrites the same placeholders (they sit in `servers` instead of `basePath`) and writes `static/openapi3-latest.json` and `static/openapi3-<minor>.json`. Versions that do not have one (1.26 and older) are skipped with a message and keep their Swagger 2.0 document.
- The OpenAPI 3.0 document is rendered where it exists (`/api/` and `/api/next/`), the older versions keep rendering Swagger 2.0. Both documents describe the same api and carry the same operation ids, so no url of an operation page changes; the `basePath` normalization is now only applied to the Swagger 2.0 documents, since a full url in `servers` is valid.
- The overview page of each version links both documents for download, which is what the issue actually needs: `https://docs.gitea.com/openapi3-27.json` for the current release, `https://docs.gitea.com/openapi3-latest.json` for gitea main.
- The scheduled workflow now refreshes and proposes both documents of gitea main.
**Verification**
- `pnpm dlx @redocly/cli lint static/openapi3-latest.json`: valid, only content warnings that come from upstream (missing 4xx responses, ambiguous paths).
- `openapi-python-client generate --path static/openapi3-latest.json`, the tool from the issue, generates a client. The only warning left is `POST /markdown/raw`, whose request body is `text/plain`.
- Operation ids of `static/swagger-27.json` and `static/openapi3-27.json` are identical (481 on both sides), so the operation pages keep their urls.
- Built the api product and compared a rendered operation page against the Swagger 2.0 one: same sections, the request body is now marked required where the document says so.
The released Swagger 2.0 documents are kept: they are the only description 1.26 and older ever produced, and some tooling still expects them.
<!-- cloudflare-preview --> Preview: https://pr-514.docs-gitea-com.pages.dev
Reviewed-on: https://gitea.com/gitea/docs/pulls/514
Reviewed-by: bircni <[email protected]>
Closes#146.
The published site runs pagefind, not docsearch: `PUBLIC_DOCSEARCH_APP_ID` and `PUBLIC_DOCSEARCH_API_KEY` are not set, so `astro.config.mjs` falls back to `pagefind: true`, and a page of docs.gitea.com ships starlight's `#starlight__search` with the `/pagefind/` bundle. The version scoping we have is only implemented for docsearch (`docsearch:product` / `docsearch:version` meta tags plus `facetFilters` in `src/config/docsearch.ts`), so nothing consumes it today.
Pagefind builds one index for the whole site, partitioned only by the html language, and nothing tags the pages with a version, so a search started in the 1.23 docs answers with every version of the same page and the latest one usually wins. That is what the issue reports; the original cause (the docusaurus search plugin) is gone, this one replaced it.
**What this does**
- `src/components/MarkdownContent.astro` wraps the content in two `data-pagefind-filter` elements, `product` and `version`, so the filters land in the index. One filter per element on purpose: pagefind reads the whole attribute as a single `name:value` pair, a comma separated value ends up as one filter named `product` with the value `docs,version:1.26`.
- The same scope is written to a `gitea:search-filters` meta tag next to the docsearch ones (`src/lib/search.ts`).
- Starlight builds the search ui from a build time configuration and has no option for per page filters, so its `@pagefind/default-ui` import is redirected to a subclass in `src/lib/pagefind-ui.ts` by the `gitea-pagefind-filters` plugin in `astro.config.mjs`, the same approach the `gitea-openapi-overview` plugin already uses. The subclass selects the filters of the page the modal was opened on.
- A "Search all versions" checkbox below the search input drops the filters again and labels each result with the version (and the product for the api and the runner) it comes from, so the duplicates are distinguishable. Translated into 简体中文 and 繁體中文.
- Pagefind's own filter panel is hidden, it is redundant next to the checkbox and starlight does not style it. The checkbox gets its native rendering back, pagefind resets everything it renders with `all: unset`.
- A `gitea-pagefind-filters-check` integration fails the build if the redirect did not run, so a starlight upgrade that moves the import cannot silently bring back an unscoped search.
`@pagefind/default-ui` is added to `sites/docs/package.json`; it was only reachable as a transitive dependency of starlight, and the version is the one already in the lockfile.
**Verification**
Built the whole site and drove the search with a headless browser against `astro preview` (the search does not run in `pnpm dev`):
| Page | Query | Results |
| --- | --- | --- |
| `/1.23/usage/actions/comparison/` | email | only `/1.23/...` |
| `/usage/actions/overview/` | email | only the version served at the root |
| `/runner/registration/` | label | only `/runner/...` |
| `/api/operations/tags/issue/` | label | only `/api/...` |
| `/zh-cn/1.26/usage/actions/overview/` | email | only `/zh-cn/1.26/...` |
| `/1.23/...` with the checkbox ticked | email | every version, results labelled `... · API 1.25`, `... · next` |
`pnpm check` passes. The docsearch path is unchanged: when the credentials are set the plugin takes over, the redirect does not run and the check integration skips.
<!-- cloudflare-preview --> Preview: https://pr-512.docs-gitea-com.pages.dev
Reviewed-on: https://gitea.com/gitea/docs/pulls/512
## Problem
`https://docs.gitea.com/help/seek-help` returns 404. It is still linked as the
*Support* item of the blog.gitea.com navbar, and it is not the only url in that
state: `/usage/webhooks`, `/usage/agit`, `/usage/protected-tags` and
`/usage/repo-mirror` are linked from gitea itself and 404 as well.
## Root cause
Not a rendering problem of the new site: those pages were moved years ago.
`docs/help/seek-help.md` became `docs/help/support.md` in 2023 (`slug: support`),
and the flat `/usage/<page>`, `/advanced/<page>`, `/developers/<page>` layout of
1.19 and 1.20 was reorganized into `usage/repository/`, `administration/` and
`development/`.
The old urls kept working because the site was published to S3 with
`aws s3 sync` **without** `--delete`: every page built before a move stayed in
the bucket and CloudFront kept serving it. The archived copy of
`/help/seek-help` still carries `last-modified: Wed, 12 Jul 2023` - the file was
six years stale but reachable.
The Astro deployment publishes to Cloudflare Pages, which only serves what the
current build emits, so all of those leftovers disappeared at once.
I crawled the urls the Wayback Machine has for `docs.gitea.com` and checked them
against the live site: 335 non-removed-version urls 404 today, and they are all
of this kind.
## Fix
301s in `cloudflare/_redirects`, from every legacy url that has a current
equivalent to that page, generated for the root, the `zh-cn` and `zh-tw`
prefixes and the `next` (develop) version. Also the runner docs that were
published under a full version number (`/runner/0.2.11/`, `/runner/1.0.8/`) and
`/runner/next/`, which is `/runner/develop/` now.
Checked while generating them, against a full local build:
- no rule shadows a page that exists today - the zh translations of `usage/agit`
and `usage/profile-readme` were never moved, so they are still served at the
old path and are left alone
- every target resolves to a page that exists, in the language and version the
rule redirects within
- no duplicated source, 417 static and 10 dynamic rules, well inside the
Cloudflare Pages limits (2100 / 100)
## Out of scope
- `/contributing/*`, `/developers/guidelines-*` and `/developers/hacking-on-gitea`
404 too, but those pages moved to the gitea repository, there is nothing on
docs.gitea.com to point them at.
- The `aliases:` frontmatter of the sources (`/en-us/seek-help`, `/webhooks`,
...) is a leftover of the Hugo site. Docusaurus ignored it and so does the
Astro build; those urls have been 404 for years and are not resurrected here.
- The blog.gitea.com navbar should link to `/help/support` directly, that needs a
pull request against gitea/blog.
Reviewed-on: https://gitea.com/gitea/docs/pulls/507
Reviewed-by: bircni <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
Replace [#307](https://gitea.com/gitea/docs/issues/307)
Closes [#237](https://gitea.com/gitea/docs/issues/237)
## Summary
Rebuilds docs.gitea.com with [Astro](https://astro.build) and [Starlight](https://starlight.astro.build), replacing Docusaurus. Every
published url keeps working and no content file was moved: the site is a new rendering layer over the existing `docs/`, `versioned_docs/`, `i18n/`, `runner-docs/` and `static/swagger-*.json` trees.
For the first time the API reference is part of the site rather than a Redoc
bundle: all seven swagger documents are rendered into real pages, one per
operation, so they are linkable, crawlable and searchable.
## Why
- the Docusaurus build needs an 8 GB heap and about 2 minutes for 2478 pages;
the Astro build produces 5751 pages, API reference included, in about 100
seconds
- the API reference was a single client rendered Redoc page per version, absent
from the site search and from search engines
- sidebars, version lists and language lists were configured in three different
places and drifted apart
## What is in here
- **`packages/content-loader`** — the product × version × language matrix
(`products.ts`) and an Astro content loader that reads the existing markdown
trees directly. The matrix is the single source of truth: content loading,
sidebars, the version and language pickers, the version banner, the search
facets and the API schemas are all derived from it.
- **Content compatibility** — frontmatter `slug`, `sidebar_position` and
`sidebar_label` keep working, `_category_.json` still drives sidebar labels,
order and the generated category pages, `@version@` style release variables are
still substituted, `:::note` admonitions become Starlight asides and the 2778
relative `*.md` links are rewritten to urls while the site is built.
- **API reference** — `starlight-openapi` renders the seven swagger documents.
Operation urls are hyphenated (`/api/operations/list-admin-workflow-jobs/`),
the sidebar shows the operations of the version being read with a coloured
HTTP method badge, and the overview page links to one page per tag instead of
repeating all 484 operations.
- **Navigation** — a version picker that follows the reader to the same page in
another version, a language picker that only offers the languages the current
product is published in, and product links for Docs, API, Runner and
Enterprise.
- **Theme** — the light and dark palettes of about.gitea.com, mapped onto the
Starlight variables.
- **Search** — Pagefind by default; Algolia DocSearch takes over when
`PUBLIC_DOCSEARCH_APP_ID` and `PUBLIC_DOCSEARCH_API_KEY` are set. Every page
carries `docsearch:product`, `docsearch:version` and `docsearch:language` meta
tags, so a search stays inside what is being read.
`cloudflare/docsearch-crawler.json` holds the crawler configuration.
## Bugs fixed along the way
- `GET /user/applications/oauth2` and `GET /user/applications/oauth2/{id}` have
operation ids that only differ in case, so they collapsed onto the same url
and one of the two pages was silently dropped. They are now
`user-get-oauth2-application` and `user-get-oauth2-application-by-id`.
- The API overview and every tag page were all titled "Overview".
## Url compatibility
The routes of both builds were compared page by page during the migration with
`scripts/url-diff.mjs`:
```
identical: 2368, missing: 0, accepted: 110, added: 3292
```
The 110 accepted ones are all redirected in `cloudflare/_redirects`: the
localized copies of the English-only API and Runner docs, the Docusaurus search
page, and `/1.27/`, `/runner/3/`, `/api/1.27/` which are aliases of the versions
served at the product root. The added ones are the API operation and tag pages
plus the routes the Starlight language fallback serves in English when a
translation is missing — Docusaurus answered those with a 404.
## Workflows
- `checks` builds the site and type checks it on every pull request
- `Build and Publish Docs site` publishes `sites/docs/dist` to S3/CloudFront and
to Cloudflare Pages, and copies `cloudflare/_headers` and
`cloudflare/_redirects` into the deployment
- `update swagger files` and `update runner reference` are unchanged, they only
touch content
- `make cut-version PRODUCT=docs VERSION=1.28` replaces
`docusaurus docs:version`
## Removed
`docusaurus.config.js`, the swizzled theme under `src/`, and the Docusaurus UI
translations (`i18n/*/code.json`, `i18n/*/docusaurus-theme-classic/`). The
strings those carried — the product names, the footer column titles and the
outdated translation notice — were ported to
`sites/docs/src/config/strings.ts`; Starlight ships the rest of its interface in
both Chinese locales. The documentation content itself is untouched.
## Follow ups
- nine relative links are broken in the sources and reported by every build, the
same ones Docusaurus warned about; `GITEA_DOCS_STRICT_LINKS=true` turns them
into an error once they are fixed
- `cloudflare/worker.js` has to be deployed for `/enterprise/` to keep resolving
- the Algolia index has to be created and crawled before the search credentials
are set
## Testing
```shell
make install
make serve-fast # english, the version served at the root
make serve # the whole matrix
make build # 5751 pages
make check # 0 errors
make serve-built # build and serve, the only way to try the search locally
```
## Screenshots
<img width="1371" alt="image.png" src="attachments/69acdd77-cc89-4635-a8bd-1163a34afa86">
<img width="1810" alt="image.png" src="attachments/76212416-4825-4b4d-bf59-3e549900c96f">
<img width="1789" alt="image.png" src="attachments/7be84cda-5abe-48bd-8839-7ae1ee7806e7">
---------
Co-authored-by: bircni <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/496
Reviewed-by: bircni <[email protected]>
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | Type | Update | Pending |
|---|---|---|---|---|---|---|
| [@easyops-cn/docusaurus-search-local](https://github.com/easyops-cn/docusaurus-search-local) ([source](https://github.com/easyops-cn/docusaurus-search-local/tree/HEAD/packages/docusaurus-search-local)) | [`0.55.2` → `0.55.3`](https://renovatebot.com/diffs/npm/@easyops-cn%2fdocusaurus-search-local/0.55.2/0.55.3) |  |  | dependencies | patch | |
| [pnpm](https://pnpm.io) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm11/pnpm)) | [`11.17.0` → `11.20.0`](https://renovatebot.com/diffs/npm/pnpm/11.17.0/11.20.0) |  |  | packageManager | minor | `11.21.0` |
| [pnpm/action-setup](https://github.com/pnpm/action-setup) ([changelog](https://github.com/pnpm/action-setup/compare/0ebf47130e4866e96fce0953f49152a61190b271..0977fd99725f1db4007ccb2928dbb4e90d06cc86)) | `0ebf471` → `0977fd9` | | | action | digest | |
---
### Release Notes
<details>
<summary>easyops-cn/docusaurus-search-local (@​easyops-cn/docusaurus-search-local)</summary>
### [`v0.55.3`](https://github.com/easyops-cn/docusaurus-search-local/releases/tag/v0.55.3)
[Compare Source](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.55.2...v0.55.3)
##### Bug Fixes
- trigger a release for refining search icon for [#​577](https://github.com/easyops-cn/docusaurus-search-local/issues/577) ([9a7eb91](https://github.com/easyops-cn/docusaurus-search-local/commit/9a7eb91393f389838cc31f45e4f4737dc4bb325e))
</details>
<details>
<summary>pnpm/pnpm (pnpm)</summary>
### [`v11.20.0`](https://github.com/pnpm/pnpm/releases/tag/v11.20.0): pnpm 11.20
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.19.0...v11.20.0)
#### Minor Changes
- **Security fix.** Affects projects using `namedRegistries` on pnpm 11.1.0–11.19.x. It is **semi-breaking** for those projects — see "If you use named registries" below.
The lockfile recorded no marker for which registry a package came from. Packages were keyed by `name@version` alone, and entry lookup went through `refToRelative(ref, name)`, so a dependency you declared against one registry could be satisfied by an entry that was actually resolved from another. When two registries served the same name and version, both collapsed onto a single `packages:` entry and whichever resolved first decided the tarball every consumer got.
That is a package-substitution risk: a package you expect from your private registry could be installed from a different registry that publishes the same name and version, and the lockfile recorded nothing that would let you tell.
Packages resolved from a named registry are now recorded under registry-qualified keys (`<name>@​<registryName>:<version>`, e.g. `foo@work:1.0.0`), so each registry gets its own entry and the lockfile pins which one a dependency came from.
The lockfile format version is unchanged. Registry-qualified keys appear only for packages resolved from a named registry, so a project that does not use `namedRegistries` sees no difference, and older pnpm versions keep reading the file.
##### If you use named registries
Your next non-frozen install re-keys those entries, which shows up as a lockfile diff. Commit it — that diff is the fix being applied. Review it: an entry that moves to a registry you did not expect is worth investigating.
Everyone working on the project should be on this version or newer before you do. An older pnpm reads the re-keyed lockfile fine — frozen installs are unaffected — but it does not produce registry-qualified keys itself, so any install that updates the lockfile writes those entries back to the old shape, and the next install on a current pnpm re-qualifies them. The result is a lockfile that flips back and forth, and while it is in the old shape the project is exposed again. Because the lockfile format version is deliberately unchanged, pnpm cannot detect this and warn you about it.
There is no setting to keep the old behavior: the old shape is the vulnerability.
Tarball URLs that follow the standard registry layout are no longer written to the lockfile for named-registry packages; they are recomputed from the `namedRegistries` setting on demand.
To use named registries, map your aliases in `pnpm-workspace.yaml`:
```yaml
namedRegistries:
work: https://npm.enterprise.example.com/
```
##### New built-in `npmjs:` alias
`npmjs:` now resolves to `https://registry.npmjs.org/` with no configuration, alongside the existing `gh:` alias for GitHub Packages. It pins a dependency to the public registry even when `registry` points elsewhere, such as an internal proxy:
```json
{ "dependencies": { "left-pad": "npmjs:^1.3.0" } }
```
`npm:` cannot do this — it is the alias protocol (`npm:<name>@​<range>`) and resolves through whatever `registry` points at.
**If you mirror or proxy npmjs, point the alias at your mirror:**
```yaml
namedRegistries:
npmjs: https://npm.internal.example.com/
```
Built-in registry URLs are also the prefixes a lockfile's recorded tarball URL is matched against when pnpm verifies a package. Without the override, an entry whose tarball URL is on `registry.npmjs.org` is verified against the public registry rather than your mirror. This only affects lockfiles that record such URLs — a canonical URL for your configured registry is omitted from the lockfile and unaffected — and only when a tarball-URL, `minimumReleaseAge`, or `trustPolicy` check runs. Overriding the alias is the same escape hatch GHES users already have for `gh`.
Every alias the lockfile references must stay in `namedRegistries`: reading an entry whose alias is gone fails with `ERR_PNPM_MISSING_NAMED_REGISTRY` rather than silently falling back to the default registry, since that would fetch a different package. Renaming an alias re-resolves the packages that used it.
Named registry aliases that shadow a reserved dependency specifier prefix (`file`, `link`, `workspace`, `runtime`, `npm`, `jsr`, ...) are now rejected with `ERR_PNPM_RESERVED_NAMED_REGISTRY_NAME` instead of being silently shadowed by the corresponding resolver.
`pnpm licenses` and `pnpm sbom` now keep the two artifacts apart as well: license records carry the registry alias, and SBOM components carry the purl `repository_url` qualifier.
#### Patch Changes
- An empty `http-proxy`, `https-proxy`, `proxy`, or `no-proxy` value — from the `.npmrc`, `pnpm-workspace.yaml`, the CLI, or the `HTTP_PROXY` / `HTTPS_PROXY` / `PROXY` / `NO_PROXY` environment variables — no longer fails the install with `ERR_PNPM_INVALID_PROXY`. Empty settings read as unset, so a shell exporting `HTTP_PROXY=` disables the proxy, and an empty `proxy=` in the `.npmrc` no longer suppresses `HTTPS_PROXY` [#​13533](https://github.com/pnpm/pnpm/issues/13533).
`proxy=false` in the `.npmrc` or `proxy: false` in `pnpm-workspace.yaml` now turns proxying off instead of being read as a proxy host named `false`. `false` and `null` on `https-proxy` / `http-proxy` / `no-proxy` read as unset, and on the command line they are ordinary host names, since a flag carries its value verbatim.
- The env lockfile no longer pins `@pnpm/exe` alongside `pnpm` when the wanted pnpm version is 12 or newer. From v12 the unscoped `pnpm` package is itself the native executable, so `@pnpm/exe` is not published for it and resolving it would fail. The engine identity check now verifies the native binary through whichever package ships it.
- `lexCompare` and `nerfDart` are now published as `@pnpm/text.ordinal-comparator` and `@pnpm/config.registry-auth-key`. Use these instead of `@pnpm/util.lex-comparator` and `@pnpm/config.nerf-dart`.
- Fixed the order in which pnpm matches a lockfile's recorded tarball URL against known registry URLs. Two registry URLs of equal length were previously ordered arbitrarily, so which one a tarball URL matched could differ between runs.
- Dependency resolution is faster: package metadata is now filtered once per packument instead of once per dependency edge when `minimumReleaseAge` is active, and parsed semver versions and ranges are reused instead of re-parsed on every comparison.
- Security: `pnpm rebuild` now refuses a lockfile whose `packages` key carries a path traversal in the package name (e.g. `../../../[email protected]`), instead of running that package's lifecycle scripts and linking its bins in a directory outside the virtual store. Such a name is rejected with `ERR_PNPM_INVALID_DEPENDENCY_NAME`.
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
### [`v11.19.0`](https://github.com/pnpm/pnpm/releases/tag/v11.19.0): pnpm 11.19
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.18.0...v11.19.0)
#### Minor Changes
- `pnpm login` no longer requires an interactive terminal when the registry supports web-based login: without a TTY it prints the authentication URL (skipping the QR code and the "Press ENTER to open the URL in your browser" prompt) and polls the registry until the browser approval completes. Only the classic username/password login still fails with `ERR_PNPM_LOGIN_NON_INTERACTIVE` in a non-interactive terminal.
- The `save-prefix` setting now accepts `=`: newly added dependencies are saved with an explicit `=` operator (`=1.2.3`) instead of the setting being silently treated as the default `^`.
#### Patch Changes
- `allowBuilds` entries can now approve git-hosted packages that pnpm downloads as a tarball, such as `github:` dependencies (which are fetched from `codeload.github.com` rather than cloned), by their repository URL without the resolved commit hash. This matches the hashless `git+` matching already supported for cloned git dependencies. For example:
```yaml
allowBuilds:
"foo@git+https://github.com/org/foo.git": true
```
This approves the package whether pnpm clones it or downloads a tarball, so the entry no longer has to be updated every time the pinned commit changes. GitLab and Bitbucket tarball downloads are matched the same way. Approving or denying a specific resolved commit by its full tarball dep path continues to work.
- `pnpm outdated --include-github-actions` no longer blocks on an interactive git credential prompt when a workflow uses a private action repo.
- Prevented `minimumReleaseAge` from replacing `latest` with a SemVer-greater version than the registry tag target [#​13034](https://github.com/pnpm/pnpm/issues/13034).
- Fixed empty `bundledDependencies` and `bundleDependencies` arrays causing nondeterministic lockfile changes. See [#​13123](https://github.com/pnpm/pnpm/issues/13123).
- The install summary no longer prints `(X is available)` when the registry's `dist-tags.latest` is still held back by the active `minimumReleaseAge` policy. The hint only ever names the actual latest tag, so an immature latest suppresses the hint instead of advertising the version pnpm just refused to install [#​11698](https://github.com/pnpm/pnpm/issues/11698).
- `pnpm update` keeps the explicit `=` operator of an exact version pin: a dependency saved as `=3.5.1` now updates to `=3.5.2` instead of the bare `3.5.2`. See [#​13168](https://github.com/pnpm/pnpm/issues/13168).
- Preserve a workspace dependency's `link:` entry when a run does not target it — e.g. `pnpm update <other-pkg>` (with or without `--recursive`), or a plain install after a root/catalog dependency change — with `injectWorkspacePackages`, instead of spuriously rewriting it to a peer-suffixed `file:` protocol. See [#​10433](https://github.com/pnpm/pnpm/issues/10433).
- Workspace dependencies declared with a relative path (e.g. `"foo": "workspace:../foo"`) are no longer silently dropped from the workspace projects graph, so `--filter` selection and the topological order of recursive commands take them into account.
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
### [`v11.18.0`](https://github.com/pnpm/pnpm/releases/tag/v11.18.0): pnpm 11.18
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.17.0...v11.18.0)
#### Minor Changes
- Fixed an installed optional dependency being left without one of its own required dependencies. When a package reached through `optionalDependencies` is installable on the current system but one of its regular `dependencies` is not, a lockfile-based install skipped that dependency and installed the parent anyway, so importing the parent failed with `MODULE_NOT_FOUND`. The dependency is now installed, and an install-check warning reports the incompatibility. A dependency is still only skipped when every path to it is optional, or when the package that pulls it in was itself skipped [#​13286](https://github.com/pnpm/pnpm/issues/13286).
- `pnpm setup` now appends `PNPM_HOME` and the global bin directory to the GitHub Actions environment files (`GITHUB_ENV` and `GITHUB_PATH`), so later steps in the same job can run `pnpm add --global` and other global commands [#​9191](https://github.com/pnpm/pnpm/issues/9191).
- Added support for `publishConfig.name`, which publishes a package under a different name than the one its manifest carries in the workspace. It is for a project whose published name is already taken by a sibling project, which otherwise has to be renamed by a build step just before publishing. Only the published artifact is renamed — dependents, `pnpm-lock.yaml`, and release tooling keep addressing the project by its manifest name — and the new name reaches the packed manifest, the tarball filename, and everything that addresses the package at the registry: the already-published check of `pnpm publish -r`, its registry selection, and the release-planning probes of `pnpm change status` and `pnpm version -r` [#​13345](https://github.com/pnpm/pnpm/issues/13345).
- `pnpm self-update` no longer takes any instruction from the project it is run in:
- pnpm is fetched through the same trusted registry and auth configuration used when switching pnpm versions, so a project `.npmrc` or `pnpm-workspace.yaml` can no longer redirect the download or attach credentials to it, and the project's default `.pnpmfile.(c|m)js` is no longer loaded. Pnpmfiles from trusted sources (the `pnpmfile` setting, the global pnpmfile, config dependencies) still apply.
- The `minimumReleaseAge` settings in `pnpm-workspace.yaml` no longer affect `self-update`. They still govern the project's own dependencies; for `self-update` the cooldown now comes from the built-in default, your global config, a `PNPM_CONFIG_*` environment variable, or a command-line flag. This fixes `self-update` failing inside a workspace that raises the cutoff while succeeding everywhere else, and stops a repository from either waiving the cooldown or keeping you on an outdated pnpm by raising it.
- The same applies to the `trustPolicy` settings and to `ci`: a project can no longer weaken the trust check that guards the pnpm download, nor re-enable the confirmation prompt that a CI run suppresses.
When `self-update` refuses a version that is younger than the cutoff, an interactive run now offers to update anyway; non-interactive runs still fail. CI never prompts, even on a runner that attaches a TTY.
#### Patch Changes
- Fixed `pnpm licenses list` to report every version when the same package is installed under multiple aliases [pnpm/pnpm#13438](https://github.com/pnpm/pnpm/issues/13438).
- Sort `pnpm dedupe --check` snapshot changes for stable output across pnpm implementations.
- Strip Unicode formatting characters from registry- and manifest-derived terminal output.
- Speed up installs after compatible catalog or direct dependency range changes by retaining the locked version without resolving the dependency graph again.
- Speed up installs after safe override changes by reusing unambiguous compatible dependency resolutions, pruning obsolete dependencies, applying independent replacements and removals together, and handling parent-scoped `"-"` overrides without full lockfile resolution.
- Installing a local `file:` directory dependency with the global virtual store enabled no longer fails with `TypeError: Cannot read properties of undefined (reading 'split')` [#​13335](https://github.com/pnpm/pnpm/issues/13335).
Local directory dependencies — `file:` directories and injected workspace packages — now get a global-virtual-store slot of their own per project. They used to share one slot across every project that depended on a directory of the same name, so a project could end up linked to another project's copy of the dependency.
- The `Workspace` column of `pnpm update --interactive` now falls back to the project's path when its `name` is only whitespace, as it already did for a missing or empty one — all three render an equally blank label otherwise.
- Checking GitHub Actions dependencies for updates is now opt-in for every command. Neither `pnpm outdated` nor `pnpm update` reads the workflow files unless `--include-github-actions` is passed or `update.githubActions` is set to `true` in `pnpm-workspace.yaml`. Reading them runs `git ls-remote` against every referenced repository, which fails in environments where GitHub is not reachable the way pnpm assumes (a GitHub Enterprise Server, a custom certificate authority, or an offline network) [#​13254](https://github.com/pnpm/pnpm/issues/13254).
`pnpm outdated` accepts the `--include-github-actions` option too.
- `pnpm update --interactive` now measures its table in terminal columns rather than in characters. A package name, workspace name, or version containing wide characters (CJK, most emoji) no longer knocks its row's columns out of line with the rest of the group, and a wide character in a version no longer aborts the command with `Subject parameter value width cannot be greater than the container width` [#​13357](https://github.com/pnpm/pnpm/issues/13357).
- The `Workspace` column of `pnpm update --interactive` is more informative in two cases. A dependency outdated at the same version in several workspace projects is offered as one choice, since selecting it updates every project — that choice now names all of them instead of only the first. And a workspace project without a `name` is now labelled with its path rather than left blank, so several unnamed projects can be told apart.
- An auto-installed *optional* peer is no longer hoisted at a version the workspace root's own dependency on that package excludes. `resolvePeersFromWorkspaceRoot` already made the workspace root's specifier decide which version a missing *required* peer is installed at; the optional-peer picker ignored it and always took the highest version present anywhere in the graph. In a workspace whose root pins `postcss: 8.5.10`, an importer that depends on `webpack` and declares no `postcss` of its own got `[email protected]` hoisted for `terser-webpack-plugin`'s optional `postcss` peer, leaving two `[email protected]` instances in the graph [#​13320](https://github.com/pnpm/pnpm/issues/13320).
- `overrides` now also govern peers that pnpm auto-installs. Previously an override only rewrote dependencies declared in a manifest, so a peer nobody declares — installed because `autoInstallPeers` is on — resolved against its declared peer range and could bring in a second copy of the very package the override pinned. For example, with `overrides: { react: npm:[email protected] }` and a lone `lucide-react` dependency, pnpm installed `[email protected]`; it now installs the pinned `[email protected]` [#​13320](https://github.com/pnpm/pnpm/issues/13320).
- Under `resolvePeersFromWorkspaceRoot`, a workspace root dependency declared with `link:` or `file:` (or the path form of `workspace:`, such as `workspace:../pkg`) now satisfies another project's missing peer dependency at the linked package's own version, instead of being hoisted as a path. Those specifiers are relative to the project that declares them, so the same specifier reached a different directory — or none — from the project the peer was hoisted into, leaving a broken link. The root now has the same authority over the peer as it has when it declares the package with a version range [#​13373](https://github.com/pnpm/pnpm/issues/13373).
- Installs through a pnpr server now apply the project's whole verification policy. `minimumReleaseAgeExclude`, `minimumReleaseAgeIgnoreMissingTime`, `trustPolicy`, `trustPolicyExclude`, `trustPolicyIgnoreAfter`, and `trustLockfile` were ignored, so excluded packages were still held back and a lockfile containing them could be rejected.
`trustPolicy: no-downgrade` no longer fails with `TRUST_POLICY_INCOMPATIBLE_WITH_PNPR` when a pnpr server is configured.
`--frozen-lockfile` and `--no-prefer-frozen-lockfile` are now honored on the pnpr path, instead of resolving and rewriting the lockfile anyway. Since `frozenLockfile` defaults to `true` on CI, a CI install through a pnpr server now fails on an out-of-date lockfile rather than updating it.
- Workspace installs through a pnpr server no longer crash with `Cannot read properties of undefined (reading 'filter')` after linking, when `minimumReleaseAge` is active [#​13275](https://github.com/pnpm/pnpm/issues/13275).
- Fixed `pnpm dedupe` updating valid catalog resolutions when another matching version exists in the lockfile.
- `pnpm -r run "/pattern/" --no-bail` no longer exits zero when one of a project's matched scripts fails and a later one passes. The run summary carries a single status per project, and the passing script overwrote the recorded failure.
- Restored the store block a first install prints, naming how packages were materialized and where the stores live [#​13315](https://github.com/pnpm/pnpm/issues/13315):
```text
Packages are hard linked from the content-addressable store to the virtual store.
Content-addressable store is at: ~/.local/share/pnpm/store/v11
Virtual store is at: node_modules/.pnpm
```
- The root project's `pnpm:devPreinstall` script now runs before resolution and linking, as it does in pnpm 11. It is skipped under `--ignore-scripts`, `--lockfile-only` and `--dry-run`, by `pnpm fetch` and `pnpm rebuild`, and by a repeat install that is already up to date. Workspaces that use the hook to prepare state the install depends on — such as [next.js](https://github.com/vercel/next.js), which generates a placeholder `next` bin with it — were left with dependents linked against files that were never created [#​13313](https://github.com/pnpm/pnpm/issues/13313).
- Prevented `pnpm dedupe --check` from removing an incompatible `node_modules` directory.
- `pnpm update --workspace` no longer links dependencies the user never named:
- Running it with `updateConfig.ignoreDependencies` configured no longer fails with `ERR_PNPM_WORKSPACE_PACKAGE_NOT_FOUND` for a dependency that is only published to the registry. Such dependencies keep their specifiers, as they already did when no dependencies were ignored.
- Passing package selectors that match no direct dependency no longer falls back to linking every workspace dependency.
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
<!-- cloudflare-preview --> Preview: https://pr-500.docs-gitea-com.pages.dev
---------
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/500
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
Pull requests now get a Cloudflare Pages preview deployment after the site build succeeds, and the preview URL is written back as the last line of the pull request description.
- `concurrency` cancels the previous preview build when a pull request is pushed again.
- After `make build`, the workflow copies `cloudflare/_headers` into `build/` (same as the production deployment, so the file is never published to S3/CloudFront) and runs `wrangler pages deploy build --project-name docs-gitea-com --branch pr-<number>`, then extracts the `*.pages.dev` URL from the wrangler output.
Notes:
- Pull requests from forks do not receive the secrets, in that case the preview steps are skipped with a log message and the build check still runs.
- Requires `CLOUDFLARE_ACCOUNT_ID` / `CLOUDFLARE_API_TOKEN` (Pages edit permission) and `DEPLOY_TOKEN` (pull request write permission).
<!-- cloudflare-preview --> Preview: https://pr-498.docs-gitea-com.pages.dev
Reviewed-on: https://gitea.com/gitea/docs/pulls/498
Reviewed-by: Zettat123 <[email protected]>
The scheduled `update swagger files` job has failed on **every** run since it was added (I checked the run list on gitea.com, ~250 consecutive failures). Two reasons:
1. Upstream moved the file: `go-gitea/gitea` main no longer has `templates/swagger/v1_json.tmpl`, it is now `templates/swagger/v1-swagger.generated.json`, and the placeholders changed from `{{.SwaggerAppVer}}` / `{{.SwaggerAppSubUrl}}` to `0.0.0+GITEA-API-APP-VERSION` / `/GITEA-API-APP-SUBURL/api/v1`. Because the script used `curl --silent` without `--fail`, the 404 body was written into `static/swagger-latest.json`.
2. `main` is protected (`required_approvals=1`), so the job's `git push` to main could never succeed.
Changes:
- `update_api_docs.sh`: `set -euo pipefail`, download with `--fail` (a broken download now aborts instead of committing garbage), try the new generated json first and fall back to the old template for released tags, handle the 1.28+/1.24+/<1.24 placeholder variants, and add a `--latest-only` flag.
- `Makefile`: new `update-api-docs-latest` target for the cron job; `clean` no longer deletes the committed `static/swagger-*.json` files (deleting them breaks `make build`).
- `.gitea/workflows/update_swagger.yaml`: every 12h (plus `workflow_dispatch`) it regenerates only `static/swagger-latest.json`, verifies no placeholder is left and the file is valid JSON, force pushes to `bot/update-swagger-latest` and opens a pull request via the API (HTTP 409 = a PR is already open, it just now points at the new commit). It skips entirely when the bot branch already carries the same file, so no PR churn.
- `README.md`: document the two make targets and the automation.
`secrets.DEPLOY_TOKEN` must belong to a real user with `write:repository` so the PR checks are triggered; the job fails with a clear message if it is empty.
Tested locally in a scratch clone: `make update-api-docs-latest` produces a valid `dev` spec with no placeholders left, `make update-api-docs` still regenerates all released versions, and the workflow shell logic was simulated against a local bare repo for all three paths (open PR / bot branch already up to date / main already up to date), including a shallow clone to confirm `fetch-depth: 1` force pushes work.
Fixes#454
Reviewed-on: https://gitea.com/gitea/docs/pulls/481
Reviewed-by: techknowlogick <[email protected]>
The `usage/actions/runner` has duplicated runner documentations as `/runner`. This PR remove the duplicated content and leave obtain registry token in `usage/actions/runner` and runner install/configurations in `/runner`.
Reviewed-on: https://gitea.com/gitea/docs/pulls/479
Reviewed-by: silverwind <[email protected]>
Fixes https://gitea.com/gitea/docs/issues/386
`gitea.event` was documented as `{...}` only. Adds an "Event payload" section listing the commonly used fields per event, including `gitea.event.schedule`, and notes where Gitea's payloads deviate from GitHub's.
Also corrects the trigger event table:
1. `pull_request` takes `synchronize`, not `synchronized`
1. `workflow_run` also emits `in_progress`
1. `schedule`, `workflow_call` and `pull_request_target` were missing
Reviewed-on: https://gitea.com/gitea/docs/pulls/478
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
Documents the WebSocket endpoint `/-/ws` added in https://github.com/go-gitea/gitea/pull/36965 and fixes the examples that could not serve it.
1. Nginx: adds the missing `proxy_http_version 1.1`, without it Nginx talks HTTP/1.0 upstream and Gitea rejects the handshake.
1. Apache HTTPD: `upgrade=websocket` on the existing `ProxyPass` rule, handled by `mod_proxy_http` since 2.4.48.
1. Nginx Proxy Manager: use the `Websockets Support` toggle, a duplicate `proxy_http_version` stops Nginx from starting.
1. IIS: the `WebSocket Protocol` Windows feature is required.
---------
Co-authored-by: silverwind <[email protected]>
Co-authored-by: silverwind <[email protected]>
Co-authored-by: mohammad rahimi <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/463
Reviewed-by: Lunny Xiao <[email protected]>
Reviewed-by: silverwind <[email protected]>
Co-authored-by: mohammad rahimi <[email protected]>
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [pnpm](https://pnpm.io) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm11/pnpm)) | [`11.11.0` → `11.15.0`](https://renovatebot.com/diffs/npm/pnpm/11.11.0/11.15.0) |  |  |
---
### Release Notes
<details>
<summary>pnpm/pnpm (pnpm)</summary>
### [`v11.15.0`](https://github.com/pnpm/pnpm/releases/tag/v11.15.0): pnpm 11.15
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.14.0...v11.15.0)
##### Minor Changes
- Optional peer dependencies declared only via `peerDependenciesMeta` (for example `debug`'s `supports-color` peer) are now resolved from a satisfying version already present in the dependency graph, the same way explicitly declared optional peer dependencies are. Previously such peers were only resolved this way when the package's metadata was read back from the lockfile, so an unrelated dependency change could rewrite peer resolutions across the whole lockfile.
##### Patch Changes
- Updated `adm-zip` to prevent crafted ZIP archives from causing excessive memory allocation.
- `pnpm version -r` no longer writes a versioning-ledger entry with no consumed intents as a bare `intents:` key, which the next run failed to read with `ERR_PNPM_INVALID_VERSIONING_LEDGER`. Empty intent lists are now written as `intents: []`, and the ledger reader accepts the bare form left by earlier releases.
- Fixed pnpr workspace resolution to preserve project names and versions for `workspace:` dependencies.
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
### [`v11.14.0`](https://github.com/pnpm/pnpm/releases/tag/v11.14.0): pnpm 11.14
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.13.1...v11.14.0)
#### Minor Changes
- `peerDependencies` now accept dependency specifiers that carry a scheme — a named-registry spec (`<registry>:<version>`), an `npm:` alias, or a `file:`/git/URL spec — instead of rejecting them with `ERR_PNPM_INVALID_PEER_DEPENDENCY_SPECIFICATION` [#​13095](https://github.com/pnpm/pnpm/issues/13095). Such a peer is matched against the semver range carried by the specifier (`work:5.x.x` is checked as `5.x.x`, `npm:bar@^5` as `^5`), or against `*` when it carries no version, while the original specifier still selects the package to auto-install. Bare `name@version` values, which are almost always a mistake, are still rejected.
- Added `pnpm doctor`, which diagnoses the pnpm installation and the environment it runs in: the versions and install method, whether the global bin directory is on `PATH`, whether the store and cache are writable, which link strategies (reflink, hardlink, symlink) the store's filesystem supports, registry connectivity, and an offline `file:` install that exercises the resolve/store/link path end to end. Each check reports how to fix what it finds, and the command exits non-zero when any check fails.
Use `--offline` to skip the checks that need network access, `--json` for machine-readable output, and `--benchmark` to time the filesystem and install checks.
- Added support for executing multiple scripts matching a RegExp passed to `pnpm run` (e.g., `pnpm run "/^build:.*/"`), running matched scripts in deterministic lexicographical order. Restored the `--sequential` (`-s`) CLI option for `pnpm run`, which forces `workspaceConcurrency` to 1 so that matched scripts run sequentially one by one across and within packages.
#### Patch Changes
- Fixed `pnpm install` failing with `ERR_PNPM_LOCKFILE_IS_SYMLINK` when `pnpm-lock.yaml` is a symlink, as build sandboxes such as Bazel and Nix stage it [#​13073](https://github.com/pnpm/pnpm/issues/13073). Reading a lockfile through a symlink is allowed again, and an install that leaves the lockfile unchanged no longer rewrites it, so `--frozen-lockfile` no longer needs to write at all. Writing a *changed* lockfile through a symlink is still refused, as that would redirect the write onto the symlink's target.
- Fixed frozen installs incorrectly treating equivalent Git dependency specifiers as a stale lockfile. See [#​13039](https://github.com/pnpm/pnpm/issues/13039).
- `pnpm owner ls` now reports authentication and authorization failures (401/403) as dedicated errors that include the registry's response body, matching `pnpm owner add`/`rm`, instead of a generic `Failed to fetch owners` message.
- Recover from a metadata cache entry that disappears (concurrent cache cleanup, antivirus) after the registry has already answered the conditional request with `304 Not Modified`. The metadata is re-requested once without cache validators instead of failing the install with `ERR_PNPM_CACHE_MISSING_AFTER_304`.
- A project pinned to a broken pnpm release via `packageManager` or `devEngines.packageManager` now reports which release is broken and what to do about it, instead of failing inside the installer. `pnpm self-update` already refused these releases; the version switch does too.
- Prevent broken-lockfile errors from including snippets of the lockfile's contents.
- `pnpm self-update` now checks that the version it installed can run before making it the active pnpm. A release that installs but cannot execute is discarded with an error instead of replacing a working installation.
- Fixed an out-of-memory regression when workspace projects concurrently resolve a package with large registry metadata [pnpm/pnpm#13077](https://github.com/pnpm/pnpm/issues/13077).
- Fixed `pnpm update` rewriting exact version pins that use the `=` operator (for example `=3.5.1`) to a caret range (`^3.5.1`). Exact pins are now preserved and written back as the bare version. See [#​12745](https://github.com/pnpm/pnpm/issues/12745).
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
### [`v11.13.1`](https://github.com/pnpm/pnpm/releases/tag/v11.13.1): pnpm 11.13.1
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.13.0...v11.13.1)
#### Patch Changes
- Fixed `pnpm pack` applying workspace-root ignore rules when a workspace package has its own `.npmignore` file.
- Keep the interactive `minimumReleaseAge` approval prompt visible during `pnpm install`. The progress reporter now pauses its redraws while a prompt is waiting for input instead of overwriting it, so the install no longer hangs on a question the user cannot see [#​13019](https://github.com/pnpm/pnpm/issues/13019).
- Fixed `pnpm self-update` failing to link native platform binaries stored in sibling global virtual store slots.
### [`v11.13.0`](https://github.com/pnpm/pnpm/releases/tag/v11.13.0): pnpm 11.13
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.12.0...v11.13.0)
#### Minor Changes
- Added `versioning.epics` to `pnpm-workspace.yaml`. An epic ties a group of member packages to a lead package, constraining every member's major version to a band derived from the lead's major: while the lead is on major `M`, members live in `M*100 … M*100+99`. Members move independently inside the band (patch, minor, and a `major` intent that stays in-band); a bump that would carry a member past the band ceiling is rejected until the lead advances its own major. When a release plan takes the lead to a new stable major, every member re-bases to the band floor in the same plan. Membership is matched with pnpm's package selectors — name globs, `./`-prefixed directory globs, and `!`-prefixed negations.
- Added the `team` command for managing organization teams and team memberships on the registry, with create, destroy, add, rm, and ls subcommands and support for --otp, --parseable, and --json flags.
- Added native workspace release management [#​12952](https://github.com/pnpm/pnpm/issues/12952): the new `pnpm change` command records change intents as changesets-compatible `.changeset/*.md` files (`pnpm change status` shows the pending release plan), and the bare `pnpm version -r` consumes them — bumping versions across the workspace with dependent propagation through `workspace:` ranges, fixed groups, a `maxBump` cap, `--filter` narrowing, and `--dry-run` — writing changelogs, and recording consumed intents in a committed ledger that keeps cherry-picks and merge-backs between release branches safe. Packages can be moved onto per-package release lanes with the new `pnpm lane <name> --filter <pkg>` command and back with `pnpm lane main --filter <pkg>` (`pnpm lane` shows the membership), releasing `X.Y.Z-lane.N` prereleases from the same runs that release stable versions of the packages on the main lane. Configuration lives under the new `versioning` key of `pnpm-workspace.yaml` (`fixed`, `ignore`, `maxBump`, `lanes`, `changelog`). When two workspace projects publish the same name, intent files, `versioning.lanes`, and `versioning.fixed`/`ignore` may reference a project by its workspace-relative directory path (e.g. `"./pnpm/npm/pnpm"`) — the one additive extension to the changesets format, applied automatically by `pnpm change`.
Release changelogs default to `registry` storage (`versioning.changelog.storage`): no `CHANGELOG.md` is committed. Each release's section is composed at publish time and packed into the published tarball on top of the previously published version's changelog, and the consumed change intents are garbage-collected by a later `pnpm version -r` only once the registry confirms the version is published with its section. Set `versioning.changelog.storage: repository` to keep committed `CHANGELOG.md` files instead.
- Added a new override selector form with an empty range — `"pkg@": "<version>"` — called a convergence override. It rewrites a dependency edge only when its exact version satisfies the edge's declared range, so compatible consumers converge on one version while incompatible consumers keep their own resolution — now and for any dependent added in the future [#​12794](https://github.com/pnpm/pnpm/issues/12794).
```yaml
overrides:
"form-data@": 4.0.6
```
The value must be an exact version. When a full resolution detects that every declared range also admits a newer version, pnpm warns that the override is stale and names the version to converge on. Previously an empty range in an override selector was undocumented and behaved like a bare (unscoped) override.
#### Patch Changes
- A `tokenHelper` set in the global pnpm `auth.ini` is no longer rejected as project-level configuration. The guard that blocks `tokenHelper` from a project `.npmrc` only treated `~/.npmrc` as a trusted source, so a helper written to `auth.ini` (for example by `pnpm config set`) failed on every command and could not even be removed with `pnpm config delete`. A `tokenHelper` in a workspace or project `.npmrc` is still rejected.
- `pnpm cache delete` now removes a package's metadata from every metadata cache directory (`metadata`, `metadata-full`, and `metadata-full-filtered`), instead of only the one the current resolution mode reads. Previously a package cached under a different mode (e.g. `metadata-full-filtered`) was left behind. Closes [#​12753](https://github.com/pnpm/pnpm/issues/12753).
- Fixed an injected workspace dependency (`injectWorkspacePackages: true`) incorrectly staying as `file:` instead of deduping back to `link:` when an unrelated, ordinary shared dependency resolved to a peer-suffixed variant for the target project's own copy but not for the injected occurrence. See [#​10433](https://github.com/pnpm/pnpm/issues/10433).
- `pnpm deploy` now supports workspaces that use catalogs.
- Fixed `pnpm deploy` with a shared lockfile so local `file:` tarball dependencies keep their package name in the generated deploy lockfile. This prevents warm-store deploys from failing with `ERR_PNPM_UNEXPECTED_PKG_CONTENT_IN_STORE` when the tarball filename includes the version.
- Options that follow `create`, `exec`, or `test` appearing as a subcommand of another command are now parsed instead of being silently treated as positional parameters. For example, `pnpm team create @​org:team --registry <url>` previously ignored the `--registry` option and sent the request to the default registry.
- `pnpm add -g`, `pnpm update -g`, `pnpm setup`, and the self-updater no longer fail with `ERR_PNPM_MISSING_TIME` when `trustPolicy: no-downgrade` or `resolutionMode: time-based` is set in the global config [#​12883](https://github.com/pnpm/pnpm/issues/12883). The decision to fetch full registry metadata now lives in one place, and the `no-downgrade` trust policy always requests full metadata (matching the self-updater), since the trust evidence it checks is missing from abbreviated metadata even on registries that include the `time` field.
- `pnpm list` and `pnpm why` no longer crash with `EMFILE: too many open files` when a project has a large number of unsaved dependencies (packages present in `node_modules` but not in the lockfile). The reads of those packages are now concurrency-limited.
- The published `pnpm` package no longer declares `dependencies` or `devDependencies`. Because the CLI bundles its runtime dependencies into `dist/node_modules`, those fields are dropped when packing, so `npm install` of the tarball no longer tries to resolve internal-only packages such as `@pnpm/test-ipc-server`. Closes [#​12955](https://github.com/pnpm/pnpm/issues/12955).
- Fixed `pnpm publish --otp` and `pnpm publish --batch --otp` to send the configured OTP to the registry.
- `pnpm publish` again sends the package's README to the registry as metadata, so registries can render it on the package page. The readme is always included in the published metadata (matching the npm CLI), while the `embed-readme` setting continues to control only whether the readme is written into the `package.json` inside the tarball. This restores the behavior that was lost when publishing became fully native. Closes [#​12966](https://github.com/pnpm/pnpm/issues/12966).
- Fixed the dependency status check wrongly reporting "up to date" when a `package.json`, `.pnpmfile.cjs`, or patch file was edited in the same second as the previous install, on filesystems that record mtimes at whole-second resolution (for example ext4 with 128-byte inodes). The optimistic repeat-install fast path and `verify-deps-before-run` compared mtimes strictly, so a same-second edit whose mtime rounded down looked unchanged and re-resolution was skipped. Such a file's whole second is now treated as possibly-modified, falling through to the content check; behavior on sub-second filesystems is unchanged.
- Retry package metadata requests when a registry or proxy returns `304 Not Modified` to an unconditional request, preventing false `ERR_PNPM_CACHE_MISSING_AFTER_304` failures [pnpm/pnpm#12882](https://github.com/pnpm/pnpm/issues/12882).
If the retry also returns `304`, report `ERR_PNPM_META_NOT_MODIFIED_WITHOUT_CACHE` instead.
- Fixed `pnpm update` removing transitive lockfile entries when `dedupePeerDependents` is disabled and the selected package is absent [pnpm/pnpm#12456](https://github.com/pnpm/pnpm/issues/12456).
- Limit modern deploy lockfiles and localized virtual stores to dependencies reachable from the selected dependency groups.
- A `tokenHelper` command is now given a 60-second time limit. A helper that hangs (deadlock, stuck I/O) is killed and reported as an error instead of leaving the command waiting forever.
- Fixed orphaned child processes on Windows when pnpm exits on an error while commands spawned by `pnpm exec` or `pnpm dlx` are still running (for example, when one project's command fails during `pnpm --recursive exec`). The PIDs of these commands are now recorded when they are spawned and their whole process trees are terminated with `taskkill` on an error exit. Previously the cleanup relied on enumerating the system process list, which is so slow on Windows that the enumeration hit its timeout and the cleanup was silently skipped [#​12406](https://github.com/pnpm/pnpm/issues/12406).
- `pnpm pack` now respects workspace-root `.npmignore` and `.gitignore` files when packing workspace packages.
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
### [`v11.12.0`](https://github.com/pnpm/pnpm/releases/tag/v11.12.0): pnpm 11.12
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.11.0...v11.12.0)
#### Minor Changes
- [`a897ef7`](https://github.com/pnpm/pnpm/commit/a897ef7): Custom fetchers exported from a pnpmfile can now delegate by returning a `{ delegate: <resolution> }` envelope: pnpm rewrites the package's resolution to the delegated shape and runs the built-in fetcher on it. This is the portable delegation form that also works in pacquet, where `cafs` and `fetchers` cannot be passed to the hook. Related to [pnpm/pnpm#11685](https://github.com/pnpm/pnpm/issues/11685).
#### Patch Changes
- [`2b02764`](https://github.com/pnpm/pnpm/commit/2b02764): The changed-packages filter (`--filter "...[<since>]"`) no longer allows an option-like `<since>` value (such as `--output=<path>`) to be interpreted as a git option — git now rejects it as a bad revision. The repository root is also resolved to the nearest `.git` entry, so the filter works in a git worktree checked out inside another repository's tree.
- [`43711ce`](https://github.com/pnpm/pnpm/commit/43711ce): `pnpm outdated` no longer checks the registry for dependencies that are resolved from local `link:`, `file:`, or `workspace:` references in the lockfile [#​12827](https://github.com/pnpm/pnpm/issues/12827).
- [`3c6718b`](https://github.com/pnpm/pnpm/commit/3c6718b): Fixed a deadlock in peer dependency resolution: `pnpm install` hung forever when a peer dependency cycle spanned a project's own dependencies and auto-installed peer providers, for example when installing `[email protected].3` [#​12921](https://github.com/pnpm/pnpm/issues/12921).
- [`252f15e`](https://github.com/pnpm/pnpm/commit/252f15e): Fixed peer dependency auto-install picking a version the peer range rejects. In a workspace with several projects, a package declaring a peer dependency with a semver range (for example `^1.0.0`) could get the highest version found anywhere in the workspace (for example a `2.0.0` resolved for another project) instead of a version that satisfies the range. Peers are now deduplicated onto the highest preferred version that satisfies the declared range, and when none does, the range is resolved from the registry.
Also fixed re-resolving with an existing lockfile hoisting a different peer version than a fresh install of the same manifest: root dependencies reused from the lockfile were invisible to peer hoisting, so a peer that a root dependency provides could be bound to another version.
- [`a38adda`](https://github.com/pnpm/pnpm/commit/a38adda): `pnpm self-update <version>` now installs the requested pnpm version when it matches the currently running version but is missing from the global self-update directory.
- [`6a85968`](https://github.com/pnpm/pnpm/commit/6a85968): `pnpm stage list` now stops paginating after a fail-safe cap of 1000 pages, so a misbehaving registry cannot keep the command looping forever.
- [`eee7c9a`](https://github.com/pnpm/pnpm/commit/eee7c9a): `verify-deps-before-run` no longer spawns a `pnpm install` when pnpm is executed in a directory that has no `package.json`. A mistyped command run outside a project (for example `pnpm witch 10 login`) used to crash with a confusing error from the spawned install; now it fails with the regular "no package.json found" error.
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
---------
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/469
Reviewed-by: silverwind <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [pnpm](https://pnpm.io) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm11/pnpm)) | [`11.10.0` → `11.11.0`](https://renovatebot.com/diffs/npm/pnpm/11.10.0/11.11.0) |  |  |
---
### Release Notes
<details>
<summary>pnpm/pnpm (pnpm)</summary>
### [`v11.11.0`](https://github.com/pnpm/pnpm/blob/HEAD/pnpm11/pnpm/CHANGELOG.md#11110)
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.10.0...v11.11.0)
##### Minor Changes
- [`508b8c2`](https://github.com/pnpm/pnpm/commit/508b8c2): Added the `pnpm access` command for managing package access and visibility on the registry, supporting listing packages and collaborators, getting and setting package status and MFA requirements, and granting or revoking team access.
##### Patch Changes
- [`c70e33e`](https://github.com/pnpm/pnpm/commit/c70e33e): Allow `allowBuilds` entries for git-hosted packages to match by repository URL without pinning the resolved commit hash. This lets trusted git repositories keep running their build scripts after branch updates without approving each new commit, while package-name-only rules still do not approve git-hosted artifacts.
- [`3067e4f`](https://github.com/pnpm/pnpm/commit/3067e4f): Reduced peak memory usage during cold-cache dependency resolution. The metadata fetch is memoized for the whole resolution phase, and it was retaining each package's raw registry response body (used only to mirror the response to disk) for that entire time. The memoized cache now holds a body-less copy, so the raw body only lives as long as the call that writes the disk mirror. On large graphs that fetch full metadata (e.g. with `minimumReleaseAge` or `trustPolicy` enabled) this cuts peak RSS by roughly 30%, back in line with pnpm 10. The resolved lockfile is unchanged.
- [`51300fd`](https://github.com/pnpm/pnpm/commit/51300fd): Prevent a crafted `pnpm-lock.yaml` from writing package content outside the virtual store. A dependency path key whose name reconstructs to a path-traversal sequence (e.g. `../../../tmp/[email protected]`) is now rejected by the isolated (virtual-store) linker and the Plug'n'Play resolver map, matching the containment already applied to the hoisted linker. Under the global virtual store, a traversal in the version-derived path segment (e.g. a snapshot `version: "../../x"`) is now rejected at `formatGlobalVirtualStorePath`, the single point every global-virtual-store slot path funnels through — closing the same escape in the isolated linker, the resolver's dependency-graph builder, and the config-dependency installer.
- [`f8058eb`](https://github.com/pnpm/pnpm/commit/f8058eb): Reject symlinked `pnpm-lock.yaml` files when reading or writing the env lockfile document.
- [`9318a11`](https://github.com/pnpm/pnpm/commit/9318a11): Allow `registries` and `namedRegistries` to be configured in the global `config.yaml` file.
- [`51300fd`](https://github.com/pnpm/pnpm/commit/51300fd): Fixed a path traversal vulnerability where a dependency whose manifest `name` was a scoped path traversal (e.g. `@x/../../../<path>`) could be written outside `node_modules` to an attacker-controlled location during `pnpm install`, even with `--ignore-scripts`. The isolated linker now validates the package name before using it as a directory name, matching the existing protection in the hoisted linker.
- [`14332f0`](https://github.com/pnpm/pnpm/commit/14332f0): Fail instead of silently removing an optional dependency's locked entries from `pnpm-lock.yaml` when the registry cannot resolve it. Previously, when registry metadata lacked a version that the lockfile already pinned (for example, a mirror that had not synced a recent release yet), `pnpm install` and `pnpm dedupe` silently dropped the optional dependency's entries — emptying maps such as the platform binaries of `@napi-rs/canvas` — so the lockfile differed between machines and frozen installs on other hosts had nothing to link [#​12853](https://github.com/pnpm/pnpm/issues/12853).
- [`fecfe83`](https://github.com/pnpm/pnpm/commit/fecfe83): Fixed peer dependency resolution with `autoInstallPeers` when a workspace package depends on a version of a package that a transitive dependency's self-contained closure also provides for itself. The peer providers that are attached to the root project for reuse are no longer peer-resolved a second time in the root context, so packages inside such a closure no longer get their peers bound to the root project's incompatible version [#​4993](https://github.com/pnpm/pnpm/issues/4993).
- [`5a4daec`](https://github.com/pnpm/pnpm/commit/5a4daec): `${...}` environment-variable placeholders in the `httpProxy`, `httpsProxy`, `noProxy`, `proxy`, and `noproxy` settings are no longer expanded when these settings come from a project's `pnpm-workspace.yaml`. They now receive the same protection already applied to `registry`, `namedRegistries`, and `pnprServer`.
- [`d1da02e`](https://github.com/pnpm/pnpm/commit/d1da02e): `pnpm publish` no longer prints credentials when the target registry is configured with inline `user:pass@` credentials (e.g. `registry=https://user:[email protected]/`). They are now redacted both from the "publishing to registry" line and from the OIDC (trusted publishing) failure messages.
- [`dcfc611`](https://github.com/pnpm/pnpm/commit/dcfc611): `pnpm self-update` now honors `trustPolicy=no-downgrade`. It resolves the target pnpm version against full registry metadata, so it refuses to switch to a version whose supply-chain trust evidence is weaker than an earlier-published one, the same way a regular install does.
- [`a8ad82d`](https://github.com/pnpm/pnpm/commit/a8ad82d): Register the `pn` alias in generated shell completion scripts.
- [`25bd5c3`](https://github.com/pnpm/pnpm/commit/25bd5c3): Fixed standalone installer downgrades from pnpm v12 to v11.
- [`23996e9`](https://github.com/pnpm/pnpm/commit/23996e9): `pnpm runtime set <name> <version>` now validates its arguments: the name must be `node`, `deno`, or `bun`, and the version must not contain a comma. Previously these were interpolated straight into a `pnpm add` selector, where an unsupported name or a comma (e.g. `node 22,is-positive`) could be misread as a list of packages or a local directory and install unintended packages or bins.
</details>
---
This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->Reviewed-on: https://gitea.com/gitea/docs/pulls/465
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [pnpm](https://pnpm.io) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm11/pnpm)) | [`11.9.0` → `11.10.0`](https://renovatebot.com/diffs/npm/pnpm/11.9.0/11.10.0) |  |  |
---
### Release Notes
<details>
<summary>pnpm/pnpm (pnpm)</summary>
### [`v11.10.0`](https://github.com/pnpm/pnpm/blob/HEAD/pnpm11/pnpm/CHANGELOG.md#11100)
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.9.0...v11.10.0)
##### Minor Changes
- [`e2e3c81`](https://github.com/pnpm/pnpm/commit/e2e3c81): Added the `issues` command as an alias of `bugs`, so `pnpm issues` opens the package's bug tracker URL in the browser.
- [`8491f8e`](https://github.com/pnpm/pnpm/commit/8491f8e): Added the `prefix` command which prints the current package prefix directory (or global prefix directory if `-g` / `--global` is used).
- [`3425e80`](https://github.com/pnpm/pnpm/commit/3425e80): Added an `_auth` setting for configuring registry authentication as a single structured (URL-keyed) value. It can be set in the **global** pnpm config (`config.yaml`) or, for CI, via the `pnpm_config__auth` environment variable. The env form sidesteps the GitHub Actions / bash / zsh limitation that broke the existing `pnpm_config_//host/:_authToken=…` form (env var names containing `/`, `:`, or `.` are silently dropped). Closes [#​12314](https://github.com/pnpm/pnpm/issues/12314).
The value is keyed by registry URL so each secret is explicitly bound to the host that may receive it. Registry URL keys must use `http` or `https` and must not include credentials, query strings, or fragments:
```sh
export pnpm_config__auth='{"https://registry.npmjs.org":{"@​":{"authToken":"npm-token"},"@​org":{"authToken":"org-token"}}}'
```
The equivalent in the global `config.yaml`:
```yaml
_auth:
https://registry.npmjs.org:
"@​":
authToken: npm-token
"@​org":
authToken: org-token
```
Within each registry URL, `@` means registry-wide/default credentials and package scopes like `@org` bind credentials to that scope on the same host. The only supported credential field is `authToken` (maps to `_authToken` / bearer auth); the deprecated `basicAuth` / `username` + `password` forms are intentionally not accepted here.
Each entry also infers a trusted registry route: `@` routes the default registry (and `pnpm add <pkg>` resolves there), and `@org` routes that scope. Because the credential and destination host arrive in one trusted value, repo-controlled `pnpm-workspace.yaml` or project `.npmrc` cannot redirect the token to a different host. `_auth` is honored **only** from the env var and the global config — it is ignored in a project `pnpm-workspace.yaml` / `.npmrc`, so repo-controlled config can never supply registry auth. Precedence: CLI flags (`--registry`, `--@​scope:registry`) > `pnpm_config__auth` > global `config.yaml` `_auth` > `pnpm-workspace.yaml`.
Both `pnpm_config__auth` (lowercase, documented form) and `PNPM_CONFIG__AUTH` (all-caps, the shell convention some CI runners apply) are honored. If both are set, lowercase wins unless it is empty, in which case uppercase is used. The env var wins over the global `config.yaml` `_auth` on a conflicting key. `tokenHelper` is not supported in `_auth`. Parsing is strict: a malformed value (bad JSON, wrong shape, invalid registry URL or scope, an unsupported credential field) fails fast with an error rather than being silently dropped.
**Pacquet parity note:** the pacquet (Rust) port supports the same single credential field as the TS CLI: `authToken`.
- [`a33eeec`](https://github.com/pnpm/pnpm/commit/a33eeec): `pnpm self-update` and `packageManager` version-switching can now install and link pnpm v12 (the Rust port), published with equal content under both the `pnpm` and `@pnpm/exe` names on the `next-12` dist-tag. Its native binaries ship as `@pnpm/exe.<platform>-<arch>` packages, which pnpm's built-in installer links directly — no Node.js launcher, so the command pays no Node startup cost. v12 is initialized exactly like `@pnpm/exe`, including per-platform global-virtual-store hashing. From v12 onward the install converges on the unscoped `pnpm` package (the Rust exe) — even when updating from the SEA `@pnpm/exe` build.
- [`1dd12bd`](https://github.com/pnpm/pnpm/commit/1dd12bd): When resolving through a pnpr install-accelerator server, pnpm no longer forwards its own upstream registry credentials in the resolve request. Only the `Authorization` header identifying the caller to pnpr is sent. The pnpr server now selects upstream credentials from its own route policy (operator-configured upstream credential aliases), so private dependencies resolve through a pnpr-managed alias the caller is authorized to use, rather than by sending the client's registry tokens to the server.
- [`1e81761`](https://github.com/pnpm/pnpm/commit/1e81761): Expose web authentication `authUrl` and `doneUrl` in JSON error output when OTP is required in a non-interactive terminal [#​12724](https://github.com/pnpm/pnpm/issues/12724).
##### Patch Changes
- [`2f389d6`](https://github.com/pnpm/pnpm/commit/2f389d6): Added the Node.js release team's new signing key (Stewart X Addison, `655F3B5C1FB3FA8D1A0CA6BDE4A7D232B936D2FD`) to the embedded Node.js release keys, so runtimes whose `SHASUMS256.txt` is signed by the new releaser verify successfully.
- [`acbdb94`](https://github.com/pnpm/pnpm/commit/acbdb94): Fixed shell tab completion not suggesting workspaces after the `-F` alias for `--filter` option.
- [`dcabb78`](https://github.com/pnpm/pnpm/commit/dcabb78): Fixed `pnpm up -r <pkg>` bumping unrelated packages that have open semver ranges. Previously, any update mutation nullified the lockfile-derived `preferredVersions` globally, so packages with `^x.y.z` ranges could re-resolve to newer compatible versions even though the user only asked to update a specific package. The install layer now always seeds `preferredVersions` from the lockfile, and caller-supplied preferred versions (such as the vulnerability penalties of `pnpm audit --fix`) layer on top of the seed instead of replacing it. The targeted package still bumps: the per-resolve `updateRequested` flag makes the resolver ignore the target's own lockfile pins.
Closes [#​10662](https://github.com/pnpm/pnpm/issues/10662).
- [`d539172`](https://github.com/pnpm/pnpm/commit/d539172): Fixed pnpm pack and pnpm publish failing when prepack generates files that are included in the package and postpack cleans them up.
- [`be6505a`](https://github.com/pnpm/pnpm/commit/be6505a): Hardened global package management:
- On Windows, removing or updating a global package now also cleans up the `node.exe` flavor of a bin, so a stale `node.exe` no longer survives on `PATH` after uninstall, and a new global install no longer silently overwrites an existing `node.exe`.
- `pnpm add -g pnpm@<version>` (and `@pnpm/exe@<version>`) is now rejected like the bare `pnpm` form, pointing to `pnpm self-update`.
- Dependency aliases read from a global package's manifest are validated before being joined onto `node_modules` paths, preventing a tampered manifest from escaping the install directory.
- Each global install group is created in its own freshly-made directory (no longer reusing a colliding or pre-existing path).
- Removing or updating a global package no longer unlinks a bin that belongs to a different globally installed package.
- [`25c7388`](https://github.com/pnpm/pnpm/commit/25c7388): pnpm now rejects `jsr:` specifiers whose package name is not a valid npm package name — an empty scope or name (e.g. `jsr:@​scope/`), path separators inside the name, or any other shape `validate-npm-package-name` rejects — with `ERR_PNPM_INVALID_JSR_PACKAGE_NAME` instead of silently converting them into a malformed `@jsr/...` npm package name.
- [`25c7388`](https://github.com/pnpm/pnpm/commit/25c7388): pnpm now rejects named-registry specifiers (e.g. `gh:`) whose package name is not a valid npm package name — an empty scope (e.g. `gh:@​/bar`), path separators inside the name (e.g. `gh:@​scope/../name`), or any other shape `validate-npm-package-name` rejects — with `ERR_PNPM_INVALID_NAMED_REGISTRY_PACKAGE_NAME` instead of passing the name through to registry URLs and metadata cache file paths.
- [`96da7c5`](https://github.com/pnpm/pnpm/commit/96da7c5): node-gyp's `gyp_main.py` and `gyp` entrypoints are now packed with the executable bit in the `pnpm` and `@pnpm/exe` tarballs. Without it, building native addons from source could fail with a permission error.
- [`99982b9`](https://github.com/pnpm/pnpm/commit/99982b9): Sped up resolution and reduced memory use against registries that ignore npm's abbreviated metadata format and always return the full package document (for example, Azure DevOps Artifacts). pnpm now strips such documents down to the abbreviated field set before caching them. Resolution output is unchanged, and registries that honor the abbreviated format (such as the npm registry) pay no extra cost.
- [`11a7fdd`](https://github.com/pnpm/pnpm/commit/11a7fdd): Sped up offline and `--prefer-offline` resolution on large workspaces (e.g. `pnpm dedupe --offline`, `pnpm install --offline`). Package metadata loaded from the local cache is now kept in memory, so each package's metadata is parsed once per command instead of once per dependent that references it.
- [`2c7369d`](https://github.com/pnpm/pnpm/commit/2c7369d): `pnpm pack-app` now rejects `--entry` / `pnpm.app.entry` and `--output-dir` / `pnpm.app.outputDir` values that are absolute paths or escape the project directory via `..` (or a symlink that resolves outside it), and refuses to write the produced executable when its target path already exists as a symlink (or other non-regular file). This prevents a repository-controlled `package.json` from embedding host files (such as an SSH key) into the produced executable, writing build artifacts outside the project, or overwriting an arbitrary file through a committed symlink. The new error codes are `ERR_PNPM_PACK_APP_ENTRY_OUTSIDE_PROJECT`, `ERR_PNPM_PACK_APP_OUTPUT_DIR_OUTSIDE_PROJECT`, and `ERR_PNPM_PACK_APP_OUTPUT_FILE_NOT_REGULAR`.
When ad-hoc signing macOS targets, `pnpm pack-app` now runs the system `codesign` by absolute path and resolves `ldid` to a location outside the project, so a repository-controlled `node_modules/.bin` on `PATH` cannot hijack the signer.
- [`ce5d5a5`](https://github.com/pnpm/pnpm/commit/ce5d5a5): Relative paths in `patchedDependencies` are now resolved against the lockfile directory when computing patch file hashes, so running `pnpm install` from a subdirectory no longer fails with `ENOENT` looking for the patch file in the wrong location [#​12762](https://github.com/pnpm/pnpm/pull/12762).
- [`ebb4096`](https://github.com/pnpm/pnpm/commit/ebb4096): `pnpm peers` no longer reports a conflict for a missing peer dependency that is ignored via `pnpm.peerDependencyRules.ignoreMissing`.
- [`dcabb78`](https://github.com/pnpm/pnpm/commit/dcabb78): Fixed a prototype-pollution hazard when seeding preferred versions: a dependency named `__proto__` in a manifest or in `pnpm-lock.yaml` could write through `Object.prototype` (or crash the install) while the preferred-versions map was being built. The maps are now null-prototype objects, so crafted package names land as plain keys.
- [`f38e696`](https://github.com/pnpm/pnpm/commit/f38e696): Hardened `pnpm deploy --force` so it refuses unsafe deploy targets such as workspace roots, parent directories, out-of-workspace paths, and symlinked target parents.
- [`806c3ec`](https://github.com/pnpm/pnpm/commit/806c3ec): pnpm no longer warns about ignored project-level auth settings when `PNPM_CONFIG_NPMRC_AUTH_FILE` points at the project `.npmrc` — setting it to that file is an explicit opt-in to trusting it, so auth env variables in it are expanded [pnpm/pnpm#12480](https://github.com/pnpm/pnpm/issues/12480).
- [`991405e`](https://github.com/pnpm/pnpm/commit/991405e): Restore differential rendering (`ansi-diff`) to fix duplicated output lines introduced by [#​12351](https://github.com/pnpm/pnpm/issues/12351).
- [`c121235`](https://github.com/pnpm/pnpm/commit/c121235): Fixed the topological order of `--filter`ed commands (`pnpm run`, `pnpm exec`, `pnpm publish`, `pnpm pack`, `pnpm rebuild`) when the selected projects depend on each other only transitively through projects that were not selected. Previously such selected projects could run concurrently or in the wrong order; now a project always runs after the selected projects it transitively depends on, while projects without a real dependency relationship still run concurrently. This now also holds for prod-only filters (`--filter-prod`), which resolve order through the production dependency graph so transitive production dependencies are respected without pulling back the dev dependencies the filter drops, and for selections that mix `--filter` with `--filter-prod` [#​8335](https://github.com/pnpm/pnpm/issues/8335).
- [`d539172`](https://github.com/pnpm/pnpm/commit/d539172): `pnpm pack` and `pnpm publish` no longer follow a symlinked workspace `LICENSE` file when injecting it into a package that has no license of its own. Following the symlink could pack bytes from outside the workspace into the published tarball.
- [`dcabb78`](https://github.com/pnpm/pnpm/commit/dcabb78): Fixed `pnpm up <pkg>` producing a different result than a fresh install of the same manifests would. The resolver now distinguishes `updateRequested` (true only for packages that match the user's update target) from the broader `update` flag, and for the targeted package ignores only its own lockfile-derived preferred-version pins — so the target re-resolves exactly as if its lockfile entries were deleted and `pnpm install` ran. Preferred versions a fresh install applies (manifest pins, versions propagated down the dependency chain, and the vulnerability-avoidance penalties of `pnpm audit --fix`) stay in effect, so an update never installs duplicate versions that a reinstall from scratch would not reproduce. When a preferred version holds the update target below the newest version its range admits, pnpm now prints a warning explaining that reaching the newer version everywhere requires an override.
- [`dcabb78`](https://github.com/pnpm/pnpm/commit/dcabb78): `pnpm update <dep>@​<version>` now prints a warning when `<dep>` is only present as a transitive dependency: the requested version cannot be applied there (updates resolve the target the way a fresh install would), and the warning recommends adding the version to `pnpm.overrides` instead, which is the mechanism that does pin transitive dependencies. Closes [#​12744](https://github.com/pnpm/pnpm/issues/12744).
- [`a6c4d5f`](https://github.com/pnpm/pnpm/commit/a6c4d5f): When a dependency cannot be found in the registry (404) or the registry has no matching version, and a workspace project with the same name exists only at non-matching versions, the error now reports the available workspace versions (`ERR_PNPM_NO_MATCHING_VERSION_INSIDE_WORKSPACE`) instead of the raw registry failure [pnpm/pnpm#1379](https://github.com/pnpm/pnpm/issues/1379). Other registry failures (authorization, network, server errors) still propagate unchanged. The pacquet (Rust) resolver applies the same behavior.
</details>
---------
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/460
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
This PR contains the following updates:
| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [pnpm](https://pnpm.io) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm)) | [`11.7.0` → `11.9.0`](https://renovatebot.com/diffs/npm/pnpm/11.7.0/11.9.0) |  |  |
---
### Release Notes
<details>
<summary>pnpm/pnpm (pnpm)</summary>
### [`v11.9.0`](https://github.com/pnpm/pnpm/releases/tag/v11.9.0): pnpm 11.9
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.8.0...v11.9.0)
#### Minor Changes
- [`bae694f`](https://github.com/pnpm/pnpm/commit/bae694f): Some registries generate tarballs on-demand and cannot provide an integrity checksum in their package metadata. In that case pnpm now computes the integrity from the downloaded tarball and stores it in the lockfile, so the entry is verifiable on subsequent installs instead of being written without an integrity (which would fail the next install). This also applies to `--lockfile-only`: the tarball is downloaded so its integrity can be computed. A lockfile entry that is still missing its integrity is rejected as a `ERR_PNPM_MISSING_TARBALL_INTEGRITY` lockfile verification violation (the install fails closed) rather than being silently re-fetched.
- [`6c35a43`](https://github.com/pnpm/pnpm/commit/6c35a43): Added `--exclude-peers` to `pnpm sbom`. With `auto-install-peers` (the default), peer dependencies resolve into the lockfile and are otherwise indistinguishable from the package's own dependencies. The flag drops peer dependencies (and any transitive subtree reachable only through them) from the SBOM. CycloneDX 1.7 has no scope or relationship that expresses "consumer-provided peer", so omission is the only spec-clean handling. The flag name matches `pnpm list --exclude-peers`; note the SBOM flag prunes a peer's exclusive subtree, which is stricter than `pnpm list` (which only hides leaf peers).
#### Patch Changes
- [`25a829e`](https://github.com/pnpm/pnpm/commit/25a829e): `pnpm audit --fix` now writes a single combined `minimumReleaseAgeExclude` entry per package (e.g. `[email protected].1 || 0.21.1`) instead of one entry per version, matching the format documented for the setting. Existing per-version entries in `pnpm-workspace.yaml` are merged into the combined form rather than left as duplicates. Installs that auto-collect immature versions into `minimumReleaseAgeExclude` now report the same combined entries, so the "Added N entries" message matches what is written to the manifest [#​12534](https://github.com/pnpm/pnpm/issues/12534).
- [`1cbb5f2`](https://github.com/pnpm/pnpm/commit/1cbb5f2): Fixed non-deterministic peer resolution that could add or remove an optional transitive peer — for example `@babel/core`, reached through `styled-jsx` — from a package's peer-dependency suffix across otherwise identical installs, churning the lockfile and causing intermittent `pnpm dedupe --check` failures in CI. When a package's children are resolved by one occurrence (the "owner") and reused by a deeper consumer, whether that consumer inherited the owner's missing peers depended on whether the owner's resolution had finished yet — a race under concurrent resolution. The decision is now a function of the dependency graph's structure rather than resolution-completion order.
- [`d577eea`](https://github.com/pnpm/pnpm/commit/d577eea): Fixed a Windows flakiness in `pnpm dlx` where a failed install could surface a spurious `EBUSY: resource busy or locked` error. The cleanup of a partially-populated dlx cache is now best-effort with retries and no longer masks the original error.
- [`ec7cf70`](https://github.com/pnpm/pnpm/commit/ec7cf70): Shortened the `pnpm dlx` cache path so deep dependency trees no longer overflow Windows' `MAX_PATH`, which could make a dependency's lifecycle script fail with `spawn cmd.exe ENOENT`.
- [`05b95ab`](https://github.com/pnpm/pnpm/commit/05b95ab): Fixed `pnpm` hanging (and crashing with an unhandled promise rejection) when a non-retryable network error such as `SELF_SIGNED_CERT_IN_CHAIN` occurs while fetching from a registry. The error is now rejected through the returned promise instead of being thrown inside the detached retry callback.
- [`d3f68e2`](https://github.com/pnpm/pnpm/commit/d3f68e2): Fix a `pnpm audit` performance regression on lockfiles that contain dependency cycles. The reachable-vulnerability pruning added in pnpm 11.5.1 only memoized acyclic subtrees, so any node whose subtree touched a cycle — together with all of its ancestors — was recomputed on every query, making the path walk quadratic. Reachability is now computed once per node using Tarjan's strongly-connected-components algorithm, so cyclic graphs are handled in linear time [#​12212](https://github.com/pnpm/pnpm/issues/12212).
The audit path walk also no longer recurses, so a deeply nested dependency graph can no longer overflow the call stack, and the install path to each finding is tracked without per-node copying, keeping memory linear in the graph depth.
- [`322f88f`](https://github.com/pnpm/pnpm/commit/322f88f): Fix failed optional dependency updates so they don't rewrite unrelated dependency specs [#​11267](https://github.com/pnpm/pnpm/issues/11267).
- [`1488db1`](https://github.com/pnpm/pnpm/commit/1488db1): When `enableGlobalVirtualStore` is toggled on for a project that was previously installed without it, stale hoisted symlinks under `node_modules/.pnpm/node_modules` are now replaced instead of being left pointing at the old per-project virtual store location [#​9739](https://github.com/pnpm/pnpm/issues/9739).
- [`6545793`](https://github.com/pnpm/pnpm/commit/6545793): Fixed `pnpm install --ignore-workspace` overwriting the `allowBuilds` map in `pnpm-workspace.yaml`. The ignored builds of a package with a build script were auto-populated into `allowBuilds` even though `--ignore-workspace` was passed, clobbering committed `true`/`false` values with the `set this to true or false` placeholder [#​12469](https://github.com/pnpm/pnpm/issues/12469).
- [`fbdc0eb`](https://github.com/pnpm/pnpm/commit/fbdc0eb): Fixed `minimumReleaseAgeExclude` and `trustPolicyExclude` so multiple exact-version entries for the same package behave the same as a single `||` disjunction entry. Previously only the first matching rule's versions were honored, so a config like `[[email protected], [email protected]]` could still flag `[email protected]` as violating `minimumReleaseAge`, while `[[email protected] || 2.5.6]` worked as expected [#​12463](https://github.com/pnpm/pnpm/issues/12463).
- [`fa7004b`](https://github.com/pnpm/pnpm/commit/fa7004b): The in-memory package metadata cache is now populated on the exact-version disk fast path, so repeated resolutions of the same package within one install no longer re-read and re-parse the on-disk metadata. In large monorepos this brings the time for adding a new package down from minutes to seconds. The in-memory cache key now also includes the registry, so a package of the same name served by two different registries in a single install can no longer share a cache slot and resolve the wrong tarball.
- [`0a154b1`](https://github.com/pnpm/pnpm/commit/0a154b1): Fixed `pnpm patch` dropping the package name (and leaking internal option fields) when the patched dependency resolves to a single git-hosted version.
- [`4d3fe4b`](https://github.com/pnpm/pnpm/commit/4d3fe4b): The pnpr resolver endpoints moved under the reserved `/-/pnpr` namespace: `POST /v1/resolve` is now `POST /-/pnpr/v0/resolve` and `POST /v1/verify-lockfile` is now `POST /-/pnpr/v0/verify-lockfile`. The capability handshake at `GET /-/pnpr` advertises protocol version `0` to match. This keeps every pnpr-proprietary route in npm's reserved namespace, so it can never collide with a package path.
- [`0ec878d`](https://github.com/pnpm/pnpm/commit/0ec878d): Removing a runtime dependency now removes the matching `devEngines.runtime` or `engines.runtime` entry that was materialized from it. Blank runtime selectors are normalized to `latest`.
- [`17e7f2c`](https://github.com/pnpm/pnpm/commit/17e7f2c): `pnpm sbom` now emits a CycloneDX `issue-tracker` external reference for components (and the root) whose `package.json` declares a `bugs` URL. Email-only `bugs` entries are skipped, since the reference requires a URL.
- [`a84d2a1`](https://github.com/pnpm/pnpm/commit/a84d2a1): Add `@pnpm/resolving.tarball-url`, which builds and recognizes the canonical npm tarball URL of a package. It vendors `getNpmTarballUrl` (previously the external `get-npm-tarball-url` package) and adds `isCanonicalRegistryTarballUrl`, the predicate the lockfile writer uses to decide whether a tarball URL is derivable from name+version+registry (and can therefore be omitted from `pnpm-lock.yaml`).
Exposing `isCanonicalRegistryTarballUrl` lets a custom resolver (pnpmfile `resolvers`) fronting a proxy that serves tarballs on a non-canonical path (e.g. an ephemeral `localhost:<port>`) rewrite the resolved tarball to the canonical form, so nothing host-specific is persisted to the lockfile. Previously this logic was private to `@pnpm/lockfile.utils`.
Two correctness fixes are included while consolidating the logic: the scoped-package unescape now handles uppercase `%2F` as well as `%2f` (percent-encoding is case-insensitive), and protocol-insensitive comparison strips only a leading `http(s)://` scheme instead of splitting on the first `://` (which could truncate URLs containing a later `://`).
- [`852d537`](https://github.com/pnpm/pnpm/commit/852d537): Lockfile verification no longer reports a registry metadata fetch failure (for example a `403`/`401` on a private registry, or a network error) as `ERR_PNPM_TARBALL_URL_MISMATCH`. When the registry can't be reached to verify an entry, the install now aborts with the registry's own fetch error (such as `ERR_PNPM_FETCH_403`, which already explains the authentication situation) instead of mislabeling a transport failure as lockfile tampering. Registry fetch errors no longer leak basic-auth credentials embedded in the registry URL (`https://user:pass@host/`) into their message.
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
### [`v11.8.0`](https://github.com/pnpm/pnpm/releases/tag/v11.8.0): pnpm 11.8
[Compare Source](https://github.com/pnpm/pnpm/compare/v11.7.0...v11.8.0)
#### Minor Changes
- [`c112b61`](https://github.com/pnpm/pnpm/commit/c112b61): Added a `--dry-run` option to `pnpm install`. It runs a full dependency resolution and reports what an install would change, but writes nothing to disk (no lockfile, no `node_modules`) and always exits with code 0. This mirrors the preview semantics of `npm install --dry-run` [#​7340](https://github.com/pnpm/pnpm/issues/7340).
- [`179ebc4`](https://github.com/pnpm/pnpm/commit/179ebc4): `pnpm run --no-bail` now exits with a non-zero exit code when any of the executed scripts fail, while still running every matched script to completion. This makes the exit-code behavior of `--no-bail` consistent between recursive and non-recursive runs (recursive runs already failed at the end). Previously, a non-recursive `pnpm run --no-bail` always exited with code 0, even when a script failed [#​8013](https://github.com/pnpm/pnpm/issues/8013).
- [`0474a9c`](https://github.com/pnpm/pnpm/commit/0474a9c): Added support for generating Node.js package maps at `node_modules/.package-map.json` during isolated and hoisted installs. Added the `node-experimental-package-map` setting to inject the generated map into pnpm-managed Node.js script environments, and the `node-package-map-type` setting to choose between `standard` and `loose` package maps.
- [`dcededc`](https://github.com/pnpm/pnpm/commit/dcededc): `pnpm sbom` now marks components reachable only through `devDependencies` with CycloneDX `scope: "excluded"` and the `cdx:npm:package:development` property. The `excluded` scope documents "component usage for test and other non-runtime purposes", which matches the semantics of a devDependency; the property is the CycloneDX npm-taxonomy marker emitted by `@cyclonedx/cyclonedx-npm`, so both modern (scope) and existing (property) consumers are covered. Components reachable at runtime (including installed `optionalDependencies`) omit `scope` and default to `required`.
- [`1495cb0`](https://github.com/pnpm/pnpm/commit/1495cb0): Added per-package SBOM generation with `--out` and `--split` flags. Use `--out out/%s.cdx.json` to write one SBOM per workspace package to individual files, or `--split` for NDJSON output to stdout. When `--filter` selects a single package, the SBOM root component now uses that package's metadata. Workspace inter-dependencies (`workspace:` protocol) and their transitive dependencies are included. Author, repository, and license fall back to the root manifest when the package doesn't define them.
- [`293921a`](https://github.com/pnpm/pnpm/commit/293921a): feat(view): support searching project manifest upward when package name is omitted
When running `pnpm view` without a package name, the command now searches
upward for the nearest project manifest (`package.json`, `package.yaml`, or `package.json5`) and uses its `name` field.
If the manifest exists but lacks a `name` field, an error is thrown.
This change also replaces the `find-up` dependency with `empathic` for
improved performance and consistency across workspace tools.
#### Patch Changes
- [`29ab905`](https://github.com/pnpm/pnpm/commit/29ab905): Fixed `pnpm update` overriding the version range policy of a named catalog whose name parses as a version (e.g. `catalog:express4-21`). The `catalog:` reference carries no pinning of its own, so the prefix from the catalog entry (such as `~`) is now preserved instead of being widened to `^` [#​10321](https://github.com/pnpm/pnpm/issues/10321).
- [`bee4bf4`](https://github.com/pnpm/pnpm/commit/bee4bf4): Security: validate config dependency names and versions from the env lockfile (`pnpm-lock.yaml`) before using them to build filesystem paths. A committed lockfile with a traversal-shaped `configDependencies` name (such as `../../PWNED`) or version (such as `../../../PWNED`) could previously cause `pnpm install` to create symlinks or write package files outside `node_modules/.pnpm-config` and the store. Names must now be valid npm package names and versions must be exact semver versions; the same validation is applied to optional subdependencies of config dependencies, and to the legacy workspace-manifest format before any lockfile is written. See [GHSA-qrv3-253h-g69c](https://github.com/pnpm/pnpm/security/advisories/GHSA-qrv3-253h-g69c).
- [`96bdd57`](https://github.com/pnpm/pnpm/commit/96bdd57): Fix `link:` workspace protocol switching to `file:` after `pnpm rm` is run from inside a workspace package whose target workspace dependency has its own dependencies, when `injectWorkspacePackages: true` is set. Follow-up to [#​10575](https://github.com/pnpm/pnpm/pull/10575), which fixed the same symptom for workspace packages without dependencies.
- [`302a2f7`](https://github.com/pnpm/pnpm/commit/302a2f7): No longer warn about using both `packageManager` and `devEngines.packageManager` when the two fields pin the same package manager at the same version with the same integrity hash (e.g. both `[email protected]+sha512.…`). Previously the hash was stripped from the legacy `packageManager` field but not from `devEngines.packageManager`, so even identical specifications looked like a mismatch [#​12028](https://github.com/pnpm/pnpm/issues/12028).
The warning still fires on any genuine divergence, and several cases now state the specific reason instead of a single generic message: a different package manager, a different version, or contradictory integrity hashes for the same version.
- [`3f0fb21`](https://github.com/pnpm/pnpm/commit/3f0fb21): Fixed the progress line showing leftover characters from external processes that write to the terminal between progress updates (e.g. an SSH passphrase prompt would leave a fragment like `added 0sa':`). The interactive reporter now redraws each frame in place, erasing to the end of the display before reprinting, so any such remnants are cleared [#​12350](https://github.com/pnpm/pnpm/issues/12350).
- [`564619f`](https://github.com/pnpm/pnpm/commit/564619f): Fixed `pnpm approve-builds` reporting "no packages awaiting approval" when a build-script dependency whose approval was revoked (e.g. after `git stash` drops the `allowBuilds` from `pnpm-workspace.yaml`) is re-added. The revoked packages are now correctly recorded in `.modules.yaml` so `approve-builds` can find them. [#​12221](https://github.com/pnpm/pnpm/issues/12221)
- [`3d1fd20`](https://github.com/pnpm/pnpm/commit/3d1fd20): Skip the redundant "target bin directory already contains an exe called node" warning on Windows when the existing `node.exe` already matches the target (same hard link or identical content) [pnpm/pnpm#12203](https://github.com/pnpm/pnpm/issues/12203).
- [`1b02b47`](https://github.com/pnpm/pnpm/commit/1b02b47): Fix macOS Gatekeeper blocking native binaries (`.node`, `.dylib`, `.so`) by removing the `com.apple.quarantine` extended attribute after importing them from the store.
When pnpm imports files from its content-addressable store into `node_modules`, macOS preserves extended attributes, including `com.apple.quarantine`. If this xattr is present on a store blob (e.g. it was first written under a Gatekeeper-enabled app such as a Git client), it propagates to `node_modules`, and Gatekeeper blocks the native binary from loading even though pnpm already verified the file's integrity against the lockfile.
After importing a package, pnpm now strips `com.apple.quarantine` from its native binaries, matching Homebrew's behaviour of dropping quarantine from verified downloads. The cleanup is macOS-only, runs in a single batched `xattr` call per package, is restricted to native binaries (other files are untouched), and is non-fatal (it logs a warning on unexpected errors).
Fixes [#​11056](https://github.com/pnpm/pnpm/issues/11056)
- [`61969fb`](https://github.com/pnpm/pnpm/commit/61969fb): Fix `pnpm install` with `optimisticRepeatInstall` incorrectly reporting `Already up to date` when `pnpm-lock.yaml` changed but project manifests did not. This affected workflows such as checking out or restoring only the lockfile [#​12100](https://github.com/pnpm/pnpm/issues/12100).
Also fixes `checkDepsStatus` to use the correct lockfile path when `useGitBranchLockfile` is enabled, so the optimistic fast-path and lockfile modification detection work with `pnpm-lock.<branch>.yaml` files instead of always stat'ing `pnpm-lock.yaml`. Merge-conflict detection now reads the resolved lockfile name as well, and with `mergeGitBranchLockfiles` enabled every `pnpm-lock.*.yaml` is scanned for modifications and conflicts. The git branch is now resolved by reading `.git/HEAD` directly (no process spawn) and uses the workspace directory rather than `process.cwd()`.
- [`5c12968`](https://github.com/pnpm/pnpm/commit/5c12968): Fix recursive updates of transitive dependencies when the update command mixes transitive dependency patterns with direct dependency selectors. For example, `pnpm up -r "@​babel/core" uuid` now updates matching transitive `@babel/core` dependencies even when `uuid` is a direct dependency selector [#​12103](https://github.com/pnpm/pnpm/issues/12103).
- [`9d79ba1`](https://github.com/pnpm/pnpm/commit/9d79ba1): Register the `pnpm update --no-save` flag in the CLI help and option parser.
- [`0474a9c`](https://github.com/pnpm/pnpm/commit/0474a9c): Fixed `pnpm import` for Yarn v2 lockfiles when `js-yaml` v4 is installed.
- [`9e0c375`](https://github.com/pnpm/pnpm/commit/9e0c375): Fixed `pnpm install` repeatedly prompting to remove and reinstall `node_modules` in a workspace package when `enableGlobalVirtualStore` is enabled. The post-install build step recorded a per-project `node_modules/.pnpm` virtual store directory in `node_modules/.modules.yaml`, overwriting the global `<storeDir>/links` value the install step had written. The next install then detected a virtual-store mismatch (`ERR_PNPM_UNEXPECTED_VIRTUAL_STORE`). The build step now derives the same global virtual store directory as the install step [#​12307](https://github.com/pnpm/pnpm/issues/12307).
- [`223d060`](https://github.com/pnpm/pnpm/commit/223d060): Document the `--cpu`, `--os` and `--libc` flags in the output of `pnpm install --help`. These flags were already supported but were only documented on the website [#​12359](https://github.com/pnpm/pnpm/issues/12359).
- [`e85aea2`](https://github.com/pnpm/pnpm/commit/e85aea2): Avoid reading `README.md` from disk when publishing if the publish manifest already provides a `readme` field. The README is now only read lazily, inside `createExportableManifest`, when it is actually needed.
- [`3188ae7`](https://github.com/pnpm/pnpm/commit/3188ae7): Fixed `pnpm peers check` to accept loose peer dependency ranges such as `>=3.16.0 || >=4.0.0-` when the installed peer version satisfies the range [#​12149](https://github.com/pnpm/pnpm/issues/12149).
- [`531f2a3`](https://github.com/pnpm/pnpm/commit/531f2a3): Fixed `pnpm update` rewriting a `workspace:` dependency that points at a local path (e.g. `workspace:../packages/foo/dist`) into a normalized `link:` or version-range specifier. Such specifiers are now preserved verbatim when the workspace protocol is preserved [#​3902](https://github.com/pnpm/pnpm/issues/3902).
- [`fe66535`](https://github.com/pnpm/pnpm/commit/fe66535): Fixed a lockfile non-convergence bug where an incremental install kept a duplicate transitive dependency that a fresh install would not produce. When a package is reused from the lockfile, its child edges are taken verbatim and bypass the preferred-versions walk, so a transitive dependency could stay pinned to an older version even after a direct dependency resolved to a higher version that satisfies the same range. The resolver now refreshes such a stale pin to the higher direct-dependency version during resolution — so the older version is never resolved or fetched, and the incremental result converges to the fresh one.
- [`6d35338`](https://github.com/pnpm/pnpm/commit/6d35338): `pnpm install` detects changes inside local file dependencies again. The optimistic repeat-install fast path only tracks manifest and lockfile modification times, so edits inside a local dependency's directory (or a repacked local tarball) were reported as "Already up to date". Projects with local file dependencies (`file:` and bare local path or tarball specifiers, declared directly or through `pnpm.overrides`) now always run a full install, which refetches those dependencies, matching pnpm v10 behavior [#​11795](https://github.com/pnpm/pnpm/issues/11795).
- [`4ca9247`](https://github.com/pnpm/pnpm/commit/4ca9247): Preserve the existing Node.js runtime version prefix when resolving `node@runtime:<range>` to a concrete version.
- [`30c7590`](https://github.com/pnpm/pnpm/commit/30c7590): Create shorter CAFS temporary package directories to leave room for lifecycle scripts that create IPC socket paths under TMPDIR.
- [`13815ad`](https://github.com/pnpm/pnpm/commit/13815ad): Reporter output (warnings, progress) for `pnpm store` and `pnpm config` subcommands now goes to stderr instead of stdout. This fixes scripts that capture their stdout (e.g. `PNPM_STORE=$(pnpm store path)`, `pnpm config list --json | jq`) from getting warnings mixed into the result.
- [`1c05876`](https://github.com/pnpm/pnpm/commit/1c05876): Avoid relinking unchanged child dependencies and remove stale child links during warm installs.
- [`817f99d`](https://github.com/pnpm/pnpm/commit/817f99d): Fixed lockfile churn where a package's `transitivePeerDependencies` could be dropped (and shift between packages) when the package participates in a dependency cycle. A cycle re-entry resolves against truncated children, so it must not be cached as "pure"; otherwise sibling occurrences of the same package short-circuit and lose transitive peers depending on traversal order [#​5108](https://github.com/pnpm/pnpm/issues/5108).
- [`eba03e0`](https://github.com/pnpm/pnpm/commit/eba03e0): Fix `pnpm install` reporting "Already up to date" after a catalog entry in `pnpm-workspace.yaml` was reverted to a previous version. After an update modified a catalog, the workspace state cache stored the pre-update catalog versions, so reverting the entry back to its original version was not detected as an outdated state [#​12418](https://github.com/pnpm/pnpm/issues/12418).
- [`3b54d79`](https://github.com/pnpm/pnpm/commit/3b54d79): `pnpm update` now keeps lockfile `overrides` that resolve through a catalog in sync with the catalog. Previously, when an override referenced a catalog (e.g. `overrides: { foo: 'catalog:' }`) and `pnpm update` bumped that catalog entry, the lockfile's `catalogs` advanced while the resolved `overrides` kept the old version. The resulting lockfile was internally inconsistent, so a later `pnpm install --frozen-lockfile` failed with `ERR_PNPM_LOCKFILE_CONFIG_MISMATCH`.
- [`9d0a300`](https://github.com/pnpm/pnpm/commit/9d0a300): Fixed `pnpm version --recursive` so it honors the workspace selection. In recursive mode the version bump now applies to the packages resolved from the workspace filter (`selectedProjectsGraph`), matching the behavior of `pnpm publish --recursive`, instead of always bumping every workspace package [#​11348](https://github.com/pnpm/pnpm/issues/11348).
<!-- sponsors -->
#### Platinum Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
<img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
#### Gold Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
<img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
<img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
</picture>
</a>
</td>
</tr>
<tr>
<td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
</picture>
</a>
</td>
<td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
<img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
</picture>
</a>
</td>
</tr>
</tbody>
</table>
<!-- sponsors end -->
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
Reviewed-on: https://gitea.com/gitea/docs/pulls/446
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
Co-committed-by: Renovate Bot <[email protected]>
Adds a versioned docs snapshot for Gitea Runner v1.0.8 (latest stable),
updates lastVersion and navbar to point to the new version while keeping
0.2.11 in the dropdown for historical reference.
---------
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/435
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Nicolas <[email protected]>
Co-committed-by: Nicolas <[email protected]>
Adds documentation for the `DEFAULT_TITLE_SOURCE` setting.
- Added `DEFAULT_TITLE_SOURCE` to the config cheat sheet under `[repository.pull-request]`
- Added a "Default pull request title" section to the pull request usage docs explaining both modes (`first-commit` and `auto`)
---------
Co-authored-by: Nicolas <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/391
Reviewed-by: Nicolas <[email protected]>
Co-authored-by: 0xGREG <[email protected]>
Co-committed-by: 0xGREG <[email protected]>
Sync the zh-cn and zh-tw `config-cheat-sheet.md` translations with the English source for current and 1.26 versions.
Changes:
- Add 17 missing sections (`qos`, `mailer.override_header`, `markup.external-render-name`, `lfs_client`, `storage_minio`, `storage_azureblob`, `storage_override`, and 10 cron task subsections including the `Actions` cron tasks group)
- Add ~30 missing individual settings across existing sections
- Restructure storage sections to match English (separate Minio/Azure/Override subsections)
- Remove stale settings (`TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY`, old inline MINIO duplicates, removed git timeout settings)
- Fix `MERMAID_MAX_SOURCE_CHARACTERS` default value (5000 -> 50000)
- Replace full-width Unicode punctuation (U+FF1A, U+FF08, U+FF09) with ASCII equivalents
All 4 i18n files now have 745 settings matching the English source.
---
This PR was written with the help of Claude Opus 4.6
Reviewed-on: https://gitea.com/gitea/docs/pulls/381
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
Co-committed-by: silverwind <[email protected]>
Add documentation for the new `REVERSE_PROXY_LOGOUT_REDIRECT` setting in the `[security]` section, which allows redirecting users to an external URL or relative path after logout when using reverse proxy authentication.
For Gitea 1.26, ref https://github.com/go-gitea/gitea/pull/36085.
---
This PR was written with the help of Claude Opus 4.6
Reviewed-on: https://gitea.com/gitea/docs/pulls/380
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
Co-committed-by: silverwind <[email protected]>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [pnpm/action-setup](https://github.com/pnpm/action-setup) | action | major | `v4` → `v5` |
---
### Release Notes
<details>
<summary>pnpm/action-setup (pnpm/action-setup)</summary>
### [`v5`](https://github.com/pnpm/action-setup/compare/v4...v5)
[Compare Source](https://github.com/pnpm/action-setup/compare/v4...v5)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My43Ni41IiwidXBkYXRlZEluVmVyIjoiNDMuNzYuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
---------
Co-authored-by: silverwind <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/365
Reviewed-by: silverwind <[email protected]>
Reviewed-by: Nicolas <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
Co-committed-by: Renovate Bot <[email protected]>
The standalone `environment-to-ini` tool was removed in https://github.com/go-gitea/gitea/pull/35735 and its functionality is now built into the Gitea binary. This PR:
- Removes outdated links to the removed `contrib/environment-to-ini` directory
- Updates the "Use environment variables to setup Gitea" section in the config cheat sheet
- Adds examples showing how env vars map to `app.ini` settings and the `__FILE` suffix for secrets
*This PR was authored by Claude.*
Reviewed-on: https://gitea.com/gitea/docs/pulls/355
Reviewed-by: wxiaoguang <[email protected]>
Reviewed-by: TheFox0x7 <[email protected]>
Fix act runner doc typos and errors and simplify some grammar.
Co-authored-by: Peter Ryszkiewicz <[email protected]>
Co-committed-by: Peter Ryszkiewicz <[email protected]>
Original Gitea's repository no longer contains "Environment to INI" document referenced in "Managing Deployments With Environment Variables" section.
This commit fixes the reference by pointing the link to the last commit where needed doc was still present.
Reviewed-on: https://gitea.com/gitea/docs/pulls/315
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: andriibratanin <[email protected]>
Co-committed-by: andriibratanin <[email protected]>
This adds explanations, that were missing regarding Token scopes and the packages feature requiring a token with said scope. Also added a missing explanation, that tokens can be created in the user interface, not just the API. The reason this PR is created was due to misunderstandings around the package feature, that arose during the discussion in https://github.com/go-gitea/gitea/issues/32048 .
This PR aims to clarify the misunderstood points around tokens, scopes and the package feature.
During the creation of this PR bug https://github.com/go-gitea/gitea/issues/32078 was found, the scopes are always reported as `null` during the response of the initial `POST` to create the token.
Co-authored-by: Wladislav ヴラド Artsimovich <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/72
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: FrostKiwi <[email protected]>
Co-committed-by: FrostKiwi <[email protected]>
The SMTPS protocol uses port 465, not 587. Port 587 is instead used for STARTTLS.
Helps getting administrators stuck in cryptic errors such as:
Failed to send a testing email to "[email protected]": could not initiate SMTP session: tls: first record does not look like a TLS handshake
Reviewed-on: https://gitea.com/gitea/docs/pulls/295
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: kairosys-dev <[email protected]>
Co-committed-by: kairosys-dev <[email protected]>
Fix JSON syntax error in token creation request
The previous JSON was malformed:
{"name":test_token","scopes":[...]}
The value of "name" was missing opening quotes, causing the error:
invalid character 't' looking for beginning of value
Fixed by enclosing the string in double quotes:
{"name":"test_token","scopes":[...]}
Reviewed-on: https://gitea.com/gitea/docs/pulls/269
Reviewed-by: techknowlogick <[email protected]>
Co-authored-by: desysoft <[email protected]>
Co-committed-by: desysoft <[email protected]>
Added instructions on how to download the signature file using wget, and fixed a typo in the wget commands that would have caused the command to fail when copied/pasted.
Reviewed-on: https://gitea.com/gitea/docs/pulls/262
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: kmanwar89 <[email protected]>
Co-committed-by: kmanwar89 <[email protected]>
Documentation for my changes to ssh commit signing in <https://github.com/go-gitea/gitea/pull/34341>.
* Renames "GPG Commit Signatures" to "GPG/SSH Commit Signatures", since the url is called just signing and creating a new page would duplicate a lot
* _"The default option and repository specific signing keys are not supported for ssh keys"_
* the original draft implementation did support this for ssh keys
* this warning should avoid people expecting this gitconfig style things to work for ssh keys, since verifying is disabled in this case (e.g. pre 1.25 undocumented behavior preserved).
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/241
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Christopher Homberger <[email protected]>
Co-committed-by: Christopher Homberger <[email protected]>
## Description
Fix step 1 of the [Database Preparation](https://docs.gitea.com/installation/database-prep) docs.
## Changes
When a user modifies the */etc/mysql/my.cnf* config file as instructed in step 1 of the database preparation guide, they get an error message from MySQL when trying to log in as the root user after saving changes.
```shell
mysql: [ERROR] Found option without preceding group in config file /etc/mysql/my.cnf at line 37.
mysql: [ERROR] Fatal error in defaults handling. Program aborted!
```
The solution is to include precede `bind-address` with a group like this.
```ini
[mysqld]
bind-address = 203.0.113.3
```
Reviewed-on: https://gitea.com/gitea/docs/pulls/173
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: b-nagaj <[email protected]>
Co-committed-by: b-nagaj <[email protected]>
I can not understand the old logic:
- download the web page (not the raw data) from GitHub
- replace `AppVer`
- remove the file???
It does nothing.
The correct logic:
- download the raw file from GitHub
- replace `AppVer` and `AppSubUrl`
- move the file to the correct place
As the script is not correct for a long time, added the support for all version since 1.19.
Fix#142
Reviewed-on: https://gitea.com/gitea/docs/pulls/150
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: yp05327 <[email protected]>
Co-committed-by: yp05327 <[email protected]>
"body": "Automated update of the generated runner reference pages from gitea/runner (main for the develop docs, the newest stable tag for every documented series), opened by the \"update runner reference\" scheduled workflow."
"body": "Automated update of static/swagger-latest.json and static/openapi3-latest.json from the gitea main branch, opened by the \"update api spec files\" scheduled workflow."
"_comment":"Algolia DocSearch crawler configuration. The three facets come from the docsearch:* meta tags every page carries; only the versions people read are indexed, the older ones stay reachable through the version picker.",
@@ -12,10 +12,10 @@ Some jurisdictions (such as EU), requires certain legal pages (e.g. Privacy Poli
## Getting Pages
## Getting Pages
Gitea source code ships with sample pages, available in `contrib/legal` directory. Copy them to `custom/public/assets/`. For example, to add Privacy Policy:
Gitea source code ships with sample pages, available in `contrib/service/sample-page` directory. Copy them to `custom/public/assets/`. For example, to add Privacy Policy:
Now you need to edit the page to meet your requirements. In particular you must change the email addresses, web addresses and references to "Your Gitea Instance" to match your situation.
Now you need to edit the page to meet your requirements. In particular you must change the email addresses, web addresses and references to "Your Gitea Instance" to match your situation.
Disabling `synchronous_commit` makes PostgreSQL less resilient to crashes, but makes the import a lot faster. Since we already have a backup of the original database and we can check that the import completes successfully, it should be a good trade-off.
Disabling `synchronous_commit` makes PostgreSQL less resilient to crashes, but makes the import a lot faster. Since we already have a backup of the original database and we can check that the import completes successfully, it should be a good trade-off.
After the import is completed, set up Gitea to use PostgreSQL and start the Gitea server again. Good luck!
After the import is completed, set up Gitea to use PostgreSQL and start the Gitea server again. Good luck!
Customizing Gitea is typically done using the `CustomPath` folder - by default this is
Customizing Gitea is typically done using the `CustomPath` folder - by default this is
the `custom` folder from the working directory (WorkPath), but may be different if your build has
the `custom` folder from the working directory (WorkPath), but may be different if your [installation](../installation/from-binary.md) has
set this differently. This is the central place to override configuration settings,
set this differently. This is the central place to override configuration settings,
templates, etc. You can check the `CustomPath` using `gitea help`. You can also find
templates, etc. You can check the `CustomPath` using `gitea help`. You can also find
the path on the _Configuration_ tab in the _Site Administration_ page. You can override
the path on the _Configuration_ tab in the _Site Administration_ page. You can override
@@ -23,7 +23,7 @@ the Linux Filesystem Standard. Gitea will attempt to create required folders, in
`custom/`. Distributions may provide a symlink for `custom` using `/etc/gitea/`.
`custom/`. Distributions may provide a symlink for `custom` using `/etc/gitea/`.
Application settings can be found in file `CustomConf` which is by default,
Application settings can be found in file `CustomConf` which is by default,
`$GITEA_CUSTOM/conf/app.ini` but may be different if your build has set this differently.
`$GITEA_CUSTOM/conf/app.ini` but may be different if your [installation](../installation/from-binary.md) has set this differently.
Again `gitea help` will allow you review this variable and you can override it using the
Again `gitea help` will allow you review this variable and you can override it using the
`--config` option on the `gitea` binary.
`--config` option on the `gitea` binary.
@@ -85,6 +85,8 @@ To obtain any embedded file (including templates), the [`gitea embedded` tool](.
Be aware that any statement contained inside `{{` and `}}` are Gitea's template syntax and
Be aware that any statement contained inside `{{` and `}}` are Gitea's template syntax and
shouldn't be touched without fully understanding these components.
shouldn't be touched without fully understanding these components.
Gitea pages are protected by Content-Security-Policy, use `<script nonce="{{ctx.CspScriptNonce}}">...</script>` for script tags.
### Customizing startpage / homepage
### Customizing startpage / homepage
Copy [`home.tmpl`](https://github.com/go-gitea/gitea/blob/main/templates/home.tmpl) for your version of Gitea from `templates` to `$GITEA_CUSTOM/templates`.
Copy [`home.tmpl`](https://github.com/go-gitea/gitea/blob/main/templates/home.tmpl) for your version of Gitea from `templates` to `$GITEA_CUSTOM/templates`.
@@ -136,10 +138,10 @@ The data is encoded and sent to the PlantUML server which generates the picture.
demo server at http://www.plantuml.com/plantuml, but if you (or your users) have sensitive data you
demo server at http://www.plantuml.com/plantuml, but if you (or your users) have sensitive data you
can set up your own [PlantUML server](https://plantuml.com/server) instead. To set up PlantUML rendering,
can set up your own [PlantUML server](https://plantuml.com/server) instead. To set up PlantUML rendering,
copy JavaScript files from https://gitea.com/davidsvantesson/plantuml-code-highlight and put them in your
copy JavaScript files from https://gitea.com/davidsvantesson/plantuml-code-highlight and put them in your
`$GITEA_CUSTOM/public/assets/` folder. Then add the following to `custom/footer.tmpl`:
`$GITEA_CUSTOM/public/assets/` folder. Then add the following to `$GITEA_CUSTOM/templates/custom/footer.tmpl`:
```html
```html
<script>
<scriptnonce="{{ctx.CspScriptNonce}}">
$(async()=>{
$(async()=>{
if(!$('.language-plantuml').length)return;
if(!$('.language-plantuml').length)return;
awaitPromise.all([
awaitPromise.all([
@@ -165,52 +167,186 @@ Alice <-- Bob: Another authentication Response
The script will detect tags with `class="language-plantuml"`, but you can change this by providing a second argument to `parsePlantumlCodeBlocks`.
The script will detect tags with `class="language-plantuml"`, but you can change this by providing a second argument to `parsePlantumlCodeBlocks`.
### Example: STL Preview
### Example: CAD Files Preview using Online 3D Viewer
You can display STL file directly in Gitea by adding:
You can implement CAD file preview inside your Gitea instance. This implemenation uses [`Online 3D Viewer`](https://github.com/kovacsv/Online3DViewer).
console.log('New Raw file link detected after delay:',fileName);
onPageChange();
}
};
constobserver=newMutationObserver(()=>{
// Delay execution by 300ms after last mutation
clearTimeout(timeoutId);
timeoutId=setTimeout(checkAndRun,300);
});
observer.observe(document.body,{
childList:true,
subtree:true,
});
});
}
</script>
</script>
```
```
to the file `templates/custom/footer.tmpl`
#### Part 2: Add public files
You also need to download the content of the library [Madeleine.js](https://github.com/beige90/Madeleine.js) and place it under `$GITEA_CUSTOM/public/assets/` folder.
Now we need to download latest version of O3DV. Go to "$GITEA_CUSTOM/public/assets/".
Create folder using (and cd into it):
You should end-up with a folder structure similar to:
```
mkdir o3dv
cd o3dv
```
Copy latest release zip link from [`GitHub`](https://github.com/kovacsv/Online3DViewer/releases) (v0.18.0 as of now).
Now the last thing. Change permissions on the public folder:
```
chown -R git:git $GITEA_CUSTOM/public
```
Now we have everything ready! Restart your gitea instance to apply these changes and test it in your browser.
Sanity check. You should end-up with a folder structure similar to this:
```
```
$GITEA_CUSTOM/templates
$GITEA_CUSTOM/templates
@@ -218,49 +354,14 @@ $GITEA_CUSTOM/templates
`-- footer.tmpl
`-- footer.tmpl
$GITEA_CUSTOM/public/assets/
$GITEA_CUSTOM/public/assets/
-- Madeleine.js
-- o3dv
|-- LICENSE
|-- o3dv.zip
|-- README.md
|-- o3dv.license.md
|-- css
|-- o3dv.min.js
| |-- pygment_trac.css
|-- envmaps
| `-- stylesheet.css
\...
|-- examples
| |-- ajax.html
| |-- index.html
| `-- upload.html
|-- images
| |-- bg_hr.png
| |-- blacktocat.png
| |-- icon_download.png
| `-- sprite_download.png
|-- models
| |-- dino2.stl
| |-- ducati.stl
| |-- gallardo.stl
| |-- lamp.stl
| |-- octocat.stl
| |-- skull.stl
| `-- treefrog.stl
`-- src
|-- Madeleine.js
|-- css
| `-- Madeleine.css
|-- icons
| |-- logo.png
| |-- madeleine.eot
| |-- madeleine.svg
| |-- madeleine.ttf
| `-- madeleine.woff
`-- lib
|-- MadeleineConverter.js
|-- MadeleineLoader.js
|-- detector.js
|-- stats.js
`-- three.min.js
```
```
Then restart Gitea and open a STL file on your Gitea instance.
## Customizing Gitea mails
## Customizing Gitea mails
The `$GITEA_CUSTOM/templates/mail` folder allows changing the body of every mail of Gitea.
The `$GITEA_CUSTOM/templates/mail` folder allows changing the body of every mail of Gitea.
@@ -295,15 +396,16 @@ Starting with Gitea 1.20, you can customize the git configuration via the `git.c
### Enabling signed git pushes
### Enabling signed git pushes
To enable signed git pushes, set these two options:
[Signed pushes](https://git-scm.com/docs/git-push#Documentation/git-push.txt---signedtruefalseif-asked) allow clients to cryptographically sign the push operation itself (not just individual commits). To enable signed pushes, add the following to `app.ini`:
```ini
```ini
[git.config]
[git.config]
receive.advertisePushOptions=true
receive.certNonceSeed=<randomstring>
receive.certNonceSeed=<randomstring>
```
```
`certNonceSeed` should be set to a random string and be kept secret.
`certNonceSeed` should be set to a random string and be kept secret. It is used to generate anti-replay nonces. Gitea already sets `receive.advertisePushOptions = true` by default, so no additional configuration is needed. Note that Gitea does not read `/etc/gitconfig`, so this option must be set via `app.ini` as shown above.
On the client side, pushes can be signed via `git push --signed` or enabled permanently using `git config --global push.gpgSign if-asked`.
### Labels
### Labels
@@ -321,7 +423,7 @@ The [legacy file format](https://github.com/go-gitea/gitea/blob/main/options/lab
`#hex-color label name ; label description`
`#hex-color label name ; label description`
For more information, see the [labels documentation](usage/labels.md).
For more information, see the [labels documentation](../usage/issues-prs/labels.md).
### Licenses
### Licenses
@@ -380,13 +482,27 @@ To make a custom theme available to all users:
The value of `$GITEA_CUSTOM` of your instance can be queried by calling `gitea help` and looking up the value of "CustomPath".
The value of `$GITEA_CUSTOM` of your instance can be queried by calling `gitea help` and looking up the value of "CustomPath".
2. Add `<theme-name>` to the comma-separated list of setting `THEMES` in `app.ini`, or leave `THEMES` empty to allow all themes.
2. Add `<theme-name>` to the comma-separated list of setting `THEMES` in `app.ini`, or leave `THEMES` empty to allow all themes.
A custom theme file named `theme-my-theme.css` will be displayed as `my-theme` on the user's theme selection page.
It could add theme meta information into the custom theme CSS file to provide more information about the theme.
If a custom theme is a dark theme, please set the global css variable `--is-dark-theme: true` in the `:root` block.
This allows Gitea to adjust the Monaco code editor's theme accordingly.
An "auto" theme could be implemented by using "theme-gitea-auto.css" as a reference.
```css
gitea-theme-meta-info {
--theme-display-name: "My Awesome Theme"; /* this theme will be display as "My Awesome Theme" on the UI */
}
:root {
--is-dark-theme: true; /* if it is a dark theme */
--color-primary: #112233;
/* more custom theme variables ... */
}
```
Community themes are listed in [gitea/awesome-gitea#themes](https://gitea.com/gitea/awesome-gitea#themes).
Community themes are listed in [gitea/awesome-gitea#themes](https://gitea.com/gitea/awesome-gitea#themes).
The default theme sources can be found [here](https://github.com/go-gitea/gitea/blob/main/web_src/css/themes).
The default theme sources can be found [here](https://github.com/go-gitea/gitea/blob/main/web_src/css/themes).
If your custom theme is considered a dark theme, set the global css variable `--is-dark-theme` to `true`.
This allows Gitea to adjust the Monaco code editor's theme accordingly.
Gitea has mailer functionality for sending transactional emails (such as registration confirmation). It can be configured to either use Sendmail (or compatible MTAs like Postfix and msmtp) or directly use SMTP server.
Gitea has mailer functionality for sending transactional emails (such as registration confirmation). It can be configured to either use Sendmail (or compatible MTAs like Postfix and msmtp) or directly use SMTP server.
:::note
Be sure to set ENABLE_NOTIFY_MAIL=true to allow Gitea to send email notifications. Check the [Config Cheat Sheet](../administration/config-cheat-sheet.md#service-service) for details.
@@ -56,7 +60,7 @@ For the full list of options check the [Config Cheat Sheet](../administration/co
Authentication is only supported when the SMTP server communication is encrypted with TLS or `HOST=localhost`. TLS encryption can be through:
Authentication is only supported when the SMTP server communication is encrypted with TLS or `HOST=localhost`. TLS encryption can be through:
:::
:::
- STARTTLS (also known as Opportunistic TLS) via port 587. Initial connection is done over cleartext, but then be upgraded over TLS if the server supports it.
- STARTTLS (also known as Opportunistic TLS) via port 587 with `PROTOCOL=smtp+starttls`. Initial connection is done over cleartext, but then be upgraded over TLS if the server supports it.
- SMTPS connection (SMTP over TLS) via the default port 465. Connection to the server use TLS from the beginning.
- SMTPS connection (SMTP over TLS) via the default port 465. Connection to the server use TLS from the beginning.
- Forced SMTPS connection with `PROTOCOL=smtps`. (These are both known as Implicit TLS.)
- Forced SMTPS connection with `PROTOCOL=smtps`. (These are both known as Implicit TLS.)
This is due to protections imposed by the Go internal libraries against STRIPTLS attacks.
This is due to protections imposed by the Go internal libraries against STRIPTLS attacks.
@@ -82,6 +86,21 @@ PROTOCOL = smtps
Note that you'll need to create and use an [App password](https://support.google.com/accounts/answer/185833?hl=en) by enabling 2FA on your Google
Note that you'll need to create and use an [App password](https://support.google.com/accounts/answer/185833?hl=en) by enabling 2FA on your Google
account. You won't be able to use your Google account password directly.
account. You won't be able to use your Google account password directly.
An app password is the only option: Google
[turned off access for apps that sign in with a password alone](https://workspaceupdates.googleblog.com/2023/09/winding-down-google-sync-and-less-secure-apps-support.html)
in 2024 and asks applications to use OAuth instead, which Gitea's mailer does
not implement — it authenticates with `CRAM-MD5`, `PLAIN` or `LOGIN`.
Two things to keep in mind:
- app passwords require 2-step verification on the account, and a Google
Workspace administrator can switch them off for the whole domain. If they are
- port `587` works as well, with `SMTP_PORT = 587` and
`PROTOCOL = smtp+starttls`.
### ProtonMail
### ProtonMail
This feature is currently only available for select Proton for Business customers and those with Visionary and Family plans with custom domain addresses. See [ProtonMail's SMTP documentation](https://proton.me/support/smtp-submission) for more information. This limitation can be circumvented by using the ProtonMail Bridge application.
This feature is currently only available for select Proton for Business customers and those with Visionary and Family plans with custom domain addresses. See [ProtonMail's SMTP documentation](https://proton.me/support/smtp-submission) for more information. This limitation can be circumvented by using the ProtonMail Bridge application.
@@ -16,6 +16,8 @@ The logging configuration of Gitea mainly consists of 3 types of components:
There is a fully functional log output by default, so it is not necessary to define one.
There is a fully functional log output by default, so it is not necessary to define one.
Security-relevant events (repository transfers, token changes, impersonation, and similar) are recorded separately. See [Audit Logging](audit-logging.md).
## Collecting Logs for Help
## Collecting Logs for Help
To collect logs for help and issue report, see [Support Options](help/support.md).
To collect logs for help and issue report, see [Support Options](help/support.md).
1. Set `[server] ROOT_URL = https://git.example.com/` in your `app.ini` file.
1. Set `[server] ROOT_URL = https://git.example.com/` in your `app.ini` file.
2. Make the reverse-proxy pass `https://git.example.com/foo` to `http://gitea:3000/foo`.
2. Make the reverse-proxy pass `https://git.example.com/foo` to `http://gitea:3000/foo`.
3. Make sure the reverse-proxy does not decode the URI. The request `https://git.example.com/a%2Fb` should be passed as `http://gitea:3000/a%2Fb`.
3. Make sure the reverse-proxy does not decode the URI. The request `https://git.example.com/a%2Fb` should be passed as `http://gitea:3000/a%2Fb`.
4. Make sure `Host` and `X-Fowarded-Proto` headers are correctly passed to Gitea to make Gitea see the real URL being visited.
4. Make sure `Host` and `X-Forwarded-Proto` headers are correctly passed to Gitea to make Gitea see the real URL being visited.
5. Make sure your webserver has a certificate, including all intermediate and RootCA certificates, for `git clone` and `git pull` to work.
6. Gitea uses a WebSocket connection at `/-/ws` for real-time updates like the notification counter. Make sure the reverse-proxy talks HTTP/1.1 and forwards the `Upgrade` and `Connection` headers, see the examples below. Without it, Gitea falls back to periodic polling.
### Use a sub-path
### Use a sub-path
@@ -40,6 +42,7 @@ server {
location/{
location/{
client_max_body_size512M;
client_max_body_size512M;
proxy_passhttp://localhost:3000;
proxy_passhttp://localhost:3000;
proxy_http_version1.1;
proxy_set_headerConnection$http_connection;
proxy_set_headerConnection$http_connection;
proxy_set_headerUpgrade$http_upgrade;
proxy_set_headerUpgrade$http_upgrade;
proxy_set_headerHost$host;
proxy_set_headerHost$host;
@@ -66,6 +69,7 @@ server {
rewrite^$request_uri;
rewrite^$request_uri;
rewrite^/(gitea($|/))?(.*)/$3break;
rewrite^/(gitea($|/))?(.*)/$3break;
proxy_passhttp://127.0.0.1:3000$uri;
proxy_passhttp://127.0.0.1:3000$uri;
proxy_http_version1.1;
# other common HTTP headers, see the "Nginx" config section above
# other common HTTP headers, see the "Nginx" config section above
proxy_set_headerConnection$http_connection;
proxy_set_headerConnection$http_connection;
@@ -112,6 +116,7 @@ server {
}
}
location/{
location/{
# other directives, see the "Nginx" config section above
proxy_passhttp://localhost:3000;
proxy_passhttp://localhost:3000;
}
}
}
}
@@ -128,6 +133,7 @@ server {
server_namegit.example.com;
server_namegit.example.com;
location/{
location/{
# other directives, see the "Nginx" config section above
proxy_passhttp://localhost:3000;
proxy_passhttp://localhost:3000;
}
}
}
}
@@ -149,6 +155,20 @@ server {
}
}
```
```
## Nginx Proxy Manager
If you are using Nginx Proxy Manager to serve your Gitea instance it differs slighly from the raw Nginx.
It is [adding some directives](https://github.com/NginxProxyManager/nginx-proxy-manager/blob/master/docker/rootfs/etc/nginx/conf.d/include/proxy.conf) for a custom location by default, so you have to skip these from the above mentioned Nginx config. Otherwise Nginx will produce `400 bad request` error due to duplicated directives (`proxy_set_header Host $host` is the particularly problematic one).
So while creating the `/` Custom location, just add the following line to it's configuration:
```nginx
client_max_body_size512M;
```
Enable `Websockets Support` on the proxy host, Nginx Proxy Manager then adds the WebSocket directives itself. Adding `proxy_http_version` on top of that makes Nginx refuse to start.
## Apache HTTPD
## Apache HTTPD
If you want Apache HTTPD to serve your Gitea instance, you can add the following to your Apache HTTPD configuration (usually located at `/etc/apache2/httpd.conf` in Ubuntu):
If you want Apache HTTPD to serve your Gitea instance, you can add the following to your Apache HTTPD configuration (usually located at `/etc/apache2/httpd.conf` in Ubuntu):
@@ -159,13 +179,15 @@ If you want Apache HTTPD to serve your Gitea instance, you can add the following
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
</VirtualHost>
```
```
:::note
:::note
The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`.
The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`.
`upgrade=websocket` requires Apache HTTPD 2.4.48 or later. On older versions you **MUST** remove it, otherwise Apache HTTPD will not start.
:::
:::
If you wish to use Let's Encrypt with webroot validation, add the line `ProxyPass /.well-known !` before `ProxyPass` to disable proxying these requests to Gitea.
If you wish to use Let's Encrypt with webroot validation, add the line `ProxyPass /.well-known !` before `ProxyPass` to disable proxying these requests to Gitea.
@@ -183,7 +205,7 @@ In case you already have a site, and you want Gitea to share the domain name, yo
</Proxy>
</Proxy>
AllowEncodedSlashes NoDecode
AllowEncodedSlashes NoDecode
# Note: no trailing slash after either /git or port
# Note: no trailing slash after either /git or port
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
</VirtualHost>
@@ -192,7 +214,55 @@ In case you already have a site, and you want Gitea to share the domain name, yo
Then you **MUST** set something like `[server] ROOT_URL = http://git.example.com/git/` correctly in your configuration.
Then you **MUST** set something like `[server] ROOT_URL = http://git.example.com/git/` correctly in your configuration.
:::note
:::note
The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`.
The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`.`upgrade=websocket` requires Apache HTTPD 2.4.48 or later, remove it on older versions.
:::
## Apache HTTPD and serve static resources directly
We can tune the performance in splitting requests into categories static and dynamic.
CSS files, JavaScript files, images and web fonts are static content.
The front page, a repository view or issue list is dynamic content.
Apache HTTPD can serve static resources directly and proxy only the dynamic requests to Gitea.
Download a snapshot of the Gitea source repository to `/path/to/gitea/`.
After this, run `make frontend` in the repository directory to generate the static resources. We are only interested in the `public/` directory for this task, so you can delete the rest.
(You will need to have [Node with npm](https://nodejs.org/en/download/) and `make` installed to generate the static resources)
Depending on the scale of your user base, you might want to split the traffic to two distinct servers,
or use a cdn for the static files.
### Single node and single domain
Set `[server] STATIC_URL_PREFIX = /_/static` in your configuration.
```apacheconf
<VirtualHost*:80>
...
<Proxy*>
Order allow,deny
Allow from all
</Proxy>
ProxyPass /_/static/ !
Alias /_/static/ /path/to/gitea/public/
<Directory/path/to/gitea/public/>
Options FollowSymlinks
AllowOverrideNone
Requireall granted
</Directory>
AllowEncodedSlashes NoDecode
# Note: no trailing slash after either /git or port
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
```
:::note
The following Apache HTTPD mods must be enabled: `proxy`, `proxy_http`. `upgrade=websocket` requires Apache HTTPD 2.4.48 or later, remove it on older versions.
:::
:::
## Caddy
## Caddy
@@ -229,11 +299,13 @@ If you wish to run Gitea with IIS. You will need to setup IIS with URL Rewrite a
- Install Application Request Routing (ARR for short) either by using the Microsoft Web Platform Installer 5.1 (WebPI) or downloading the extension from [IIS.net](https://www.iis.net/downloads/microsoft/application-request-routing)
- Install Application Request Routing (ARR for short) either by using the Microsoft Web Platform Installer 5.1 (WebPI) or downloading the extension from [IIS.net](https://www.iis.net/downloads/microsoft/application-request-routing)
- Once the module is installed in IIS, you will see a new Icon in the IIS Administration Console called URL Rewrite.
- Once the module is installed in IIS, you will see a new Icon in the IIS Administration Console called URL Rewrite.
- Install the `WebSocket Protocol` Windows feature, otherwise ARR cannot proxy Gitea's WebSocket endpoint.
- Open the IIS Manager Console and click on the `Gitea Proxy` Website from the tree view on the left. Select and double click the URL Rewrite Icon from the middle pane to load the URL Rewrite interface.
- Open the IIS Manager Console and click on the `Gitea Proxy` Website from the tree view on the left. Select and double click the URL Rewrite Icon from the middle pane to load the URL Rewrite interface.
- Choose the `Add Rule` action from the right pane of the management console and select the `Reverse Proxy Rule` from the `Inbound and Outbound Rules` category.
- Choose the `Add Rule` action from the right pane of the management console and select the `Reverse Proxy Rule` from the `Inbound and Outbound Rules` category.
- In the Inbound Rules section, set the server name to be the host that Gitea is running on with its port. e.g. if you are running Gitea on the localhost with port 3000, the following should work: `127.0.0.1:3000`
- In the Inbound Rules section, set the server name to be the host that Gitea is running on with its port. e.g. if you are running Gitea on the localhost with port 3000, the following should work: `127.0.0.1:3000`
- Enable SSL Offloading
- Enable SSL Offloading
- In the Outbound Rules, ensure `Rewrite the domain names of the links in HTTP response` is set and set the `From:` field as above and the `To:` to your external hostname, say: `git.example.com`
- In the Outbound Rules, ensure `Rewrite the domain names of the links in HTTP response` is set and set the `From:` field as above and the `To:` to your external hostname, say: `git.example.com`
- Turn `Reverse rewrite host in response headers` off, in the `Server Proxy Settings` of Application Request Routing (select the server node in the IIS Manager, open `Application Request Routing Cache`, then `Server Proxy Settings` in the right pane). While it is on, ARR rewrites the host of the `Location` header back to the internal one, so the redirects Gitea sends after a sign-in or a form submission send the browser to `127.0.0.1:3000` instead of `git.example.com`.
- Now edit the `web.config` for your website to match the following: (changing `127.0.0.1:3000` and `git.example.com` as appropriate)
- Now edit the `web.config` for your website to match the following: (changing `127.0.0.1:3000` and `git.example.com` as appropriate)
Gitea will verify GPG commit signatures in the provided tree by
Gitea will verify gpg/ssh commit signatures in the provided tree by
checking if the commits are signed by a key within the Gitea database,
checking if the commits are signed by a key within the Gitea database,
or if the commit matches the default key for Git.
or if the commit matches the default key for Git.
Additionally Gitea will verify commits signed by ssh keys, which public keys are part of [`TRUSTED_SSH_KEYS`](#general-configuration).
Keys are not checked to determine if they have expired or revoked.
Keys are not checked to determine if they have expired or revoked.
Keys are also not checked with keyservers.
Keys are also not checked with keyservers.
@@ -46,6 +48,11 @@ for GPG - in particular it is probably advisable to only install a
signing secret subkey without the master signing and certifying secret
signing secret subkey without the master signing and certifying secret
key.
key.
## Installing and generating a SSH key for Gitea
You can run `ssh-keygen -t ed25519 -f gitea-signing-key` to generate the private/public keypair for commit signing without any password. Usually you would store the key next to the gitea configuration, then point `SIGNING_KEY` to the generated public key `/path/to/gitea-signing-key.pub`. Gitea generates all its commits using the server `git` command at present - and therefore the server `ssh-keygen` will be used for
signing (if configured.)
## General Configuration
## General Configuration
Gitea's configuration for signing can be found with the
Gitea's configuration for signing can be found with the
For SSH commit signing, you need to specify the `SIGNING_FORMAT` to `ssh` instead of the default `openpgp`. `SIGNING_NAME` and `SIGNING_EMAIL` are required for verifing the signatures.
This looks like this:
```ini
...
[repository.signing]
SIGNING_KEY=/path/to/gitea-signing-key.pub
SIGNING_NAME=
SIGNING_EMAIL=
SIGNING_FORMAT=ssh
INITIAL_COMMIT=always
CRUD_ACTIONS=pubkey, twofa, parentsigned
WIKI=never
MERGES=pubkey, twofa, basesigned, commitssigned
...
```
-`/path/to/gitea-signing-key` is expected to be the private key for `/path/to/gitea-signing-key.pub` [see here how to generate a new ssh keypair](#installing-and-generating-a-ssh-key-for-gitea).
-`TRUSTED_SSH_KEYS = ssh-<algorithm> <key>` or `TRUSTED_SSH_KEYS = ssh-<algorithm> <key1>, ssh-<algorithm> <key2>` can be used for rotating the global ssh signing key to continue verifying commits signed by the previous keys.
### `SIGNING_KEY`
### `SIGNING_KEY`
The first option to discuss is the `SIGNING_KEY`. There are three main
The first option to discuss is the `SIGNING_KEY`. There are three main
options:
options:
-`none` - this prevents Gitea from signing any commits
-`none` - this prevents Gitea from signing any commits
-`default` - Gitea will default to the key configured within `git config`
-`default` - Gitea will default to the gpg key configured within `git config`
-`KEYID` - Gitea will sign commits with the gpg key with the ID
-`KEYID` - Gitea will sign commits with the gpg key with the ID
`KEYID`. In this case you should provide a `SIGNING_NAME` and
`KEYID`. In this case you should provide a `SIGNING_NAME` and
`SIGNING_EMAIL` to be displayed for this key.
`SIGNING_EMAIL` to be displayed for this key.
-`/path/to/gitea-signing-key.pub` - Gitea will sign commits with the ssh key without the `.pub` suffix `/path/to/gitea-signing-key`. In this case you should provide a `SIGNING_NAME` and
`SIGNING_EMAIL` to be displayed for this key and set `SIGNING_FORMAT` to `ssh`.
The `default` option will interrogate `git config` for
The `default` option will interrogate `git config` for
`commit.gpgsign` option - if this is set, then it will use the results
`commit.gpgsign` option - if this is set, then it will use the results
@@ -97,6 +129,10 @@ Related home files for git command (like `.gnupg`) should also be put in Gitea's
If you like to keep the `.gnupg` directory outside of `{[git].HOME_PATH}/`, consider setting the `$GNUPGHOME` environment variable to your preferred location, otherwise Gitea will use the gpg keys only under `{[git].HOME_PATH}/.gnupg`.
If you like to keep the `.gnupg` directory outside of `{[git].HOME_PATH}/`, consider setting the `$GNUPGHOME` environment variable to your preferred location, otherwise Gitea will use the gpg keys only under `{[git].HOME_PATH}/.gnupg`.
:::
:::
:::warning
The default option and repository specific signing keys are not supported for ssh keys
:::
### `INITIAL_COMMIT`
### `INITIAL_COMMIT`
This option determines whether Gitea should sign the initial commit
This option determines whether Gitea should sign the initial commit
@@ -168,3 +204,9 @@ In cases where there is a repository specific key this can be obtained from:
```sh
```sh
/api/v1/repos/:username/:reponame/signing-key.gpg
/api/v1/repos/:username/:reponame/signing-key.gpg
```
```
For ssh commit signing the default ssh public key can be obtained via the API at:
specification (not RFC 9421). The signature is sent in the `Signature` header,
and SSH certificates additionally include an `x-ssh-certificate` header. The
official [go-sdk](https://gitea.com/gitea/go-sdk) implements this flow if you
need a reference implementation.
## Generating and listing API tokens
## Generating and listing API tokens
API tokens can be created either in the user interface or via the API. Tokens have by default limited permissions and it is important to create tokens with the correct permissions for your task.
### User Interface
Tokens can be created via the `Manage Access Tokens` dialog, accessed via `User Settings` / `Applications` or via the link `gitea-domain.example/user/settings/applications`. The interface allows you to create tokens and manage their permissions via the `Select permissions` sub-menu.
Once created, the token is displayed in a toast message above the `Manage Access Tokens` dialog. Please note, that you can view this toast only once and it is not possible to redisplay the token for security reasons.
### Token API
A new token can be generated with a `POST` request to
A new token can be generated with a `POST` request to
`/users/:name/tokens`.
`/users/:name/tokens`.
@@ -35,8 +54,10 @@ Note that `/users/:name/tokens` is a special endpoint and requires you
to authenticate using `BasicAuth` and a password, as follows:
to authenticate using `BasicAuth` and a password, as follows:
By default, this creates a token with very limited permissions. To complete your tasks, your token may require extra permissions. These permissions are created via the json variable `scopes`, which takes an array of permissions as strings. Eg.: `"scopes":["all"]`. Possible permissions, as reflected in the user interface are:
- `activitypub`
- `admin`
- `issue`
- `misc`
- `notification`
- `organization`
- `package`
- `repository`
- `user`
Each permission may be set to `read` or `write`. `write` implies both Read & Write. To set permissions you write the permissions string as `<read or write>:<permission name>`, eg.: `write:package` or `read:notification`. A properly formatted API call may look like:
@@ -33,7 +33,7 @@ then the config file (app.ini) should exists in the "custom/conf" directory of y
Some package vendors might use "/etc/gitea" to store the config file, while some others don't.
Some package vendors might use "/etc/gitea" to store the config file, while some others don't.
You could manually find the config file (app.ini) by checking Gitea's startup logs
You could manually find the config file (app.ini) by checking Gitea's startup logs
or reading the Gitea Web's Site Administrator -> Confugiraton Summary.
or reading the Gitea Web's Site Administrator -> Configuration Summary.
If you are using some isolated enviroments like container (docker),
If you are using some isolated enviroments like container (docker),
the path you see usually is not what it is in the host's filesystem.
the path you see usually is not what it is in the host's filesystem.
@@ -330,9 +330,9 @@ It is highly recommended to back-up your database before running these commands.
- Add your (bare) repositories to the correct spot for your configuration (`repository.ROOT`), ensuring they are in the correct layout `<REPO_ROOT>/[user]/[repo].git`.
- Add your (bare) repositories to the correct spot for your configuration (`repository.ROOT`), ensuring they are in the correct layout `<REPO_ROOT>/[user]/[repo].git`.
- **Note:** the directory names must be lowercase.
- **Note:** the directory names must be lowercase.
- You can also check `<ROOT_URL>/admin/config` for the repository root path.
- You can also check `<ROOT_URL>/-/admin/config` for the repository root path.
- Ensure that the user/org exists that you want to adopt repositories for.
- Ensure that the user/org exists that you want to adopt repositories for.
- As an admin, go to `<ROOT_URL>/admin/repos/unadopted` and search.
- As an admin, go to `<ROOT_URL>/-/admin/repos/unadopted` and search.
- Users can also be given similar permissions via config [`ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES`](../administration/config-cheat-sheet.md#repository-repository).
- Users can also be given similar permissions via config [`ALLOW_ADOPTION_OF_UNADOPTED_REPOSITORIES`](../administration/config-cheat-sheet.md#repository-repository).
- If the above steps are done correctly, you should be able to select repositories to adopt.
- If the above steps are done correctly, you should be able to select repositories to adopt.
- If no repositories are found, enable [debug logging](../administration/config-cheat-sheet.md#repository-repository) to check for any specific errors.
- If no repositories are found, enable [debug logging](../administration/config-cheat-sheet.md#repository-repository) to check for any specific errors.
@@ -13,7 +13,7 @@ Gitea was originally forked from [Gogs](https://gogs.io) and almost all the code
:::warning
:::warning
Gitea does not sent or cherry-picked commits from upstream, so there is no guarantee it will work if you upgrade from Gogs to Gitea. The recommended method is to migrate repositories from Gogs to Gitea.
Gitea does not send commits to upstream or cherry-pick commits from it, so there is no guarantee it will work if you upgrade from Gogs to Gitea. The recommended method is to migrate repositories from Gogs to Gitea.
:::
:::
@@ -31,11 +31,11 @@ You can try it out using [the online demo](https://demo.gitea.com).
- **Code Hosting**
- **Code Hosting**
Gitea supports creating and managing repositories, browsing commit history and code files, reviewing and merging code submissions, managing collaborators, handling branches, and more. It also supports many common Git features such as tags, Cherry-pick, hooks, integrated collaboration tools, and more.
Gitea supports creating and managing repositories, browsing commit history and code files, reviewing and merging code submissions, managing collaborators, handling branches, and more. It also supports many common Git features such as tags, cherry-picking, hooks, integrated collaboration tools, and more.
- **Lightweight and Fast**
- **Lightweight and Fast**
One of Gitea's design goals is to be lightweight and fast in response. Unlike some large code hosting platforms, it remains lean, performs well in terms of speed, and is suitable for resource-limited server environments. Due to its lightweight design, Gitea has relatively low resource consumption and performs well in resource-constrained environments.
One of Gitea's design goals is to be lightweight and fast in response. Unlike some large code hosting platforms, it remains lean, performs well in terms of speed, and is suitable for resource-limited server environments.
- **Easy Deployment and Maintenance**
- **Easy Deployment and Maintenance**
@@ -43,7 +43,7 @@ You can try it out using [the online demo](https://demo.gitea.com).
- **Security**
- **Security**
Gitea places a strong emphasis on security, offering features such as user permission management, access control lists, and more to ensure the security of code and data.
Gitea places a strong emphasis on security, offering features such as user permission management, access control lists, [audit logging](administration/audit-logging.md), and more to ensure the security of code and data.
- **Code Review**
- **Code Review**
@@ -105,6 +105,6 @@ For more detailed information, please refer to: https://docs.gitea.com/installat
@@ -24,9 +24,10 @@ All steps below requires that the database engine of your choice is installed on
## MySQL/MariaDB
## MySQL/MariaDB
1. For remote database setup, you will need to make MySQL listen to your IP address. Edit`bind-address` option on `/etc/mysql/my.cnf` on database instance to:
1. For remote database setup, you will need to make MySQL listen to your IP address. Configure the`bind-address` option in `/etc/mysql/my.cnf` on database instance by adding the following lines:
Note that the above command will download Gitea @version@ for 64-bit Linux.
Note that the above command will download Gitea @version@ for 64-bit Linux.
## Verify GPG signature
## Verify signature
### Sigstore
Starting with v1.27 Gitea signs all binaries using [sigstore](https://sigstore.dev/) to prevent against unwanted modification of binaries.
To validate the binary, download the bundle file which ends in `sigstore.json` for the binary you downloaded and use the [cosign](https://docs.sigstore.dev/cosign/system_config/installation/) command line tool.
If the command outputs `Verified OK`, binary was not modified.
:::note
The above command will match any release workflow. You may choose to restrict the identity further by requiring a specific branch or workflow to be matched. For example this url will match only nightly builds made on main branch: `https://github.com/go-gitea/gitea/.github/workflows/release-nightly.yml@refs/heads/main`
:::
### GPG
Gitea signs all binaries with a [GPG key](https://keys.openpgp.org/search?q=teabot%40gitea.io) to prevent against unwanted modification of binaries.
Gitea signs all binaries with a [GPG key](https://keys.openpgp.org/search?q=teabot%40gitea.io) to prevent against unwanted modification of binaries.
To validate the binary, download the signature file which ends in `.asc` for the binary you downloaded and use the GPG command line tool.
To validate the binary, download the signature file which ends in `.asc` for the binary you downloaded and use the GPG command line tool.
A script to enable bash-completion can be found at [`contrib/autocompletion/bash_autocomplete`](https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/autocompletion/bash_autocomplete). This can be copied to `/usr/share/bash-completion/completions/gitea`
### Adding shell autocompletion (from 1.25)
or sourced within your `.bashrc`.
Similarly a script for zsh-completion can be found at [`contrib/autocompletion/zsh_autocomplete`](https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/autocompletion/zsh_autocomplete). This can be copied to `/usr/share/zsh/_gitea` or sourced within your
Shell completion can be generated directly from binary with:
`.zshrc`.
```sh
gitea completion <shell>
```
YMMV and these scripts may need further improvement.
Supported values for `<shell>` are `bash`, `fish`, `pwsh` and `zsh`. Details on how to load the completion for your shell can be found in the completion command help.
## Running Gitea
## Running Gitea
After you complete the above steps, you can run Gitea two ways:
After you complete the above steps, you can run Gitea two ways:
:::note
On a distribution with SELinux in enforcing mode (Fedora, RHEL, CentOS Stream,
Rocky Linux, AlmaLinux and others), the binary and the data directory need
labels the default policy does not give them, and binding to a port below 1024
takes an extra step. See [running Gitea with SELinux](selinux.md).
:::
### 1. Creating a service file to start Gitea automatically (recommended)
### 1. Creating a service file to start Gitea automatically (recommended)
See how to create [Linux service](installation/run-as-service-in-ubuntu.md)
See how to create [Linux service](installation/run-as-service-in-ubuntu.md)
@@ -214,9 +239,7 @@ As of v1.8, there is a problem with the arm7 version of Gitea, and it doesn't ru
It is recommended to switch to the arm6 version, which has been tested and shown to work on Raspberry Pis and similar devices.
It is recommended to switch to the arm6 version, which has been tested and shown to work on Raspberry Pis and similar devices.
<!---
{/* please remove after fixing the arm7 bug */}
please remove after fixing the arm7 bug
--->
### Git error after updating to a new version of Gitea
### Git error after updating to a new version of Gitea
If during the update, the binary file name has been changed to a new version of Gitea,
If during the update, the binary file name has been changed to a new version of Gitea,
This can be combined with `CC`, `GOOS`, and `GOARCH` as above.
This can be combined with `CC`, `GOOS`, and `GOARCH` as above.
### Adding bash/zsh autocompletion (from 1.19)
### Adding shell autocompletion (from 1.25)
A script to enable bash-completion can be found at [`contrib/autocompletion/bash_autocomplete`](https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/autocompletion/bash_autocomplete). This should be altered as appropriate and can be `source` in your `.bashrc`
Shell completion can be generated directly from binary with:
or copied as `/usr/share/bash-completion/completions/gitea`.
```sh
gitea completion <shell>
```
Similarly, a script for zsh-completion can be found at [`contrib/autocompletion/zsh_autocomplete`](https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/autocompletion/zsh_autocomplete). This can be copied to `/usr/share/zsh/_gitea` or sourced within your
Supported values for `<shell>` are `bash`, `fish`, `pwsh` and `zsh`. Details on how to load the completion for your shell can be found in the completion command help.
`.zshrc`.
YMMV and these scripts may need further improvement.
@@ -12,7 +12,7 @@ You can run Gitea as a Linux service, using either systemd or supervisor. The st
## Using systemd
## Using systemd
Copy the sample [gitea.service](https://github.com/go-gitea/gitea/blob/main/contrib/systemd/gitea.service) to `/etc/systemd/system/gitea.service`, then edit the file with your favorite editor.
Copy the sample [gitea.service](https://github.com/go-gitea/gitea/blob/main/contrib/service/systemd/gitea.service) to `/etc/systemd/system/gitea.service`, then edit the file with your favorite editor.
Uncomment any service that needs to be enabled on this host, such as MySQL.
Uncomment any service that needs to be enabled on this host, such as MySQL.
@@ -56,115 +58,15 @@ Note that the volume should be owned by the user/group with the UID/GID specifie
sudo chown 1000:1000 config/ data/
sudo chown 1000:1000 config/ data/
```
```
> If you don't give the volume correct permissions, the container may not start.
> If you don't give the volume correct permissions, the container may present the following errors in the logs:
For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:@dockerVersion@-rootless`, but if you'd like to use the latest development version then `:nightly-rootless` would be an appropriate tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-nightly-rootless` tag, where x is the minor version of Gitea. (e.g. `:1.16-nightly-rootless`)
For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:@dockerVersion@-rootless`, but if you'd like to use the latest development version then `:main-nightly-rootless` would be an appropriate tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-nightly-rootless` tag, where x is the minor version of Gitea. (e.g. `:1.27-nightly-rootless`)
To start Gitea in combination with a MySQL database, apply these changes to the
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""
```
To set required TOKEN and SECRET values, consider using Gitea's built-in [generate utility functions](../administration/command-line.md#generate).
# SSH Container Passthrough
Since SSH is running inside the container, SSH needs to be passed through from the host to the container if SSH support is desired. One option would be to run the container SSH on a non-standard port (or moving the host port to a non-standard port). Another option which might be more straightforward is to forward SSH commands from the host to the container. This setup is explained in the following.
This guide assumes that you have created a user on the host called `git` with permission to run `docker exec`, and that the Gitea container is called `gitea`. You will need to modify that user's shell to forward the commands to the `sh` executable inside the container, using `docker exec`.
First, create the file `/usr/local/bin/gitea-shell` on the host, with the following contents:
```bash
#!/bin/sh
/usr/bin/docker exec -i --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
```
Note that `gitea` in the docker command above is the name of the container. If you named yours differently, don't forget to change that.
You should also make sure that you’ve set the permissions of the shell wrapper correctly:
```bash
sudo chmod +x /usr/local/bin/gitea-shell
```
Once the wrapper is in place, you can make it the shell for the `git` user:
```bash
sudo usermod -s /usr/local/bin/gitea-shell git
```
Now that all the SSH commands are forwarded to the container, you need to set up the SSH authentication on the host. This is done by leveraging the [SSH AuthorizedKeysCommand](../administration/command-line.md#keys) to match the keys against those accepted by Gitea. Add the following block to `/etc/ssh/sshd_config`, on the host:
Gitea supports blocking of users to restrict how they can interact with you and your content.
You can block a user in your account settings, from the user's profile or from comments created by the user.
The user is not directly notified about the block, but they can notice they are blocked when they attempt to interact with you.
Organization owners can block anyone who is not a member of the organization too.
If a blocked user has admin permissions, they can still perform all actions even if blocked.
### When you block a user
- the user stops following you
- you stop following the user
- the user's stars are removed from your repositories
- your stars are removed from their repositories
- the user stops watching your repositories
- you stop watching their repositories
- the user's issue assignments are removed from your repositories
- your issue assignments are removed from their repositories
- the user is removed as a collaborator on your repositories
- you are removed as a collaborator on their repositories
- any pending repository transfers to or from the blocked user are canceled
### When you block a user, the user cannot
- follow you
- watch your repositories
- star your repositories
- fork your repositories
- transfer repositories to you
- open issues or pull requests on your repositories
- comment on issues or pull requests you've created
- comment on issues or pull requests on your repositories
- react to your comments on issues or pull requests
- react to comments on issues or pull requests on your repositories
- assign you to issues or pull requests
- add you as a collaborator on their repositories
- send you notifications by @mentioning your username
- be added as team member (if blocked by an organization)
Loaded 50 of 2085 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.