Compare commits

..

84 commits

Author SHA1 Message Date
famfo
4e40eede03 [v15.0/forgejo] fix(activitypub): only return public activities on request (#12533)
Manual backport of #12382

The endpoint returning individual activities was missing access control checks, since IDs are sequential, this is not ideal.

Fixes #12333

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12533
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-05-12 04:57:33 +02:00
Mathieu Fenniak
97a0ab9833 [v15.0/forgejo] 2026-05-12 security patches (#12494)
- fix: prevent git write to wiki repo from unauthorized user via git HTTP
- fix: prevent LFS authorization token from being used for read/write access after user's access is restricted from Forgejo
- fix: prevent scoped API access (OAuth tokens, Access tokens) from accessing resources beyond their permitted scope via non-API endpoints (e.g. /user/repo/raw/...)
- fix: implementing missing OAuth validation checks, improve protections against race conditions
- fix: prevent OAuth redirect URI spoofing via non-ascii case collision
- fix: strengthen Actions Artifact V4 signature algorithm against spoofing attacks

Co-authored-by: Derzsi Dániel <daniel@tohka.us>
Co-authored-by: jvoisin <julien.voisin@dustri.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12494
2026-05-12 04:54:28 +02:00
Renovate Bot
3330f75a2e Update dependency mermaid to v11.15.0 [SECURITY] (v15.0/forgejo) (#12531)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [mermaid](https://github.com/mermaid-js/mermaid) | [`11.13.0` → `11.15.0`](https://renovatebot.com/diffs/npm/mermaid/11.13.0/11.15.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/mermaid/11.15.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/mermaid/11.13.0/11.15.0?slim=true) |

---

### Mermaid Gantt Charts are vulnerable to an Infinite Loop DoS
[CVE-2026-41150](https://nvd.nist.gov/vuln/detail/CVE-2026-41150) / [GHSA-6m6c-36f7-fhxh](https://github.com/advisories/GHSA-6m6c-36f7-fhxh)

<details>
<summary>More information</summary>

#### Details
##### Impact

Mermaid v11.14.0 and earlier are vulnerable to a denial-of-service attack when rendering gantt charts, if they use the [`excludes` attribute](https://mermaid.js.org/syntax/gantt.html?#excludes) to exclude all dates.

Example:

```
gantt
  excludes monday,tuesday,wednesday,thursday,friday,saturday,sunday
  DoS :2025-01-01, 1d
```

`mermaid.parse` is unaffected, unless you then call the `ganttDb.getTasks()` (which is called when rendering a diagram).

##### Patches

This has been patched in:

- [v11.15.0](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0) (see [faafb5d49106dd32c367f3882505f2dd625aa30e](faafb5d491))
- [v10.9.6](https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6) (see [a59ea56174712ee5430dfd5bc877cb5151f501a6](a59ea56174))

##### Workarounds

There are no workarounds available without updating to a newer version of mermaid.

#### Severity
- CVSS Score: 5.3 / 10 (Medium)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L`

#### References
- [https://github.com/mermaid-js/mermaid/security/advisories/GHSA-6m6c-36f7-fhxh](https://github.com/mermaid-js/mermaid/security/advisories/GHSA-6m6c-36f7-fhxh)
- [a59ea56174)
- [faafb5d491)
- [https://github.com/mermaid-js/mermaid](https://github.com/mermaid-js/mermaid)
- [https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0)
- [https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6](https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6)

This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-6m6c-36f7-fhxh) and the [GitHub Advisory Database](https://github.com/github/advisory-database) ([CC-BY 4.0](https://github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Mermaid: Improper sanitization of configuration leads to CSS injection
[CVE-2026-41159](https://nvd.nist.gov/vuln/detail/CVE-2026-41159) / [GHSA-87f9-hvmw-gh4p](https://github.com/advisories/GHSA-87f9-hvmw-gh4p)

<details>
<summary>More information</summary>

#### Details
##### Impact

Mermaid's default configuration allows injecting CSS that applies outside of the Mermaid diagram via the `fontFamily`, `themeCSS`, and `altFontFamily` configuration options.

Live demo: [mermaid.live](https://mermaid.live/edit#pako:eNpNjktLxDAUhf9KvFBR6JS-60QQfODKlUvJ5k6TtsEmKTHFGUP-u-mI6Nmdy3fOPR56wwVQSBIvtXSUeAaD0e4ZlZxPDChhcLxFfwiEauOuLq_9Afv30ZpVczpaITS5kGox1qF2gfSeBwYhJAnThAyz-ewntI68vG5-0z3Z7e7IA9OQwmglB-rsKlJQwircLPgNZeAmocTPAi4GXGfHgOkQYwvqN2PUbzJuGSegA84f0a0LRyeeJI4W_xChubCPcbQD2pwbgHo4Aq2aKmvbqq3zoiu7pizqFE6RybN9VFfFY1HWXRVS-Dr_zLObrt7_V_gGGXZlGg)

Example code:

```
%%{init: {"fontFamily": "x;a{b} :not(&){background:green !important} c{d}"}}%%
flowchart LR
    A --> B
```

The injected CSS exploits stylis's `&` (scope reference) handling. `:not(&)` escapes the `#mermaid-xxx` automatic scoping, applying styles to all page elements. Global at-rules (`@font-face`, `@keyframes`, `@counter-style`) are also injectable as stylis hoists them to top level.

This allows page defacement and DOM attribute exfiltration via CSS `:has()` selectors.

##### Patches

- [v11.15.0](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0) (see [64769738d5b59211e1decb471ffbaca8afec51aa](64769738d5))
- [v10.9.6](https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6) (see [a9d9f0d8eb790349121508688cd338253fd80d76](a9d9f0d8eb))

##### Workarounds

If you can't upgrade mermaid, you can set the [`secure`](https://mermaid.js.org/config/schema-docs/config.html#secure) config value in the mermaid config to avoid allowing diagrams to modify `fontFamily`, `themeCSS`, `altFontFamily`, and `themeVariables`.

Setting [`"securityLevel": "sandbox"`](https://mermaid.js.org/config/schema-docs/config.html#securitylevel)  will also prevent this.

##### Credits

Reported by @&#8203;zsxsoft on behalf of @&#8203;KeenSecurityLab

#### Severity
- CVSS Score: 5.3 / 10 (Medium)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:L/VA:N/SC:L/SI:L/SA:L`

#### References
- [https://github.com/mermaid-js/mermaid/security/advisories/GHSA-87f9-hvmw-gh4p](https://github.com/mermaid-js/mermaid/security/advisories/GHSA-87f9-hvmw-gh4p)
- [64769738d5)
- [a9d9f0d8eb)
- [https://github.com/mermaid-js/mermaid](https://github.com/mermaid-js/mermaid)
- [https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0)
- [https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6](https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6)

This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-87f9-hvmw-gh4p) and the [GitHub Advisory Database](https://github.com/github/advisory-database) ([CC-BY 4.0](https://github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Mermaid: Improper sanitization of `classDef` in state diagrams leads to HTML injection
[CVE-2026-41149](https://nvd.nist.gov/vuln/detail/CVE-2026-41149) / [GHSA-ghcm-xqfw-q4vr](https://github.com/advisories/GHSA-ghcm-xqfw-q4vr)

<details>
<summary>More information</summary>

#### Details
##### Impact

Under the default configuration, Mermaid state diagram's `classDef` allow DOM injection that escapes the SVG, although `<script>` tags are removed, preventing XSS.

##### Proof-of-concept

```
stateDiagram-v2
  classDef xss fill:red</style></svg><style>*{x:x;y:y;overflow:visible!important;contain:none!important;transform:none!important;filter:none!important;clip-path:none!important}</style><div style="x:x;y:y;color:red;font:5em/1 monospace;display:grid;place-items:center;z-index:2147483647;width:100vw;height:100vh;position:fixed;top:0;left:0;background:black">HACKED</div><svg><style>a:b
  [*] --> A:::xss
```

##### Patches

- [v11.15.0](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0) (see [37ff937f1da2e19f882fd1db01235db4d01f4056](37ff937f1d))
- [v10.9.6](https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6) (see [4e2d512bf5bf6f9de1a8f0a48da78dc4d09ac4f3](4e2d512bf5))

##### Workarounds

If you can not update to a patched version, setting [`"securityLevel": "sandbox"`](https://mermaid.js.org/config/schema-docs/config.html#securitylevel)  will prevent this, by rendering the mermaid diagram in a sandboxed `<iframe>`.

##### Credits

Thanks to @&#8203;zsxsoft from @&#8203;KeenSecurityLab for reporting this vulnerability.

#### Severity
- CVSS Score: 5.3 / 10 (Medium)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:L/VA:N/SC:L/SI:L/SA:L`

#### References
- [https://github.com/mermaid-js/mermaid/security/advisories/GHSA-ghcm-xqfw-q4vr](https://github.com/mermaid-js/mermaid/security/advisories/GHSA-ghcm-xqfw-q4vr)
- [37ff937f1d)
- [4e2d512bf5)
- [https://github.com/mermaid-js/mermaid](https://github.com/mermaid-js/mermaid)
- [https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0)
- [https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6](https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6)
- [https://mermaid.js.org/config/schema-docs/config.html#securitylevel](https://mermaid.js.org/config/schema-docs/config.html#securitylevel)

This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-ghcm-xqfw-q4vr) and the [GitHub Advisory Database](https://github.com/github/advisory-database) ([CC-BY 4.0](https://github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Mermaid: Improper sanitization of `classDefs` in diagrams leads to CSS injection
[CVE-2026-41148](https://nvd.nist.gov/vuln/detail/CVE-2026-41148) / [GHSA-xcj9-5m2h-648r](https://github.com/advisories/GHSA-xcj9-5m2h-648r)

<details>
<summary>More information</summary>

#### Details
##### Details

The state diagram and any other diagram type that routes user-controlled style strings through createCssStyles parser for Mermaid v11.14.0 and earlier captures `classDef` values with an unrestricted regex:

```jison
// packages/mermaid/src/diagrams/state/parser/stateDiagram.jison:83
<CLASSDEFID>[^\n]*   { this.popState(); return 'CLASSDEF_STYLEOPTS' }
```

The value passes unsanitized through `addStyleClass()` -> `createCssStyles()` -> `style.innerHTML` (mermaidAPI.ts:418). A `}` in the value closes the generated CSS selector, and everything after becomes a new CSS rule on the page.

##### PoC

```
stateDiagram-v2
      classDef x }*{ background-image: url("http://media.giphy.com/media/SggILpMXO7Xt6/giphy.gif")}
```

Live demo:
<https://mermaid.live/edit#pako:eNpFjzFvgzAQhf-KdVNbEcBgMHhtlkqtOnSJKi8ONsYKBmRMlRTx3-skanvTfbp7996t0IxSAYPZC6_2Rmgn7O4rQ00v5nmvWnRG29OKjqI5aTcug9wZK7RiaHH9A4fO-4kliVXSiFibqbvEzWjvnHxo_fI6vR3e6cGXyX2qTcvhcYMItDMSmHeLisAqZ8UVYeUDQhx8p6ziwEIrhTtx4MNVM4nhcxztrywE0h2wVvRzoGWS_z_8rahBKvcckntgmN5OAFvhDIzUNCZZQXCR5nVaZkUEF2BVFpOcEkoxxhUuyRbB980yjStapKHqoKFlhvPtB7BFZEU>

##### Patches

This has been patched in:

- [v11.15.0](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0) (see [e9b0f34d8d82a6260077764ee45e1d7d90957a0f](e9b0f34d8d))
- [v10.9.6](https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6) (see [8fead23c59166b7bab6a39eac81acebee2859102](8fead23c59))

##### Workarounds

Setting [`"securityLevel": "sandbox"`](https://mermaid.js.org/config/schema-docs/config.html#securitylevel)  will prevent this, by rendering the mermaid diagram in a sandboxed `<iframe>`.

##### Impact

 Enables page defacement, user tracking via `url()` callbacks, and DOM attribute exfiltration via CSS `:has()` selectors.

#### Severity
- CVSS Score: 5.3 / 10 (Medium)
- Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:L/VA:N/SC:L/SI:L/SA:L`

#### References
- [https://github.com/mermaid-js/mermaid/security/advisories/GHSA-xcj9-5m2h-648r](https://github.com/mermaid-js/mermaid/security/advisories/GHSA-xcj9-5m2h-648r)
- [8fead23c59)
- [e9b0f34d8d)
- [https://github.com/mermaid-js/mermaid](https://github.com/mermaid-js/mermaid)
- [https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0)
- [https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6](https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6)
- [https://mermaid.js.org/config/schema-docs/config.html#securitylevel](https://mermaid.js.org/config/schema-docs/config.html#securitylevel)

This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-xcj9-5m2h-648r) and the [GitHub Advisory Database](https://github.com/github/advisory-database) ([CC-BY 4.0](https://github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Release Notes

<details>
<summary>mermaid-js/mermaid (mermaid)</summary>

### [`v11.15.0`](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0)

[Compare Source](https://github.com/mermaid-js/mermaid/compare/mermaid@11.14.0...mermaid@11.15.0)

##### Minor Changes

- [#&#8203;7174](https://github.com/mermaid-js/mermaid/pull/7174) [`0aca217`](0aca21739c) Thanks [@&#8203;milesspencer35](https://github.com/milesspencer35)! - feat(sequence): Add support for decimal start and increment values in the `autonumber` directive

- [#&#8203;7512](https://github.com/mermaid-js/mermaid/pull/7512) [`8e17492`](8e17492f73) Thanks [@&#8203;aruncveli](https://github.com/aruncveli)! - feat(flowchart): add datastore shape

  In Data flow diagrams, a datastore/warehouse/file/database is used to represent data persistence. It is denoted by a rectangle with only top and bottom borders, and can be used in flowcharts with `A@{ shape: datastore, label: "Datastore" }`.

- [#&#8203;6440](https://github.com/mermaid-js/mermaid/pull/6440) [`9ad8dde`](9ad8dde6d0) Thanks [@&#8203;yordis](https://github.com/yordis), [@&#8203;lgazo](https://github.com/lgazo)! - feat: add Event Modeling diagram

- [#&#8203;7707](https://github.com/mermaid-js/mermaid/pull/7707) [`27db774`](27db774627) Thanks [@&#8203;txmxthy](https://github.com/txmxthy)! - feat(architecture): expose four fcose layout knobs for `architecture-beta` diagrams (`nodeSeparation`, `idealEdgeLengthMultiplier`, `edgeElasticity`, `numIter`) so authors can tune layout density and spread overlapping siblings without changing diagram source

- [#&#8203;7604](https://github.com/mermaid-js/mermaid/pull/7604) [`bf9502f`](bf9502fb60) Thanks [@&#8203;M-a-c](https://github.com/M-a-c)! - feat(class): add nested namespace support for class diagrams via dot notation and syntactic nesting

  If you have namespaces in class diagrams that use `.`s already and want to render them without nesting (≤v11.14.0 behaviour), you can use set `class.hierarchicalNamespaces=false` in your mermaid config:

  ```yaml
  config:
    class:
      hierarchicalNamespaces: false
  ```

- [#&#8203;7272](https://github.com/mermaid-js/mermaid/pull/7272) [`88cdd3d`](88cdd3dc0a) Thanks [@&#8203;xinbenlv](https://github.com/xinbenlv)! - feat(sankey): add outlined label style, configurable nodeWidth/nodePadding, and custom node colors

##### Patch Changes

- [#&#8203;7737](https://github.com/mermaid-js/mermaid/pull/7737) [`e9b0f34`](e9b0f34d8d) Thanks [@&#8203;ashishjain0512](https://github.com/ashishjain0512)! - fix: prevent unbalanced CSS styles in classDefs

- [#&#8203;7737](https://github.com/mermaid-js/mermaid/pull/7737) [`37ff937`](37ff937f1d) Thanks [@&#8203;ashishjain0512](https://github.com/ashishjain0512)! - fix: create CSS styles using the CSSOM

  This removes some invalid CSS and normalizes some CSS formatting.

- [#&#8203;7508](https://github.com/mermaid-js/mermaid/pull/7508) [`bfe60cc`](bfe60cc67b) Thanks [@&#8203;biiab](https://github.com/biiab)! - fix(stateDiagram): `end note` now only closes a note when used on a new line

- [#&#8203;7737](https://github.com/mermaid-js/mermaid/pull/7737) [`faafb5d`](faafb5d491) Thanks [@&#8203;ashishjain0512](https://github.com/ashishjain0512)! - fix(gantt): add iteration limit for `excludes` field

- [#&#8203;7737](https://github.com/mermaid-js/mermaid/pull/7737) [`65f8be2`](65f8be2a42) Thanks [@&#8203;ashishjain0512](https://github.com/ashishjain0512)! - fix: disallow some CSS at-rules in custom CSS

- [#&#8203;7726](https://github.com/mermaid-js/mermaid/pull/7726) [`1502f32`](1502f32f3c) Thanks [@&#8203;aloisklink](https://github.com/aloisklink)! - fix(wardley): fix unnecessary sanitization of text

- [#&#8203;7578](https://github.com/mermaid-js/mermaid/pull/7578) [`1f98db8`](1f98db8e32) Thanks [@&#8203;Gaston202](https://github.com/Gaston202)! - fix(class): self-referential class multiplicity labels no longer rendered multiple times

  Fixes [#&#8203;7560](https://github.com/mermaid-js/mermaid/issues/7560). Resolves an issue where cardinality labels on self-referential class relationships were rendered three times due to edge splitting in the dagre layout. The fix ensures that each sub-edge only carries its relevant label positions.

- [#&#8203;7592](https://github.com/mermaid-js/mermaid/pull/7592) [`2343e38`](2343e38498) Thanks [@&#8203;knsv-bot](https://github.com/knsv-bot)! - fix(sequence): add background box behind alt/else section title labels in sequence diagrams

- [#&#8203;7589](https://github.com/mermaid-js/mermaid/pull/7589) [`7fb9509`](7fb9509b8b) Thanks [@&#8203;NYCU-Chung](https://github.com/NYCU-Chung)! - fix(block): prevent column widths from shrinking when mixing different column spans

- [#&#8203;7632](https://github.com/mermaid-js/mermaid/pull/7632) [`3f9e0f1`](3f9e0f15be) Thanks [@&#8203;ekiauhce](https://github.com/ekiauhce)! - fix(sequence): correct messageAlign label position for right-to-left arrows in sequence diagrams

- [#&#8203;7642](https://github.com/mermaid-js/mermaid/pull/7642) [`7a8fb85`](7a8fb8532c) Thanks [@&#8203;tractorjuice](https://github.com/tractorjuice)! - fix(wardley): allow hyphens in unquoted component names

  Multi-word names containing hyphens — e.g. `real-time processing`, `end-user`, `on-call engineer` — now parse without quoting, bringing the grammar in line with the OnlineWardleyMaps (OWM) convention. `A->B` (no-space arrow) still tokenises correctly.

- [#&#8203;7523](https://github.com/mermaid-js/mermaid/pull/7523) [`5144ed4`](5144ed4b13) Thanks [@&#8203;darshanr0107](https://github.com/darshanr0107)! - fix(block): Arrow blocks in block-beta diagrams not spanning the specified number of columns when using `:n` syntax.

- [#&#8203;7262](https://github.com/mermaid-js/mermaid/pull/7262) [`13d9bfa`](13d9bfa474) Thanks [@&#8203;darshanr0107](https://github.com/darshanr0107)! - fix(block): Ensure block diagram hexagon blocks respect column spanning syntax

- [#&#8203;7684](https://github.com/mermaid-js/mermaid/pull/7684) [`e14bb88`](e14bb88bdb) Thanks [@&#8203;aloisklink](https://github.com/aloisklink)! - fix: loosen `uuid` dependency range to allow v14

  Mermaid does not use any of the vulnerable code in CVE-2026-41907,
  but this allows users to silence any `npm audit` alerts on it.

- [#&#8203;7633](https://github.com/mermaid-js/mermaid/pull/7633) [`9217c0d`](9217c0d8b2) Thanks [@&#8203;Felix-Garci](https://github.com/Felix-Garci)! - fix(block): add support for all arrow types in block diagrams

- [#&#8203;7587](https://github.com/mermaid-js/mermaid/pull/7587) [`5e7eb62`](5e7eb62e3a) Thanks [@&#8203;MaddyGuthridge](https://github.com/MaddyGuthridge)! - chore: drop lodash-es in favour of es-toolkit

- [#&#8203;7693](https://github.com/mermaid-js/mermaid/pull/7693) [`afaf306`](afaf306238) Thanks [@&#8203;dull-bird](https://github.com/dull-bird)! - fix(quadrant-chart): allow CJK, emoji, Latin-1 accented characters, and other non-ASCII text in unquoted axis/quadrant/point labels.

  Previously the lexer only matched ASCII `[A-Za-z]+` for text tokens, even though the grammar referenced `UNICODE_TEXT`. Bare Chinese, Japanese, Korean, emoji, and accented Latin characters in labels caused a parse error. Added a `[^\x00-\x7F]+` lexer rule to emit `UNICODE_TEXT` and included it in the `alphaNumToken` grammar rule.

  Fixes [#&#8203;7120](https://github.com/mermaid-js/mermaid/issues/7120).

- [#&#8203;7737](https://github.com/mermaid-js/mermaid/pull/7737) [`4755553`](4755553d5f) Thanks [@&#8203;ashishjain0512](https://github.com/ashishjain0512)! - fix: improve D3 types for mermaidAPI funcs

- [#&#8203;7737](https://github.com/mermaid-js/mermaid/pull/7737) [`6476973`](64769738d5) Thanks [@&#8203;ashishjain0512](https://github.com/ashishjain0512)! - fix: handle `&` when namespacing CSS rules

- [#&#8203;7520](https://github.com/mermaid-js/mermaid/pull/7520) [`8c1a0c1`](8c1a0c1fd1) Thanks [@&#8203;RodrigojndSantos](https://github.com/RodrigojndSantos)! - fix(stateDiagram): comments starting with one `%` are no longer treated as comments

  Switch to using two `%%` if you want to write a comment.

- Updated dependencies \[[`7a8fb85`](7a8fb8532c), [`675a64c`](675a64ca0e)]:
  - [@&#8203;mermaid-js/parser](https://github.com/mermaid-js/parser)@&#8203;1.1.1

### [`v11.14.0`](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.14.0)

[Compare Source](https://github.com/mermaid-js/mermaid/compare/mermaid@11.13.0...mermaid@11.14.0)

Thanks to our awesome mermaid community that contributed to this release: [@&#8203;ashishjain0512](https://github.com/ashishjain0512), [@&#8203;tractorjuice](https://github.com/tractorjuice), [@&#8203;autofix-ci\[bot\]](https://github.com/autofix-ci%5Bbot%5D), [@&#8203;aloisklink](https://github.com/aloisklink), [@&#8203;knsv](https://github.com/knsv), [@&#8203;kibanana](https://github.com/kibanana), [@&#8203;chandershekhar22](https://github.com/chandershekhar22), [@&#8203;khalil](https://github.com/khalil), [@&#8203;ytatsuno](https://github.com/ytatsuno), [@&#8203;sidharthv96](https://github.com/sidharthv96), [@&#8203;github-actions\[bot\]](https://github.com/github-actions%5Bbot%5D), [@&#8203;dripcoding](https://github.com/dripcoding), [@&#8203;knsv-bot](https://github.com/knsv-bot), [@&#8203;jeroensmink98](https://github.com/jeroensmink98), [@&#8203;Alex9583](https://github.com/Alex9583), [@&#8203;GhassenS](https://github.com/GhassenS), [@&#8203;omkarht](https://github.com/omkarht), [@&#8203;darshanr0107](https://github.com/darshanr0107), [@&#8203;leentaylor](https://github.com/leentaylor), [@&#8203;lee-treehouse](https://github.com/lee-treehouse), [@&#8203;veeceey](https://github.com/veeceey), [@&#8203;turntrout](https://github.com/turntrout), [@&#8203;Mermaid-Chart](https://github.com/Mermaid-Chart), [@&#8203;BambioGaming](https://github.com/BambioGaming), Claude

### Releases

#### [@&#8203;mermaid-js/examples](https://github.com/mermaid-js/examples)@&#8203;1.2.0

##### Minor Changes

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - add new TreeView diagram

#### mermaid\@&#8203;11.14.0

##### Minor Changes

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - Add Wardley Maps diagram type (beta)

  Adds Wardley Maps as a new diagram type to Mermaid (available as `wardley-beta`). Wardley Maps are visual representations of business strategy that help map value chains and component evolution.

  Features:

  - Component positioning with \[visibility, evolution] coordinates (OWM format)
  - Anchors for users/customers
  - Multiple link types: dependencies, flows, labeled links
  - Evolution arrows and trend indicators
  - Custom evolution stages with optional dual labels
  - Custom stage widths using [@&#8203;boundary](https://github.com/boundary) notation
  - Pipeline components with visibility inheritance
  - Annotations, notes, and visual elements
  - Source strategy markers: build, buy, outsource, market
  - Inertia indicators
  - Theme integration

  Implementation includes parser, D3.js renderer, unit tests, E2E tests, and comprehensive documentation.

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look styling for state diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look support for sequence diagrams with drop shadows, and enhanced styling

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: add `randomize` config option for architecture diagrams, defaulting to `false` for deterministic layout

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - feat: Add option to change timeline direction

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - Fix duplicate SVG element IDs when rendering multiple diagrams on the same page. Internal element IDs (nodes, edges, markers, clusters) are now prefixed with the diagram's SVG element ID across all diagram types. Custom CSS or JS using exact ID selectors like `#arrowhead` should use attribute-ending selectors like `[id$="-arrowhead"]` instead.

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look styling for ER diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look styling for requirement diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - feat: add theme support for data label colour in xy chart

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - feat: implement neo look styling for mindmap diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - feat: implement neo look for mermaid flowchart diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - feat: implement neo look and themes for class diagram

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - feat: add showDataLabelOutsideBar option for xy chart

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look support for timeline diagram with drop shadows, additoinal redux themes and enhanced styling

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look and themes for gitGraph diagram

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - add new TreeView diagram

##### Patch Changes

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - add link to ishikawa diagram on mermaid.js.org

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - docs: document valid duration token formats in gantt.md

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - fix: ER diagram parsing when using "1" as entity identifier on right side

  The parser was incorrectly tokenizing the second "1" in patterns like `a many to 1 1:` because the lookahead rule only checked for alphabetic characters after whitespace, not digits. Added a new lookahead pattern `"1"(?=\s+[0-9])` to correctly identify the cardinality alias before a numeric entity name.

  Fixes [#&#8203;7472](https://github.com/mermaid-js/mermaid/issues/7472)

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: scope cytoscape label style mapping to edges with labels to prevent console warnings

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - fix: support inline annotation syntax in class diagrams (class Shape <<interface>>)

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: Align branch label background with text for multi-line labels in LR GitGraph layout

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - fix: preserve cause hierarchy when ishikawa effect is indented more than causes

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - refactor: remove unused createGraphWithElements function and add regression test for open edge arrowheads

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: Prevent long pie chart titles from being clipped by expanding the viewBox

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - fix: prevent sequence diagram hang when "as" is used without a trailing space in participant declarations

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: warn when `style` statement targets a non-existent node in flowcharts

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - fix: group state diagram SVG children under single root <g> element

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - fix: Allow :::className syntax inside composite state blocks

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) Thanks [@&#8203;aloisklink](https://github.com/aloisklink), [@&#8203;BambioGaming](https://github.com/BambioGaming)! - fix: prevent escaping `<` and `&` when `htmlLabels: false`

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: treemap title and labels use theme-aware colors for dark backgrounds

- Updated dependencies \[[`efe218a`](efe218a47f)]:
  - [@&#8203;mermaid-js/parser](https://github.com/mermaid-js/parser)@&#8203;1.1.0

#### [@&#8203;mermaid-js/parser](https://github.com/mermaid-js/parser)@&#8203;1.1.0

##### Minor Changes

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - add new TreeView diagram

#### [@&#8203;mermaid-js/tiny](https://github.com/mermaid-js/tiny)@&#8203;11.14.0

##### Minor Changes

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - Add Wardley Maps diagram type (beta)

  Adds Wardley Maps as a new diagram type to Mermaid (available as `wardley-beta`). Wardley Maps are visual representations of business strategy that help map value chains and component evolution.

  Features:

  - Component positioning with \[visibility, evolution] coordinates (OWM format)
  - Anchors for users/customers
  - Multiple link types: dependencies, flows, labeled links
  - Evolution arrows and trend indicators
  - Custom evolution stages with optional dual labels
  - Custom stage widths using [@&#8203;boundary](https://github.com/boundary) notation
  - Pipeline components with visibility inheritance
  - Annotations, notes, and visual elements
  - Source strategy markers: build, buy, outsource, market
  - Inertia indicators
  - Theme integration

  Implementation includes parser, D3.js renderer, unit tests, E2E tests, and comprehensive documentation.

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - feat: implement neo look styling for state diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look support for sequence diagrams with drop shadows, and enhanced styling

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - feat: add `randomize` config option for architecture diagrams, defaulting to `false` for deterministic layout

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: Add option to change timeline direction

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) - Fix duplicate SVG element IDs when rendering multiple diagrams on the same page. Internal element IDs (nodes, edges, markers, clusters) are now prefixed with the diagram's SVG element ID across all diagram types. Custom CSS or JS using exact ID selectors like `#arrowhead` should use attribute-ending selectors like `[id$="-arrowhead"]` instead.

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look styling for ER diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look styling for requirement diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: add theme support for data label colour in xy chart

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look styling for mindmap diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look for mermaid flowchart diagrams

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look and themes for class diagram

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: add showDataLabelOutsideBar option for xy chart

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look support for timeline diagram with drop shadows, additoinal redux themes and enhanced styling

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - feat: implement neo look and themes for gitGraph diagram

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - add new TreeView diagram

##### Patch Changes

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - add link to ishikawa diagram on mermaid.js.org

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - docs: document valid duration token formats in gantt.md

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: ER diagram parsing when using "1" as entity identifier on right side

  The parser was incorrectly tokenizing the second "1" in patterns like `a many to 1 1:` because the lookahead rule only checked for alphabetic characters after whitespace, not digits. Added a new lookahead pattern `"1"(?=\s+[0-9])` to correctly identify the cardinality alias before a numeric entity name.

  Fixes [#&#8203;7472](https://github.com/mermaid-js/mermaid/issues/7472)

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: scope cytoscape label style mapping to edges with labels to prevent console warnings

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: support inline annotation syntax in class diagrams (class Shape <<interface>>)

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: Align branch label background with text for multi-line labels in LR GitGraph layout

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: preserve cause hierarchy when ishikawa effect is indented more than causes

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - refactor: remove unused createGraphWithElements function and add regression test for open edge arrowheads

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: Prevent long pie chart titles from being clipped by expanding the viewBox

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: prevent sequence diagram hang when "as" is used without a trailing space in participant declarations

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: warn when `style` statement targets a non-existent node in flowcharts

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: group state diagram SVG children under single root <g> element

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: Allow :::className syntax inside composite state blocks

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f) Thanks [@&#8203;aloisklink](https://github.com/aloisklink), [@&#8203;BambioGaming](https://github.com/BambioGaming)! - fix: prevent escaping `<` and `&` when `htmlLabels: false`

- [#&#8203;7526](https://github.com/mermaid-js/mermaid/pull/7526) [`efe218a`](efe218a47f)  - fix: treemap title and labels use theme-aware colors for dark backgrounds

- Updated dependencies \[[`efe218a`](efe218a47f)]:
  - [@&#8203;mermaid-js/parser](https://github.com/mermaid-js/parser)@&#8203;1.1.0

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - ""
- Automerge
  - Between 12:00 AM and 03:59 AM (`* 0-3 * * *`)

🚦 **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:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzAuMjAiLCJ1cGRhdGVkSW5WZXIiOiI0My4xNzAuMjAiLCJ0YXJnZXRCcmFuY2giOiJ2MTUuMC9mb3JnZWpvIiwibGFiZWxzIjpbImRlcGVuZGVuY3ktdXBncmFkZSIsInRlc3Qvbm90LW5lZWRlZCJdfQ==-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12531
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-05-12 03:56:15 +02:00
Mathieu Fenniak
75c3da0f92 [v15.0/forgejo] chore: PGP sign .well-known/security.txt [skip ci] (#12503)
Manual backport of #12502.

Sign the distributed version of `.well-known/security.txt`, just like https://forgejo.org/.well-known/security.txt is signed.

```
$ gpg --verify ./security.txt
gpg: Signature made Sat 09 May 2026 05:59:29 PM MDT
gpg:                using EDDSA key 1B638BDF10969D627926B8D9F585D0F99E1FB56F
gpg: Good signature from "Forgejo Security <security@forgejo.org>" [unknown]
Primary key fingerprint: 1B63 8BDF 1096 9D62 7926  B8D9 F585 D0F9 9E1F B56F
```

In the future this signature will have to be updated before the key expires; but as the expiry is already documented in the file this isn't significantly different than the current state.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12503
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-05-11 04:49:13 +02:00
limiting-factor
51866ad6b8 [v15.0/forgejo] fix: in actions_service cancelJobsForRun is bugous use killRun instead (#12492)
The conflict resolution is explained in the "Conflict" section of the commit message. I used `cherry-pick -x`. Here is the conflict for information (simple one).

```diff
unmerged   services/actions/schedule_tasks.go
@@@ -22,8 -22,7 +22,12 @@@ import

  	"code.forgejo.org/forgejo/runner/v12/act/jobparser"
  	act_model "code.forgejo.org/forgejo/runner/v12/act/model"
++<<<<<<< HEAD
 +	"github.com/robfig/cron/v3"
 +	"xorm.io/builder"
++=======
+ 	"github.com/gdgvda/cron"
++>>>>>>> b6af380324 (fix: in actions_service cancelJobsForRun is bugous use killRun instead)
  )

  // StartScheduleTasks start the task
```

---

**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12366

The cancelJobsForRun function is redundant with the killRun function
and has bugs:

- It does not use a transaction and may fail in a non-recoverable way
- It does not update the commit status of the run
- It does not set NeedRemoval to false if needed

Remove the cancelJobsForRun function and use killRun instead (fixing
forgejo/forgejo#12386). Both calls are covered by existing tests:

- TestCancelPreviousJobs
- TestCancelPreviousWithConcurrencyGroup

A new integration test TestActionsPullRequestTrustPushCancel is added
to verify that the NeedApproval field is set to false whenever a run
is cancelled (fixing forgejo/forgejo#12350).

Closes forgejo/forgejo#12350
Closes forgejo/forgejo#12386

(cherry picked from commit b6af380324)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12492
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-05-09 21:00:52 +02:00
Renovate Bot
ed2a3d8681 Update module golang.org/x/net to v0.53.0 [SECURITY] (v15.0/forgejo) (#12465)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12465
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-05-08 07:57:07 +02:00
forgejo-backport-action
2c5695cd12 [v15.0/forgejo] fix: Prevent unremovable review requests after submitting pending reviews (#12470)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12302

Some notes:
- I didn't write integration tests because it's a pure bugfix that addresses implementation details of the model layer.
  - I can see interpretations of "it involves interactions with a live Forgejo server" that would cover this PR, but they don't make sense to me in context.
  - If they are expected, please let me know!
- I didn't add anything to the documentation because it's a pure bugfix - the system should always have worked this way
  - there's no value in confusing people trying to figure out how the system works now with how it didn't work in the past
- However, there IS value in informing people who may have gotten bitten by this in the past, so I think a release note makes sense
- These fixes are closely related, and the changes small, so I decided to make just one PR.
  - From a user perspective, this is just one issue, and I think in terms of release notes, it makes more sense to have just this one.
  - But I can split it up if that's preferred, ofc
- Technically, fixing only one of the underlying issues would be enough. Since this is a case of invalid states being representable, it makes sense to both try to prevent it happening in the first place, and deal with it gracefully if it does happen.
  - At the very least, fixing #12245 is required unless we want to live with data generated in the past being broken

Fixes #12243
Fixes #12245

Co-authored-by: Thomas Kolar <thomas.kolar@uni-ak.ac.at>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12470
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-05-08 07:45:15 +02:00
forgejo-backport-action
e2eb0b4a86 [v15.0/forgejo] [pagure] ensure moving all commits in a pull request (#12467)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12433

While the changes were conveyed in the pull request in its entirety, the commit
history of a pull request having more than one commit was bugged and the log
would have shown just the presence of the most recent commit event, having the
entire changes contained in a pull request.

This is a problem that was mostly noticed in the closed pull request, so it is
not as bad as it looks. Even then, if we are migrating closed pull requests, we
should do it the right way. We do not want to retain these pull requests for
archival purposes if they are not accurate.

Signed-off-by: Akashdeep Dhar <akashdeep.dhar@gmail.com>

Fixes https://forge.fedoraproject.org/forge/forge/issues/556

Co-authored-by: Akashdeep Dhar <akashdeep.dhar@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12467
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-05-08 07:31:49 +02:00
forgejo-backport-action
a1222ebb5b [v15.0/forgejo] refactor: clarify four different outputs that authentication methods provide (#12468)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12231

#12202 began a refactor of Forgejo's authentication implementations by providing structured data on an authentication success.  However, error cases were maintained as-is in that refactor, leaving a complex situation: what does returning an error from an authentication method mean?; does it mean that the authentication failed, or that a server error occurred?  Can another authentication still be tried?

This PR changes authentication methods so that they can return one of four things:
- `AuthenticationSuccess` with an authentication result.
- `AuthenticationNotAttempted` which indicates that no credentials relevant for this authentication method were presented.  If every method returned `AuthenticationNotAttempted`, then you would have an unauthenticated access.
- `AuthenticationAttemptedIncorrectCredential` which indicates that credentials were present and failed validation -- a situation indicating a `401 Unauthorized`.
- `AuthenticationError` which indicates that an internal server error occurred and failed authentication -- indicating a `500 Internal Server Error`.

This paves the way for one more refactor coming next: `basic.go` and `oauth2.go` perform 3-4 different authentications each (access tokens, oauth JWTs, actions tokens, actions JWTs, and username/password).  With the capability to return these more precise responses, these authentication methods can be split up into separate logic that isn't intertwined together.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12468
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-05-08 07:31:33 +02:00
forgejo-backport-action
0aa1b45956 [v15.0/forgejo] refactor: change authentication to return structured data (#12462)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12202

Currently authentication methods return information in two forms: they return who was authenticated as a `*user_model.User`, and then they insert key-values into `ctx.Data` which has critical impact on how the authenticated request is treated.  This PR changes the authentication methods to return structured data in the form of an `AuthenticationResult`, with all the key-value information in `ctx.Data` being moved into methods on the `AuthenticationResult` interface.

Authentication workflows in Forgejo are a real mess.  This is the first step in trying to clean it up and make the code predictable and reasonable, and is both follow-up work that was identified from the repo-specific access tokens (where the `"ApiTokenReducer"` key-value was added), and is pre-requisite work to future JWT enhancements that are [being discussed](https://codeberg.org/forgejo/forgejo/issues/3571#issuecomment-13268004).

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12462
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-05-08 04:07:32 +02:00
forgejo-backport-action
9381a425f9 [v15.0/forgejo] fix: paginate team members list (#12461)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12447

Fixes #12103.

Paginate the list of team members on the page for that team.

Co-authored-by: Antonin Delpeuch <antonin@delpeuch.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12461
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-05-08 02:43:47 +02:00
Renovate Bot
91a44affa4 Update go toolchain directive to v1.26.3 (v15.0/forgejo) (#12456) 2026-05-07 21:57:50 +02:00
forgejo-backport-action
1b7b1e4fe5 [v15.0/forgejo] fix: make package cleanup work again (#12452)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12446

- Regression of forgejo/forgejo!11776 (and forgejo/forgejo!11881)
- Scope of the transaction is moved to a per-package cleanup rule basis.
This is also a enhancement for scaling (already deployed on Codeberg for a while).
- Package cleanup is now run with `RetryTx`, because rebuilding
  repository files runs `RetryTx` and it could indicate to retry the whole
  transaction.
- Previously it would error and say running `RetryTx` in a
  transaction was not possible, this is now possible. Nested `RetryTx` is
  always allowed, matching of which errors to retry is still the responsible
  of the inner `RetryTx`.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12452
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-05-07 19:44:33 +02:00
forgejo-backport-action
80476238ab [v15.0/forgejo] fix: cleanup data before migration retry (#12422)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12370

In the case you hit some API error (Github ratelimit was often a problem) or the instance restarted in the middle of your migration, you would be left with data on the disk and/or database. Upon retrying the migration the migration code would (rightfully) fail because it's trying to migrate stuff that already exists.

This was hit so often on Codeberg it was better to force people to delete and start whole migration process again: 28ee60c91f

Delete the repository data before retrying to solve this.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12422
2026-05-06 15:31:51 +02:00
forgejo-backport-action
d3dd397001 [v15.0/forgejo] fix: get tag must return the tag signature instead of commit signature (#12395)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12351

## Fix: `GET /api/v1/repos/{owner}/{repo}/git/tags/{sha}` returns empty verification for signed tags

### Problem

When an annotated tag is signed (GPG or SSH) but the underlying commit is **not** signed, the API endpoint `GET /repos/{owner}/{repo}/git/tags/{sha}` returns an empty `verification.signature` field.

This is because `ToAnnotatedTag` was calling `ToVerification(ctx, c)` with the **commit** object, which checks the commit's signature — not the tag's own signature. Since the commit is unsigned, the API returns `signature: ""` and `verified: false`.

This causes issues for tools that rely on the tag signature from the API to validate that a tag push event is from a trusted source.

### Fix

`ToAnnotatedTag` now checks if the tag has its own signature (`t.Signature != nil`). If so, it uses `ParseTagWithSignature` to verify the tag's signature and populates the `verification` field from the tag. Otherwise, it falls back to the commit signature (existing behavior for unsigned/lightweight tags).

Co-authored-by: steven.guiheux <steven.guiheux@ovhcloud.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12395
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-05-03 06:38:17 +02:00
forgejo-backport-action
b2c9c14dea [v15.0/forgejo] fix: set repo_id for migrated attachment (#12362)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12357

Was not required until ce0a376723 added extra checks which did require `repo_id` of the attachment to be set correctly.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12362
2026-05-01 03:42:32 +02:00
forgejo-backport-action
4f44317622 [v15.0/forgejo] fix(oauth): only accept refresh tokens as refresh tokens (#12354)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12291

`handleRefreshToken` never checked `token.Type == TypeRefreshToken`. When
`InvalidateRefreshTokens` is disabled, an access token could be submitted as a
`refresh_token` and exchanged for a new token pair.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: jvoisin <jvoisin@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12354
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-04-30 20:10:43 +02:00
forgejo-backport-action
64c30d8034 [v15.0/forgejo] Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.6.0 (forgejo) (#12317)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12156

Co-authored-by: Renovate Bot <bot@kriese.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12317
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2026-04-29 08:26:24 +02:00
Mathieu Fenniak
fdd794abe3 [v15.0/forgejo] fix: verify PR author has write access to head to support allow maintainers edit (#12293)
Backport: https://codeberg.org/forgejo/forgejo/pulls/12292

When a pull request is opened, the author is able to mark that pull request to "Allow edits from maintainers", which grants the maintainers of the pull request's repo access to edit the pull request branch contents.  It is possible to create a pull request where the pull request author does not have the ability to edit the pull request branch.  Due to a missing security check for this case, maintainers of the pull request repo would be granted the ability to edit the pull request branch, even if the author of the pull request did not have that ability.  By exploiting this missing security check, a user can edit any branch in a repository if they're able to fork that repository.  The issue is being fixed by restricting the scope of "Allow edits from maintainers" to only grant that access if the pull request author also had access to edit the branch.

Thanks to Arvin Shivram of Brutecat Security for discovering and responsibly disclosing the vulnerability.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12293
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
2026-04-29 05:28:56 +02:00
0ko
b05e3eb55f merge commit: [v15.0/forgejo] i18n: backport of translations from Codeberg Translate (#12306)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12306
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2026-04-28 20:31:57 +02:00
0ko
0c1f3851da [v15.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v15 branch were picked from this commit:
5e5ad79d10

Changes to strings that are only present in the newer branches were not picked.

Below is a list of co-authors of the ported commit. It may contain co-authors who's changes were not picked due to only being relevant to newer branches.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: AshyPinguin <ashypinguin@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Fjuro <fjuro@noreply.codeberg.org>
Co-authored-by: Goudarz Jafari <goudarz.jafari@gmail.com>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: Lauri Lepik <laurilepik@noreply.codeberg.org>
Co-authored-by: Lzebulon <lzebulon@noreply.codeberg.org>
Co-authored-by: PatoFlamejanteTV <patoflamejantetv@noreply.codeberg.org>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: TAGerritsen <tagerritsen@noreply.codeberg.org>
Co-authored-by: Tamil <tamil@noreply.codeberg.org>
Co-authored-by: Wuzzy <wuzzy@disroot.org>
Co-authored-by: arifpedia <arifpedia@gmail.com>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: augustd <augustd@noreply.codeberg.org>
Co-authored-by: fserrador <fserrador@noreply.codeberg.org>
Co-authored-by: gallegonovato <gallegonovato@noreply.codeberg.org>
Co-authored-by: mahlzahn <mahlzahn@posteo.de>
Co-authored-by: rdeavila <rdeavila@noreply.codeberg.org>
Co-authored-by: universish <universish@noreply.codeberg.org>
Co-authored-by: vmtj <vmtj@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
2026-04-28 22:27:43 +05:00
forgejo-backport-action
2b692f2f5c [v15.0/forgejo] fix: allow viewing Actions run triggered by deleted user (#12272)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12271

Fixes #9371.  Manually reproduced and tested by setting `action_run.triggering_user_id` to a non-existent user ID.  Manually tested that runs can be cancelled in this state as well.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12272
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-04-26 16:00:57 +02:00
Renovate Bot
483b99889b Update dependency postcss to v8.5.10 [SECURITY] (v15.0/forgejo) (#12255)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12255
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-04-24 19:56:09 +02:00
Renovate Bot
eedf05f897 Update module github.com/jackc/pgx/v5 to v5.9.2 [SECURITY] (v15.0/forgejo) (#12235)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12235
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-04-23 16:04:34 +02:00
forgejo-backport-action
ab9856c92d [v15.0/forgejo] fix: compare branches with names diff or patch (#12233)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12227

Closes: Codeberg/Community#2538
Regression of: !5385

Co-authored-by: Robert Wolff <mahlzahn@posteo.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12233
Reviewed-by: Robert Wolff <mahlzahn@posteo.de>
2026-04-23 01:28:54 +02:00
forgejo-backport-action
2bd5fcbd2a [v15.0/forgejo] fix: resolve outer workflow call to success, not failure, on inner job skip (#12229)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12224

If one or more of a workflow expansion's inner jobs are status "skipped", consider that as a success, rather than a failure.  Fixes https://code.forgejo.org/forgejo/runner/issues/1490.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12229
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-04-22 20:40:54 +02:00
Renovate Bot
d3b0d7f8c2 Update module golang.org/x/image to v0.39.0 (v15.0/forgejo) (#12218)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12218
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-04-22 00:03:55 +02:00
forgejo-backport-action
f47ed4c45e [v15.0/forgejo] fix: secret name-prefix regex (#12216)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12213

Fixes: #12212
Sorry for this bug, I introduced it by not testing !10682 better. Now the `forbiddenPrefixPattern`-regex is compliant to the docu:
```
It cannot start with FORGEJO_, GITEA_, GITHUB_, or a number.
```

Co-authored-by: zokki <zokki.softwareschmiede@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12216
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-21 20:52:57 +02:00
forgejo-backport-action
2ba190f562 [v15.0/forgejo] fix(ui): allow creating files with name starting with dash (#12215)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12214

Closes: #12204

The underlying git option was already changed in git 2.0.0 to use format `<mode>,<object>,<path>`. See ec160ae12b.

Co-authored-by: Robert Wolff <mahlzahn@posteo.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12215
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-21 20:34:37 +02:00
forgejo-backport-action
7aa4b29d56 [v15.0/forgejo] fix: CodeMirror e2e test (#12199)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12151

I tried a lot, but this seems to work. I know it is ugly, but checking and waiting after every action seems to make it stable. At least it succeeded five times in a row and the CI seemed to be under load due to the dependency updates. Maybe it is worth a try...

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12199
Reviewed-by: Beowulf <beowulf@beocode.eu>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-20 14:23:22 +02:00
forgejo-backport-action
4a97de08f4 [v15.0/forgejo] fix(i18n): don't log harmless missing translations as errors (#12185)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12183

Followup to https://codeberg.org/forgejo/forgejo/pulls/6203

Currently it is logging an error wherever a template is rendered in language that doesn't have all plural strings covered. For example, Esperanto isn't well maintained.

Since more plural strings were migrated in v15 to new format, these errors became much more common. However, for all languages but the base one (English) they are completely harmless and just indicate an incomplete translation.

However, for base (English) they indicate a bug in either template or en-US.json, which should be still logged as an error.

The error is being logged by `LookupPluralByForm`, which is called by `TrPluralStringAllForms` and (`TrPluralString` through `LookupPluralByCount`). I originally intended to just pass log func directly to `LookupPluralByForm` from both, but since `TrPluralString` isn't calling `LookupPluralByForm` directly, it didn't look clean, so I went with passing a flag around instead and implemented logging logic in `LookupPluralByForm` itself.

I little concern is with that the so-called "default lang" is configurable, and if it is configured to something with less than 100% completion, it will cause fallback bugs, as well as a lot of logging of this as an error. But this is why changing "default lang" is a bad idea in the first place, and broken fallbacks should be greater concern than junk in the logs.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12185
Reviewed-by: Beowulf <beowulf@beocode.eu>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-19 01:46:40 +02:00
Renovate Bot
b57ea8239e Update github.com/go-git/go-git/v5 (indirect) to v5.18.0 [SECURITY] (v15.0/forgejo) (#12177)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) | `v5.17.1` → `v5.18.0` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgo-git%2fgo-git%2fv5/v5.18.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fgo-git%2fgo-git%2fv5/v5.17.1/v5.18.0?slim=true) |

---

### go-git: Credential leak via cross-host redirect in smart HTTP transport
[GHSA-3xc5-wrhm-f963](https://github.com/advisories/GHSA-3xc5-wrhm-f963)

<details>
<summary>More information</summary>

#### Details
##### Impact
`go-git` may leak HTTP authentication credentials when following redirects during smart-HTTP clone and fetch operations.

If a remote repository responds to the initial `/info/refs` request with a redirect to a different host, go-git updates the session endpoint to the redirected location and reuses the original authentication for subsequent requests. This can result in the credentials (e.g. Authorization headers) being sent to an unintended host.

An attacker controlling or influencing the redirect target can capture these credentials and potentially reuse them to access the victim’s repositories or other resources, depending on the scope of the credential.

**Clients using `go-git` exclusively with trusted remotes (for example, GitHub or GitLab), and over a secure HTTPS connection, are not affected by this issue.** The risk arises when interacting with untrusted or misconfigured Git servers, or when using unsecured HTTP connections, which is not recommended. Such configurations also expose clients to a broader class of security risks beyond this issue, including credential interception and tampering of repository data.

##### Patches
Users should upgrade to `v5.18.0`, or `v6.0.0-alpha.2`, in order to mitigate this vulnerability. Versions prior to v5 are likely to be affected, users are recommended to upgrade to a supported `go-git` version.

The patched versions add support for configuring [followRedirects](https://git-scm.com/docs/git-config#Documentation/git-config.txt-httpfollowRedirects). In line with upstream behaviour, the default is now `initial`, while users can opt into `FollowRedirects` or `NoFollowRedirects` programmatically.

##### Credit
Thanks to the 3 separate reports from @&#8203;celinke97, @&#8203;N0zoM1z0 and @&#8203;AyushParkara. Thanks for finding and reporting this issue privately to the `go-git` project. 🙇

#### Severity
- CVSS Score: 4.7 / 10 (Medium)
- Vector String: `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:N/A:N`

#### References
- [https://github.com/go-git/go-git/security/advisories/GHSA-3xc5-wrhm-f963](https://github.com/go-git/go-git/security/advisories/GHSA-3xc5-wrhm-f963)
- [https://github.com/go-git/go-git](https://github.com/go-git/go-git)

This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-3xc5-wrhm-f963) and the [GitHub Advisory Database](https://github.com/github/advisory-database) ([CC-BY 4.0](https://github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Release Notes

<details>
<summary>go-git/go-git (github.com/go-git/go-git/v5)</summary>

### [`v5.18.0`](https://github.com/go-git/go-git/releases/tag/v5.18.0)

[Compare Source](https://github.com/go-git/go-git/compare/v5.17.2...v5.18.0)

#### What's Changed

- plumbing: transport/http, Add support for followRedirects policy by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;2004](https://github.com/go-git/go-git/pull/2004)

**Full Changelog**: <https://github.com/go-git/go-git/compare/v5.17.2...v5.18.0>

### [`v5.17.2`](https://github.com/go-git/go-git/releases/tag/v5.17.2)

[Compare Source](https://github.com/go-git/go-git/compare/v5.17.1...v5.17.2)

#### What's Changed

- build: Update module github.com/go-git/go-git/v5 to v5.17.1 \[SECURITY] (releases/v5.x) by [@&#8203;go-git-renovate](https://github.com/go-git-renovate)\[bot] in [#&#8203;1941](https://github.com/go-git/go-git/pull/1941)
- dotgit: skip writing pack files that already exist on disk by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;1944](https://github.com/go-git/go-git/pull/1944)

⚠️ This release fixes a bug ([#&#8203;1942](https://github.com/go-git/go-git/issues/1942)) that blocked some users from upgrading to `v5.17.1`. Thanks [@&#8203;pskrbasu](https://github.com/pskrbasu) for reporting it. 🙇

**Full Changelog**: <https://github.com/go-git/go-git/compare/v5.17.1...v5.17.2>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - ""
- Automerge
  - Between 12:00 AM and 03:59 AM (`* 0-3 * * *`)

🚦 **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:eyJjcmVhdGVkSW5WZXIiOiI0My4xMTEuMCIsInVwZGF0ZWRJblZlciI6IjQzLjExMS4wIiwidGFyZ2V0QnJhbmNoIjoidjE1LjAvZm9yZ2VqbyIsImxhYmVscyI6WyJkZXBlbmRlbmN5LXVwZ3JhZGUiLCJ0ZXN0L25vdC1uZWVkZWQiXX0=-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12177
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-04-18 05:09:31 +02:00
forgejo-backport-action
7c50c5e684 [v15.0/forgejo] fix: always include files set to be detectable for language stats (#12171)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11685

- The documentation has the correct behavior about `linguist-detectable`: In cases where a file should be considered for language statistics, regardless of its category, the linguist-detectable attribute can be used.
- This patch follows that behavior by not skipping the file even if some heuristic would've said to skip the file.
- Document the conditions in more natural language.
- Resolves forgejo/forgejo#11248

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12171
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-18 01:59:11 +02:00
forgejo-backport-action
facbdef3c1 [v15.0/forgejo] Exclude SSH certificate principals from output when viewing user's SSH keys (#12166)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12079

Fixes #11590

When viewing a user's SSH keys, SSH principals are now excluded from the output.  This would previously either result in a panic in [OmitEmail](cfd4d53e32/models/asymkey/ssh_key.go (L67)), if the principal name didn't contain any spaces, or truncate the principal name, if it did contain spaces.

The TestExportUserSSHKeys test was also updated and fails if the fix(commit cfcbc33af0) is reverted.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing
  - [x] `make test`
  - [x] `make test-sqlite#TestExportUserSSHKeys`

I have also manually tested the change.

The full integration tests(`make test-sqlite`) report some errors, but I get the same errors without this PR(tested on commit [6a5dda7116](6a5dda7116)).

I have not tested with the other database backends.

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/12166): <!--number 12166 --><!--line 0 --><!--description RXhjbHVkZSBTU0ggY2VydGlmaWNhdGUgcHJpbmNpcGFscyBmcm9tIG91dHB1dCB3aGVuIHZpZXdpbmcgdXNlcidzIFNTSCBrZXlz-->Exclude SSH certificate principals from output when viewing user's SSH keys<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Alec Walsh <code@alecwalsh.name>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12166
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-17 21:34:12 +02:00
Mathieu Fenniak
081941c0fb [v15.0/forgejo] chore: bump xorm to v1.3.9-forgejo.11 (#12154)
**Backport**: #12153

Should fix intermittent test failures in Forgejo's integration test suite, in [`TestPackageDebianConcurrent`](https://codeberg.org/forgejo-integration/forgejo/actions/runs/16661/jobs/3/attempt/1#jobstep-5-1271), where this error is occurring.  Backported to v15 as the same test is present there, to keep the LTS tests healthy.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12154
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2026-04-17 02:28:45 +02:00
forgejo-backport-action
0403a38217 [v15.0/forgejo] fix: make /repos/search?uid=-2 return zero results, no repos with that owner (#12150)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12144

API calls to `.../api/v1/repos/search?uid=-2&archived=false` currently do not apply the filter `uid` because of the negative value.  This can occur when APIs are interacting with `${{ forgejo.token }}` and believe they're operating as the Forgejo Actions user, which has UID -2.

In combination with the security checks that occur in the `/repos/search` API to validate that repositories accessed are visible to the user, this can result in 500 error responses when a more correct expectation would be to receive no repositories:

da8898822c/routers/api/v1/repo/repo.go (L237-L242)

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12150
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-16 21:00:50 +02:00
forgejo-backport-action
b7319ea4a6 [v15.0/forgejo] fix: continued API response processing after error in /repos/search API (#12147)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12143

Prevent continued execution of some APIs with error responses that didn't correctly interrupt execution, resulting in bizarre outputs and possibly leaking secure data:

```
> GET /api/v1/repos/search?uid=-2&archived=false HTTP/2
> Host: example.org
> user-agent: curl/7.88.1
> accept: */*
> authorization: bearer ***
>
< HTTP/2 500
< server: nginx
< date: Thu, 16 Apr 2026 14:20:09 GMT
< content-type: application/json;charset=utf-8
< cache-control: max-age=0, private, must-revalidate, no-transform
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
<
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"message":"","url":"https://example.org/api/swagger"}
{"ok":true,"data":[{"id":68,"owner":{"id":1,"login":"mfenniak", ...
```

As these errors only occur on situations that shouldn't be reproducible (minus software bugs), test automation isn't practical.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [ ] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12147
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-16 19:05:38 +02:00
forgejo-backport-action
f25747d0f6 [v15.0/forgejo] chore(Dockerfile.rootless): update shadowed env variables (#12137)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11720

This was missed in https://codeberg.org/forgejo/forgejo/pulls/11098.

See https://github.com/go-gitea/gitea/pull/17846 for why this was added in the first place.

Note that this is not backwards compatible. For users with a custom `app.ini`-config this won't work. But it also didn't work with the previous config. This change only aligns it with the default app.ini-path.

I guess this needs some more discussion.

Co-authored-by: jaylinski <jaylinski@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12137
Reviewed-by: Beowulf <beowulf@beocode.eu>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-16 10:44:47 +02:00
forgejo-backport-action
acfea14f20 [v15.0/forgejo] chore: fix TestMirrorPull on older git (2.34.1) installation (#12136)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12134

`TestMirrorPull` is currently failing when run on git 2.34.1 in the `testing-integration.yml` workflow: https://codeberg.org/forgejo-integration/forgejo/actions/runs/16661/jobs/1/attempt/1#jobstep-5-2539  Began to fail after #11909 when additional checks on pull mirror configuration was added.

This PR addresses the issue and has been manually tested against the same git version:
```
$ git --version
git version 2.34.1

$ make test-sqlite#TestMirrorPull 2>&1
...
=== TestMirrorPull/migrate_from_repo_config_credentials (tests/integration/mirror_pull_test.go:238)
PASS
```

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12136
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-16 03:15:48 +02:00
forgejo-backport-action
1fe8a91202 [v15.0/forgejo] chore: fix cookie name comments in example ini (#12132)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12131

See: https://codeberg.org/forgejo/forgejo/pulls/10645#issuecomment-13135707

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12132
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-15 23:26:05 +02:00
Beowulf
7530fac1a5 [v15.0/forgejo] i18n: backport of translations from Codeberg Translate (#12129)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12129
Reviewed-by: Beowulf <beowulf@beocode.eu>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2026-04-15 22:43:16 +02:00
forgejo-backport-action
a6b29a65a8 [v15.0/forgejo] fix: improve runner list and details view (#12130)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12113

- shrink runner list width (use icons, move details link to runner name)
- add owner to runner details on admin view
- #11516 removed a lot details which makes it much harder for an admin to find a specific runner

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12130
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-15 22:07:25 +02:00
0ko
7b90e4bdec [v15.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v15 branch were picked from this commit:
88a0551f54

Changes to strings that are only present in the v16 branch were not picked.

Below is a list of co-authors of the ported commit. It may contain co-authors who's changes were not picked due to only being relevant to v16.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@noreply.codeberg.org>
Co-authored-by: AshyPinguin <ashypinguin@noreply.codeberg.org>
Co-authored-by: Atalanttore <atalanttore@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Coral Pink <coral.pink@disr.it>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@noreply.codeberg.org>
Co-authored-by: Lzebulon <lzebulon@noreply.codeberg.org>
Co-authored-by: Shadow_Glider <shadow_glider@noreply.codeberg.org>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Vyxie <kitakita@disroot.org>
Co-authored-by: Wuzzy <wuzzy@disroot.org>
Co-authored-by: Zughy <zughy@noreply.codeberg.org>
Co-authored-by: alissonlauffer <alissonlauffer@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: augustd <augustd@noreply.codeberg.org>
Co-authored-by: bahrom04 <bahrom04@noreply.codeberg.org>
Co-authored-by: bittin <bittin@noreply.codeberg.org>
Co-authored-by: butterflyoffire <butterflyoffire@noreply.codeberg.org>
Co-authored-by: cirilla <cirilla@noreply.codeberg.org>
Co-authored-by: hanklank <hanklank@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: kwoot <kwoot@noreply.codeberg.org>
Co-authored-by: mahlzahn <mahlzahn@posteo.de>
Co-authored-by: michi-onl <michi-onl@noreply.codeberg.org>
Co-authored-by: mkljczk <mkljczk@noreply.codeberg.org>
Co-authored-by: ospalh <ospalh@noreply.codeberg.org>
Co-authored-by: pakus <pakus@noreply.codeberg.org>
Co-authored-by: pixelcode <pixelcode@noreply.codeberg.org>
Co-authored-by: vmtj <vmtj@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
2026-04-15 22:37:40 +05:00
0ko
83d5137efd [v15.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v15 branch were picked from this commit:
728936ccd9

Changes to strings that are only present in the v16 branch were not picked.

Below is a list of co-authors of the ported commit. It may contain co-authors who's changes were not picked due to only being relevant to v16.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: AndreiSerban <andreiserban@noreply.codeberg.org>
Co-authored-by: AshyPinguin <ashypinguin@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Fjuro <fjuro@noreply.codeberg.org>
Co-authored-by: Languages add-on <noreply-addon-languages@weblate.org>
Co-authored-by: Lzebulon <lzebulon@noreply.codeberg.org>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Wuzzy <wuzzy@disroot.org>
Co-authored-by: Yago Raña Gayoso <yago.rana.gayoso@gmail.com>
Co-authored-by: bittin <bittin@noreply.codeberg.org>
Co-authored-by: dyniec <dyniec@noreply.codeberg.org>
Co-authored-by: hanklank <hanklank@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: krisfremen <krisfremen@noreply.codeberg.org>
Co-authored-by: mahlzahn <mahlzahn@posteo.de>
Co-authored-by: main_void <main_void@noreply.codeberg.org>
Co-authored-by: markinosags <markinosags@noreply.codeberg.org>
Co-authored-by: sindrenm <sindrenm@noreply.codeberg.org>
Co-authored-by: vitoravelino <vitoravelino@noreply.codeberg.org>
Co-authored-by: vmtj <vmtj@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
Co-authored-by: yeager <yeager@noreply.codeberg.org>
2026-04-15 22:37:01 +05:00
0ko
e7e0c18841 [v15.0/forgejo] fix(ui): a few small runners UI fixes (#12114)
Followup to https://codeberg.org/forgejo/forgejo/pulls/11516.

v15-specific backport of https://codeberg.org/forgejo/forgejo/pulls/12115 fixing all i18n strings in-place.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12114
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-04-14 18:50:08 +02:00
forgejo-backport-action
36bf4722a2 [v15.0/forgejo] i18n(mailer): Fix special usage of .Locale in admin_new_user (#12112)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12009

This PR is in reaction to https://codeberg.org/forgejo/forgejo/issues/1711 .

Co-authored-by: Έλλεν Εμίλια Άννα Zscheile <fogti+devel@ytrizja.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12112
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-14 07:22:44 +02:00
Mathieu Fenniak
c8156fbc60 [v15.0/forgejo] Revert "Improve repo file list table semantics for screen readers (#12031)" (#12094)
This reverts commit d76d6f24ce / #12031 to address the problem in #12082.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12094
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2026-04-12 03:25:15 +02:00
forgejo-backport-action
3f65795f4d [v15.0/forgejo] fix: prevent jobs with unknown needs from running (#12077)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12046

If Forgejo encounters an Actions workflow with unknown jobs in a needs definition, Forgejo will ignore those and run the job anyway. That is bad. For example, releases could be published without any testing because the name of the testing job was misspelt.

Workflow that demonstrates the problem:

```yaml
on:
  push:
  workflow_dispatch:
jobs:
  build:
    runs-on: debian
    steps:
      - run: |
          echo "OK"
  test:
    runs-on: debian
    needs: [does-not-exist]
    steps:
      - run: |
          echo "OK"
```

Now, before a workflow is run, Forgejo will check whether all jobs referenced in `needs` exist. If any of them does not, it raises a pre-execution error which fails the workflow immediately. It also displays an appropriate error to the user, for example:

```
Workflow was not executed due to an error that blocked the execution attempt.
Job with ID test references unknown jobs in `needs`: does-not-exist.
```

Futhermore, workflows with pre-execution errors can no longer be rerun, which was previously possible.

Original issue: https://code.forgejo.org/forgejo/runner/issues/977.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Tests for JavaScript changes

(can be removed for Go changes)

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12077
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-10 18:22:49 +02:00
forgejo-backport-action
f777d93ebd [v15.0/forgejo] fix: display runner version on details page (#12063)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12059

Display the version of Forgejo Runner on the runner's detail page. That is useful for diagnostics.

Originally, the version was displayed on the overview page, but removed in https://codeberg.org/forgejo/forgejo/pulls/11516 due to space constraints. It should have been moved to the details page, but that never happened.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Tests for JavaScript changes

(can be removed for Go changes)

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [x] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12063
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-09 17:57:49 +02:00
forgejo-backport-action
0af89931e2 [v15.0/forgejo] Revert "fix: add challenge for HTTP Basic Authentication to container registry" (#12060)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12058

This reverts commit 79ed45d39a.

Testing has shown that it breaks Docker 26 which is the version included in Debian Trixie.

It was originally introduced with https://codeberg.org/forgejo/forgejo/pulls/11678.

Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12060
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-09 13:08:58 +02:00
forgejo-backport-action
085d449bc5 [v15.0/forgejo] Preserve focus on star/unstar & watch/unwatch buttons after click (#12033)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11932

Fixes https://codeberg.org/forgejo/forgejo/issues/11880.

Adding `hx-on::after-settle="this.querySelector('button').focus()"` restores focus after the content has been swapped and the DOM has been setled. I tried `hx-on::after-swap` first since it's mentioned more often in https://github.com/bigskysoftware/htmx/issues/1869, but it didn't work.

The demo attached in `focus.mp4` runs through a series of repeated clicks on both buttons. You can hear the screen reader announce the button's new label when focus is restored.

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/12033): <!--number 12033 --><!--line 0 --><!--description UHJlc2VydmUgZm9jdXMgb24gc3Rhci91bnN0YXIgJiB3YXRjaC91bndhdGNoIGJ1dHRvbnMgYWZ0ZXIgY2xpY2s=-->Preserve focus on star/unstar & watch/unwatch buttons after click<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Henry Catalini Smith <henry@catalinismith.se>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12033
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-08 21:47:06 +02:00
forgejo-backport-action
d76d6f24ce [v15.0/forgejo] Improve repo file list table semantics for screen readers (#12031)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11846

https://codeberg.org/forgejo/forgejo/issues/11116

To understand the impact of this you really need to listen to the before and after screen recordings attached. https://codeberg.org/forgejo/forgejo/issues/11116 is a really great bug report, and I was surprised by how disorienting this actually was when testing manually compared to my expectation after reading the issue. This is an impactful improvement!

This is my first time adding new translation strings. Excited to learn more about that if I've guessed wrong about how to do it.

To summarise, what we're doing here is as follows.

1. Address the core issue by changing the existing `<th>` elements to `<td>` so that screen readers stop semantically associating them with each row and reading them out for every table cell.
2. Replace them with real `<th>` elements that communicate the true semantic role of each column.
3. Add a `<caption>`. This serves a dual purpose: it gives the table an accessible name which improves the navigability of the page, and it gives us a place to explain to the user that the first row of the table is a little bit different because it's the latest commit rather than a file in the repo.
4. Visually hide the new caption and headings so that only screen reader users get them.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for JavaScript changes

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/12031): <!--number 12031 --><!--line 0 --><!--description SW1wcm92ZSByZXBvIGZpbGUgbGlzdCB0YWJsZSBzZW1hbnRpY3MgZm9yIHNjcmVlbiByZWFkZXJz-->Improve repo file list table semantics for screen readers<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Henry Catalini Smith <henry@catalinismith.se>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12031
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-08 21:14:39 +02:00
forgejo-backport-action
50a30eb54f [v15.0/forgejo] fix: incorrect identification of outdated run attempts (#12044)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12021

Since https://codeberg.org/forgejo/forgejo/pulls/11750, the attempt number of a Forgejo Actions job is set eagerly. When an job is ultimately not run, for example, because its `needs` weren't satisfied, it leads to discontinuous attempt numbers of completed attempts that the component for viewing action logs could not handle. This has been rectified by actually determining the number of the last attempt.

Resolves https://codeberg.org/forgejo/forgejo/issues/11994.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Tests for JavaScript changes

(can be removed for Go changes)

- I added test coverage for JavaScript changes...
  - [x] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12044
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-08 21:12:56 +02:00
forgejo-backport-action
3e17afc266 [v15.0/forgejo] fix(doctor): remove broken mergebase check (#12040)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12023

Fixes https://codeberg.org/forgejo/forgejo/issues/6163
Fixes https://codeberg.org/forgejo/forgejo/issues/3343

The merge base doctor check & fix was broken and could introduce irreversible "fixes" to wrong merge bases for PRs using the `fast-forward` and `rebase-and-merge` strategies.

The mergebase fix was originally introduced in a migration [0] to fix an existing issue [1] in the merge code in 2020.
Later added as a doctor command without explanation [2].

We decided to remove this check, as there is no apparent reason for it to still be necessary or any PR merge base state being out of sync with the current implementation.
It does more harm to keep the code in and there is no way to fix `fast-forward` and `rebase-and-merge` PRs, due to their merge implementation.

`fast-forward`: The git state inherently cannot reconstruct a merge base in this scenario by design.
`rebase-and-merge`: Is rebased on a temporary repository clone and thus might receive a different merge base, depending on how far the target branch is ahead.

[0]: 4a2b76d9c8
[1]: 4a2b76d9c8
[2]: d26885e2bf (diff-84d6d60112991392d6ba2cae4cd919fb3ee8afb8)

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Saibotk <git@saibotk.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12040
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-08 21:09:40 +02:00
forgejo-backport-action
437aa7f4a1 [v15.0/forgejo] fix: prevent actions workflows from generating OIDC tokens if not authorized in workflow (#12038)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12030

When using Forgejo's `enable-openid-connect: true`, a URL is generated into the actions under `$ACTIONS_ID_TOKEN_REQUEST_URL` that can be used to generate a JWT for accessing third-party resources authenticated as the action executing in this server on this repo.  However, the endpoint of that url (`.../idtoken`) had unintentionally missed a `return` on an internal server error, and was missing a check that the action actually had `enable-openid-connect: true` on it.  As a result, it was possible to generate a JWT for accessing third-party resources from an action that wasn't expected to be generating JWTs.

In terms of real-world vulnerability, the most likely risk is that the JWT could be generated from a forked pull request.  By not using the `$ACTIONS_ID_TOKEN_REQUEST_URL` and instead going directly to the `.../idtoken` endpoint, and parsing a generated JWT response that will be mixed with an error response, it's possible to retrieve a JWT in a forked pull request.  It would require a slight misconfiguration on a third-party system to allow that JWT access, but it's a plausible risk.

As this is a feature in Forgejo 15 that hasn't been released, it will be fixed in-public.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.
    - Feature is not yet released.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12038
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-08 17:08:17 +02:00
Renovate Bot
72c9acee10 Update dependency go to v1.26.2 (v15.0/forgejo) (#12029)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12029
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-04-08 15:34:17 +02:00
forgejo-backport-action
825c2a1744 [v15.0/forgejo] test: fix intermittent test failure in TestPackageDebianConcurrent (#11998)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11997

Fixes #11968.

Adds deadlocks to the package `RetryTx` operations, and bumps the attempt count to 3.  Technically this affects production code, not just test code, but the resulting failure is only likely to occur in highly concurrent operations when uploading packages to the debian registry for the first time for a user, which is more of a test artifact than a production likelihood.

Manually tested by modifying the `Makefile` to add the `-test.count=25` option to the test command.  This failed consistently on my dev system before this change, failed consistently after the deadlock err was added, and then succeeded consistently (multiple runs) after both changes were combined, giving me confidence that the intermittent failure is squashed.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
      - Fixing a test failure, so no new tests added, but they already failed.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11998
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-06 03:39:53 +02:00
Mathieu Fenniak
a4ec71067c [v15.0/forgejo] chore(deps): bump xorm to v1.3.9-forgejo.10 (#11992) (#11996)
Backport #11992.  As I'm intending to fix the intermittently failing test (#11968), I'd like to backport that so we don't have an intermittent failing test in the LTS, and this is a requirement.

Brings [deadlock error type](https://code.forgejo.org/xorm/xorm/pulls/95), which should allow fixing #11968.

(cherry picked from commit 15b4c5efe8)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11992
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11996
Reviewed-by: Otto <otto@codeberg.org>
2026-04-06 02:45:39 +02:00
forgejo-backport-action
d4f7b536bc [v15.0/forgejo] fix: missing syntax dialog rounded corners (#11987)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11945

Fixes #11299

Co-authored-by: grangelouis <grangelouis@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11987
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-06 02:44:05 +02:00
forgejo-backport-action
1176b58f28 [v15.0/forgejo] refactor: reduce code duplication when accessing DefaultMaxInSize (#12000)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11999

`DefaultMaxInSize` is an internal parameter for limiting the size of `field IN (...)` clauses in DB queries, which is a reasonable thing to do -- in addition to the errors noted when [originally introduced](https://github.com/go-gitea/gitea/pull/4594), there are technical limits that apply to each of PostgreSQL, MySQL, and SQLite which would prevent an unbounded size for a query like this.  However: the size is incredibly small at 50, and, the implementation of `DefaultMaxInSize` is really wasteful with copy-and-paste coding.

This PR:
- introduces `GetByIDs` which fetches a `map[int64]*Model` from the database for an array of ID values, while respecting `IN` clause size limits
- introduces `GetByFieldIn` which fetches a `map[int64][]*Model` from the database for an array of field values, while respecting `IN` clause size limits
- uses `slices.Chunk` for other locations where queries are too complex for these implementations
- bumps the `DefaultMaxInSize` parameter from 50 to 500, a conservative increase well under known limits, but 10x the current value:
    - PostgreSQL supports up to 1GB query text size with 65,535 parameters, but I've experienced performance degradation at high value counts
    - MySQL supports 64MB query text size without known limits of parameter count
    - SQLite supports 32,766 parameters in a query

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
      - Refactored functions are assumed to be covered by existing tests to some extent; that assumption is probably wrong but the changes here are relatively easily reviewed for correctness as well.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12000
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-05 22:53:13 +02:00
forgejo-backport-action
397c8755f2 [v15.0/forgejo] perf: bulk load resolvers & reactions on pull request comments (#11995)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11988

Optimize loading pull request review comments, which currently perform separate database queries for each comment in order to load the resolver of the comment, and the reactions on that comment, and the users on each reaction of the comments.

I stumbled across this ugly code, which enticed me to look into this:

80d840c128/routers/web/repo/pull.go (L1107-L1120)

It appeared to load the attachments from each comment on the pull request review page in separate database queries.  It turned out to be a noop, as the attachments are already loaded in bulk:

80d840c128/models/issues/comment_code.go (L120-L122)

but the `findCodeComments` method loads the "resolver doer" and the reactions one-by-one for each comment.  So I fixed that instead, and removed the ineffective deeply nested for loop.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11995
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-05 17:30:39 +02:00
forgejo-backport-action
4ca6b703af [v15.0/forgejo] feat: support timezone in scheduled workflows (#11986)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11851

GitHub recently added the ability to [specify a time zone for scheduled workflows](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#onschedule), thereby making it possible to run scheduled workflows at a certain local time, no matter whether daylight saving time (DST) is currently active or not. Example copied from GitHub's documentation:

```yaml
on:
  schedule:
    - cron: '30 5 * * 1-5'
      timezone: "America/New_York"
```

The workflow would run at 05:30 each morning in the America/New_York timezone every Monday through Friday. `timezone` accepts IANA time zone names. If `timezone` is absent, `Etc/UTC` is used. GitHub runs workflows that were scheduled during DST jumps forward, for example, between 2 o'clock and 3 o'clock, directly after the clock jumped forward. In this case, that would be 3 o'clock.

Forgejo already supports time zones by prepending cron schedules with `TZ=<zone-id>` or `CRON_TZ=<zone-id>`:

```yaml
on:
  schedule:
    - cron: 'CRON_TZ=America/New_York 30 5 * * 1-5'
```

However, that capability is not documented. Workflows that are scheduled to run during DST changes are skipped when the clock jumps forward and run twice when it jumps backward.

This two-part PR adds support for `timezone` to improve compatibility with GitHub. `TZ` and `CRON_TZ` continue working. When both `timezone` and `TZ` or `CRON_TZ` are present, `timezone` takes precedence. When neither `timezone` nor `TZ` nor `CRON_TZ` are present, `Etc/UTC` is used as before. Because `TZ` and `CRON_TZ` were already supported by Forgejo before GitHub introduced `timezone`, `timezone` behaves during DST changes as previous versions of Forgejo, thereby deviating from GitHub. That means that workflows that are scheduled to run during DST changes are skipped when the clock jumps forward. And they run twice when it jumps backwards. However, it is generally recommended not to schedule workflows during the time of day when DST changes occur.

This part of the PR integrates the [workflow validation and parsing of the `timezone` field](https://code.forgejo.org/forgejo/runner/pulls/1454) supplied by Forgejo Runner.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Tests for JavaScript changes

(can be removed for Go changes)

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [x] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
    - https://codeberg.org/forgejo/docs/pulls/1853
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/11851): <!--number 11851 --><!--line 0 --><!--description c3VwcG9ydCBgdGltZXpvbmVgIGluIHNjaGVkdWxlZCB3b3JrZmxvd3M=-->support `timezone` in scheduled workflows<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11986
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-04 19:16:35 +02:00
forgejo-backport-action
06888ca34a [v15.0/forgejo] fix: store pull mirror creds encrypted with keying (#11984)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11909

Fixes #9629.

New pull mirrors have credentials stored encrypted in the database, the same as push mirrors, rather than in the repository's `config` file.  `git fetch` on the pull mirror is updated to use the credential store.  Pull mirrors will have their credentials migrated to the encrypted storage in the database as they're synced or otherwise accessed via the web UI.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11984
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-04 14:47:05 +02:00
forgejo-backport-action
6d67717a21 [v15.0/forgejo] Add aria-labels to ensure watch and star buttons always have a text label (#11967)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11878

Fixes https://codeberg.org/forgejo/forgejo/issues/6621.

The attached screen recording `before.mp4` demos the problem as described by https://codeberg.org/forgejo/forgejo/issues/6621. And `after.mp4` is the fixed version.

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Henry Catalini Smith <henry@catalinismith.se>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11967
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-03 21:20:36 +02:00
forgejo-backport-action
6f396c2001 [v15.0/forgejo] Add aria-label="Copy" to copy button (#11970)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11895

This copy button on the pull request page lacks an accessible name. You can hear the screen reader announce it as just "button" in the screen recording `button.mp4`, and then hear the amended version in `copy.mp4` where it's announced as "copy, button".

The most relevant WCAG success criteria here is [1.1.1 Non-text content](https://www.w3.org/WAI/WCAG21/Understanding/non-text-content.html).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Henry Catalini Smith <henry@catalinismith.se>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11970
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-03 19:12:51 +02:00
forgejo-backport-action
7822ed2030 [v15.0/forgejo] Add aria-current="page" to active navbar items (#11969)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11887

By setting `aria-current="page"` on the active navbar item we make the information about which one corresponds to the current page available in a non-visual way. Both the attached screen recordings were produced on http://localhost:3000/pulls, so the "Pull requests" link is the active one. In `before.mp4` all the links are announced identically, and in `after.mp4` the "Pull requests" link is announced like this.

> current page, visited, link, Pull requests

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Henry Catalini Smith <henry@catalinismith.se>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11969
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-03 18:53:23 +02:00
forgejo-backport-action
0b0aa6170f [v15.0/forgejo] Make label dropdown menu items with .tw-hidden unselectable (#11966)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11858

Fixes https://codeberg.org/forgejo/forgejo/issues/9894.

The dropdown menu items are being hidden with `.tw-hidden`. The Fomentic dropdown  makes items with `.disabled` and `.filtered` unselectable by default but can be [easily configured](https://fomantic-ui.com/modules/dropdown.html#/settings) to broaden this selector.

In the before & after GIFs attached, there is an archived label between "duplicate" and "help wanted". In the before GIF, focus disappears momentarily between the two, which is when the hidden, archived label has been programmatically focused by Fomentic. In the after GIF, focus hops instantaneously between the two selectable labels because of the broader `unselectable` selector.

### Tests for JavaScript changes

(can be removed for Go changes)

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https
- [ ]
- [ ] ://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Henry Catalini Smith <henry@catalinismith.se>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11966
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-03 18:45:32 +02:00
forgejo-backport-action
8b81d86c38 [v15.0/forgejo] fix: superfluous increment of ActionTask attempt breaks job view (#11964)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11956

https://codeberg.org/forgejo/forgejo/pulls/11750 missed a place where the attempt number is incremented independently. This caused the job view to break when running a reusable workflow with workflow expansion.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Tests for JavaScript changes

(can be removed for Go changes)

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11964
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-03 18:29:31 +02:00
forgejo-backport-action
bbbdc3bf67 [v15.0/forgejo] enh: add suggestion to document reason for repository archival (#11950)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11375

Fixes #11370

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- User Interface features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/11375): <!--number 11375 --><!--line 0 --><!--description ZW5oOiBhZGQgc3VnZ2VzdGlvbiB0byBkb2N1bWVudCByZWFzb24gZm9yIHJlcG9zaXRvcnkgYXJjaGl2YWw=-->enh: add suggestion to document reason for repository archival<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Eloy <degeneloy@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11950
Reviewed-by: Beowulf <beowulf@beocode.eu>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Reviewed-by: Robert Wolff <mahlzahn@posteo.de>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-02 22:10:21 +02:00
Gusted
607d031069 [v15.0/forgejo]: chore: add modernizer linter (#11949)
**Backport: !11936**

- Go has a suite of small linters that helps with modernizing Go code by using newer functions and catching small mistakes, https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize.
- Enable this linter in golangci-lint.
- There's also [`go fix`](https://go.dev/blog/gofix), which is not yet released as a linter in golangci-lint: https://github.com/golangci/golangci-lint/pull/6385

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11949
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
2026-04-02 16:54:46 +02:00
Renovate Bot
a32804bebe Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.11.4 (v15.0/forgejo) (#11948)
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-04-02 03:29:58 +02:00
forgejo-backport-action
d60af095dd [v15.0/forgejo] fix: allow repository deletion when referenced by a repo-specific access token (#11933)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11927

Fixes #11919.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11933
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-01 17:35:43 +02:00
forgejo-backport-action
e919aedcec [v15.0/forgejo] fix: allow modals to be submitted multiple times (#11931)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11843

Fixes #11842.

The `once: true` was likely added to prevent multiple concurrent
submissions of the same form. This could still be worth preventing,
but I suspect it would require wrapping the supplied `onApprove`
callback with the corresponding logic, implemented manually, as I
am not aware of any native API to prevent concurrent executions of
callbacks.

## Checklist

### Tests for JavaScript changes

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [x] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Antonin Delpeuch <antonin@delpeuch.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11931
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-01 08:13:12 +02:00
forgejo-backport-action
00f9d01593 [v15.0/forgejo] ci: prevent usage of live application models & services in migrations (#11907)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11872

Prevent access to "current" application models and services from migrations via `golangci` config:

eg:
```
models/forgejo_migrations/v14a_ap-change-fedi-handle-structure.go:18:2: import 'forgejo.org/models/user' is not allowed from list 'migration-isolation': Migrations must not import application models. Application models will be the most recent schema for Forgejo, while migrations will be operating against the database schema that existed when they were authored. (depguard)
	user_model "forgejo.org/models/user"
	^
models/forgejo_migrations/v14a_ap-change-fedi-handle-structure.go:21:2: import 'forgejo.org/services/user' is not allowed from list 'migration-isolation': Migrations must not import application services. Application services will reference application models which will use the most recent schema for Forgejo, while migrations will be operating against the database schema that existed when they were authored. (depguard)
	user_service "forgejo.org/services/user"
```

Fixes an existing migration issue where it isn't possible to add a new column to the `User` table ([test errors that occur](https://codeberg.org/forgejo/forgejo/actions/runs/148633/jobs/10/attempt/1#jobstep-5-323)), but also guarantees that future migrations don't stumble into the same issue by inadvertently referencing live application code from historical migrations.

Originally identified and draft fix by @codecat w/ proposed fix in #11870.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [x] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Melissa Geels <melissa@nimble.tools>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11907
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-01 02:57:09 +02:00
forgejo-backport-action
2c59849072 [v15.0/forgejo] Fix @mention combobox semantics for screen reader accessibility (#11922)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11860

Fixes https://codeberg.org/forgejo/forgejo/issues/7668.

This was simpler to fix than my theory I posted on https://codeberg.org/forgejo/forgejo/issues/7668 about needing to patch the upstream package. When testing in Firefox with the developer console open and warnings enabled, I noticed a `Empty string passed to getElementById()` warning coming from `@github/combobox-nav` while attempting to manage the `aria-activedescendant` attribute. Then I found this in the [README for that project](https://github.com/github/combobox-nav).

> Markup requirements:
> - Each option needs to have role="option" and a unique id

This was easy to miss, as we're using `@github/text-expander-element` and the combobox-nav package is one of _its_ dependencies. Without a unique ID on each dropdown menu item, `@github/text-expander-element` is unable to set an appropriate `aria-activedescendant` attribute on the textarea. Once that's in place, the screen reader announcements come to life beautifully.

While working on it I noticed the emoji picker combobox was affected by the same problem and patched that as well.

Co-authored-by: Henry Catalini Smith <henry@catalinismith.se>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11922
Reviewed-by: Otto <otto@codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-04-01 02:17:05 +02:00
forgejo-backport-action
d42c66471a [v15.0/forgejo] fix: unique key violation in first-time concurrent debian package uploads to a user (#11906)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11881

Fixes an intermittent test failure in `TestPackageDebianConcurrent`, [example](https://codeberg.org/forgejo/forgejo/actions/runs/148747/jobs/9/attempt/1#jobstep-5-981), introduced by testing in #11776.  This one is caused by duplicate writes to `user_setting` to store a GPG key (questionable place for that...).

Confirmed reproduced in local testing and test now passes:
```
=== TestPackageDebianConcurrent (tests/test_utils.go:344)
=== TestPackageDebianConcurrent/Concurrent_Upload (tests/integration/api_packages_debian_test.go:334)
... other duplicate key violations ...
// TestPackageDebianConcurrent/Concurrent_Upload
	"2026/03/29 10:31:57 ...dels/user/setting.go:210:func1() [E] [Error SQL Query] INSERT INTO \"gtestschema\".\"user_setting\" (\"user_id\",\"setting_key\",\"setting_value\") VALUES ($1,$2,$3) RETURNING \"id\" [2 debian.key.private -----BEGIN PGP PRIVATE KEY BLOCK-----

...snip...
-----END PGP PRIVATE KEY BLOCK-----] - ERROR: duplicate key value violates unique constraint \"UQE_user_setting_key_userid\" (SQLSTATE 23505)",
PASS
```

No additional test required as it is already tripping a test failure.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server. (already present and failing)
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11906
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-03-31 05:32:57 +02:00
Renovate Bot
adebf2adac Update github.com/go-git/go-git/v5 (indirect) to v5.17.1 [SECURITY] (v15.0/forgejo) (#11900)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) | `v5.17.0` → `v5.17.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgo-git%2fgo-git%2fv5/v5.17.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fgo-git%2fgo-git%2fv5/v5.17.0/v5.17.1?slim=true) |

---

### go-git missing validation decoding Index v4 files leads to panic
[CVE-2026-33762](https://nvd.nist.gov/vuln/detail/CVE-2026-33762) / [GHSA-gm2x-2g9h-ccm8](https://github.com/advisories/GHSA-gm2x-2g9h-ccm8)

<details>
<summary>More information</summary>

#### Details
##### Impact

`go-git`’s index decoder for format version 4 fails to validate the path name prefix length before applying it to the previously decoded path name. A maliciously crafted index file can trigger an out-of-bounds slice operation, resulting in a runtime panic during normal index parsing.

This issue only affects Git index format version 4. Earlier formats (`go-git` supports only `v2` and `v3`) are not vulnerable to this issue.

An attacker able to supply a crafted `.git/index` file can cause applications using go-git to panic while reading the index. If the application does not recover from panics, this results in process termination, leading to a denial-of-service (DoS) condition.

Exploitation requires the ability to modify or inject a Git index file within the local repository in disk. This typically implies write access to the `.git` directory.

##### Patches

Users should upgrade to `v5.17.1`, or the latest `v6` [pseudo-version](https://go.dev/ref/mod#pseudo-versions), in order to mitigate this vulnerability.

##### Credit

go-git maintainers thank @&#8203;kq5y for finding and reporting this issue privately to the `go-git` project.

#### Severity
- CVSS Score: 2.8 / 10 (Low)
- Vector String: `CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:L`

#### References
- [https://github.com/go-git/go-git/security/advisories/GHSA-gm2x-2g9h-ccm8](https://github.com/go-git/go-git/security/advisories/GHSA-gm2x-2g9h-ccm8)
- [https://github.com/go-git/go-git](https://github.com/go-git/go-git)

This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-gm2x-2g9h-ccm8) and the [GitHub Advisory Database](https://github.com/github/advisory-database) ([CC-BY 4.0](https://github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### go-git: Maliciously crafted idx file can cause asymmetric memory consumption
[CVE-2026-34165](https://nvd.nist.gov/vuln/detail/CVE-2026-34165) / [GHSA-jhf3-xxhw-2wpp](https://github.com/advisories/GHSA-jhf3-xxhw-2wpp)

<details>
<summary>More information</summary>

#### Details
##### Impact

A vulnerability has been identified in which a maliciously crafted `.idx` file can cause asymmetric memory consumption, potentially exhausting available memory and resulting in a Denial of Service (DoS) condition.

Exploitation requires write access to the local repository's `.git` directory, it order to create or alter existing `.idx` files.

##### Patches

Users should upgrade to `v5.17.1`, or the latest `v6` [pseudo-version](https://go.dev/ref/mod#pseudo-versions), in order to mitigate this vulnerability.

##### Credit

The go-git maintainers thank @&#8203;kq5y for finding and reporting this issue privately to the `go-git` project.

#### Severity
- CVSS Score: 5.0 / 10 (Medium)
- Vector String: `CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H`

#### References
- [https://github.com/go-git/go-git/security/advisories/GHSA-jhf3-xxhw-2wpp](https://github.com/go-git/go-git/security/advisories/GHSA-jhf3-xxhw-2wpp)
- [https://github.com/go-git/go-git](https://github.com/go-git/go-git)
- [https://github.com/go-git/go-git/releases/tag/v5.17.1](https://github.com/go-git/go-git/releases/tag/v5.17.1)

This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-jhf3-xxhw-2wpp) and the [GitHub Advisory Database](https://github.com/github/advisory-database) ([CC-BY 4.0](https://github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Release Notes

<details>
<summary>go-git/go-git (github.com/go-git/go-git/v5)</summary>

### [`v5.17.1`](https://github.com/go-git/go-git/releases/tag/v5.17.1)

[Compare Source](https://github.com/go-git/go-git/compare/v5.17.0...v5.17.1)

#### What's Changed

- build: Update module github.com/cloudflare/circl to v1.6.3 \[SECURITY] (releases/v5.x) by [@&#8203;go-git-renovate](https://github.com/go-git-renovate)\[bot] in [#&#8203;1930](https://github.com/go-git/go-git/pull/1930)
- \[v5] plumbing: format/index, Improve v4 entry name validation by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;1935](https://github.com/go-git/go-git/pull/1935)
- \[v5] plumbing: format/idxfile, Fix version and fanout checks by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;1937](https://github.com/go-git/go-git/pull/1937)

**Full Changelog**: <https://github.com/go-git/go-git/compare/v5.17.0...v5.17.1>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (UTC), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **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:eyJjcmVhdGVkSW5WZXIiOiI0My45OS4xIiwidXBkYXRlZEluVmVyIjoiNDMuOTkuMSIsInRhcmdldEJyYW5jaCI6InYxNS4wL2Zvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11900
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-03-31 02:48:18 +02:00
Renovate Bot
e045fb9b77 Update dependency happy-dom to v20.8.9 [SECURITY] (v15.0/forgejo) (#11886)
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-03-30 01:00:08 +02:00
forgejo-backport-action
a90e9b827c [v15.0/forgejo] feat: use --token-url in runner setup instructions (#11877)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11874

Use `--token-url` instead of `--token` in the runner setup instructions. `--token-url` is more secure. It was also decided [not to implement `--token`](https://code.forgejo.org/forgejo/runner/pulls/1457). The new instructions look as follows:

```
$ echo -n "a3bac733-079f-4917-ae9f-4acb99f1827b" > /path/to/runner-token
$ forgejo-runner daemon \
	--url http://192.168.178.62:3000/ \
	--uuid 5982831f-8ee7-42c7-abcc-49c7d6dba586 \
	--token-url file:///path/to/runner-token \
	--label docker:docker://node:lts
```

`--label` is also new because Forgejo Runner is inoperable when neither a runner configuration nor `--label` are present.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Tests for JavaScript changes

(can be removed for Go changes)

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [x] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11877
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-03-29 19:28:34 +02:00
Renovate Bot
7a2bd542bd Update dependency happy-dom to v20.8.8 [SECURITY] (v15.0/forgejo) (#11839)
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-03-27 06:49:10 +01:00
forgejo-backport-action
ebac8b38cb [v15.0/forgejo] fix: duplicate key violates unique constraint in concurrent debian package uploads (#11833)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11776

Fixes #11438.

Whenever a "unique constraint violation" error is encountered by package mutation, detect if a `xorm.ErrUniqueConstraintViolation` error occurs.  If it does, retry the entire transaction.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [ ] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11833
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-03-27 01:36:18 +01:00
forgejo-backport-action
4230ba6ed0 [v15.0/forgejo] fix: out of synchronization error after interrupting a PR merge by user-agent disconnect (#11830)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11821

If the HTTP request to `/user/repo/pulls/N/merge` is cancelled by the user agent, don't stop work once we've passed validation and started to merge the PR.  Go will automatically cancel the context if the user-agent disconnects, but that can leave Forgejo in an inconsistent state -- the `git` command can be cancelled at an arbitrary location, the `branch` database table update may not be completed, timers may not be stopped, cross-references may not be populated, etc.

Added test `TestMergeHTTPRequestCancellation` stress-tests the fix by cancelling merge requests, and then verifying that the in-database repository state and in-repository database state are consistent.  I've verified that this test fails if the fix is removed -- the in-database commit and commit messages don't match the repository in all PRs.

This is a problem that likely affects other Forgejo endpoints.  For example, even the PR merge API would be impacted.  But this will be one of the most common real-world places for it to occur, so my thought is we'll see how well this fix works and what (if any) side-effects it has.  We can apply a similar pattern in other areas if they are identified as problems.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [ ] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11830
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-03-26 19:20:19 +01:00
forgejo-backport-action
0245410cdc [v15.0/forgejo] fix(api): package name in route not properly unescaped (#11829)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11822

This pull fixes the issue described in https://codeberg.org/forgejo/forgejo/issues/11427 .

The api handler of link/unlink packages use escaped path params to find packages. It causes errors when it comes to npm packages, which contains characters like `@` and `/`.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

(can be removed for JavaScript changes)

- I added test coverage for Go changes...
  - [ ] in their respective `*_test.go` for unit tests.
  - [x] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Tests for JavaScript changes

(can be removed for Go changes)

- I added test coverage for JavaScript changes...
  - [ ] in `web_src/js/*.test.js` if it can be unit tested.
  - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

*The decision if the pull request will be shown in the release notes is up to the mergers / release team.*

The content of the `release-notes/<pull request number>.md` file will serve as the basis for the release notes. If the file does not exist, the title of the pull request will be used instead.

Co-authored-by: Guangxiong Lin <hi@gxlin.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11829
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2026-03-26 19:19:09 +01:00
Renovate Bot
88c4f035ea Update module golang.org/x/image to v0.38.0 [SECURITY] (v15.0/forgejo) (#11825)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [golang.org/x/image](https://pkg.go.dev/golang.org/x/image) | [`v0.37.0` → `v0.38.0`](https://cs.opensource.google/go/x/image/+/refs/tags/v0.37.0...refs/tags/v0.38.0) | ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fimage/v0.38.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fimage/v0.37.0/v0.38.0?slim=true) |

---

### OOM from malicious IFD offset in golang.org/x/image/tiff
[CVE-2026-33809](https://nvd.nist.gov/vuln/detail/CVE-2026-33809) / [GO-2026-4815](https://pkg.go.dev/vuln/GO-2026-4815)

<details>
<summary>More information</summary>

#### Details
A maliciously crafted TIFF file can cause image decoding to attempt to allocate up 4GiB of memory, causing either excessive resource consumption or an out-of-memory error.

#### Severity
Unknown

#### References
- [https://go.dev/cl/757660](https://go.dev/cl/757660)
- [https://go.dev/issue/78267](https://go.dev/issue/78267)

This data is provided by [OSV](https://osv.dev/vulnerability/GO-2026-4815) and the [Go Vulnerability Database](https://github.com/golang/vulndb) ([CC-BY 4.0](https://github.com/golang/vulndb#license)).
</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (UTC), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **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:eyJjcmVhdGVkSW5WZXIiOiI0My44Ni4wIiwidXBkYXRlZEluVmVyIjoiNDMuODYuMCIsInRhcmdldEJyYW5jaCI6InYxNS4wL2Zvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11825
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-03-26 14:52:07 +01:00
714 changed files with 11364 additions and 29005 deletions

View file

@ -58,6 +58,7 @@ forgejo.org/models/user
IsErrUserSettingIsNotExist
GetUserAllSettings
DeleteUserSetting
GetFederatedUser
forgejo.org/modules/activitypub
NewContext
@ -87,6 +88,7 @@ forgejo.org/modules/eventsource
Event.String
forgejo.org/modules/forgefed
NewForgeFollow
NewForgeUndoLike
ForgeUndoLike.UnmarshalJSON
ForgeUndoLike.Validate
@ -132,9 +134,6 @@ forgejo.org/modules/json
StdJSON.Indent
forgejo.org/modules/log
eventWriterBuffer.Close
eventWriterBuffer.Write
eventWriterBuffer.GetString
NewEventWriterBuffer
forgejo.org/modules/markup
@ -225,6 +224,9 @@ forgejo.org/routers/web/org
forgejo.org/services/context
GetPrivateContext
forgejo.org/services/federation
FollowRemoteActor
forgejo.org/services/notify
UnregisterNotifier

View file

@ -1,5 +1,5 @@
{
"name": "forgejo-dev",
"name": "Gitea DevContainer",
"image": "mcr.microsoft.com/devcontainers/go:1.26-trixie",
"features": {
// installs nodejs into container

View file

@ -9,7 +9,7 @@
"baseBranchPatterns": [
"$default",
"/^v11\\.\\d+/forgejo$/",
"/^v15\\.\\d+/forgejo$/"
"/^v14\\.\\d+/forgejo$/"
],
"postUpdateOptions": ["gomodTidy", "gomodUpdateImportPaths", "npmDedupe"],
"prConcurrentLimit": 10,
@ -138,13 +138,6 @@
],
"automerge": true
},
{
"description": "Run end-to-end tests for some dependencies",
"matchPackageNames": [
"code.forgejo.org/forgejo/runner/**"
],
"addLabels": ["run-end-to-end-tests"]
},
{
"description": "Disable indirect updates for stable branches",
"matchBaseBranches": ["/^v\\d+\\.\\d+\\/forgejo$/"],
@ -159,12 +152,6 @@
"matchUpdateTypes": ["major"],
"enabled": false
},
{
"description": "Disable updates for old stable branches but still allow security updates",
"matchBaseBranches": ["v11.0/forgejo", "v14.0/forgejo"],
"matchUpdateTypes": ["minor", "patch", "digest"],
"enabled": false
},
{
"description": "Require approval for stable branches (must be last rule to override all others)",
"matchBaseBranches": ["/^v\\d+\\.\\d+\\/forgejo$/"],

View file

@ -47,7 +47,7 @@ jobs:
cat <<'EOF'
${{ toJSON(github) }}
EOF
- uses: https://data.forgejo.org/actions/git-backporting@v4.9.1
- uses: https://data.forgejo.org/actions/git-backporting@v4.8.7
with:
target-branch-pattern: "^backport/(?<target>(v.*))$"
strategy: ort

View file

@ -2,7 +2,7 @@ name: Integration tests for the release process
enable-email-notifications: true
env:
FORGEJO_VERSION: 11.0.14 # renovate: datasource=docker depName=data.forgejo.org/forgejo/forgejo
FORGEJO_VERSION: 11.0.11 # renovate: datasource=docker depName=data.forgejo.org/forgejo/forgejo
on:
push:
@ -32,7 +32,7 @@ jobs:
- uses: https://data.forgejo.org/actions/checkout@v6
- id: forgejo
uses: https://data.forgejo.org/actions/setup-forgejo@v3.1.11
uses: https://data.forgejo.org/actions/setup-forgejo@v3.1.8
with:
user: root
password: admin1234

View file

@ -6,7 +6,7 @@ on:
env:
RNA_WORKDIR: /srv/rna
RNA_VERSION: v1.7.0 # renovate: datasource=forgejo-releases depName=forgejo/release-notes-assistant registryUrl=https://code.forgejo.org
RNA_VERSION: v1.6.1 # renovate: datasource=forgejo-releases depName=forgejo/release-notes-assistant registryUrl=https://code.forgejo.org
jobs:
release-notes:

View file

@ -8,7 +8,7 @@ on:
- labeled
env:
RNA_VERSION: v1.7.0 # renovate: datasource=forgejo-releases depName=forgejo/release-notes-assistant registryUrl=https://code.forgejo.org
RNA_VERSION: v1.6.1 # renovate: datasource=forgejo-releases depName=forgejo/release-notes-assistant registryUrl=https://code.forgejo.org
jobs:
release-notes:

View file

@ -224,6 +224,9 @@ linters:
- path: models/dbfs/dbfile.go
linters:
- nilnil
- path: models/forgefed/federationhost_repository.go
linters:
- nilnil
- path: models/forgejo_migrations_legacy/v32.go
linters:
- nilnil
@ -281,6 +284,9 @@ linters:
- path: models/repo/repo.go
linters:
- nilnil
- path: models/user/user_repository.go
linters:
- nilnil
- path: modules/git/commit.go
linters:
- nilnil
@ -359,6 +365,9 @@ linters:
- path: routers/api/packages/conan/auth.go
linters:
- nilnil
- path: services/federation/signature_service.go
linters:
- nilnil
- path: services/issue/commit.go
linters:
- nilnil

View file

@ -1,17 +0,0 @@
formatter: gofmt
template: testify
packages:
forgejo.org/modules/nosql:
config:
filename: mocks.go # make mocks public so that external packages can use
forgejo.org/services/auth/method:
forgejo.org/services/authz:
config:
filename: authorization_reducer_mock.go # make mocks public so that external packages can use
code.forgejo.org/go-chi/cache:
interfaces:
Cache:
config:
pkgname: cache
dir: modules/cache
filename: mocks.go # make mocks public, not `_test.go`, so that external packages can mock caching

View file

@ -1 +1 @@
24.15.0
24.14.1

View file

@ -7,7 +7,6 @@ branch-from-version: 'v%[1]d.%[2]d/forgejo'
tag-from-version: 'v%[1]d.%[2]d.%[3]d'
supported-release-count: 3
branch-known:
# replace with v15 when v11 becomes EOL
- 'v11.0/forgejo'
cleanup-line: 'sed -Ee "s/^(feat|fix):\s*//g" -e "s/^\[WIP\] //" -e "s/^WIP: //" -e "s;\[(UI|BUG|FEAT|v.*?/forgejo)\]\s*;;g"'
render-header: |

View file

@ -1,11 +0,0 @@
rules:
- id: forgejo-logic-suspicious-OwnerID-check
pattern: |-
$X.OwnerID > 0
languages:
- go
severity: ERROR
message: >
Many resources like comments or runners cannot only be owned by regular users, which have positive IDs, but also
by predefined system users like Ghost or Forgejo Actions that have negative IDs. In those cases, ownership checks
should only exclude 0: `OwnerID != 0`.

View file

@ -1,35 +0,0 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package actions
import "xorm.io/builder"
type FindRunJobOptions struct {
RepoID int64
OwnerID int64
}
func (opts FindRunJobOptions) Bad() builder.Cond {
cond := builder.NewCond()
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
// ruleid:forgejo-logic-suspicious-OwnerID-check
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}
return cond
}
func (opts FindRunJobOptions) Good() builder.Cond {
cond := builder.NewCond()
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
// ok:forgejo-logic-suspicious-OwnerID-check
if opts.OwnerID != 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}
return cond
}

View file

@ -45,10 +45,10 @@ SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.33.2 # renova
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses/v2@v2.0.1 # renovate: datasource=go
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.45.0 # renovate: datasource=go
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.43.0 # renovate: datasource=go
ERRORTYPE_PACKAGE ?= fillmore-labs.com/errortype@v0.0.11 # renovate: datasource=go
RENOVATE_NPM_PACKAGE ?= renovate@43.170.20 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
MOCKERY_PACKAGE ?= github.com/vektra/mockery/v3@v3.7.0 # renovate: datasource=go
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.6.0 # renovate: datasource=go
RENOVATE_NPM_PACKAGE ?= renovate@43.86.1 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
@ -245,7 +245,7 @@ help:
@echo " - generate-license update license files"
@echo " - generate-gitignore update gitignore files"
@echo " - generate-manpage generate manpage"
@echo " - generate-mockery generate mockery files"
@echo " - generate-gomock generate gomock files"
@echo " - generate-forgejo-api generate the forgejo API from spec"
@echo " - forgejo-api-validate check if the forgejo API matches the specs"
@echo " - generate-swagger generate the swagger spec from code comments"
@ -562,12 +562,12 @@ test: test-frontend test-backend
.PHONY: test-backend
test-backend: | compute-go-test-packages
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
@TZ=UTC GITEA_ROOT="$(CURDIR)" $(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_PACKAGES)
@TZ=UTC $(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_PACKAGES)
.PHONY: test-remote-cacher
test-remote-cacher:
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
GITEA_ROOT="$(CURDIR)" $(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_REMOTE_CACHER_PACKAGES)
@$(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_REMOTE_CACHER_PACKAGES)
.PHONY: test-frontend
test-frontend: node_modules
@ -592,7 +592,7 @@ test-check:
.PHONY: test\#%
test\#%: | compute-go-test-packages
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
@TZ=UTC GITEA_ROOT="$(CURDIR)" $(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_TEST_PACKAGES)
@TZ=UTC $(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_TEST_PACKAGES)
coverage-merge:
rm -fr coverage/merged ; mkdir -p coverage/merged
@ -968,8 +968,8 @@ deps-tools:
$(GO) install $(XGO_PACKAGE)
$(GO) install $(GO_LICENSES_PACKAGE)
$(GO) install $(GOVULNCHECK_PACKAGE)
$(GO) install $(GOMOCK_PACKAGE)
$(GO) install $(ERRORTYPE_PACKAGE)
$(GO) install $(MOCKERY_PACKAGE)
node_modules: package-lock.json
npm install --no-save
@ -1024,9 +1024,9 @@ generate-license:
generate-gitignore:
$(GO) run build/generate-gitignores.go
.PHONY: generate-mockery
generate-mockery:
$(GO) run $(MOCKERY_PACKAGE)
.PHONY: generate-gomock
generate-gomock:
$(GO) run $(GOMOCK_PACKAGE) -package mock -destination ./modules/queue/mock/redisuniversalclient.go forgejo.org/modules/nosql RedisClient
.PHONY: generate-images
generate-images: | node_modules

File diff suppressed because one or more lines are too long

View file

@ -6,12 +6,32 @@ translation_meta.test
# this also gets instantiated as a Messenger once
repo.migrate.migrating_failed.error
# models/system/notice.go: func (n *Notice) TrStr() string
admin.notices.type_1
admin.notices.type_2
# modules/setting/ui.go
themes.names.
# services/context/context.go
relativetime.
# templates/repo/issue/view_content.tmpl: indirection via $closeTranslationKey
repo.issues.close
repo.pulls.close
# templates/repo/issue/view_content/comments.tmpl: indirection via $refTr
repo.issues.ref_closing_from
repo.issues.ref_issue_from
repo.issues.ref_pull_from
repo.issues.ref_reopening_from
# templates/repo/issue/view_content/comments.tmpl: ctx.Locale.Tr (printf "projects.type-%d.display_name" .OldProject.Type)
projects.
projects.type-1.display_name
projects.type-2.display_name
projects.type-3.display_name
# templates/repo/settings/webhook/link_menu.tmpl, templates/webhook/new.tmpl: repo.settings.web_hook_name_
# tests/integration/repo_archive_text_test.go
repo.settings.

View file

@ -37,172 +37,144 @@ func HandleGoFile(handler llu.Handler, fname string, src any) error {
}
ast.Inspect(node, func(n ast.Node) bool {
return HandleGoNode(handler, fset, fname, n)
})
// search for function calls of the form `anything.Tr(any-string-lit, ...)`
return nil
}
func HandleGoNode(handler llu.Handler, fset *token.FileSet, fname string, n ast.Node) bool {
// search for function calls of the form `anything.Tr(any-string-lit, ...)`
switch n2 := n.(type) {
case *ast.CallExpr:
if len(n2.Args) == 0 {
return true
}
funSel, ok := n2.Fun.(*ast.SelectorExpr)
if !ok {
return true
}
ltf, ok := handler.LocaleTrFunctions[funSel.Sel.Name]
if !ok {
return true
}
var gotUnexpectedInvoke *int
for _, argNum := range ltf {
if len(n2.Args) <= int(argNum) {
argc := len(n2.Args)
gotUnexpectedInvoke = &argc
} else {
handler.HandleGoTrArgument(fset, n2.Args[int(argNum)], "")
switch n2 := n.(type) {
case *ast.CallExpr:
if len(n2.Args) == 0 {
return true
}
}
if gotUnexpectedInvoke != nil {
handler.OnUnexpectedInvoke(fset, funSel.Sel.NamePos, funSel.Sel.Name, *gotUnexpectedInvoke)
}
case *ast.CompositeLit:
if strings.HasSuffix(fname, "models/unit/unit.go") {
lluUnit.HandleCompositeUnit(handler, fset, n2)
} else if strings.Contains(fname, "models/asymkey/") {
lluAsymKey.HandleCompositeErrorReason(handler, fset, n2)
}
case *ast.FuncDecl:
if matchInsPrefix := handler.HandleGoCommentGroup(fset, n2.Doc, "llu:returnsTrKeyWeak"); matchInsPrefix != nil {
results := n2.Type.Results.List
if len(results) != 1 {
handler.OnWarning(fset, n2.Type.Func, fmt.Sprintf("function %s has unexpected return type; expected single return value", n2.Name.Name))
funSel, ok := n2.Fun.(*ast.SelectorExpr)
if !ok {
return true
}
ast.Inspect(n2.Body, func(n ast.Node) bool {
// search for return stmts
// TODO: what about nested functions?
if ret, ok := n.(*ast.ReturnStmt); ok {
for _, res := range ret.Results {
ast.Inspect(res, func(n ast.Node) bool {
if expr, ok := n.(ast.Expr); ok {
handler.HandleGoTrArgument(fset, expr, *matchInsPrefix)
}
return true
})
}
return false
ltf, ok := handler.LocaleTrFunctions[funSel.Sel.Name]
if !ok {
return true
}
var gotUnexpectedInvoke *int
for _, argNum := range ltf {
if len(n2.Args) <= int(argNum) {
argc := len(n2.Args)
gotUnexpectedInvoke = &argc
} else {
handler.HandleGoTrArgument(fset, n2.Args[int(argNum)], "")
}
return true
})
}
if matchInsPrefix := handler.HandleGoCommentGroup(fset, n2.Doc, "llu:returnsTrKey"); matchInsPrefix != nil {
results := n2.Type.Results.List
if len(results) != 1 {
handler.OnWarning(fset, n2.Type.Func, fmt.Sprintf("function %s has unexpected return type; expected single return value", n2.Name.Name))
return true
}
ast.Inspect(n2.Body, func(n ast.Node) bool {
// search for return stmts
if ret, ok := n.(*ast.ReturnStmt); ok {
for _, res := range ret.Results {
handler.HandleGoTrArgument(fset, res, *matchInsPrefix)
}
return false
} else if _, ok := n.(*ast.FuncDecl); ok {
ast.Inspect(n, func(n2 ast.Node) bool {
return HandleGoNode(handler, fset, fname, n2)
})
// don't search inside nested functions for return stmts
return false
if gotUnexpectedInvoke != nil {
handler.OnUnexpectedInvoke(fset, funSel.Sel.NamePos, funSel.Sel.Name, *gotUnexpectedInvoke)
}
case *ast.CompositeLit:
if strings.HasSuffix(fname, "models/unit/unit.go") {
lluUnit.HandleCompositeUnit(handler, fset, n2)
} else if strings.Contains(fname, "models/asymkey/") {
lluAsymKey.HandleCompositeErrorReason(handler, fset, n2)
}
case *ast.FuncDecl:
matchInsPrefix := handler.HandleGoCommentGroup(fset, n2.Doc, "llu:returnsTrKey")
if matchInsPrefix != nil {
results := n2.Type.Results.List
if len(results) != 1 {
handler.OnWarning(fset, n2.Type.Func, fmt.Sprintf("function %s has unexpected return type; expected single return value", n2.Name.Name))
return true
}
return true
})
}
if strings.HasSuffix(fname, "services/migrations/migrate.go") {
lluMigrate.HandleMessengerInFunc(handler, fset, n2)
}
return true
case *ast.GenDecl:
switch n2.Tok {
case token.CONST, token.VAR:
matchInsPrefix := handler.HandleGoCommentGroup(fset, n2.Doc, " llu:TrKeys")
if matchInsPrefix == nil {
return true
}
for _, spec := range n2.Specs {
// interpret all contained strings as message IDs
ast.Inspect(spec, func(n ast.Node) bool {
if argLit, ok := n.(*ast.BasicLit); ok {
handler.HandleGoTrBasicLit(fset, argLit, *matchInsPrefix)
ast.Inspect(n2.Body, func(n ast.Node) bool {
// search for return stmts
// TODO: what about nested functions?
if ret, ok := n.(*ast.ReturnStmt); ok {
for _, res := range ret.Results {
ast.Inspect(res, func(n ast.Node) bool {
if expr, ok := n.(ast.Expr); ok {
handler.HandleGoTrArgument(fset, expr, *matchInsPrefix)
}
return true
})
}
return false
}
return true
})
}
case token.TYPE:
// modules/web/middleware/binding.go:Validate uses the convention that structs
// entries can have tags.
// In particular, `locale:$msgid` should be handled; any fields with `form:-` shouldn't.
// Problem: we don't know which structs are forms, actually.
for _, spec := range n2.Specs {
tspec := spec.(*ast.TypeSpec)
structNode, ok := tspec.Type.(*ast.StructType)
if !ok || !(strings.HasSuffix(tspec.Name.Name, "Form") ||
(tspec.Doc != nil &&
slices.ContainsFunc(tspec.Doc.List, func(c *ast.Comment) bool {
return c.Text == "// swagger:model"
}))) {
continue
if strings.HasSuffix(fname, "services/migrations/migrate.go") {
lluMigrate.HandleMessengerInFunc(handler, fset, n2)
}
return true
case *ast.GenDecl:
switch n2.Tok {
case token.CONST, token.VAR:
matchInsPrefix := handler.HandleGoCommentGroup(fset, n2.Doc, " llu:TrKeys")
if matchInsPrefix == nil {
return true
}
for _, field := range structNode.Fields.List {
if field.Names == nil {
for _, spec := range n2.Specs {
// interpret all contained strings as message IDs
ast.Inspect(spec, func(n ast.Node) bool {
if argLit, ok := n.(*ast.BasicLit); ok {
handler.HandleGoTrBasicLit(fset, argLit, *matchInsPrefix)
return false
}
return true
})
}
case token.TYPE:
// modules/web/middleware/binding.go:Validate uses the convention that structs
// entries can have tags.
// In particular, `locale:$msgid` should be handled; any fields with `form:-` shouldn't.
// Problem: we don't know which structs are forms, actually.
for _, spec := range n2.Specs {
tspec := spec.(*ast.TypeSpec)
structNode, ok := tspec.Type.(*ast.StructType)
if !ok || !(strings.HasSuffix(tspec.Name.Name, "Form") ||
(tspec.Doc != nil &&
slices.ContainsFunc(tspec.Doc.List, func(c *ast.Comment) bool {
return c.Text == "// swagger:model"
}))) {
continue
}
if len(field.Names) != 1 {
handler.OnWarning(fset, field.Type.Pos(), "unsupported multiple field names")
continue
}
msgidPos := field.Names[0].NamePos
msgid := "form." + field.Names[0].Name
if field.Tag != nil && field.Tag.Kind == token.STRING {
rawTag, err := strconv.Unquote(field.Tag.Value)
if err != nil {
handler.OnWarning(fset, field.Tag.ValuePos, "invalid tag value encountered")
for _, field := range structNode.Fields.List {
if field.Names == nil {
continue
}
tag := reflect.StructTag(rawTag)
if tag.Get("form") == "-" {
if len(field.Names) != 1 {
handler.OnWarning(fset, field.Type.Pos(), "unsupported multiple field names")
continue
}
tmp := tag.Get("locale")
if len(tmp) != 0 {
msgidPos = field.Tag.ValuePos
msgid = tmp
msgidPos := field.Names[0].NamePos
msgid := "form." + field.Names[0].Name
if field.Tag != nil && field.Tag.Kind == token.STRING {
rawTag, err := strconv.Unquote(field.Tag.Value)
if err != nil {
handler.OnWarning(fset, field.Tag.ValuePos, "invalid tag value encountered")
continue
}
tag := reflect.StructTag(rawTag)
if tag.Get("form") == "-" {
continue
}
tmp := tag.Get("locale")
if len(tmp) != 0 {
msgidPos = field.Tag.ValuePos
msgid = tmp
}
}
handler.OnMsgid(fset, msgidPos, msgid, true)
}
handler.OnMsgid(fset, msgidPos, msgid, true)
}
}
}
}
return true
return true
})
return nil
}

View file

@ -13,7 +13,6 @@ import (
"io/fs"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
@ -45,57 +44,12 @@ type StringTrie interface {
type StringTrieMap map[string]StringTrie
func printfPatternToRegex(key string) (string, bool) {
parts := strings.Split(key, "%")
if len(parts) < 2 {
return key, false
}
var pattern strings.Builder
pattern.WriteString("^")
pattern.WriteString(parts[0])
skip := false
for _, part := range parts[1:] {
if skip {
skip = false
continue
}
if len(part) == 0 {
// "%%"
pattern.WriteString("%")
continue
}
switch part[0] {
case 'd':
pattern.WriteString("[0-9]+")
default:
pattern.WriteString("[A-Za-z0-9]*")
}
pattern.WriteString(part[1:])
}
pattern.WriteString("$")
return pattern.String(), true
}
func (m StringTrieMap) Matches(key []string) bool {
if len(key) == 0 || m == nil {
return true
}
value, ok := m[key[0]]
if !ok {
for altKey, value := range m {
// TODO: cache mapping $printfFormatString -> $regexpCompileOutput
pattern, found := printfPatternToRegex(altKey)
if !found {
continue
}
matched, err := regexp.MatchString(pattern, key[0])
if err != nil {
panic(fmt.Sprintf("unable to compile regexp '%s': %s", pattern, err.Error()))
}
if matched && (value == nil || value.Matches(key[1:])) {
return true
}
}
return false
}
if value == nil {
@ -147,7 +101,7 @@ func ParseAllowedMaskedUsages(fname string, usedMsgids container.Set[string], al
if line == "" || strings.HasPrefix(line, "#") {
continue
}
if linePrefix, found := strings.CutSuffix(line, "."); found || strings.Contains(line, "%") {
if linePrefix, found := strings.CutSuffix(line, "."); found {
allowedMaskedPrefixes.Insert(strings.Split(linePrefix, "."))
} else {
if !chkMsgid(line) {
@ -191,14 +145,9 @@ func Usage() {
fmt.Fprintf(outp, "\nSpecial Go doc comments:\n")
for _, i := range []string{
"//llu:returnsTrKeyWeak",
"\tcan be used in front of functions to indicate",
"\tthat the function returns message IDs (allows nesting inside complicated function calls)",
"\tWARNING: this currently doesn't support nested functions properly",
"",
"//llu:returnsTrKey",
"\tcan be used in front of functions to indicate",
"\tthat the function returns message IDs (doesn't allow nesting inside complicated function calls)",
"\tthat the function returns message IDs",
"\tWARNING: this currently doesn't support nested functions properly",
"",
"//llu:returnsTrKeySuffix prefix.",
@ -311,10 +260,6 @@ func main() {
}
handler := llu.Handler{
OnMsgidPattern: func(fset *token.FileSet, pos token.Pos, msgidPattern string) {
msgidPatternSplit := strings.Split(msgidPattern, ".")
allowedMaskedPrefixes.Insert(msgidPatternSplit)
},
OnMsgidPrefix: func(fset *token.FileSet, pos token.Pos, msgidPrefix string, truncated bool) {
msgidPrefixSplit := strings.Split(msgidPrefix, ".")
if !truncated {
@ -325,10 +270,6 @@ func main() {
}
},
OnMsgid: func(fset *token.FileSet, pos token.Pos, msgid string, weak bool) {
if strings.Contains(msgid, "%") {
fmt.Printf("%s:\tunexpected msgid pattern: %s\n", fset.Position(pos).String(), msgid)
return
}
if !msgids.Contains(msgid) {
if weak && allowWeakMissingMsgids {
return

View file

@ -34,14 +34,12 @@ func (handler Handler) HandleGoTrBasicLit(fset *token.FileSet, argLit *ast.Basic
}
func (handler Handler) HandleGoTrArgument(fset *token.FileSet, n ast.Expr, prefix string) {
switch n := n.(type) {
case *ast.BasicLit:
handler.HandleGoTrBasicLit(fset, n, prefix)
case *ast.BinaryExpr:
if n.Op != token.ADD {
if argLit, ok := n.(*ast.BasicLit); ok {
handler.HandleGoTrBasicLit(fset, argLit, prefix)
} else if argBinExpr, ok := n.(*ast.BinaryExpr); ok {
if argBinExpr.Op != token.ADD {
// pass
} else if argLit, ok := n.X.(*ast.BasicLit); ok && argLit.Kind == token.STRING {
} else if argLit, ok := argBinExpr.X.(*ast.BasicLit); ok && argLit.Kind == token.STRING {
// extract string content
arg, err := strconv.Unquote(argLit.Value)
if err != nil {
@ -55,39 +53,6 @@ func (handler Handler) HandleGoTrArgument(fset *token.FileSet, n ast.Expr, prefi
}
handler.OnMsgidPrefix(fset, argLit.ValuePos, prep, trunc)
}
case *ast.CallExpr:
if selExpr, ok := n.Fun.(*ast.SelectorExpr); ok {
if xIdent, xok := selExpr.X.(*ast.Ident); !xok || xIdent.Name != "fmt" {
return
}
if selExpr.Sel.Name != "Sprintf" {
handler.OnWarning(fset, selExpr.Sel.NamePos, fmt.Sprintf("unexpected formatting function encountered: %s", selExpr.Sel.Name))
return
}
if len(n.Args) == 0 {
handler.OnWarning(fset, selExpr.Sel.NamePos, fmt.Sprintf("unexpected formatting function invocation (no arguments) of '%s'", selExpr.Sel.Name))
return
}
if argLit, ok := n.Args[0].(*ast.BasicLit); ok && argLit.Kind == token.STRING {
// extract string content
arg, err := strconv.Unquote(argLit.Value)
if err != nil {
return
}
if strings.Contains(arg, " ") {
handler.OnWarning(fset, argLit.ValuePos, fmt.Sprintf(
"formatting function invocation of '%s' with weird msgid format string: %s",
selExpr.Sel.Name,
arg,
))
return
}
// found interesting strings
handler.OnMsgidPattern(fset, argLit.ValuePos, prefix+arg)
}
}
}
}

View file

@ -150,12 +150,16 @@ func (handler Handler) handleTemplateMsgid(fset *token.FileSet, node tmplParser.
handler.OnMsgid(fset, stringPos, msgidPrefix, false)
} else {
if nodeIdent.Ident == "printf" {
// found interesting strings
if !(strings.HasSuffix(msgidPrefix, ".%s") && strings.Count(msgidPrefix, "%") == 1) {
handler.OnMsgidPattern(fset, stringPos, msgidPrefix)
parts := strings.SplitN(msgidPrefix, "%", 2)
if len(parts) != 2 {
handler.OnWarning(
fset,
stringPos,
fmt.Sprintf("unsupported invocation of locate function (format string doesn't match \"prefix%%smth\" pattern): %s", nodeString.String()),
)
return
}
msgidPrefix = strings.TrimSuffix(msgidPrefix, "%s")
msgidPrefix = parts[0]
}
msgidPrefixFin, truncated := PrepareMsgidPrefix(msgidPrefix)

View file

@ -47,7 +47,6 @@ func InitLocaleTrFunctions() map[string][]uint {
type Handler struct {
OnMsgid func(fset *token.FileSet, pos token.Pos, msgid string, weak bool)
OnMsgidPrefix func(fset *token.FileSet, pos token.Pos, msgidPrefix string, truncated bool)
OnMsgidPattern func(fset *token.FileSet, pos token.Pos, msgidPattern string)
OnUnexpectedInvoke func(fset *token.FileSet, pos token.Pos, funcname string, argc int)
OnWarning func(fset *token.FileSet, pos token.Pos, msg string)
LocaleTrFunctions map[string][]uint

View file

@ -47,6 +47,7 @@ func subcmdRegenerate() *cli.Command {
Name: "regenerate",
Usage: "Regenerate specific files",
Commands: []*cli.Command{
microcmdRegenHooks,
microcmdRegenKeys,
},
}

View file

@ -7,15 +7,36 @@ import (
"context"
asymkey_model "forgejo.org/models/asymkey"
"forgejo.org/modules/graceful"
repo_service "forgejo.org/services/repository"
"github.com/urfave/cli/v3"
)
var microcmdRegenKeys = &cli.Command{
Name: "keys",
Usage: "Regenerate authorized_keys file",
Before: noDanglingArgs,
Action: runRegenerateKeys,
var (
microcmdRegenHooks = &cli.Command{
Name: "hooks",
Usage: "Regenerate git-hooks",
Before: noDanglingArgs,
Action: runRegenerateHooks,
}
microcmdRegenKeys = &cli.Command{
Name: "keys",
Usage: "Regenerate authorized_keys file",
Before: noDanglingArgs,
Action: runRegenerateKeys,
}
)
func runRegenerateHooks(ctx context.Context, c *cli.Command) error {
ctx, cancel := installSignals(ctx)
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
return repo_service.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
}
func runRegenerateKeys(ctx context.Context, c *cli.Command) error {

View file

@ -17,7 +17,6 @@ func subcmdUser() *cli.Command {
microcmdUserChangePassword(),
microcmdUserDelete(),
microcmdUserGenerateAccessToken(),
microcmdUserCreateAuthorizedIntegration(),
microcmdUserMustChangePassword(),
microcmdUserResetMFA(),
},

View file

@ -1,269 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package cmd
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"strings"
auth_model "forgejo.org/models/auth"
"forgejo.org/models/db"
"forgejo.org/models/repo"
user_model "forgejo.org/models/user"
"forgejo.org/modules/json"
"forgejo.org/services/authz"
"github.com/urfave/cli/v3"
)
func microcmdUserCreateAuthorizedIntegration() *cli.Command {
return &cli.Command{
Name: "create-authorized-integration",
Description: `Creates an authorized integration. Authorized integrations allow Forgejo to
receive JWTs from external sources, validate their claims against
user-defined rules, and grant access to Forgejo's API on behalf of a user.
The issuer may be set to "urn:forgejo:authorized-integrations:actions"
to support JWTs from the local instance's Forgejo Actions, utilizing the
enable-openid-connect flag in a workflow.`,
// `--claim-in sub=v1,v2,v3` needs to be parsed as a single parameter so that we can comma-split the value into
// an array. To accomplish this, we disable urfave 's slice flag separator, which would cause this to be
// treated as "sub=v1", "v2=?", and "v3=?", resulting in an error of missing values.
DisableSliceFlagSeparator: true,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "username",
Aliases: []string{"u"},
Usage: "Username",
Required: true,
},
&cli.StringFlag{
Name: "name",
Usage: "Name of the authorized integration for later identification",
Required: true,
},
&cli.StringFlag{
Name: "description",
Usage: "Optional description for the authorized integration",
},
// JWT validation:
&cli.StringFlag{
Name: "issuer",
Usage: `JWT issuer ('iss' claim), example: https://forgejo.example.org/api/actions`,
Required: true,
},
&cli.StringMapFlag{
Name: "claim-eq",
Value: map[string]string{},
Usage: `Zero-or-more claim equality checks, formatted as claim=value, example: "actor=someuser"`,
},
&cli.StringMapFlag{
Name: "claim-in",
Value: map[string]string{},
Usage: `Zero-or-more claim equality in list checks, formatted as claim=value1,value2,... example: "actor=user1,user2"`,
},
&cli.StringMapFlag{
Name: "claim-glob",
Value: map[string]string{},
Usage: `Zero-or-more claim glob checks, formatted as claim=value, example: "sub=repo:forgejo/*:pull_request"`,
},
&cli.StringMapFlag{
Name: "claim-glob-in",
Value: map[string]string{},
Usage: `Zero-or-more claim glob in list checks, formatted as claim=va*ue1,va*ue2,... example: "sub=repo:*/*:pull_request,repo:*/*:refs:*"`,
},
// nested claim support omitted for now -- pretty complex for a CLI
// Permissions available on successful auth:
&cli.StringSliceFlag{
Name: "scope",
Value: []string{"all"},
Usage: `One-or-more scopes to apply to access token, examples: "all", "read:issue", "write:repository"`,
},
&cli.StringSliceFlag{
Name: "repo",
Value: []string{"all"},
Usage: `Zero-or-more specific repositories that can be accessed, or "all" to allow access to all repositories, example: "owner1/repo1"`,
},
},
Before: noDanglingArgs,
Action: runCreateAuthorizedIntegration,
}
}
func runCreateAuthorizedIntegration(ctx context.Context, c *cli.Command) error {
if !c.IsSet("username") {
return errors.New("you must provide a username to generate a token for")
}
ctx, cancel := installSignals(ctx)
defer cancel()
if err := initDB(ctx); err != nil {
return err
}
user, err := user_model.GetUserByName(ctx, c.String("username"))
if err != nil {
return err
}
ai := &auth_model.AuthorizedIntegration{
UserID: user.ID,
Name: c.String("name"),
Description: c.String("description"),
}
var rules []auth_model.ClaimRule
ai.Issuer = c.String("issuer")
for claim, value := range c.StringMap("claim-eq") {
rules = append(rules, auth_model.ClaimRule{
Claim: claim,
Comparison: auth_model.ClaimEqual,
Value: value,
})
}
for claim, value := range c.StringMap("claim-in") {
values := []string{}
for s := range strings.SplitSeq(value, ",") {
values = append(values, strings.TrimSpace(s))
}
rules = append(rules, auth_model.ClaimRule{
Claim: claim,
Comparison: auth_model.ClaimIn,
Values: values,
})
}
for claim, value := range c.StringMap("claim-glob") {
rules = append(rules, auth_model.ClaimRule{
Claim: claim,
Comparison: auth_model.ClaimGlob,
Value: value,
})
}
for claim, value := range c.StringMap("claim-glob-in") {
values := []string{}
for s := range strings.SplitSeq(value, ",") {
values = append(values, strings.TrimSpace(s))
}
rules = append(rules, auth_model.ClaimRule{
Claim: claim,
Comparison: auth_model.ClaimGlobIn,
Values: values,
})
}
ai.ClaimRules = &auth_model.ClaimRules{Rules: rules}
scopes := strings.Join(c.StringSlice("scope"), ",")
accessTokenScope, err := auth_model.AccessTokenScope(scopes).Normalize()
if err != nil {
return fmt.Errorf("invalid access token scope provided: %w", err)
}
ai.Scope = accessTokenScope
allRepos := false
repos := []*repo.Repository{}
for _, repoName := range c.StringSlice("repo") {
if repoName == "all" {
allRepos = true
} else {
split := strings.Split(repoName, "/")
if len(split) != 2 {
return fmt.Errorf("invalid repo name: %q", split)
}
owner := split[0]
name := split[1]
repo, err := repo.GetRepositoryByOwnerAndName(ctx, owner, name)
if err != nil {
return err
}
repos = append(repos, repo)
}
}
ai.ResourceAllRepos = allRepos
rr := make([]*auth_model.AuthorizedIntegResourceRepo, len(repos))
for i := range repos {
rr[i] = &auth_model.AuthorizedIntegResourceRepo{RepoID: repos[i].ID}
}
if err := authz.ValidateAuthorizedIntegration(ai, rr); err != nil {
return err
}
err = db.WithTx(ctx, func(ctx context.Context) error {
if err := auth_model.InsertAuthorizedIntegration(ctx, ai); err != nil {
return err
}
if !allRepos {
if err := auth_model.InsertAuthorizedIntegrationResourceRepos(ctx, ai.ID, rr); err != nil {
return err
}
}
return nil
})
if err != nil {
return err
}
type ClaimRuleDescription struct {
Description string `json:"description"`
Claim string `json:"claim"`
Comparison auth_model.ClaimComparison `json:"compare"`
Value string `json:"value,omitempty"`
Values []string `json:"values,omitempty"`
}
output := struct {
Message string `json:"message"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Issuer string `json:"issuer"`
Audience string `json:"audience"`
ClaimRules []ClaimRuleDescription `json:"claim_rules"`
}{
Message: "Authorized integration was successfully created.",
Name: ai.Name,
Description: ai.Description,
Issuer: ai.Issuer,
Audience: ai.Audience,
}
for _, cr := range ai.ClaimRules.Rules {
var description string
switch cr.Comparison {
case auth_model.ClaimEqual:
description = fmt.Sprintf("%q = %q", cr.Claim, cr.Value)
case auth_model.ClaimIn:
description = fmt.Sprintf("%q in %q", cr.Claim, cr.Values)
case auth_model.ClaimGlob:
description = fmt.Sprintf("%q matches %q", cr.Claim, cr.Value)
case auth_model.ClaimGlobIn:
description = fmt.Sprintf("%q matches in %q", cr.Claim, cr.Values)
}
output.ClaimRules = append(output.ClaimRules, ClaimRuleDescription{
Description: description,
Claim: cr.Claim,
Comparison: cr.Comparison,
Value: cr.Value,
Values: cr.Values,
})
}
raw, err := json.Marshal(output)
if err != nil {
return err
}
var indent bytes.Buffer
if err := json.Indent(&indent, raw, "", " "); err != nil {
return err
}
os.Stdout.Write(indent.Bytes())
return nil
}

View file

@ -112,10 +112,7 @@ func getArchiverByType(outType string) (archives.ArchiverAsync, error) {
var archiver archives.ArchiverAsync
switch outType {
case "zip":
archiver = archives.Zip{
Compression: 8,
SelectiveCompression: false,
}
archiver = archives.Zip{}
case "tar":
archiver = archives.Tar{}
case "tar.sz":

View file

@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"testing"
@ -63,12 +62,7 @@ func runTestApp(app *cli.Command, args ...string) (runResult, error) {
}
func TestCliCmd(t *testing.T) {
path, err := os.Executable()
if err != nil {
panic(err)
}
defaultWorkPath := filepath.Dir(path)
defaultWorkPath := filepath.Dir(setting.AppPath)
defaultCustomPath := filepath.Join(defaultWorkPath, "custom")
defaultCustomConf := filepath.Join(defaultCustomPath, "conf/app.ini")

View file

@ -290,9 +290,10 @@ func runServ(ctx context.Context, c *cli.Command) error {
Op: lfsVerb,
UserID: results.UserID,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Sign and get the complete encoded token as a string using the secret
tokenString, err := setting.LFS.SigningKey.JWT(claims)
tokenString, err := token.SignedString(setting.LFS.JWTSecretBytes)
if err != nil {
return fail(ctx, "Failed to sign JWT Token", "Failed to sign JWT token: %v", err)
}

View file

@ -164,6 +164,8 @@ func serveInstall(_ context.Context, ctx *cli.Command) error {
}
func serveInstalled(_ context.Context, ctx *cli.Command) error {
setting.InitCfgProvider(setting.CustomConf)
setting.LoadCommonSettings()
setting.MustInstalled()
showWebStartupMessage("Prepare to run web server")

View file

@ -52,7 +52,7 @@ After=network.target
# Uncomment the next line if you have repos with lots of files and get a HTTP 500 error because of that
# LimitNOFILE=524288:524288
RestartSec=2s
Type=notify
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/forgejo/

View file

@ -313,9 +313,6 @@ RUN_USER = ; git
;LFS_START_SERVER = false
;;
;;
;; see JWT_* under [oauth2]
;LFS_JWT_SIGNING_ALGORITHM = HS256
;LFS_JWT_SIGNING_PRIVATE_KEY_FILE = jwt/lfs_private.pem
;; LFS authentication secret, change this yourself
;LFS_JWT_SECRET =
;;
@ -547,7 +544,6 @@ ENABLED = true
;; Private key file path used to sign OAuth2 tokens. The path is relative to APP_DATA_PATH.
;; This setting is only needed if JWT_SIGNING_ALGORITHM is set to RS256, RS384, RS512, ES256, ES384 or ES512.
;; The file must contain a RSA or ECDSA private key in the PKCS8 format. If no key exists a 4096 bit key will be created for you.
;; XXX jwt/ is a misnomer, it should rather be oauth2/, because we use many JWTs
;JWT_SIGNING_PRIVATE_KEY_FILE = jwt/private.pem
;;
;; OAuth2 authentication secret for access and refresh tokens, change this yourself to a unique string. CLI generate option is helpful in this case. https://forgejo.org/docs/latest/admin/command-line/#generate-secret
@ -2794,7 +2790,7 @@ LEVEL = Info
;; server and database workload due to more complex database queries and more frequent server task querying; this
;; feature can be disabled to reduce performance impact
;CONCURRENCY_GROUP_QUEUE_ENABLED = true
;; Algorithm used to sign ID tokens. Valid values: RS256, RS384, RS512, ES256, ES384, ES512, EdDSA.
;; Algorithm used to sign ID tokens. Valid values: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, EdDSA.
;; RS256 will ensure compatibility with all relying parties.
;; If a different algorithm is chosen, verify that relying parties of interest support the signing algorithm.
;ID_TOKEN_SIGNING_ALGORITHM = RS256
@ -2823,30 +2819,3 @@ LEVEL = Info
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; storage type
;STORAGE_TYPE = local
;; Authorized integrations are a capability for users to define external systems which can generate JWTs that Forgejo
;; will trust in order to perform API access on behalf of that user. While validating a JWT from an external system,
;; Forgejo makes outgoing HTTP requests to the JWT issuer.
; [authorized_integration]
;; Timeout for HTTP requests to remote servers. Default is 10 seconds.
;REQUEST_TIMEOUT = 10s
;
;; Allowed domains for authorized integrations. Default is blank which means all domains will be allowed (except local
;; networks, see ALLOW_LOCALNETWORKS).
;; Multiple domains can be separated by commas.
;; Wildcards are supported: "github.com, *.github.com"
;ALLOWED_DOMAINS =
;
;; Blocklist for authorized integrations, default is blank.
;; Multiple domains can be separated by commas.
;; Wildcards are supported: "github.com, *.github.com"
;BLOCKED_DOMAINS =
;
;; Allow private addresses defined by RFC 1918, RFC 1122, RFC 4632 and RFC 4291.
;; Default is false.
;; If a domain is allowed by ALLOWED_DOMAINS, this option will be ignored.
;ALLOW_LOCALNETWORKS = false
;
;; Remote requests are cached after being received for the cache time-to-live (TTL). Default is 10 minutes.
;; Caching uses the configured adapter in the [cache] config section.
;CACHE_TTL = 10m

6
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1777954456,
"narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=",
"lastModified": 1762977756,
"narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1",
"rev": "c5ae371f1a6a7fd27823bc500d9390b38c05fa55",
"type": "github"
},
"original": {

129
go.mod
View file

@ -1,6 +1,6 @@
module forgejo.org
go 1.26.0
go 1.25.0
toolchain go1.26.3
@ -11,27 +11,27 @@ require (
code.forgejo.org/forgejo/go-rpmutils v1.0.0
code.forgejo.org/forgejo/levelqueue v1.0.0
code.forgejo.org/forgejo/reply v1.0.2
code.forgejo.org/forgejo/runner/v12 v12.10.1
code.forgejo.org/forgejo/runner/v12 v12.8.0
code.forgejo.org/go-chi/binding v1.0.1
code.forgejo.org/go-chi/cache v1.0.1
code.forgejo.org/go-chi/captcha v1.0.2
code.forgejo.org/go-chi/session v1.0.4
code.forgejo.org/go-chi/session v1.0.3
code.gitea.io/sdk/gitea v0.21.0
code.superseriousbusiness.org/exif-terminator v0.11.2
code.superseriousbusiness.org/exif-terminator v0.11.1
code.superseriousbusiness.org/go-jpeg-image-structure/v2 v2.3.0
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
connectrpc.com/connect v1.19.2
connectrpc.com/connect v1.19.1
github.com/42wim/httpsig v1.2.3
github.com/42wim/sshsig v0.0.0-20250502153856-5100632e8920
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
github.com/ProtonMail/go-crypto v1.4.1
github.com/PuerkitoBio/goquery v1.12.0
github.com/PuerkitoBio/goquery v1.11.0
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0
github.com/alecthomas/chroma/v2 v2.23.1
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.6.0
github.com/blevesearch/bleve/v2 v2.5.7
github.com/buildkite/terminal-to-html/v3 v3.16.8
github.com/caddyserver/certmagic v0.25.3
github.com/caddyserver/certmagic v0.24.0
github.com/chi-middleware/proxy v1.1.1
github.com/djherbis/buffer v1.2.0
github.com/djherbis/nio/v3 v3.0.1
@ -41,46 +41,45 @@ require (
github.com/editorconfig/editorconfig-core-go/v2 v2.6.4
github.com/emersion/go-imap v1.2.1
github.com/felixge/fgprof v0.9.5
github.com/fsnotify/fsnotify v1.10.1
github.com/gdgvda/cron v0.7.0
github.com/fsnotify/fsnotify v1.9.0
github.com/gliderlabs/ssh v0.3.8
github.com/go-ap/activitypub v0.0.0-20260208110334-902f6cf8c2cc
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
github.com/go-ap/jsonld v0.0.0-20251216162253-e38fa664ea77
github.com/go-chi/chi/v5 v5.2.5
github.com/go-chi/cors v1.2.2
github.com/go-co-op/gocron v1.37.0
github.com/go-enry/go-enry/v2 v2.9.6
github.com/go-enry/go-enry/v2 v2.9.5
github.com/go-ldap/ldap/v3 v3.4.12
github.com/go-openapi/spec v0.22.3
github.com/go-sql-driver/mysql v1.10.0
github.com/go-webauthn/webauthn v0.16.5
github.com/go-sql-driver/mysql v1.9.3
github.com/go-webauthn/webauthn v0.16.1
github.com/gobwas/glob v0.2.3
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/google/go-github/v81 v81.0.0
github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc
github.com/google/pprof v0.0.0-20251114195745-4902fdda35c8
github.com/google/uuid v1.6.0
github.com/gorilla/feeds v1.2.0
github.com/gorilla/sessions v1.4.0
github.com/hashicorp/go-version v1.8.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/huandu/xstrings v1.5.0
github.com/inbucket/html2text v1.0.0
github.com/inbucket/html2text v0.9.0
github.com/jackc/pgx/v5 v5.9.2
github.com/jhillyerd/enmime/v2 v2.2.0
github.com/json-iterator/go v1.1.12
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/klauspost/compress v1.18.6
github.com/klauspost/cpuid/v2 v2.3.0
github.com/klauspost/compress v1.18.4
github.com/klauspost/cpuid/v2 v2.2.11
github.com/markbates/goth v1.82.0
github.com/mattn/go-isatty v0.0.21
github.com/mattn/go-sqlite3 v1.14.44
github.com/meilisearch/meilisearch-go v0.36.2
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-sqlite3 v1.14.42
github.com/meilisearch/meilisearch-go v0.36.0
github.com/mholt/archives v0.1.5
github.com/microcosm-cc/bluemonday v1.0.27
github.com/minio/minio-go/v7 v7.1.0
github.com/minio/minio-go/v7 v7.0.99
github.com/msteinert/pam/v2 v2.1.0
github.com/niklasfasching/go-org v1.9.1
github.com/olivere/elastic/v7 v7.0.32
@ -88,26 +87,28 @@ require (
github.com/opencontainers/image-spec v1.1.1
github.com/pquerna/otp v1.5.0
github.com/prometheus/client_golang v1.21.1
github.com/redis/go-redis/v9 v9.19.0
github.com/redis/go-redis/v9 v9.17.3
github.com/robfig/cron/v3 v3.0.1
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
github.com/sergi/go-diff v1.4.0
github.com/stretchr/testify v1.11.1
github.com/syndtr/goleveldb v1.0.0
github.com/ulikunitz/xz v0.5.15
github.com/urfave/cli/v3 v3.8.0
github.com/urfave/cli/v3 v3.7.0
github.com/valyala/fastjson v1.6.10
github.com/yohcop/openid-go v1.0.1
github.com/yuin/goldmark v1.8.2
github.com/yuin/goldmark v1.7.17
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
gitlab.com/gitlab-org/api/client-go v0.143.2
go.uber.org/mock v0.6.0
go.yaml.in/yaml/v3 v3.0.4
golang.org/x/crypto v0.51.0
golang.org/x/image v0.40.0
golang.org/x/net v0.54.0
golang.org/x/crypto v0.50.0
golang.org/x/image v0.39.0
golang.org/x/net v0.53.0
golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.20.0
golang.org/x/sys v0.44.0
golang.org/x/text v0.37.0
golang.org/x/sys v0.43.0
golang.org/x/text v0.36.0
google.golang.org/protobuf v1.36.11
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.67.0
@ -119,46 +120,46 @@ require (
require (
cloud.google.com/go/compute/metadata v0.6.0 // indirect
code.superseriousbusiness.org/go-png-image-structure/v2 v2.3.0 // indirect
filippo.io/edwards25519 v1.2.0 // indirect
filippo.io/edwards25519 v1.1.1 // indirect
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
github.com/RoaringBitmap/roaring/v2 v2.14.5 // indirect
github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect
github.com/STARRY-S/zip v0.2.3 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.24.2 // indirect
github.com/blevesearch/bleve_index_api v1.3.11 // indirect
github.com/blevesearch/geo v0.2.5 // indirect
github.com/blevesearch/go-faiss v1.1.0 // indirect
github.com/bits-and-blooms/bitset v1.22.0 // indirect
github.com/blevesearch/bleve_index_api v1.2.11 // indirect
github.com/blevesearch/geo v0.2.4 // indirect
github.com/blevesearch/go-faiss v1.0.26 // indirect
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
github.com/blevesearch/gtreap v0.1.1 // indirect
github.com/blevesearch/mmap-go v1.2.0 // indirect
github.com/blevesearch/scorch_segment_api/v2 v2.4.7 // indirect
github.com/blevesearch/mmap-go v1.0.4 // indirect
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 // indirect
github.com/blevesearch/segment v0.9.1 // indirect
github.com/blevesearch/snowballstem v0.9.0 // indirect
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
github.com/blevesearch/vellum v1.2.0 // indirect
github.com/blevesearch/zapx/v11 v11.4.3 // indirect
github.com/blevesearch/zapx/v12 v12.4.3 // indirect
github.com/blevesearch/zapx/v13 v13.4.3 // indirect
github.com/blevesearch/zapx/v14 v14.4.3 // indirect
github.com/blevesearch/zapx/v15 v15.4.3 // indirect
github.com/blevesearch/zapx/v16 v16.3.4 // indirect
github.com/blevesearch/zapx/v17 v17.1.2 // indirect
github.com/blevesearch/vellum v1.1.0 // indirect
github.com/blevesearch/zapx/v11 v11.4.2 // indirect
github.com/blevesearch/zapx/v12 v12.4.2 // indirect
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
github.com/blevesearch/zapx/v16 v16.2.8 // indirect
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
github.com/bodgit/plumbing v1.3.0 // indirect
github.com/bodgit/sevenzip v1.6.1 // indirect
github.com/bodgit/windows v1.0.1 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect
github.com/caddyserver/zerossl v0.1.5 // indirect
github.com/caddyserver/zerossl v0.1.3 // indirect
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.6.3 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/dsoprea/go-iptc v0.0.0-20200609062250-162ae6b44feb // indirect
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
@ -166,12 +167,15 @@ require (
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
github.com/go-ap/errors v0.0.0-20260208110149-e1b309365966 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
github.com/go-enry/go-oniguruma v1.2.1 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-fed/httpsig v1.1.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.8.0 // indirect
github.com/go-git/go-git/v5 v5.18.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-openapi/jsonpointer v0.22.4 // indirect
github.com/go-openapi/jsonreference v0.21.4 // indirect
@ -183,11 +187,11 @@ require (
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/go-webauthn/x v0.2.3 // indirect
github.com/go-webauthn/x v0.2.2 // indirect
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
@ -200,17 +204,19 @@ require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/crc32 v1.3.0 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/libdns/libdns v1.1.1 // indirect
github.com/lib/pq v1.11.2 // indirect
github.com/libdns/libdns v1.0.0 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/markbates/going v1.0.3 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-runewidth v0.0.17 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/mholt/acmez/v3 v3.1.6 // indirect
github.com/miekg/dns v1.1.72 // indirect
github.com/mholt/acmez/v3 v3.1.2 // indirect
github.com/miekg/dns v1.1.63 // indirect
github.com/mikelolasagasti/xz v1.0.1 // indirect
github.com/minio/crc64nvme v1.1.1 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
@ -225,7 +231,6 @@ require (
github.com/olekukonko/ll v0.0.9 // indirect
github.com/olekukonko/tablewriter v1.0.7 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.34.1 // indirect
github.com/philhofer/fwd v1.2.0 // indirect
github.com/pierrec/lz4/v4 v4.1.22 // indirect
github.com/pkg/errors v0.9.1 // indirect
@ -235,28 +240,28 @@ require (
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rhysd/actionlint v1.7.10 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rs/xid v1.6.0 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/sorairolake/lzip-go v0.3.8 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/tinylib/msgp v1.6.4 // indirect
github.com/tinylib/msgp v1.6.1 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/zeebo/assert v1.3.0 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
github.com/zeebo/xxh3 v1.1.0 // indirect
go.etcd.io/bbolt v1.4.3 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.1 // indirect
go.uber.org/zap v1.27.0 // indirect
go.uber.org/zap/exp v0.3.0 // indirect
go.yaml.in/yaml/v4 v4.0.0-rc.3 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/mod v0.35.0 // indirect
golang.org/x/mod v0.34.0 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/tools v0.44.0 // indirect
golang.org/x/tools v0.43.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
@ -269,4 +274,4 @@ replace github.com/gliderlabs/ssh => code.forgejo.org/forgejo/ssh v0.0.0-2024121
replace git.sr.ht/~mariusor/go-xsd-duration => code.forgejo.org/forgejo/go-xsd-duration v0.0.0-20220703122237-02e73435a078
replace xorm.io/xorm v1.3.9 => code.forgejo.org/xorm/xorm v1.3.9-forgejo.12
replace xorm.io/xorm v1.3.9 => code.forgejo.org/xorm/xorm v1.3.9-forgejo.11

268
go.sum
View file

@ -30,8 +30,8 @@ code.forgejo.org/forgejo/levelqueue v1.0.0 h1:9krYpU6BM+j/1Ntj6m+VCAIu0UNnne1/Uf
code.forgejo.org/forgejo/levelqueue v1.0.0/go.mod h1:fmG6zhVuqim2rxSFOoasgXO8V2W/k9U31VVYqLIRLhQ=
code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ=
code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U=
code.forgejo.org/forgejo/runner/v12 v12.10.1 h1:qRKjWItVDc2lEMl3jGlKyFpqgX4xHeOdEyl/irO/Nk8=
code.forgejo.org/forgejo/runner/v12 v12.10.1/go.mod h1:A51GyZJlril5cIpVMvOn3NqE8upOE6ePjwC6s31kRHk=
code.forgejo.org/forgejo/runner/v12 v12.8.0 h1:/MqOseYbsGaQ2qzepaZr3VyuqpESvSP/ZnC2aKfmU3g=
code.forgejo.org/forgejo/runner/v12 v12.8.0/go.mod h1:sgDAYfO4NJI1kUzGuD7klHuoFLQzWmZPw0erg7QlbJU=
code.forgejo.org/forgejo/ssh v0.0.0-20241211213324-5fc306ca0616 h1:kEZL84+02jY9RxXM4zHBWZ3Fml0B09cmP1LGkDsCfIA=
code.forgejo.org/forgejo/ssh v0.0.0-20241211213324-5fc306ca0616/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
code.forgejo.org/go-chi/binding v1.0.1 h1:coKNI+X1NzRN7X85LlrpvBRqk0TXpJ+ja28vusQWEuY=
@ -40,27 +40,25 @@ code.forgejo.org/go-chi/cache v1.0.1 h1:w6IsDcPbeEnEYZn7M2HJe3/3/Ehtcw/72VjcVK7+
code.forgejo.org/go-chi/cache v1.0.1/go.mod h1:K3aQSyRIN4xiuqV1kanfQ6O4ToDpzDpY3bNOyGjFe3U=
code.forgejo.org/go-chi/captcha v1.0.2 h1:vyHDPXkpjDv8bLO9NqtWzZayzstD/WpJ5xwEkAaqZGQ=
code.forgejo.org/go-chi/captcha v1.0.2/go.mod h1:lxiPLcJ76UCZHoH31/Wbum4GUi2NgjfFZLrJkKv1lLE=
code.forgejo.org/go-chi/session v1.0.4 h1:WQ1NaVxcCpxYwCliEGypKclZnOCjh3p1fk8XciJc62U=
code.forgejo.org/go-chi/session v1.0.4/go.mod h1:+sSTiomM5C8AUPtxZyTENIbcTz22kcVottKO0lnmDRk=
code.forgejo.org/xorm/xorm v1.3.9-forgejo.12 h1:EodlU2MGu/EeAdUpEOe+X4cU/qlnJol1ucJ0sHUCM1o=
code.forgejo.org/xorm/xorm v1.3.9-forgejo.12/go.mod h1:ozQINrM8b7uYFMBB/w19nUTTLcda3RKTQ8HspocVKdg=
code.forgejo.org/go-chi/session v1.0.3 h1:ByJ9c/UC0AU57hxiGl53TXh+NdBOBwK/bhZ9jyadEwE=
code.forgejo.org/go-chi/session v1.0.3/go.mod h1:xzGtFrV/agCJoZCUhFDlqAr1he6BrAdqlaprKOB1W90=
code.forgejo.org/xorm/xorm v1.3.9-forgejo.11 h1:EXJVQ4feAFMkpFwtHAHuXkK6TLNYqabR7QTzqL8uObY=
code.forgejo.org/xorm/xorm v1.3.9-forgejo.11/go.mod h1:C18NeM/SazG/q4eqpWnoNks7GeCyRUNQIe2onniRViU=
code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4=
code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA=
code.pfad.fr/check v1.1.0 h1:GWvjdzhSEgHvEHe2uJujDcpmZoySKuHQNrZMfzfO0bE=
code.pfad.fr/check v1.1.0/go.mod h1:NiUH13DtYsb7xp5wll0U4SXx7KhXQVCtRgdC96IPfoM=
code.superseriousbusiness.org/exif-terminator v0.11.2 h1:nkTdaghZb6I0oGYFhTLSALhA2ShgkPnYAJryE5IE9+0=
code.superseriousbusiness.org/exif-terminator v0.11.2/go.mod h1:/Z+3DHSrefCzzN5ePkGjVYKFErRimoeUf694Gz8Pn/Y=
code.superseriousbusiness.org/exif-terminator v0.11.1 h1:qnujLH4/Yk/CFtFMmtjozbdV6Ry5G3Q/E/mLlWm/gQI=
code.superseriousbusiness.org/exif-terminator v0.11.1/go.mod h1:/Z+3DHSrefCzzN5ePkGjVYKFErRimoeUf694Gz8Pn/Y=
code.superseriousbusiness.org/go-jpeg-image-structure/v2 v2.3.0 h1:r9uq8StaSHYKJ8DklR9Xy+E9c40G1Z8yj5TRGi8L6+4=
code.superseriousbusiness.org/go-jpeg-image-structure/v2 v2.3.0/go.mod h1:IK1OlR6APjVB3E9tuYGvf0qXMrwP+TrzcHS5rf4wffQ=
code.superseriousbusiness.org/go-png-image-structure/v2 v2.3.0 h1:I512jiIeXDC4//2BeSPrRM2ZS4wpBKUaPeTPxakMNGA=
code.superseriousbusiness.org/go-png-image-structure/v2 v2.3.0/go.mod h1:SNHomXNW88o1pFfLHpD4KsCZLfcr4z5dm+xcX5SV10A=
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
connectrpc.com/connect v1.19.2 h1:McQ83FGdzL+t60peksi0gXC7MQ/iLKgLduAnThbM0mo=
connectrpc.com/connect v1.19.2/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=
filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs=
@ -75,10 +73,10 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ProtonMail/go-crypto v1.4.1 h1:9RfcZHqEQUvP8RzecWEUafnZVtEvrBVL9BiF67IQOfM=
github.com/ProtonMail/go-crypto v1.4.1/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo=
github.com/PuerkitoBio/goquery v1.12.0 h1:pAcL4g3WRXekcB9AU/y1mbKez2dbY2AajVhtkO8RIBo=
github.com/PuerkitoBio/goquery v1.12.0/go.mod h1:802ej+gV2y7bbIhOIoPY5sT183ZW0YFofScC4q/hIpQ=
github.com/RoaringBitmap/roaring/v2 v2.14.5 h1:ckd0o545JqDPeVJDgeFoaM21eBixUnlWfYgjE5VnyWw=
github.com/RoaringBitmap/roaring/v2 v2.14.5/go.mod h1:eq4wdNXxtJIS/oikeCzdX1rBzek7ANzbth041hrU8Q4=
github.com/PuerkitoBio/goquery v1.11.0 h1:jZ7pwMQXIITcUXNH83LLk+txlaEy6NVOfTuP43xxfqw=
github.com/PuerkitoBio/goquery v1.11.0/go.mod h1:wQHgxUOU3JGuj3oD/QFfxUdlzW6xPHfqyHre6VMY4DQ=
github.com/RoaringBitmap/roaring/v2 v2.4.5 h1:uGrrMreGjvAtTBobc0g5IrW1D5ldxDQYe2JW2gggRdg=
github.com/RoaringBitmap/roaring/v2 v2.4.5/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0=
github.com/STARRY-S/zip v0.2.3 h1:luE4dMvRPDOWQdeDdUxUoZkzUIpTccdKdhHHsQJ1fm4=
github.com/STARRY-S/zip v0.2.3/go.mod h1:lqJ9JdeRipyOQJrYSOtpNAiaesFO6zVDsE8GIGFaoSk=
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0 h1:tgjwQrDH5m6jIYB7kac5IQZmfUzQNseac/e3H4VoCNE=
@ -103,48 +101,47 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuP
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bits-and-blooms/bitset v1.24.2 h1:M7/NzVbsytmtfHbumG+K2bremQPMJuqv1JD3vOaFxp0=
github.com/bits-and-blooms/bitset v1.24.2/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4=
github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
github.com/blevesearch/bleve/v2 v2.6.0 h1:Cyd3dd4q5tCbOV8MnKUVRUDYMHOir9xn12NZzXVSEd4=
github.com/blevesearch/bleve/v2 v2.6.0/go.mod h1:gLmI8lWgHgrIYf7UpUX7JISI1CaqC6VScu46mHThuAY=
github.com/blevesearch/bleve_index_api v1.3.11 h1:x29vbV8OjWfLcrDVd7Lr1q+BkLNS0JWNEig0MCVnKH4=
github.com/blevesearch/bleve_index_api v1.3.11/go.mod h1:xvd48t5XMeeioWQ5/jZvgLrV98flT2rdvEJ3l/ki4Ko=
github.com/blevesearch/geo v0.2.5 h1:yJg9FX1oRwLnjXSXF+ECHfXFTF4diF02Ca/qUGVjJhE=
github.com/blevesearch/geo v0.2.5/go.mod h1:Jhq7WE2K6mJTx1xS44M2pUO6Io+wjCSHh1+co3YOgH4=
github.com/blevesearch/go-faiss v1.1.0 h1:xM7Jc0ZUCv5lssG9Ohj3Jv0SdTpxcUABU1dDt9XVsc4=
github.com/blevesearch/go-faiss v1.1.0/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
github.com/blevesearch/bleve/v2 v2.5.7 h1:2d9YrL5zrX5EBBW++GOaEKjE+NPWeZGaX77IM26m1Z8=
github.com/blevesearch/bleve/v2 v2.5.7/go.mod h1:yj0NlS7ocGC4VOSAedqDDMktdh2935v2CSWOCDMHdSA=
github.com/blevesearch/bleve_index_api v1.2.11 h1:bXQ54kVuwP8hdrXUSOnvTQfgK0KI1+f9A0ITJT8tX1s=
github.com/blevesearch/bleve_index_api v1.2.11/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
github.com/blevesearch/geo v0.2.4 h1:ECIGQhw+QALCZaDcogRTNSJYQXRtC8/m8IKiA706cqk=
github.com/blevesearch/geo v0.2.4/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
github.com/blevesearch/go-faiss v1.0.26 h1:4dRLolFgjPyjkaXwff4NfbZFdE/dfywbzDqporeQvXI=
github.com/blevesearch/go-faiss v1.0.26/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
github.com/blevesearch/mmap-go v1.2.0 h1:l33nNKPFcBjJUMwem6sAYJPUzhUCABoK9FxZDGiFNBI=
github.com/blevesearch/mmap-go v1.2.0/go.mod h1:Vd6+20GBhEdwJnU1Xohgt88XCD/CTWcqbCNxkZpyBo0=
github.com/blevesearch/scorch_segment_api/v2 v2.4.7 h1:GlMzW08hcsM3DnLUxhyF/1PcDal1qtvvIuytuph5djw=
github.com/blevesearch/scorch_segment_api/v2 v2.4.7/go.mod h1://IJ7tG3QCf0cWW/aVSXqy77tc1AvLu3fcJLYEvOAFs=
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 h1:ZPjv/4VwWvHJZKeMSgScCapOy8+DdmsmRyLmSB88UoY=
github.com/blevesearch/scorch_segment_api/v2 v2.3.13/go.mod h1:ENk2LClTehOuMS8XzN3UxBEErYmtwkE7MAArFTXs9Vc=
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs=
github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMGZzVrdmaozG2MfoB+A=
github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ=
github.com/blevesearch/vellum v1.2.0 h1:xkDiOEsHc2t3Cp0NsNZZ36pvc130sCzcGKOPMzXe+e0=
github.com/blevesearch/vellum v1.2.0/go.mod h1:uEcfBJz7mAOf0Kvq6qoEKQQkLODBF46SINYNkZNae4k=
github.com/blevesearch/zapx/v11 v11.4.3 h1:PTZOO5loKpHC/x/GzmPZNa9cw7GZIQxd5qRjwij9tHY=
github.com/blevesearch/zapx/v11 v11.4.3/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc=
github.com/blevesearch/zapx/v12 v12.4.3 h1:eElXvAaAX4m04t//CGBQAtHNPA+Q6A1hHZVrN3LSFYo=
github.com/blevesearch/zapx/v12 v12.4.3/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58=
github.com/blevesearch/zapx/v13 v13.4.3 h1:qsdhRhaSpVnqDFlRiH9vG5+KJ+dE7KAW9WyZz/KXAiE=
github.com/blevesearch/zapx/v13 v13.4.3/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk=
github.com/blevesearch/zapx/v14 v14.4.3 h1:GY4Hecx0C6UTmiNC2pKdeA2rOKiLR5/rwpU9WR51dgM=
github.com/blevesearch/zapx/v14 v14.4.3/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
github.com/blevesearch/zapx/v15 v15.4.3 h1:iJiMJOHrz216jyO6lS0m9RTCEkprUnzvqAI2lc/0/CU=
github.com/blevesearch/zapx/v15 v15.4.3/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
github.com/blevesearch/zapx/v16 v16.3.4 h1:hDAqA8qusZTNbPEL7//w5P65UZ2de6yhSeUaTbp0Po0=
github.com/blevesearch/zapx/v16 v16.3.4/go.mod h1:zqkPPqs9GS9FzVWzCO3Wf1X044yWAV17+4zb+FTiEHg=
github.com/blevesearch/zapx/v17 v17.1.2 h1:avbOk2igaASNoiy0BE/jPgcxAnRI2PGeydeP4hg7Ikk=
github.com/blevesearch/zapx/v17 v17.1.2/go.mod h1:WQObxKrqUX7cd0G1GMvDfc/bmZzQvoy7APOPimx7DiI=
github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w=
github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y=
github.com/blevesearch/zapx/v11 v11.4.2 h1:l46SV+b0gFN+Rw3wUI1YdMWdSAVhskYuvxlcgpQFljs=
github.com/blevesearch/zapx/v11 v11.4.2/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc=
github.com/blevesearch/zapx/v12 v12.4.2 h1:fzRbhllQmEMUuAQ7zBuMvKRlcPA5ESTgWlDEoB9uQNE=
github.com/blevesearch/zapx/v12 v12.4.2/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58=
github.com/blevesearch/zapx/v13 v13.4.2 h1:46PIZCO/ZuKZYgxI8Y7lOJqX3Irkc3N8W82QTK3MVks=
github.com/blevesearch/zapx/v13 v13.4.2/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk=
github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT7fWYz0=
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
github.com/blevesearch/zapx/v16 v16.2.8 h1:SlnzF0YGtSlrsOE3oE7EgEX6BIepGpeqxs1IjMbHLQI=
github.com/blevesearch/zapx/v16 v16.2.8/go.mod h1:murSoCJPCk25MqURrcJaBQ1RekuqSCSfMjXH4rHyA14=
github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU=
@ -164,10 +161,10 @@ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/buildkite/terminal-to-html/v3 v3.16.8 h1:QN/daUob6cmK8GcdKnwn9+YTlPr1vNj+oeAIiJK6fPc=
github.com/buildkite/terminal-to-html/v3 v3.16.8/go.mod h1:+k1KVKROZocrTLsEQ9PEf9A+8+X8uaVV5iO1ZIOwKYM=
github.com/caddyserver/certmagic v0.25.3 h1:mGf5ba8F7xA4c5jfDZZbK2buY1VEkbnwpMDixaju94A=
github.com/caddyserver/certmagic v0.25.3/go.mod h1:YVs43D5+H/Dckt4bTga1KSO/xYfFBfVZainGDywYPAA=
github.com/caddyserver/zerossl v0.1.5 h1:dkvOjBAEEtY6LIGAHei7sw2UgqSD6TrWweXpV7lvEvE=
github.com/caddyserver/zerossl v0.1.5/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
github.com/caddyserver/certmagic v0.24.0 h1:EfXTWpxHAUKgDfOj6MHImJN8Jm4AMFfMT6ITuKhrDF0=
github.com/caddyserver/certmagic v0.24.0/go.mod h1:xPT7dC1DuHHnS2yuEQCEyks+b89sUkMENh8dJF+InLE=
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI=
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
@ -194,6 +191,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/djherbis/buffer v1.1.0/go.mod h1:VwN8VdFkMY0DCALdY8o00d3IZ6Amz/UNVMWcSaJT44o=
github.com/djherbis/buffer v1.2.0 h1:PH5Dd2ss0C7CRRhQCZ2u7MssF+No9ide8Ye71nPHcrQ=
github.com/djherbis/buffer v1.2.0/go.mod h1:fjnebbZjCUpPinBRD+TDwXSOeNQ7fPQWLfGQqiAiUyE=
@ -250,16 +249,15 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ=
github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gdgvda/cron v0.7.0 h1:LFPZUTbCb5ZpzYxavbQDDbjd6nwTwkiNUWyulOdlY2I=
github.com/gdgvda/cron v0.7.0/go.mod h1:caBF+mzTZGtQqFE05T1m6u9OmCASY3EK51XAICf3wio=
github.com/go-ap/activitypub v0.0.0-20260208110334-902f6cf8c2cc h1:yLe7YJhK+XNjNV4SqDxAjpWAgft+KU+XwKZS4AKEUV0=
github.com/go-ap/activitypub v0.0.0-20260208110334-902f6cf8c2cc/go.mod h1:jUs8eczo1EAT4ByRpZ4mQmNvjarw9eNf7Nm5udpMRhY=
github.com/go-ap/errors v0.0.0-20260208110149-e1b309365966 h1:tV+3kZgqFMKVUf+JPKBV400ISM8440+6y/SQCS0WZwQ=
github.com/go-ap/errors v0.0.0-20260208110149-e1b309365966/go.mod h1:zkp58Q5yXpCxZbh3d0GDvwqiYclfVuHEHjc9SZKAj6I=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 h1:j2TrkUG/NATGi/EQS+MvEoF79CxiRUmT16ErFroNcKI=
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9/go.mod h1:cJ9Ye0ZNSMN7RzZDBRY3E+8M3Bpf/R1JX22Ir9yX6WI=
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 h1:I2nuhyVI/48VXoRCCZR2hYBgnSXa+EuDJf/VyX06TC0=
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7/go.mod h1:5x8a6P/dhmMGFxWLcyYlyOuJ2lRNaHGhRv+yu8BaTSI=
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA=
github.com/go-ap/jsonld v0.0.0-20251216162253-e38fa664ea77 h1:yHAmoR6avNy84PlLmjHt1z9flAp2Qs2ens5QDE/CNWk=
github.com/go-ap/jsonld v0.0.0-20251216162253-e38fa664ea77/go.mod h1:4h93IBxgfnE/DEleMLgJ/XCeu/RtQ+MUh3ucANseeXA=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
@ -271,8 +269,8 @@ github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
github.com/go-enry/go-enry/v2 v2.9.6 h1:np63eOtMV56zfYDHnFVgpEVOk8fr2kmylcMnAZUDbSs=
github.com/go-enry/go-enry/v2 v2.9.6/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
github.com/go-enry/go-enry/v2 v2.9.5 h1:HPhAQQHYwJgihL2PxBZiUMFWiROsGwOBdB6/D8zCUhY=
github.com/go-enry/go-enry/v2 v2.9.5/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
@ -282,12 +280,16 @@ github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxI
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0=
github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY=
github.com/go-git/go-git/v5 v5.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM=
github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4=
github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo=
github.com/go-openapi/jsonpointer v0.22.4 h1:dZtK82WlNpVLDW2jlA1YCiVJFVqkED1MegOUy9kR5T4=
@ -316,17 +318,17 @@ github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxE
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg=
github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls=
github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
github.com/go-sql-driver/mysql v1.10.0 h1:Q+1LV8DkHJvSYAdR83XzuhDaTykuDx0l6fkXxoWCWfw=
github.com/go-sql-driver/mysql v1.10.0/go.mod h1:M+cqaI7+xxXGG9swrdeUIoPG3Y3KCkF0pZej+SK+nWk=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-webauthn/webauthn v0.16.5 h1:x+vADHlaiIjta23kGhtwyCIlB5mayKx6SBlpwQ5NF9A=
github.com/go-webauthn/webauthn v0.16.5/go.mod h1:mQC6L0lZ5Kiu35G70zeB2WnrW4+vbHjR8Koq4HdVaMg=
github.com/go-webauthn/x v0.2.3 h1:8oArS+Rc1SWFLXhE17KZNx258Z4kUSyaDgsSncCO5RA=
github.com/go-webauthn/x v0.2.3/go.mod h1:tM04GF3V6VYq79AZMl7vbj4q6pz9r7L2criWRzbWhPk=
github.com/go-webauthn/webauthn v0.16.1 h1:x5/SSki5/aIfogaRukqvbg/RXa3Sgxy/9vU7UfFPHKU=
github.com/go-webauthn/webauthn v0.16.1/go.mod h1:RBS+rtQJMkE5VfMQ4diDA2VNrEL8OeUhp4Srz37FHbQ=
github.com/go-webauthn/x v0.2.2 h1:zIiipvMbr48CXi5RG0XdBJR94kd8I5LfzHPb/q+YYmk=
github.com/go-webauthn/x v0.2.2/go.mod h1:IpJ5qyWB9NRhLX3C7gIfjTU7RZLXEP6kzFkoVSE7Fz4=
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo=
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
@ -367,8 +369,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
@ -398,8 +400,8 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc h1:VBbFa1lDYWEeV5FZKUiYKYT0VxCp9twUmmaq9eb8sXw=
github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
github.com/google/pprof v0.0.0-20251114195745-4902fdda35c8 h1:3DsUAV+VNEQa2CUVLxCY3f87278uWfIDhJnbdvDjvmE=
github.com/google/pprof v0.0.0-20251114195745-4902fdda35c8/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@ -439,8 +441,8 @@ github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
github.com/inbucket/html2text v1.0.0 h1:N5kza++4uBBDJ2Z3KUnTRyPNoBcW+YfOgNiNmNB+sgs=
github.com/inbucket/html2text v1.0.0/go.mod h1:5TrhXQKGU+LXurODaSm55Y9eXoPBRnYiOz4x2XfUoJU=
github.com/inbucket/html2text v0.9.0 h1:ULJmVcBEMAcmLE+/rN815KG1Fx6+a4HhbUxiDiN+qks=
github.com/inbucket/html2text v0.9.0/go.mod h1:QDaumzl+/OzlSVbNohhmg+yAy5pKjUjzCKW2BMvztKE=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
@ -449,6 +451,8 @@ github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw=
github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
@ -475,12 +479,12 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.18.6 h1:2jupLlAwFm95+YDR+NwD2MEfFO9d4z4Prjl1XXDjuao=
github.com/klauspost/compress v1.18.6/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU=
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM=
github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
@ -497,12 +501,10 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh5YzC3JVwU=
github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk=
github.com/letsencrypt/pebble/v2 v2.10.0 h1:Wq6gYXlsY6ubqI3hhxsTzdyotvfdjFBxuwYqCLCnj/U=
github.com/letsencrypt/pebble/v2 v2.10.0/go.mod h1:Sk8cmUIPcIdv2nINo+9PB4L+ZBhzY+F9A1a/h/xmWiQ=
github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U=
github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs=
github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
github.com/libdns/libdns v1.0.0 h1:IvYaz07JNz6jUQ4h/fv2R4sVnRnm77J/aOuC9B+TQTA=
github.com/libdns/libdns v1.0.0/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
@ -512,32 +514,32 @@ github.com/markbates/goth v1.82.0 h1:8j/c34AjBSTNzO7zTsOyP5IYCQCMBTRBHAbBt/PI0bQ
github.com/markbates/goth v1.82.0/go.mod h1:/DRlcq0pyqkKToyZjsL2KgiA1zbF1HIjE7u2uC79rUk=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.17 h1:78v8ZlW0bP43XfmAfPsdXcoNCelfMHsDmd/pkENfrjQ=
github.com/mattn/go-runewidth v0.0.17/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.14.44 h1:3VSe+xafpbzsLbdr2AWlAZk9yRHiBhTBakioXaCKTF8=
github.com/mattn/go-sqlite3 v1.14.44/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
github.com/meilisearch/meilisearch-go v0.36.2 h1:MYaMPCpdLh2aYPt+zK+19mLoA4dfBY3S1L7T0FADCjU=
github.com/meilisearch/meilisearch-go v0.36.2/go.mod h1:hWcR0MuWLSzHfbz9GGzIr3s9rnXLm1jqkmHkJPbUSvM=
github.com/mholt/acmez/v3 v3.1.6 h1:eGVQNObP0pBN4sxqrXeg7MYqTOWyoiYpQqITVWlrevk=
github.com/mholt/acmez/v3 v3.1.6/go.mod h1:5nTPosTGosLxF3+LU4ygbgMRFDhbAVpqMI4+a4aHLBY=
github.com/mattn/go-sqlite3 v1.14.42 h1:MigqEP4ZmHw3aIdIT7T+9TLa90Z6smwcthx+Azv4Cgo=
github.com/mattn/go-sqlite3 v1.14.42/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ=
github.com/meilisearch/meilisearch-go v0.36.0 h1:N1etykTektXt5KPcSbhBO0d5Xx5NaKj4pJWEM7WA5dI=
github.com/meilisearch/meilisearch-go v0.36.0/go.mod h1:HBfHzKMxcSbTOvqdfuRA/yf6Vk9IivcwKocWRuW7W78=
github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc=
github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
github.com/mholt/archives v0.1.5 h1:Fh2hl1j7VEhc6DZs2DLMgiBNChUux154a1G+2esNvzQ=
github.com/mholt/archives v0.1.5/go.mod h1:3TPMmBLPsgszL+1As5zECTuKwKvIfj6YcwWPpeTAXF4=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0=
github.com/mikelolasagasti/xz v1.0.1/go.mod h1:muAirjiOUxPRXwm9HdDtB3uoRPrGnL85XHtokL9Hcgc=
github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI=
github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.1.0 h1:QEt5IStDpxgGjEdtOgpiZ5QhmSl3ax7qy61vi2SwHO8=
github.com/minio/minio-go/v7 v7.1.0/go.mod h1:Dm7WS1AgLmBa0NcQD6SeJnJf+K/EUW3GR7Ks6olB3OA=
github.com/minio/minio-go/v7 v7.0.99 h1:2vH/byrwUkIpFQFOilvTfaUpvAX3fEFhEzO+DR3DlCE=
github.com/minio/minio-go/v7 v7.0.99/go.mod h1:EtGNKtlX20iL2yaYnxEigaIvj0G0GwSDnifnG8ClIdw=
github.com/minio/minlz v1.0.1 h1:OUZUzXcib8diiX+JYxyRLIdomyZYzHct6EShOKtQY2A=
github.com/minio/minlz v1.0.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -606,8 +608,8 @@ github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/redis/go-redis/v9 v9.19.0 h1:XPVaaPSnG6RhYf7p+rmSa9zZfeVAnWsH5h3lxthOm/k=
github.com/redis/go-redis/v9 v9.19.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA=
github.com/redis/go-redis/v9 v9.17.3 h1:fN29NdNrE17KttK5Ndf20buqfDZwGNgoUr9qjl1DQx4=
github.com/redis/go-redis/v9 v9.17.3/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rhysd/actionlint v1.7.10 h1:FL3XIEs72G4/++168vlv5FKOWMSWvWIQw1kBCadyOcM=
@ -655,13 +657,14 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ=
github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
github.com/tinylib/msgp v1.6.1 h1:ESRv8eL3u+DNHUoSAAQRE50Hm162zqAnBoGv9PzScPY=
github.com/tinylib/msgp v1.6.1/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v3 v3.8.0 h1:XqKPrm0q4P0q5JpoclYoCAv0/MIvH/jZ2umzuf8pNTI=
github.com/urfave/cli/v3 v3.8.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/urfave/cli/v3 v3.7.0 h1:AGSnbUyjtLiM+WJUb4dzXKldl/gL+F8OwmRDtVr6g2U=
github.com/urfave/cli/v3 v3.7.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
@ -673,8 +676,8 @@ github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBz
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE=
github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/yuin/goldmark v1.7.17 h1:p36OVWwRb246iHxA/U4p8OPEpOTESm4n+g+8t0EE5uA=
github.com/yuin/goldmark v1.7.17/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
@ -683,8 +686,6 @@ github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
gitlab.com/gitlab-org/api/client-go v0.143.2 h1:tfmUW8u+G/DGKOB/FDR0c06f0RVUAEe0ym8WpLoiHXI=
gitlab.com/gitlab-org/api/client-go v0.143.2/go.mod h1:gJn5yLx9vYGXr73Yv0ueHWCVl+fL8iUOgJFxC7qV+iM=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
@ -702,8 +703,8 @@ go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
@ -723,8 +724,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI=
golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8=
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -737,8 +738,8 @@ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.40.0 h1:Tw4GyDXMo+daZN1znreBRC3VayR1aLFUyUEOLUdW1a8=
golang.org/x/image v0.40.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA=
golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww=
golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -760,8 +761,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -792,8 +793,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -850,8 +851,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -861,8 +862,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -876,8 +877,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
@ -911,8 +912,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -973,6 +974,8 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -982,6 +985,7 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
@ -991,14 +995,14 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
modernc.org/libc v1.72.0 h1:IEu559v9a0XWjw0DPoVKtXpO2qt5NVLAnFaBbjq+n8c=
modernc.org/libc v1.72.0/go.mod h1:tTU8DL8A+XLVkEY3x5E/tO7s2Q/q42EtnNWda/L5QhQ=
modernc.org/libc v1.70.0 h1:U58NawXqXbgpZ/dcdS9kMshu08aiA6b7gusEusqzNkw=
modernc.org/libc v1.70.0/go.mod h1:OVmxFGP1CI/Z4L3E0Q3Mf1PDE0BucwMkcXjjLntvHJo=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/sqlite v1.50.0 h1:eMowQSWLK0MeiQTdmz3lqoF5dqclujdlIKeJA11+7oM=
modernc.org/sqlite v1.50.0/go.mod h1:m0w8xhwYUVY3H6pSDwc3gkJ/irZT/0YEXwBlhaxQEew=
modernc.org/sqlite v1.48.2 h1:5CnW4uP8joZtA0LedVqLbZV5GD7F/0x91AXeSyjoh5c=
modernc.org/sqlite v1.48.2/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig=
mvdan.cc/xurls/v2 v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI=
mvdan.cc/xurls/v2 v2.6.0/go.mod h1:bCvEZ1XvdA6wDnxY7jPPjEmigDtvtvPXAD/Exa9IMSk=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View file

@ -9,7 +9,6 @@ package actions
import (
"context"
"errors"
"fmt"
"time"
"forgejo.org/models/db"
@ -89,13 +88,6 @@ func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPa
return artifact, nil
}
// IsV4 reports whether the artifact was uploaded via the v4 backend.
// The v4 backend stores the whole artifact as a single zip file;
// v1-v3 stores each file as a separate row.
func (a *ActionArtifact) IsV4() bool {
return a.ArtifactName+".zip" == a.ArtifactPath && a.ContentEncoding == "application/zip"
}
func getArtifactByNameAndPath(ctx context.Context, runID int64, name, fpath string) (*ActionArtifact, error) {
var art ActionArtifact
has, err := db.GetEngine(ctx).Where("run_id = ? AND artifact_name = ? AND artifact_path = ?", runID, name, fpath).Get(&art)
@ -158,32 +150,11 @@ type ActionArtifactMeta struct {
Status ArtifactStatus
}
// AggregatedArtifact is the aggregated view of a logical artifact
// (one or more rows sharing the same run_id + artifact_name), used by the
// public API to represent a single artifact to clients.
type AggregatedArtifact struct {
ID int64 `xorm:"id"`
RunID int64 `xorm:"run_id"`
RepoID int64 `xorm:"-"`
ArtifactName string `xorm:"artifact_name"`
FileSize int64 `xorm:"file_size"`
Status ArtifactStatus `xorm:"status"`
CreatedUnix timeutil.TimeStamp `xorm:"created_unix"`
UpdatedUnix timeutil.TimeStamp `xorm:"updated_unix"`
ExpiredUnix timeutil.TimeStamp `xorm:"expired_unix"`
}
// APIDownloadURL returns the download URL for this artifact under the given
// repository API URL prefix (e.g. "https://host/api/v1/repos/owner/name").
func (a *AggregatedArtifact) APIDownloadURL(repoAPIURL string) string {
return fmt.Sprintf("%s/actions/artifacts/%d/zip", repoAPIURL, a.ID)
}
// ListUploadedArtifactsMeta returns all uploaded artifacts meta of a run
func ListUploadedArtifactsMeta(ctx context.Context, runID int64) ([]*ActionArtifactMeta, error) {
arts := make([]*ActionArtifactMeta, 0, 10)
return arts, db.GetEngine(ctx).Table("action_artifact").
Where(builder.Eq{"run_id": runID}.And(builder.In("status", ArtifactStatusUploadConfirmed, ArtifactStatusExpired))).
Where("run_id=? AND (status=? OR status=?)", runID, ArtifactStatusUploadConfirmed, ArtifactStatusExpired).
GroupBy("artifact_name").
Select("artifact_name, sum(file_size) as file_size, max(status) as status").
Find(&arts)
@ -221,94 +192,3 @@ func SetArtifactDeleted(ctx context.Context, artifactID int64) error {
_, err := db.GetEngine(ctx).ID(artifactID).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusDeleted)})
return err
}
// SetArtifactsOfRunDeleted marks all artifacts of the given run as deleted.
func SetArtifactsOfRunDeleted(ctx context.Context, runID int64) error {
_, err := db.GetEngine(ctx).
Where("run_id=?", runID).
Cols("status").
Update(&ActionArtifact{Status: int64(ArtifactStatusPendingDeletion)})
return err
}
// aggregatedArtifactConds returns the common WHERE clause used by aggregated
// artifact queries: restrict to visible statuses and apply the caller's filters.
// The Status field on opts is ignored — visibility is fixed to UploadConfirmed/Expired.
func aggregatedArtifactConds(opts FindArtifactsOptions) builder.Cond {
opts.Status = 0
return opts.ToConds().And(builder.In("status", ArtifactStatusUploadConfirmed, ArtifactStatusExpired))
}
const aggregatedArtifactSelect = "min(id) as id, run_id, artifact_name, sum(file_size) as file_size, max(status) as status, min(created_unix) as created_unix, max(updated_unix) as updated_unix, max(expired_unix) as expired_unix"
// ListAggregatedArtifacts returns paginated aggregated artifacts.
// Each result represents one logical artifact: a (run_id, artifact_name) group,
// with ID = MIN(id), FileSize = SUM(file_size), Status = MAX(status), and
// timestamps aggregated accordingly. Status filter in opts is ignored; results
// are always restricted to UploadConfirmed and Expired statuses.
func ListAggregatedArtifacts(ctx context.Context, opts FindArtifactsOptions) ([]*AggregatedArtifact, int64, error) {
cond := aggregatedArtifactConds(opts)
var countKeys []struct {
ID int64 `xorm:"id"`
}
if err := db.GetEngine(ctx).Table("action_artifact").
Where(cond).
GroupBy("run_id, artifact_name").
Select("min(id) as id").
Find(&countKeys); err != nil {
return nil, 0, err
}
total := int64(len(countKeys))
sess := db.GetEngine(ctx).Table("action_artifact").
Where(cond).
GroupBy("run_id, artifact_name").
Select(aggregatedArtifactSelect).
OrderBy("id DESC")
capacity := 10
if opts.PageSize > 0 {
sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
capacity = opts.PageSize
}
arts := make([]*AggregatedArtifact, 0, capacity)
return arts, total, sess.Find(&arts)
}
// GetAggregatedArtifactByID returns the aggregated artifact by its canonical ID
// (MIN(id) of the group), scoped to the given repository. Returns util.ErrNotExist
// when the ID does not exist, is not canonical for its group, or does not belong to repoID.
// The repoID scoping is performed in the query so callers don't need a follow-up check.
func GetAggregatedArtifactByID(ctx context.Context, repoID, artifactID int64) (*AggregatedArtifact, error) {
var art ActionArtifact
has, err := db.GetEngine(ctx).Where(builder.Eq{"id": artifactID, "repo_id": repoID}).Get(&art)
if err != nil {
return nil, err
}
if !has {
return nil, util.ErrNotExist
}
cond := aggregatedArtifactConds(FindArtifactsOptions{
RunID: art.RunID,
ArtifactName: art.ArtifactName,
})
meta := new(AggregatedArtifact)
has, err = db.GetEngine(ctx).Table("action_artifact").
Where(cond).
GroupBy("run_id, artifact_name").
Select(aggregatedArtifactSelect).
Get(meta)
if err != nil {
return nil, err
}
if !has || meta.ID != artifactID {
return nil, util.ErrNotExist
}
meta.RepoID = art.RepoID
return meta, nil
}

View file

@ -257,33 +257,19 @@ func (run *ActionRun) IsDispatchedRun() bool {
return run.TriggerEvent == "workflow_dispatch"
}
// IsValid indicates whether this ActionRun is valid and can be run.
func (run *ActionRun) IsValid() bool {
// IsRunnable indicates whether this ActionRun can generally be run.
func (run *ActionRun) IsRunnable() bool {
return run.PreExecutionErrorCode == 0 && run.PreExecutionError == ""
}
// CanBeRerun indicates whether this ActionRun can be rerun.
func (run *ActionRun) CanBeRerun() bool {
if !run.IsValid() {
if !run.IsRunnable() {
return false
}
return run.Status.IsDone()
}
func (run *ActionRun) PrepareNextAttempt() error {
if run.Status != StatusUnknown && !run.Status.IsDone() {
return fmt.Errorf("cannot prepare next attempt because run %d is active: %s", run.ID, run.Status.String())
}
run.PreviousDuration = run.Duration()
run.Status = StatusWaiting
run.Started = 0
run.Stopped = 0
return nil
}
func actionsCountOpenCacheKey(repoID int64) string {
return fmt.Sprintf("Actions:CountOpenActionRuns:%d", repoID)
}
@ -612,11 +598,4 @@ func ComputeRunStatus(ctx context.Context, runID int64) (run *ActionRun, columns
return run, columns, nil
}
// DeleteRun removes the given run. It is the caller's responsibility to handle the run's dependencies like artifacts or
// jobs. Nothing happens if the run does not exist.
func DeleteRun(ctx context.Context, runID int64) error {
_, err := db.GetEngine(ctx).Delete(&ActionRun{ID: runID})
return err
}
type ActionRunIndex db.ResourceIndex

View file

@ -141,16 +141,12 @@ func (job *ActionRunJob) PrepareNextAttempt(initialStatus Status) error {
}
// CanBeRerun answers whether this ActionRunJob can be rerun. Returns true if it is done and the Run it belongs to
// is valid. Returns false in all other cases.
func (job *ActionRunJob) CanBeRerun(ctx context.Context) (bool, error) {
if err := job.LoadRun(ctx); err != nil {
return false, fmt.Errorf("cannot load run %d of job %d: %w", job.RunID, job.ID, err)
// is runnable. Returns false in all other cases, including when Run is nil.
func (job *ActionRunJob) CanBeRerun() bool {
if job.Run == nil || !job.Run.IsRunnable() {
return false
}
if !job.Run.IsValid() {
return false, nil
}
return job.Status.IsDone(), nil
return job.Status.IsDone()
}
func GetRunJobByID(ctx context.Context, id int64) (*ActionRunJob, error) {
@ -365,10 +361,3 @@ func (job *ActionRunJob) AllNeedsExist(allExistingJobIDs container.Set[string])
return unknownJobIDs, len(unknownJobIDs) == 0
}
// DeleteJob removes the given job. Removing all associated tasks is up to the caller. If the given job does not exist,
// nothing happens.
func DeleteJob(ctx context.Context, jobID int64) error {
_, err := db.GetEngine(ctx).Delete(&ActionRunJob{ID: jobID})
return err
}

View file

@ -74,7 +74,7 @@ func (opts FindRunJobOptions) ToConds() builder.Cond {
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
if opts.OwnerID != 0 {
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}
if opts.CommitSHA != "" {

View file

@ -428,10 +428,9 @@ func TestAllNeedsExist(t *testing.T) {
func TestActionRunJob_CanBeRerun(t *testing.T) {
testCases := []struct {
name string
job ActionRunJob
canBeRerun bool
expectedError string
name string
job ActionRunJob
canBeRerun bool
}{
{
name: "job with unknown status",
@ -469,9 +468,9 @@ func TestActionRunJob_CanBeRerun(t *testing.T) {
canBeRerun: false,
},
{
name: "ActionRun is nil",
job: ActionRunJob{ID: 12, Run: nil, Status: StatusSuccess},
expectedError: "cannot load run 0 of job 12",
name: "ActionRun is nil",
job: ActionRunJob{Run: nil, Status: StatusSuccess},
canBeRerun: false,
},
{
name: "with busy run but completed job",
@ -490,15 +489,7 @@ func TestActionRunJob_CanBeRerun(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
result, err := testCase.job.CanBeRerun(t.Context())
if testCase.expectedError == "" {
require.NoError(t, err)
} else {
require.ErrorContains(t, err, testCase.expectedError)
}
assert.Equal(t, testCase.canBeRerun, result)
assert.Equal(t, testCase.canBeRerun, testCase.job.CanBeRerun())
})
}
}

View file

@ -85,7 +85,7 @@ func (opts FindRunOptions) ToConds() builder.Cond {
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
if opts.OwnerID != 0 {
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}
if opts.WorkflowID != "" {

View file

@ -93,27 +93,27 @@ func TestIsManualRun(t *testing.T) {
assert.False(t, pushRun.IsDispatchedRun())
}
func TestActionRun_IsValid(t *testing.T) {
func TestActionRun_IsRunnable(t *testing.T) {
testCases := []struct {
name string
run ActionRun
isValid bool
name string
run ActionRun
isRunnable bool
}{
{
name: "valid run",
run: ActionRun{},
isValid: true,
name: "valid run",
run: ActionRun{},
isRunnable: true,
},
{
name: "with pre-execution error",
run: ActionRun{PreExecutionErrorCode: ErrorCodeIncompleteRunsOnMissingOutput},
isValid: false,
name: "with pre-execution error",
run: ActionRun{PreExecutionErrorCode: ErrorCodeIncompleteRunsOnMissingOutput},
isRunnable: false,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
assert.Equal(t, testCase.isValid, testCase.run.IsValid())
assert.Equal(t, testCase.isRunnable, testCase.run.IsRunnable())
})
}
}

View file

@ -152,7 +152,6 @@ func (r *ActionRunner) Editable(ownerID, repoID int64) bool {
// LoadAttributes loads the attributes of the runner
func (r *ActionRunner) LoadAttributes(ctx context.Context) error {
// nosemgrep: forgejo-logic-suspicious-OwnerID-check (system users are not stored in the database)
if r.OwnerID > 0 {
var user user_model.User
has, err := db.GetEngine(ctx).ID(r.OwnerID).Get(&user)
@ -215,7 +214,7 @@ func (opts FindRunnerOptions) ToConds() builder.Cond {
c = c.Or(builder.Eq{"repo_id": 0, "owner_id": 0})
}
cond = cond.And(c)
} else if opts.OwnerID != 0 { // OwnerID is ignored if RepoID is set
} else if opts.OwnerID > 0 { // OwnerID is ignored if RepoID is set
c := builder.NewCond().And(builder.Eq{"owner_id": opts.OwnerID})
if opts.WithVisible {
c = c.Or(builder.Eq{"repo_id": 0, "owner_id": 0})
@ -396,13 +395,6 @@ func FixRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) {
return res.RowsAffected()
}
// DeleteEphemeralRunner removes the ephemeral runner with the given ID. If the runner with the given ID is not an
// ephemeral runner, nothing happens.
func DeleteEphemeralRunner(ctx context.Context, id int64) error {
_, err := db.GetEngine(ctx).Where(builder.Eq{"id": id, "ephemeral": true}).Delete(&ActionRunner{})
return err
}
func DeleteOfflineRunners(ctx context.Context, olderThan timeutil.TimeStamp, globalOnly bool) error {
log.Info("Doing: DeleteOfflineRunners")

View file

@ -28,7 +28,6 @@ func (runners RunnerList) LoadOwners(ctx context.Context) error {
return err
}
for _, runner := range runners {
// nosemgrep: forgejo-logic-suspicious-OwnerID-check (system users are not stored in the database)
if runner.OwnerID > 0 && runner.Owner == nil {
runner.Owner = users[runner.OwnerID]
}

View file

@ -479,62 +479,3 @@ func TestRunner_FindRunnerOptionsToConds(t *testing.T) {
})
}
}
func TestDeleteEphemeralRunner(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
persistentRunnerOne := &ActionRunner{
ID: 606526,
UUID: "d53a1222-ae7a-4430-97f8-8fcb6efd04c9",
Name: "persistent-runner-one",
OwnerID: 2,
RepoID: 0,
Ephemeral: false,
TokenHash: "J9YDsQL",
}
persistentRunnerTwo := &ActionRunner{
ID: 606527,
UUID: "3dc23067-b2fd-4daf-b428-dddad80d7f37",
Name: "persistent-runner-two",
OwnerID: 2,
RepoID: 0,
Ephemeral: false,
TokenHash: "jvIylZtHsS",
}
ephemeralRunnerOne := &ActionRunner{
ID: 606528,
UUID: "2d9bc0a1-7019-4ed3-ba67-6415415ac2a9",
Name: "ephemeral-runner-one",
OwnerID: 2,
RepoID: 0,
Ephemeral: true,
TokenHash: "t9C8L0kM3W",
}
ephemeralRunnerTwo := &ActionRunner{
ID: 606529,
UUID: "da7a03f8-ab39-4c54-9ec9-2bd312fe3be1",
Name: "ephemeral-runner-two",
OwnerID: 2,
RepoID: 0,
Ephemeral: true,
TokenHash: "g9oTOFM",
}
require.NoError(t, CreateRunner(t.Context(), persistentRunnerOne))
require.NoError(t, CreateRunner(t.Context(), persistentRunnerTwo))
require.NoError(t, CreateRunner(t.Context(), ephemeralRunnerOne))
require.NoError(t, CreateRunner(t.Context(), ephemeralRunnerTwo))
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: persistentRunnerOne.ID})
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: persistentRunnerTwo.ID})
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: ephemeralRunnerOne.ID})
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: ephemeralRunnerTwo.ID})
require.NoError(t, DeleteEphemeralRunner(t.Context(), persistentRunnerOne.ID))
require.NoError(t, DeleteEphemeralRunner(t.Context(), ephemeralRunnerOne.ID))
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: persistentRunnerOne.ID})
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: persistentRunnerTwo.ID})
unittest.AssertNotExistsBean(t, &ActionRunner{ID: ephemeralRunnerOne.ID})
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: ephemeralRunnerTwo.ID})
}

View file

@ -116,7 +116,7 @@ func (opts FindScheduleOptions) ToConds() builder.Cond {
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
if opts.OwnerID != 0 {
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}

View file

@ -13,7 +13,7 @@ import (
"forgejo.org/modules/optional"
"forgejo.org/modules/timeutil"
"github.com/gdgvda/cron"
"github.com/robfig/cron/v3"
)
// ActionScheduleSpec represents a schedule spec of a workflow file
@ -53,14 +53,16 @@ func NewActionScheduleSpec(cron string, tz optional.Option[string], referenceTim
// Parse parses the spec and returns a cron.Schedule
// Unlike the default cron parser, Parse uses UTC timezone as the default if none is specified.
func (s *ActionScheduleSpec) Parse() (cron.Schedule, error) {
parser, err := cron.NewDefaultParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
parser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
schedule, err := parser.Parse(s.Spec)
if err != nil {
return nil, err
}
schedule, err := parser.Parse(s.Spec)
if err != nil {
return nil, err
specSchedule, ok := schedule.(*cron.SpecSchedule)
// If it's not a spec schedule, like "@every 5m", timezone is not relevant
if !ok {
return schedule, nil
}
// If `timezone` is not defined in the workflow, but the spec includes a timezone, use it.
@ -79,7 +81,8 @@ func (s *ActionScheduleSpec) Parse() (cron.Schedule, error) {
location = time.UTC
}
return schedule.WithLocation(location), nil
specSchedule.Location = location
return specSchedule, nil
}
func init() {

View file

@ -13,44 +13,6 @@ import (
"github.com/stretchr/testify/require"
)
func TestActionScheduleSpec_NewActionScheduleSpec(t *testing.T) {
tests := []struct {
name string
refTime time.Time
cronPattern string
timeZone string
want string
wantErr assert.ErrorAssertionFunc
}{
{
name: "without timezone",
refTime: time.Date(2026, 4, 6, 11, 56, 0, 0, time.UTC),
cronPattern: "58 14 * * *",
want: "2026-04-06T14:58:00Z",
wantErr: assert.NoError,
},
{
name: "with separate timezone",
refTime: time.Date(2026, 4, 6, 11, 56, 0, 0, time.UTC),
cronPattern: "58 14 * * *",
timeZone: "Europe/Tallinn", // +03 (EEST)
want: "2026-04-06T11:58:00Z",
wantErr: assert.NoError,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
s, err := NewActionScheduleSpec(test.cronPattern, optional.FromNonDefault(test.timeZone), test.refTime)
test.wantErr(t, err)
if err == nil {
assert.Equal(t, test.want, s.Next.AsTime().UTC().Format(time.RFC3339))
}
})
}
}
func TestActionScheduleSpec_Parse(t *testing.T) {
// Mock the local timezone is not UTC
local := time.Local
@ -126,24 +88,24 @@ func TestActionScheduleSpec_Parse(t *testing.T) {
// skipping the execution on that day because any time between 2 and 3 o'clock never happened. Forgejo uses
// option B because the code it inherited already did that and was exposed to users.
name: "skips execution during DST jump forwards",
refTime: time.Date(2025, 3, 30, 0, 55, 0, 0, time.UTC), // 01:55 local time
spec: "10 2 * * *", // The clock jumps at 2 o'clock to 3 o'clock.
refTime: time.Date(2025, 3, 30, 1, 5, 0, 0, time.UTC),
spec: "10 2 * * *", // The clock jumps at 2 o'clock to 3 o'clock.
timeZone: "Europe/Berlin",
want: "2025-03-31T00:10:00Z",
wantErr: assert.NoError,
},
{
name: "executes a first time before DST jump backwards",
refTime: time.Date(2025, 10, 26, 0, 5, 0, 0, time.UTC), // 02:05 local time
spec: "10 2 * * *", // The clock jumps at 3 o'clock to 2 o'clock.
refTime: time.Date(2025, 10, 26, 0, 5, 0, 0, time.UTC),
spec: "10 2 * * *", // The clock jumps at 3 o'clock to 2 o'clock.
timeZone: "Europe/Berlin",
want: "2025-10-26T00:10:00Z",
wantErr: assert.NoError,
},
{
name: "executes a second time after DST jump backwards",
refTime: time.Date(2025, 10, 26, 1, 5, 0, 0, time.UTC), // 02:05 local time
spec: "10 2 * * *", // The clock jumps at 3 o'clock to 2 o'clock.
refTime: time.Date(2025, 10, 26, 1, 5, 0, 0, time.UTC),
spec: "10 2 * * *", // The clock jumps at 3 o'clock to 2 o'clock.
timeZone: "Europe/Berlin",
want: "2025-10-26T01:10:00Z",
wantErr: assert.NoError,

View file

@ -192,15 +192,6 @@ func HasTaskForRunner(ctx context.Context, runnerID int64) (bool, error) {
return db.GetEngine(ctx).Where("runner_id = ?", runnerID).Exist(&ActionTask{})
}
func GetTasksOfJob(ctx context.Context, jobID int64) ([]*ActionTask, error) {
var tasks []*ActionTask
err := db.GetEngine(ctx).Where("job_id=?", jobID).Find(&tasks)
if err != nil {
return nil, fmt.Errorf("cannot fetch tasks of job %d: %w", jobID, err)
}
return tasks, nil
}
func GetTaskByJobAttempt(ctx context.Context, jobID, attempt int64) (*ActionTask, error) {
var task ActionTask
has, err := db.GetEngine(ctx).Where("job_id=?", jobID).Where("attempt=?", attempt).Get(&task)
@ -506,27 +497,6 @@ func UpdateTask(ctx context.Context, task *ActionTask, cols ...string) error {
return err
}
// DeleteTask removes the given task including all its steps and outputs. Removing logs and ephemeral runners is the
// caller's responsibility.
func DeleteTask(ctx context.Context, taskID int64) error {
return db.WithTx(ctx, func(ctx context.Context) error {
var err error
_, err = db.GetEngine(ctx).Delete(&ActionTaskStep{TaskID: taskID})
if err != nil {
return fmt.Errorf("unable to delete steps of task %d: %w", taskID, err)
}
_, err = db.GetEngine(ctx).Delete(&ActionTaskOutput{TaskID: taskID})
if err != nil {
return fmt.Errorf("unable to delete outputs of task %d: %w", taskID, err)
}
_, err = db.GetEngine(ctx).Delete(&ActionTask{ID: taskID})
if err != nil {
return fmt.Errorf("unable to delete task %d: %w", taskID, err)
}
return nil
})
}
func FindOldTasksToExpire(ctx context.Context, olderThan timeutil.TimeStamp, limit int) ([]*ActionTask, error) {
e := db.GetEngine(ctx)

View file

@ -65,7 +65,7 @@ func (opts FindTaskOptions) ToConds() builder.Cond {
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
if opts.OwnerID != 0 {
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}
if opts.CommitSHA != "" {

View file

@ -82,7 +82,7 @@ func GetFollowingFeeds(ctx context.Context, actorID int64, opts GetFollowingFeed
sess = db.SetSessionPagination(sess, &opts)
actions := make([]*FederatedUserActivity, 0, opts.PageSize)
count, err := sess.Desc("`federated_user_activity`.created").FindAndCount(&actions)
count, err := sess.FindAndCount(&actions)
if err != nil {
return nil, 0, fmt.Errorf("FindAndCount: %w", err)
}

View file

@ -81,7 +81,7 @@ func (opts FindGPGKeyOptions) ToConds() builder.Cond {
cond = cond.And(builder.Eq{"primary_key_id": ""})
}
if opts.OwnerID != 0 {
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}
if opts.KeyID != "" {

View file

@ -11,6 +11,7 @@ import (
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
"forgejo.org/modules/timeutil"
"forgejo.org/modules/util"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/stretchr/testify/assert"
@ -457,7 +458,7 @@ epiDVQ==
func TestTryGetKeyIDFromSignature(t *testing.T) {
assert.Empty(t, tryGetKeyIDFromSignature(&packet.Signature{}))
assert.Equal(t, "038D1A3EADDBEA9C", tryGetKeyIDFromSignature(&packet.Signature{
IssuerKeyId: new(uint64(0x38D1A3EADDBEA9C)),
IssuerKeyId: util.ToPointer(uint64(0x38D1A3EADDBEA9C)),
}))
assert.Equal(t, "038D1A3EADDBEA9C", tryGetKeyIDFromSignature(&packet.Signature{
IssuerFingerprint: []uint8{0xb, 0x23, 0x24, 0xc7, 0xe6, 0xfe, 0x4f, 0x3a, 0x6, 0x26, 0xc1, 0x21, 0x3, 0x8d, 0x1a, 0x3e, 0xad, 0xdb, 0xea, 0x9c},

View file

@ -20,32 +20,14 @@ func HandleCompositeErrorReason(handler llu.Handler, fset *token.FileSet, n *ast
}
// fields are normally named
var reason ast.Expr
verified := false
for _, i := range n.Elts {
if kve, ok := i.(*ast.KeyValueExpr); ok {
ident, ok = kve.Key.(*ast.Ident)
if !ok {
continue
}
switch ident.Name {
case "Reason":
reason = kve.Value
case "Verified":
if valueIdent, ok := kve.Value.(*ast.Ident); ok {
switch valueIdent.Name {
case "true":
verified = true
case "false":
verified = false
}
}
if ok && ident.Name == "Reason" {
handler.HandleGoTrArgument(fset, kve.Value, "")
}
} else {
handler.OnWarning(fset, i.Pos(), "unable to parse ObjectVerification field assignment")
}
}
if !verified && reason != nil {
handler.HandleGoTrArgument(fset, reason, "")
}
}

View file

@ -190,7 +190,7 @@ type FindPublicKeyOptions struct {
func (opts FindPublicKeyOptions) ToConds() builder.Cond {
cond := builder.NewCond()
if opts.OwnerID != 0 {
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}
if opts.Fingerprint != "" {

View file

@ -1,9 +0,0 @@
- integ_id: 1
repo_id: 1
created_unix: 1772158384
- integ_id: 1
repo_id: 2
created_unix: 1772158384
- integ_id: 1
repo_id: 3
created_unix: 1772158384

View file

@ -1,9 +0,0 @@
- id: 1
user_id: 2
scope: all
resource_all_repos: false
issuer: https://example.org/
audience: https://forgejo.example.org/-/user/integration/abcdef123
claim_rules: "{}"
created_unix: 1777153359
updated_unix: 1777153359

View file

@ -24,10 +24,6 @@ func init() {
db.RegisterModel(new(AccessTokenResourceRepo))
}
func (atr *AccessTokenResourceRepo) GetTargetRepoID() int64 {
return atr.RepoID
}
func GetRepositoriesAccessibleWithToken(ctx context.Context, accessTokenID int64) ([]*AccessTokenResourceRepo, error) {
var resources []*AccessTokenResourceRepo
err := db.GetEngine(ctx).

View file

@ -1,189 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package auth
import (
"context"
"errors"
"fmt"
"time"
"forgejo.org/models/db"
"forgejo.org/modules/timeutil"
"forgejo.org/modules/util"
gouuid "github.com/google/uuid"
"xorm.io/builder"
)
// An Authorized Integration allow users to define external systems which can generate JSON Web Tokens (JWTs) that
// Forgejo will trust in order to perform API access on behalf of a user defined by the UserID field.
//
// When a JWT is received by Forgejo, the issuer (iss) and audience (aud) claims are used to lookup an authorized
// integration with an exact match. Together these fields serve as a unique key for the authorized issuer. Duplicates
// cannot be permitted because we would not know which user to authenticate the JWT as.
type AuthorizedIntegration struct {
ID int64 `xorm:"pk autoincr"`
UserID int64 `xorm:"NOT NULL REFERENCES(user, id)"`
Scope AccessTokenScope `xorm:"NOT NULL"`
ResourceAllRepos bool `xorm:"NOT NULL"` // flag for whether AuthorizedIntegrationResourceRepo instances will limit the resources this access token can access (false) or won't limit them (true).
Name string // short name for lists of authorized integrations
Description string `xorm:"LONGTEXT"` // long description, optional to document relevant details of the integration
// Exact-match `iss` claim of the JWT
Issuer string `xorm:"NOT NULL UNIQUE(s)"`
// Exact-match `aud` claim of the JWT
Audience string `xorm:"NOT NULL UNIQUE(s)"`
ClaimRules *ClaimRules `xorm:"NOT NULL JSON"`
CreatedUnix timeutil.TimeStamp `xorm:"NOT NULL created"`
UpdatedUnix timeutil.TimeStamp `xorm:"NOT NULL updated"`
}
func init() {
db.RegisterModel(new(AuthorizedIntegration))
}
// An [AuthorizedIntegration] can validate the claims in a JWT against a set of rules defined by this structure.
//
// JWTs can contain any number of claims, which are represented as a JSON object. A small number of common claims are
// described in RFC7519 (sec 4.1) which defines JWTs, but most claims are entirely arbitrarily defined by the JWT
// issuer.
//
// For example, eg. a claim may be {"sub": "repo:coolguy/forgejo-runner-testrepo:pull_request"} indicating that an OIDC
// token was received from an Actions execution in a specific repo on a specific event.
//
// Validating the claims from a JWT issuer is a critical part of creating a secure [AuthorizedIssuer]. For example,
// assume that we receive a JWT from a public hosting platform like Codeberg. We will validate that it is a claim
// created by the correct Issuer, Codeberg -- but anyone can do that through Forgejo Actions. We will validate that it
// has the correct audience -- but that's an *input* to Forgejo Actions, so anyone can create a claim on Codeberg with
// an arbitrary audience. The rest of the claims contain the critical information about who ran a Forgejo Action, on
// which repository, and in response to which events, and those must be validated to ensure that an authorized issuer is
// correctly authorized.
//
// Following that an example, a minimum claim rule that would be required for securely using Forgejo Actions would be
// something like:
//
// {
// "rules": [{
// "claim": "sub",
// "comparison": "eq",
// "value": "repo:forgejo/website:pull_request"
// }]
// }
//
// This defines a single rule which says that the `sub` claim must be exactly equal to
// "repo:forgejo/website:pull_request". Forgejo Actions would generate this subject when an Action is running on the
// repo forgejo/website in response to the pull_request event.
//
// Some JWT claims are JSON objects. The [ClaimNested] comparison operator can be used to define rules that inspect the
// object within a claim. For example, AWS STS generates a claim "https://sts.amazonaws.com/": {...} with values inside
// an object, like "aws_account". A nested claim can inspect those values:
//
// {
// "rules":[{
// "claim": "https://sts.amazonaws.com/",
// "compare": "nest",
// "nested": {"rules":[
// {"claim": "aws_account", "compare": "eq", "value": "1234567890"},
// {"claim": "lambda_source_function_arn", "compare": "eq", "value": "arn:aws:lambda:ca-central-1:1234567890:function:forgejo-oidc-accepting-test"}
// ]}
// }
//
// ]}
//
// This defines a rule that looks into the "https://sts..." claim and verifies the "aws_account" and
// "lambda_source_function_arn" keys match specific known values.
type ClaimRules struct {
Rules []ClaimRule `json:"rules"`
}
// Defines a single rule that will check the value of one JWT claim.
type ClaimRule struct {
// The target claim, eg. "sub"
Claim string `json:"claim"`
// Comparison rule to use on this claim
Comparison ClaimComparison `json:"compare"`
// For Comparison of ClaimEqual or ClaimGlob, the specific value or glob to match against
Value string `json:"value,omitempty"`
// For Comparison of ClaimIn or ClaimGlobIn, an array of values to match against
Values []string `json:"values,omitempty"`
// For ClaimNested, the rules to apply to the nested object
Nested *ClaimRules `json:"nested,omitempty"`
}
type ClaimComparison string
const (
ClaimEqual ClaimComparison = "eq" // exactly equal claim
ClaimIn ClaimComparison = "in" // exactly equal any of the options in a list
ClaimGlob ClaimComparison = "glob" // glob match complete claim string
ClaimGlobIn ClaimComparison = "glob-in" // glob match any of the options in a list
ClaimNested ClaimComparison = "nest" // recurse into a claim that is an map[string]any with it's own data fields
)
func GetAuthorizedIntegration(ctx context.Context, issuer, audience string) (*AuthorizedIntegration, error) {
var ai AuthorizedIntegration
found, err := db.GetEngine(ctx).Where("issuer = ? AND audience = ?", issuer, audience).Get(&ai)
if err != nil {
return nil, err
} else if !found {
return nil, util.ErrNotExist
}
return &ai, nil
}
func InsertAuthorizedIntegration(ctx context.Context, ai *AuthorizedIntegration) error {
if ai.Audience != "" {
return errors.New("audience cannot be provided, and must be generated by NewAuthorizedIntegration")
} else if err := ai.generateAudience(); err != nil {
return err
}
_, err := db.GetEngine(ctx).Insert(ai)
return err
}
// Bump the UpdatedUnix field of this authorized integration to now, tracking when it was last used for authentication.
// To reduce database write workload, this is only tracked by one-minute intervals -- the UPDATE statement conditionally
// avoids writes.
func (ai *AuthorizedIntegration) UpdateLastUsed(ctx context.Context) error {
newTime := timeutil.TimeStampNow()
cnt, err := db.GetEngine(ctx).
Table(&AuthorizedIntegration{}).
Where(builder.Eq{"id": ai.ID}).
Where(builder.Lt{"updated_unix": newTime.AddDuration(-1 * time.Minute)}).
NoAutoTime().
Update(map[string]any{"updated_unix": newTime})
if cnt == 1 {
ai.UpdatedUnix = newTime
}
return err
}
// Generates the `aud` claim that the remote JWT generator must use to match this authorized integration. The `aud`
// claim is an arbitrary value in a JWT claim, but Forgejo is faced with a few hard and soft requirements:
//
// - Hard requirement: each authorized integration must have a unique `aud`, as it is used to find the DB record that
// authenticates a request.
// - If authentication is failing, being able to inspect the `aud` claim can be useful to identify the intent.
// - Inspection should have a stable meaning -- eg. if it included the username, and the user was renamed, the `aud`
// value which can't be changed would continue to reference the old username causing confusion when inspecting it.
// - Forgejo & GitHub Actions uses a URL $ACTIONS_ID_TOKEN_REQUEST_URL&audience=... to generate a JWT for the running
// action, so it should only consist of safe characters for URL encoding.
// - It should be relatively short, as it's encoded into the JWT and increases its size.
//
// Meeting these requirements decently well is a combination of the owner's ID, a guid, and a "u:" prefix that makes the
// fact that it's an `aud` claim value a little bit identifiable.
func (ai *AuthorizedIntegration) generateAudience() error {
if ai.UserID == 0 {
return errors.New("UserID must be initialized")
}
ai.Audience = fmt.Sprintf("u:%d:%s", ai.UserID, gouuid.New().String())
return nil
}

View file

@ -1,56 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package auth
import (
"context"
"forgejo.org/models/db"
"forgejo.org/modules/timeutil"
)
// Represents a many-to-many join table which indicates specific repositories (RepoID) that can be accessed by an
// authorized integration (IntegID). An authorized integrations's ResourceAllRepos field must be false for records in
// this table to become active.
//
// Model name is shortend (from AuthorizedIntegrationResourceRepo) to accomodate recreate-tables + MySQL, where the
// "tmp_recreate_" + foreign key index name would exceed the max identifier length.
type AuthorizedIntegResourceRepo struct {
ID int64 `xorm:"pk autoincr"`
IntegID int64 `xorm:"NOT NULL REFERENCES(authorized_integration, id)"` // field name shortened (AuthorizationIntegrationID) for max identifier length
RepoID int64 `xorm:"NOT NULL REFERENCES(repository, id)"`
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
}
func init() {
db.RegisterModel(new(AuthorizedIntegResourceRepo))
}
func (air *AuthorizedIntegResourceRepo) GetTargetRepoID() int64 {
return air.RepoID
}
func GetRepositoriesAccessibleWithIntegration(ctx context.Context, aiID int64) ([]*AuthorizedIntegResourceRepo, error) {
var resources []*AuthorizedIntegResourceRepo
err := db.GetEngine(ctx).
Where("integ_id = ?", aiID).
Find(&resources)
if err != nil {
return nil, err
}
return resources, nil
}
func InsertAuthorizedIntegrationResourceRepos(ctx context.Context, aiID int64, resources []*AuthorizedIntegResourceRepo) error {
return db.WithTx(ctx, func(ctx context.Context) error {
for _, resourceRepo := range resources {
resourceRepo.IntegID = aiID
if err := db.Insert(ctx, resourceRepo); err != nil {
return err
}
}
return nil
})
}

View file

@ -1,91 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package auth_test
import (
"testing"
auth_model "forgejo.org/models/auth"
"forgejo.org/models/unittest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetRepositoriesAccessibleWithIntegration(t *testing.T) {
defer unittest.OverrideFixtures("models/auth/TestGetRepositoriesAccessibleWithIntegration")()
require.NoError(t, unittest.PrepareTestDatabase())
t.Run("No Resources", func(t *testing.T) {
resources, err := auth_model.GetRepositoriesAccessibleWithIntegration(t.Context(), 999)
require.NoError(t, err)
assert.Empty(t, resources)
})
t.Run("Has Resources", func(t *testing.T) {
resources, err := auth_model.GetRepositoriesAccessibleWithIntegration(t.Context(), 1)
require.NoError(t, err)
require.Len(t, resources, 3)
// Verify all expected repo IDs are present
repoIDs := make([]int64, len(resources))
for i, res := range resources {
repoIDs[i] = res.RepoID
}
assert.Contains(t, repoIDs, int64(1))
assert.Contains(t, repoIDs, int64(2))
assert.Contains(t, repoIDs, int64(3))
})
}
func TestInsertAuthorizedIntegration(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
ai1 := makeAuthorizedIntegration(t)
ai2 := makeAuthorizedIntegration(t)
ai3 := makeAuthorizedIntegration(t)
t.Run("blank insert", func(t *testing.T) {
err := auth_model.InsertAuthorizedIntegrationResourceRepos(t.Context(), ai1.ID, nil)
require.NoError(t, err)
})
t.Run("multiple insert", func(t *testing.T) {
resRepo1 := &auth_model.AuthorizedIntegResourceRepo{
IntegID: ai2.ID,
RepoID: 1,
}
resRepo3 := &auth_model.AuthorizedIntegResourceRepo{
IntegID: ai2.ID,
RepoID: 3,
}
err := auth_model.InsertAuthorizedIntegrationResourceRepos(t.Context(), ai2.ID,
[]*auth_model.AuthorizedIntegResourceRepo{resRepo1, resRepo3})
require.NoError(t, err)
unittest.AssertCount(t, &auth_model.AuthorizedIntegResourceRepo{IntegID: ai2.ID}, 2)
})
t.Run("in tx", func(t *testing.T) {
// Pre-condition: count is 0.
unittest.AssertCount(t, &auth_model.AuthorizedIntegResourceRepo{IntegID: ai3.ID}, 0)
// Verify that InsertAuthorizedIntegrationResourceRepos performs inserts in a TX by having a second one with an invalid
// RepoID, causing a foreign key violation
resRepo1 := &auth_model.AuthorizedIntegResourceRepo{
IntegID: ai3.ID,
RepoID: 1,
}
resRepo3 := &auth_model.AuthorizedIntegResourceRepo{
IntegID: ai3.ID,
RepoID: 30000, // invalid
}
err := auth_model.InsertAuthorizedIntegrationResourceRepos(t.Context(), ai3.ID,
[]*auth_model.AuthorizedIntegResourceRepo{resRepo1, resRepo3})
require.ErrorContains(t, err, "foreign key")
// Count remains 0; the first record was not inserted.
unittest.AssertCount(t, &auth_model.AuthorizedIntegResourceRepo{IntegID: ai3.ID}, 0)
})
}

View file

@ -1,106 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package auth_test
import (
"testing"
"time"
auth_model "forgejo.org/models/auth"
"forgejo.org/models/db"
"forgejo.org/models/unittest"
"forgejo.org/modules/timeutil"
"forgejo.org/modules/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func makeAuthorizedIntegration(t *testing.T) *auth_model.AuthorizedIntegration {
t.Helper()
ai := &auth_model.AuthorizedIntegration{
UserID: 2,
Scope: auth_model.AccessTokenScopeAll,
ResourceAllRepos: true,
Issuer: "https://example.org/",
ClaimRules: &auth_model.ClaimRules{},
}
require.NoError(t, auth_model.InsertAuthorizedIntegration(t.Context(), ai))
return ai
}
func TestGetAuthorizedIntegration(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
ai := makeAuthorizedIntegration(t)
get, err := auth_model.GetAuthorizedIntegration(t.Context(), "abc", "123")
require.ErrorIs(t, err, util.ErrNotExist)
assert.Nil(t, get)
get, err = auth_model.GetAuthorizedIntegration(t.Context(), ai.Issuer, ai.Audience)
require.NoError(t, err)
require.NotNil(t, get)
assert.Equal(t, ai.ID, get.ID)
}
func TestAuthorizedIntegrationUpdateLastUsed(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
ai := makeAuthorizedIntegration(t)
ai.UpdatedUnix = 0
cnt, err := db.GetEngine(t.Context()).ID(ai.ID).Cols("updated_unix").NoAutoTime().Update(ai)
require.NoError(t, err)
assert.EqualValues(t, 1, cnt)
timeutil.MockSet(time.Unix(1777130023, 0))
defer timeutil.MockUnset()
assert.EqualValues(t, 0, ai.UpdatedUnix)
require.NoError(t, ai.UpdateLastUsed(t.Context()))
assert.EqualValues(t, 1777130023, ai.UpdatedUnix) // object field updated
assert.EqualValues(t, 1777130023, unittest.AssertExistsAndLoadBean(t, &auth_model.AuthorizedIntegration{ID: ai.ID}).UpdatedUnix)
// nearly immediate redo should have same timestamp due to the 1 minute deduplication:
timeutil.MockSet(time.Unix(1777130025, 0))
require.NoError(t, ai.UpdateLastUsed(t.Context()))
assert.EqualValues(t, 1777130023, ai.UpdatedUnix) // object field not updated
assert.EqualValues(t, 1777130023, unittest.AssertExistsAndLoadBean(t, &auth_model.AuthorizedIntegration{ID: ai.ID}).UpdatedUnix) // database field not updated
// but if it's a little while later..
timeutil.MockSet(time.Unix(1777131139, 0))
require.NoError(t, ai.UpdateLastUsed(t.Context()))
assert.EqualValues(t, 1777131139, ai.UpdatedUnix) // object field updated
assert.EqualValues(t, 1777131139, unittest.AssertExistsAndLoadBean(t, &auth_model.AuthorizedIntegration{ID: ai.ID}).UpdatedUnix) // database field updated
}
func TestNewAuthorizedIntegration(t *testing.T) {
ai := &auth_model.AuthorizedIntegration{
UserID: 2,
Scope: auth_model.AccessTokenScopeAll,
ResourceAllRepos: true,
Issuer: "https://example.org/",
ClaimRules: &auth_model.ClaimRules{},
}
require.NoError(t, auth_model.InsertAuthorizedIntegration(t.Context(), ai))
assert.Contains(t, ai.Audience, "u:2:")
ai = &auth_model.AuthorizedIntegration{
UserID: 2,
Scope: auth_model.AccessTokenScopeAll,
ResourceAllRepos: true,
Issuer: "https://example.org/",
Audience: "I made my own audience",
ClaimRules: &auth_model.ClaimRules{},
}
require.ErrorContains(t, auth_model.InsertAuthorizedIntegration(t.Context(), ai), "audience cannot be provided")
ai = &auth_model.AuthorizedIntegration{
// Forgot to set UserID
Scope: auth_model.AccessTokenScopeAll,
ResourceAllRepos: true,
Issuer: "https://example.org/",
ClaimRules: &auth_model.ClaimRules{},
}
require.ErrorContains(t, auth_model.InsertAuthorizedIntegration(t.Context(), ai), "UserID must be initialized")
}

View file

@ -91,7 +91,7 @@ var registeredConfigs = map[Type]func() Config{}
// RegisterTypeConfig register a config for a provided type
func RegisterTypeConfig(typ Type, exemplar Config) {
if reflect.TypeOf(exemplar).Kind() == reflect.Pointer {
if reflect.TypeOf(exemplar).Kind() == reflect.Ptr {
// Pointer:
registeredConfigs[typ] = func() Config {
return reflect.New(reflect.ValueOf(exemplar).Elem().Type()).Interface().(Config)

View file

@ -1,22 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package forgefed
import (
"fmt"
)
type ErrFederationHostNotFound struct {
SearchKey string
SearchValue string
}
func (err ErrFederationHostNotFound) Error() string {
return fmt.Sprintf("ErrFederationHostNotFound: search key: %s, search value: %s", err.SearchKey, err.SearchValue)
}
func IsErrFederationHostNotFound(err error) bool {
_, ok := err.(ErrFederationHostNotFound)
return ok
}

View file

@ -16,31 +16,6 @@ func init() {
db.RegisterModel(new(FederationHost))
}
func CountFederationHosts(ctx context.Context) (int64, error) {
return db.GetEngine(ctx).Count(FederationHost{})
}
func FindFederationHosts(ctx context.Context, opts db.ListOptions) (hosts []*FederationHost, err error) {
sess := db.GetEngine(ctx)
if opts.PageSize > 0 {
sess = db.SetSessionPagination(sess, &opts)
}
err = sess.Find(&hosts)
if err != nil {
return nil, err
}
for _, host := range hosts {
if res, err := validation.IsValid(host); !res {
return nil, err
}
}
return hosts, nil
}
func GetFederationHost(ctx context.Context, ID int64) (*FederationHost, error) {
log.Trace("GetFederationHost: %v", ID)
host := new(FederationHost)
@ -57,13 +32,13 @@ func GetFederationHost(ctx context.Context, ID int64) (*FederationHost, error) {
return host, nil
}
func findFederationHostFromDB(ctx context.Context, searchKey string, searchValue ...any) (*FederationHost, error) {
func findFederationHostFromDB(ctx context.Context, searchKey, searchValue string) (*FederationHost, error) {
host := new(FederationHost)
has, err := db.GetEngine(ctx).Where(searchKey, searchValue...).Get(host)
has, err := db.GetEngine(ctx).Where(searchKey, searchValue).Get(host)
if err != nil {
return nil, err
} else if !has {
return nil, ErrFederationHostNotFound{SearchKey: searchKey, SearchValue: fmt.Sprintf("%v", searchValue)}
return nil, nil
}
if res, err := validation.IsValid(host); !res {
return nil, err
@ -72,7 +47,17 @@ func findFederationHostFromDB(ctx context.Context, searchKey string, searchValue
}
func FindFederationHostByFqdnAndPort(ctx context.Context, fqdn string, port uint16) (*FederationHost, error) {
return findFederationHostFromDB(ctx, "host_fqdn=? AND host_port=?", fqdn, port)
host := new(FederationHost)
has, err := db.GetEngine(ctx).Where("host_fqdn=? AND host_port=?", fqdn, port).Get(host)
if err != nil {
return nil, err
} else if !has {
return nil, nil
}
if res, err := validation.IsValid(host); !res {
return nil, err
}
return host, nil
}
func FindFederationHostByKeyID(ctx context.Context, keyID string) (*FederationHost, error) {

View file

@ -1,45 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package forgejo_migrations
import (
"forgejo.org/modules/timeutil"
"xorm.io/xorm"
)
func init() {
registerMigration(&Migration{
Description: "add authorized_integration tables",
Upgrade: addAuthorizedIntegrationTables,
})
}
func addAuthorizedIntegrationTables(x *xorm.Engine) error {
type ClaimRules struct{}
type AuthorizedIntegration struct {
ID int64 `xorm:"pk autoincr"`
UserID int64 `xorm:"NOT NULL REFERENCES(user, id)"`
Scope string `xorm:"NOT NULL"`
ResourceAllRepos bool `xorm:"NOT NULL"`
Issuer string `xorm:"NOT NULL UNIQUE(s)"`
Audience string `xorm:"NOT NULL UNIQUE(s)"`
ClaimRules *ClaimRules `xorm:"NOT NULL JSON"`
CreatedUnix timeutil.TimeStamp `xorm:"NOT NULL created"`
UpdatedUnix timeutil.TimeStamp `xorm:"NOT NULL updated"`
}
type AuthorizedIntegResourceRepo struct {
ID int64 `xorm:"pk autoincr"`
IntegID int64 `xorm:"NOT NULL REFERENCES(authorized_integration, id)"`
RepoID int64 `xorm:"NOT NULL REFERENCES(repository, id)"`
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
}
_, err := x.SyncWithOptions(
xorm.SyncOptions{IgnoreDropIndices: true},
new(AuthorizedIntegration),
new(AuthorizedIntegResourceRepo),
)
return err
}

View file

@ -1,68 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package forgejo_migrations
import (
"context"
"fmt"
"forgejo.org/models/db"
"forgejo.org/modules/json"
"forgejo.org/modules/optional"
"xorm.io/builder"
"xorm.io/xorm"
)
func init() {
registerMigration(&Migration{
Description: "add OIDCSubjectFormat=legacy-forgejo-v15 to all existing repositories with actions enabled",
Upgrade: setOIDCSubjectFormatLegacy15,
})
}
func setOIDCSubjectFormatLegacy15(x *xorm.Engine) error {
type Type int
const TypeActions Type = 10 // 10 Actions
type ActionsConfig struct {
DisabledWorkflows []string `json:",omitempty"`
OIDCSubjectFormat string
}
type RepoUnit struct { //revive:disable-line:exported
ID int64 `xorm:"pk"`
Type Type `xorm:"INDEX(s)"`
Config optional.Option[string] `xorm:"TEXT"`
}
return db.Iterate(
db.DefaultContext,
builder.Eq{"type": TypeActions},
func(ctx context.Context, unit *RepoUnit) error {
has, config := unit.Config.Get()
if !has {
config = "{}"
}
var actionsConfig ActionsConfig
if err := json.Unmarshal([]byte(config), &actionsConfig); err != nil {
return fmt.Errorf("failed to parse Actions config %q: %w", config, err)
}
actionsConfig.OIDCSubjectFormat = "legacy-forgejo-v15"
configBytes, err := json.Marshal(actionsConfig)
if err != nil {
return fmt.Errorf("failed to convert Actions config to JSON: %w", err)
}
r, err := db.GetEngine(ctx).
ID(unit.ID).
Cols("config").
Update(&RepoUnit{Config: optional.Some(string(configBytes))})
if err != nil {
return err
} else if r != 1 {
return fmt.Errorf("UPDATE expected to affect 1 row, but was %d", r)
}
return nil
})
}

View file

@ -1,61 +0,0 @@
// Copyright 2026 The Forgejo Authors.
// SPDX-License-Identifier: GPL-3.0-or-later
package forgejo_migrations
import (
"testing"
"forgejo.org/models/db"
migration_tests "forgejo.org/models/gitea_migrations/test"
"forgejo.org/modules/timeutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"xorm.io/xorm/convert"
)
func Test_setOIDCSubjectFormatLegacy15(t *testing.T) {
type Type int
type UnitAccessMode int
type RepoUnit struct { //revive:disable-line:exported
ID int64
RepoID int64 `xorm:"INDEX(s)"`
Type Type `xorm:"INDEX(s)"`
Config convert.Conversion `xorm:"TEXT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
DefaultPermissions UnitAccessMode `xorm:"NOT NULL DEFAULT 0"`
}
x, deferable := migration_tests.PrepareTestEnv(t, 0, new(RepoUnit))
defer deferable()
if x == nil || t.Failed() {
return
}
require.NoError(t, setOIDCSubjectFormatLegacy15(x))
var records []map[string]string
require.NoError(t,
db.GetEngine(t.Context()).
Table("repo_unit").
Select("`id`, `repo_id`, `config`").
OrderBy("`id`").
Find(&records))
assert.Equal(t, []map[string]string{
{
"config": "{\"OIDCSubjectFormat\":\"legacy-forgejo-v15\"}",
"id": "1",
"repo_id": "4",
},
{
"config": "{\"DisabledWorkflows\":[\"renovate.yml\"],\"OIDCSubjectFormat\":\"legacy-forgejo-v15\"}",
"id": "2",
"repo_id": "5",
},
{
"config": "",
"id": "3",
"repo_id": "6",
},
}, records)
}

View file

@ -1,60 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package forgejo_migrations
import (
"context"
"fmt"
"forgejo.org/models/db"
"forgejo.org/modules/timeutil"
"xorm.io/xorm"
)
func init() {
registerMigration(&Migration{
Description: "add name & description to authorized_integration",
Upgrade: addAuthorizedIntegrationNameDescription,
})
}
func addAuthorizedIntegrationNameDescription(x *xorm.Engine) error {
type AuthorizedIntegration struct {
// New fields:
Name string
Description string `xorm:"LONGTEXT"`
// Existing fields, used for UPDATE in migration:
ID int64 `xorm:"pk autoincr"`
Issuer string `xorm:"NOT NULL UNIQUE(s)"`
Audience string `xorm:"NOT NULL UNIQUE(s)"`
CreatedUnix timeutil.TimeStamp `xorm:"NOT NULL created"`
// don't include `UpdatedUnix`, so the updated timestamp isn't bumped when Name is set in migration
}
_, err := x.SyncWithOptions(
xorm.SyncOptions{IgnoreDropIndices: true},
new(AuthorizedIntegration),
)
if err != nil {
return err
}
// As v16a has creating this table, v16b will likely have no records for any users. But for developers working on
// v16, populate "Name" with a quick computed value:
return db.Iterate(db.DefaultContext, nil, func(ctx context.Context, ai *AuthorizedIntegration) error {
ai.Name = fmt.Sprintf("%s created %s", ai.Issuer, ai.CreatedUnix.FormatDate())
r, err := db.GetEngine(ctx).
ID(ai.ID).
Cols("name").
Update(ai)
if err != nil {
return err
} else if r != 1 {
return fmt.Errorf("UPDATE expected to affect 1 row, but was %d", r)
}
return nil
})
}

View file

@ -1,14 +0,0 @@
- id: 1
repo_id: 4
type: 10 # actions
# config - null
created_unix: 1773518296
- id: 2
repo_id: 5
type: 10 # actions
config: '{"DisabledWorkflows":["renovate.yml"]}'
created_unix: 1773518296
- id: 3
repo_id: 6
type: 1 # code
created_unix: 1773518296

View file

@ -6,14 +6,11 @@
package issues
import (
"bytes"
"context"
"errors"
"fmt"
"html/template"
"slices"
"strconv"
"strings"
"unicode/utf8"
"forgejo.org/models/db"
@ -22,9 +19,7 @@ import (
project_model "forgejo.org/models/project"
repo_model "forgejo.org/models/repo"
user_model "forgejo.org/models/user"
"forgejo.org/modules/cache"
"forgejo.org/modules/container"
"forgejo.org/modules/git"
"forgejo.org/modules/gitrepo"
"forgejo.org/modules/json"
"forgejo.org/modules/log"
@ -326,8 +321,6 @@ type Comment struct {
CommitsNum int64 `xorm:"-"`
IsForcePush bool `xorm:"-"`
reverseLineBlame *git.ReverseLineBlame `xorm:"-"`
// If you add new fields that might be used to store abusive content (mainly string fields),
// please also add them in the CommentData struct and the corresponding constructor.
}
@ -751,89 +744,6 @@ func (c *Comment) UnsignedLine() uint64 {
return uint64(c.Line)
}
func (c *Comment) ResolveCurrentLine(ctx context.Context, repo *repo_model.Repository, currentHead string) (*git.ReverseLineBlame, error) {
if c.reverseLineBlame != nil {
return c.reverseLineBlame, nil
}
// When a PR is viewed, the requirement to perform `git blame --reverse...` on every comment is a bit of a
// performance risk. To minimize this risk, cache the results relative to the requested head, so it only needs to be
// recalculated when head changes (or on cache eviction).
//
// Some performance testing was done which showed that a hot cache is much faster than the blame reverse
// operation -- 500-1000x runtime difference:
//
// - cache miss (Forgejo repo) took 7,690,574 ns
// - cache miss (~1000 commit repo) took 1,671,223 ns
// - cache hit (in-memory adapter) took 3,710 ns
// - cache hit (redis adapter) took 77,311 ns
resolveJSON, err := cache.GetString(fmt.Sprintf("comment.Resolve;ID=%d;HEAD=%s", c.ID, currentHead), func() (string, error) {
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
if err != nil {
return "", fmt.Errorf("failed to open repo: %w", err)
}
defer closer.Close()
var reverseBlame *git.ReverseLineBlame
if c.Line > 0 {
var err error
reverseBlame, err = gitRepo.ReverseLineBlame(c.CommitSHA, c.TreePath, c.UnsignedLine(), currentHead)
if err != nil {
return "", fmt.Errorf("failed to perform `git blame --reverse` to resolve current line for comment (id=%d): %w", c.ID, err)
}
} else {
// For comments on removed lines, perform a `git diff` between the last commit that the line of code was
// known to exist (which is recorded as CommitSHA) and the requested head. Then inspect the diff to verify
// that the removed line of code is present in the diff.
buffer := bytes.Buffer{}
err := git.GetRepoRawDiffForFile(gitRepo, c.CommitSHA, currentHead, git.RawDiffNormal, c.TreePath, &buffer)
if err != nil {
return "", fmt.Errorf("failed to get diff: %w", err)
}
diff := buffer.String()
adjustedLine, err := git.FindAdjustedLineNumber(c.Patch, int64(c.UnsignedLine()), strings.NewReader(diff))
if err != nil && errors.Is(err, git.ErrLineNotFound) {
// Line not found in the diff. Don't treat this as an error, because that would break the caching --
// instead, return a blame where CommitID != headCommitID, which will be an indicator to callers (for
// both resolution methods) that the line of code is outdated in the diff.
reverseBlame = &git.ReverseLineBlame{
CommitID: "", // not currentHead
LineNumber: c.UnsignedLine(),
FilePath: c.TreePath,
}
} else if err != nil {
return "", fmt.Errorf("failed in finding adjusted line number: %w", err)
} else {
reverseBlame = &git.ReverseLineBlame{
CommitID: currentHead,
LineNumber: uint64(adjustedLine.Left),
FilePath: c.TreePath,
}
}
}
data, err := json.Marshal(reverseBlame)
if err != nil {
return "", err
}
return string(data), nil
})
if err != nil {
return nil, err
}
var reverseBlame *git.ReverseLineBlame
err = json.Unmarshal([]byte(resolveJSON), &reverseBlame)
if err != nil {
return nil, err
}
c.reverseLineBlame = reverseBlame
return c.reverseLineBlame, nil
}
// CodeCommentLink returns the url to a comment in code
func (c *Comment) CodeCommentLink(ctx context.Context) string {
err := c.LoadIssue(ctx)

View file

@ -7,10 +7,7 @@ import (
"context"
"forgejo.org/models/db"
repo_model "forgejo.org/models/repo"
user_model "forgejo.org/models/user"
"forgejo.org/modules/git"
"forgejo.org/modules/log"
"forgejo.org/modules/markup"
"forgejo.org/modules/markup/markdown"
@ -26,62 +23,33 @@ type CodeConversationsAtLine map[int64][]CodeConversation
// CodeConversationsAtLineAndTreePath contains the conversations for a given TreePath and line
type CodeConversationsAtLineAndTreePath map[string]CodeConversationsAtLine
func newCodeConversationsAtLineAndTreePath(ctx context.Context, comments []*Comment, repo *repo_model.Repository, headCommitID string) (CodeConversationsAtLineAndTreePath, error) {
func newCodeConversationsAtLineAndTreePath(comments []*Comment) CodeConversationsAtLineAndTreePath {
tree := make(CodeConversationsAtLineAndTreePath)
for _, comment := range comments {
blame, err := comment.ResolveCurrentLine(ctx, repo, headCommitID)
if err != nil {
// ResolveCurrentLine can fail in at least one known situation -- where a comment is left on a line in a
// file that is being deleted. The blame would be for the commit that deleted the file, and a reverse git
// blame won't work because the file is missing in the target sha.
log.Warn("ResolveCurrentLine failed: %s", err.Error())
// handle gracefully -- insertComment will use the original values which may be usable
blame = nil
} else if blame.CommitID != headCommitID {
// Commit was made on a line that can't be reverse-blamed to the currently viewing head. This can happen
// because:
// - line of code was removed between the commit it was tagged on, and the head commit
// - force push on the repo caused there to be no git relationship between blame.CommitID->headCommitID
// We won't insert this comment into the comment tree because we don't know where to place it; it may appear
// when the user views a different commit in the PR, and it will always appear on the "Conversations" tab.
continue
}
tree.insertComment(comment, blame)
tree.insertComment(comment)
}
return tree, nil
return tree
}
func (tree CodeConversationsAtLineAndTreePath) insertComment(comment *Comment, blame *git.ReverseLineBlame) {
treePath := comment.TreePath
line := comment.Line
if blame != nil {
treePath = blame.FilePath
line = int64(blame.LineNumber)
if comment.Line < 0 {
line *= -1
}
}
func (tree CodeConversationsAtLineAndTreePath) insertComment(comment *Comment) {
// attempt to append comment to existing conversations (i.e. list of comments belonging to the same review)
for i, conversation := range tree[treePath][line] {
for i, conversation := range tree[comment.TreePath][comment.Line] {
if conversation[0].ReviewID == comment.ReviewID {
tree[treePath][line][i] = append(conversation, comment)
tree[comment.TreePath][comment.Line][i] = append(conversation, comment)
return
}
}
// no previous conversation was found at this line, create it
if tree[treePath] == nil {
tree[treePath] = make(map[int64][]CodeConversation)
if tree[comment.TreePath] == nil {
tree[comment.TreePath] = make(map[int64][]CodeConversation)
}
tree[treePath][line] = append(tree[treePath][line], CodeConversation{comment})
tree[comment.TreePath][comment.Line] = append(tree[comment.TreePath][comment.Line], CodeConversation{comment})
}
// FetchCodeConversations will return a 2d-map: ["Path"]["Line"] = List of CodeConversation (one per review) for this
// line. headCommitID will be used to reverse-blame the comment into the correct path & line for the current context
// that is being viewed.
func FetchCodeConversations(ctx context.Context, issue *Issue, doer *user_model.User, showOutdatedComments bool, headCommitID string) (CodeConversationsAtLineAndTreePath, error) {
// FetchCodeConversations will return a 2d-map: ["Path"]["Line"] = List of CodeConversation (one per review) for this line
func FetchCodeConversations(ctx context.Context, issue *Issue, doer *user_model.User, showOutdatedComments bool) (CodeConversationsAtLineAndTreePath, error) {
opts := FindCommentsOptions{
Type: CommentTypeCode,
IssueID: issue.ID,
@ -91,7 +59,7 @@ func FetchCodeConversations(ctx context.Context, issue *Issue, doer *user_model.
return nil, err
}
return newCodeConversationsAtLineAndTreePath(ctx, comments, issue.Repo, headCommitID)
return newCodeConversationsAtLineAndTreePath(comments), nil
}
// CodeComments represents comments on code by using this structure: FILENAME -> LINE (+ == proposed; - == previous) -> COMMENTS

View file

@ -63,7 +63,7 @@ func TestFetchCodeConversations(t *testing.T) {
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 4}),
user, true))
res, err := issues_model.FetchCodeConversations(db.DefaultContext, issue, user, false, "")
res, err := issues_model.FetchCodeConversations(db.DefaultContext, issue, user, false)
require.NoError(t, err)
require.Contains(t, res, "README.md")
require.Contains(t, res["README.md"], int64(4))
@ -77,7 +77,7 @@ func TestFetchCodeConversations(t *testing.T) {
assert.NotNil(t, r.User)
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
res, err = issues_model.FetchCodeConversations(db.DefaultContext, issue, user2, false, "")
res, err = issues_model.FetchCodeConversations(db.DefaultContext, issue, user2, false)
require.NoError(t, err)
assert.Len(t, res, 1)
}

View file

@ -27,8 +27,6 @@ type PullRequestsOptions struct {
Labels []int64
MilestoneID int64
PosterID int64
BaseBranch string
HeadBranch string
}
func listPullRequestStatement(ctx context.Context, baseRepoID int64, opts *PullRequestsOptions) *xorm.Session {
@ -53,14 +51,6 @@ func listPullRequestStatement(ctx context.Context, baseRepoID int64, opts *PullR
sess.And("issue.poster_id=?", opts.PosterID)
}
if opts.BaseBranch != "" {
sess.And("pull_request.base_branch=?", opts.BaseBranch)
}
if opts.HeadBranch != "" {
sess.And("pull_request.head_branch=?", opts.HeadBranch)
}
return sess
}

View file

@ -136,7 +136,6 @@ func ProjectLinkForRepo(repo *repo_model.Repository, projectID int64) string { /
// Link returns the project's relative URL.
func (p *Project) Link(ctx context.Context) string {
// nosemgrep: forgejo-logic-suspicious-OwnerID-check (system users are not stored in the database)
if p.OwnerID > 0 {
err := p.LoadOwner(ctx)
if err != nil {
@ -184,7 +183,7 @@ func init() {
// GetCardConfig retrieves the types of configurations project column cards could have
//
//llu:returnsTrKeyWeak
//llu:returnsTrKey
func GetCardConfig() []CardConfig {
return []CardConfig{
{CardTypeTextOnly, "repo.projects.card_type.text_only"},
@ -225,7 +224,7 @@ func (opts SearchOptions) ToConds() builder.Cond {
if opts.Type > 0 {
cond = cond.And(builder.Eq{"type": opts.Type})
}
if opts.OwnerID != 0 {
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}

View file

@ -27,7 +27,7 @@ const (
// GetTemplateConfigs retrieves the template configs of configurations project columns could have
//
//llu:returnsTrKeyWeak
//llu:returnsTrKey
func GetTemplateConfigs() []TemplateConfig {
return []TemplateConfig{
{TemplateTypeNone, "repo.projects.type.none"},

View file

@ -893,7 +893,6 @@ type CountRepositoryOptions struct {
func CountRepositories(ctx context.Context, opts CountRepositoryOptions) (int64, error) {
sess := db.GetEngine(ctx).Where("id > 0")
// nosemgrep: forgejo-logic-suspicious-OwnerID-check (repositories cannot be owned by system users)
if opts.OwnerID > 0 {
sess.And("owner_id = ?", opts.OwnerID)
}

View file

@ -220,42 +220,8 @@ func (cfg *PullRequestsConfig) GetDefaultUpdateStyle() UpdateStyle {
return UpdateStyleMerge
}
// Represents the current format for `sub` claim generation when using `enable-openid-connect: true` on an Action.
//
// We try to follow GitHub's format for the `sub` claim because it should allow third-party integrations, which may have
// existing knowledge and code that works with GitHub's OIDC tokens, to reuse that knowledge and code in the future to
// implement Forgejo support. As GitHub's format changes, we may implement those format changes to maintain that
// familarity. Forgejo isn't required to do so, though -- if future changes from GitHub don't make sense for Forgejo,
// or vice-versa, this format matching effort may be discarded.
type OIDCSubjectFormat string
var (
// Default is the current, most preferred method of generating an `sub` JWT claim for an Actions JWT token. It is
// an empty string which allows [ActionsConfig] to always default to the current preferred default value for new
// repositories. At present, it is a `sub` claim that contains information about the repository owner and
// repository where the action occurred, their immutable identifiers (ID numbers), and the event that triggered the
// Action.
//
// Immutable identifiers have been added since OIDCSubjectFormatLegacyForgejo15. The intent of adding them is to
// protect resource servers which may be requiring a specific subject claim from having that claim be impersonated
// when a user or repository are renamed or deleted. For example, if a JWT from my-org/my-repo is trusted, but then
// my-org is deleted and a new user takes ownership of the name my-org, they should not be granted the same trust.
//
// Example: repo:my-org-123456/my-repo-456789:ref:refs/heads/main
OIDCSubjectFormatDefault OIDCSubjectFormat // defaults to ""
// The `sub` JWT claim generation that was shipped in Forgejo 15. Contains information about the repository owner
// and repository where the action occurred and the event that triggered the Action.
//
// Example: repo:my-org/my-repo:ref:refs/heads/main
OIDCSubjectFormatLegacyForgejo15 OIDCSubjectFormat = "legacy-forgejo-v15"
)
type ActionsConfig struct {
DisabledWorkflows []string
// Format of the OIDC 'sub' claim that will be used when `enable-openid-connect` is true in an Action.
OIDCSubjectFormat OIDCSubjectFormat `json:",omitempty"`
}
func (cfg *ActionsConfig) EnableWorkflow(file string) {

View file

@ -38,8 +38,6 @@ func init() {
}
// TrStr returns a translation format string.
//
//llu:returnsTrKey
func (n *Notice) TrStr() string {
return fmt.Sprintf("admin.notices.type_%d", n.Type)
}

View file

@ -47,29 +47,10 @@ func fatalTestError(fmtStr string, args ...any) {
// InitSettings initializes config provider and load common settings for tests
func InitSettings() {
InitCustomSettings("unittest.ini")
}
func InitCustomSettings(confFileName string) {
root := base.SetupGiteaRoot()
if root == "" {
fatalTestError("Environment variable $GITEA_ROOT not set")
}
setting.AppPath = filepath.Join(root, "gitea")
if setting.CustomConf == "" {
templateFile := confFileName + ".tmpl"
content, err := os.ReadFile(filepath.Join(root, "tests", templateFile))
if err != nil {
log.Fatalf("couldn't read config template: %s", templateFile)
}
err = os.WriteFile(filepath.Join(root, "tests", confFileName), content, 0o644)
if err != nil {
log.Fatalf("couldn't write config: %s", confFileName)
}
setting.CustomConf = filepath.Join(root, "tests", confFileName)
setting.CustomConf = filepath.Join(setting.CustomPath, "conf/app-unittest-tmp.ini")
_ = os.Remove(setting.CustomConf)
}
os.Setenv("GITEA_CONF", setting.CustomConf)
setting.InitCfgProvider(setting.CustomConf)
setting.LoadCommonSettings()
@ -91,10 +72,9 @@ func InitCustomSettings(confFileName string) {
// TestOptions represents test options
type TestOptions struct {
FixtureFiles []string
SetUp func() error // SetUp will be executed before all tests in this package
TearDown func() error // TearDown will be executed after all tests in this package
IniFileOverride string
FixtureFiles []string
SetUp func() error // SetUp will be executed before all tests in this package
TearDown func() error // TearDown will be executed after all tests in this package
}
// MainTest a reusable TestMain(..) function for unit tests that need to use a
@ -117,11 +97,7 @@ func MainTest(m *testing.M, testOpts ...*TestOptions) {
giteaRoot = searchDir
setting.CustomPath = filepath.Join(giteaRoot, "custom")
if len(testOpts) == 0 || testOpts[0].IniFileOverride == "" {
InitSettings()
} else {
InitCustomSettings(testOpts[0].IniFileOverride)
}
InitSettings()
fixturesDir = filepath.Join(giteaRoot, "models", "fixtures")
var opts FixturesOptions

View file

@ -67,7 +67,7 @@ func BeanExists(t testing.TB, bean any, conditions ...any) bool {
}
// AssertExistsAndLoadBean assert that a bean exists and load it from the test database
func AssertExistsAndLoadBean[T any](t require.TestingT, bean T, conditions ...any) T {
func AssertExistsAndLoadBean[T any](t testing.TB, bean T, conditions ...any) T {
exists, err := LoadBeanIfExists(bean, conditions...)
require.NoError(t, err)
assert.True(t, exists,

View file

@ -105,16 +105,3 @@ func IsErrUserIsNotLocal(err error) bool {
_, ok := err.(ErrUserIsNotLocal)
return ok
}
type ErrFederatedUserNotExists struct {
Identifier string
}
func (err ErrFederatedUserNotExists) Error() string {
return fmt.Sprintf("No cached federated user found for identifier %s", err.Identifier)
}
func IsErrFederatedUserNotExists(err error) bool {
_, ok := err.(ErrFederatedUserNotExists)
return ok
}

View file

@ -5,7 +5,6 @@ package user
import (
"database/sql"
"fmt"
"forgejo.org/modules/validation"
)
@ -43,18 +42,3 @@ func (federatedUser FederatedUser) Validate() []string {
result = append(result, validation.ValidateNotEmpty(federatedUser.InboxPath, "InboxPath")...)
return result
}
func (federatedUser *FederatedUser) LogString() string {
if federatedUser == nil {
return "<FederatedUser nil>"
}
return fmt.Sprintf(
"<FederatedUser ID: %d, UserID: %d, ExternalID: %s, NormalizedOriginalURL: %s, InboxPath: %s>",
federatedUser.ID,
federatedUser.UserID,
federatedUser.ExternalID,
federatedUser.NormalizedOriginalURL,
federatedUser.InboxPath,
)
}

View file

@ -89,8 +89,8 @@ var userDataColumnNames = sync.OnceValue(func() []string {
mapper := new(names.GonicMapper)
udType := reflect.TypeFor[UserData]()
columnNames := make([]string, 0, udType.NumField())
for field := range udType.Fields() {
columnNames = append(columnNames, mapper.Obj2Table(field.Name))
for i := 0; i < udType.NumField(); i++ {
columnNames = append(columnNames, mapper.Obj2Table(udType.Field(i).Name))
}
return columnNames
})

View file

@ -65,7 +65,7 @@ func FindFederatedUser(ctx context.Context, externalID string, federationHostID
if err != nil {
return nil, nil, err
} else if !has {
return nil, nil, ErrFederatedUserNotExists{Identifier: externalID}
return nil, nil, nil
}
has, err = db.GetEngine(ctx).ID(federatedUser.UserID).Get(user)
if err != nil {
@ -83,55 +83,14 @@ func FindFederatedUser(ctx context.Context, externalID string, federationHostID
return user, federatedUser, nil
}
func CountFederatedUsers(ctx context.Context) (int64, error) {
return db.GetEngine(ctx).Count(FederatedUser{})
}
func FindFederatedUsers(ctx context.Context, opts db.ListOptions) (users []*FederatedUser, err error) {
sess := db.GetEngine(ctx)
if opts.PageSize > 0 {
sess = db.SetSessionPagination(sess, &opts)
}
err = sess.Find(&users)
func GetFederatedUser(ctx context.Context, externalID string, federationHostID int64) (*User, *FederatedUser, error) {
user, federatedUser, err := FindFederatedUser(ctx, externalID, federationHostID)
if err != nil {
return nil, err
return nil, nil, err
} else if federatedUser == nil {
return nil, nil, fmt.Errorf("FederatedUser not found (given externalId: %v, federationHostId: %v)", externalID, federationHostID)
}
for _, user := range users {
if res, err := validation.IsValid(user); !res {
return nil, err
}
}
return users, err
}
func CountFederatedUsersByHostID(ctx context.Context, federationHostID int64) (int64, error) {
return db.GetEngine(ctx).Where("federation_host_id = ?", federationHostID).Count(FederatedUser{})
}
func FindFederatedUsersByHostID(ctx context.Context, federationHostID int64, opts db.ListOptions) ([]*FederatedUser, error) {
var users []*FederatedUser
sess := db.GetEngine(ctx).Where("federation_host_id = ?", federationHostID)
if opts.PageSize > 0 {
sess = db.SetSessionPagination(sess, &opts)
}
err := sess.Find(&users)
if err != nil {
return nil, err
}
for _, user := range users {
if res, err := validation.IsValid(user); !res {
return nil, err
}
}
return users, nil
return user, federatedUser, nil
}
func GetFederatedUserByUserID(ctx context.Context, userID int64) (*User, *FederatedUser, error) {
@ -167,7 +126,7 @@ func FindFederatedUserByKeyID(ctx context.Context, keyID string) (*User, *Federa
if err != nil {
return nil, nil, err
} else if !has {
return nil, nil, ErrFederatedUserNotExists{Identifier: keyID}
return nil, nil, nil
}
has, err = db.GetEngine(ctx).ID(federatedUser.UserID).Get(user)
if err != nil {

View file

@ -111,8 +111,6 @@ func fullStepsOfEmptySteps(task *actions_model.ActionTask) []*actions_model.Acti
preStep.Status = task.Status
if preStep.Status.IsSuccess() {
postStep.Status = actions_model.StatusSuccess
} else if preStep.Status.IsSkipped() {
postStep.Status = actions_model.StatusSkipped
} else {
postStep.Status = actions_model.StatusCancelled
}

View file

@ -156,21 +156,6 @@ func TestFullSteps(t *testing.T) {
{Name: postStepName, Status: actions_model.StatusSuccess, LogIndex: 90, LogLength: 10, Started: 10090, Stopped: 10100},
},
},
{
// situation occurs with a reusable workflow's outer job which has no steps
name: "skipped task w/ zero steps",
task: &actions_model.ActionTask{
Steps: []*actions_model.ActionTaskStep{},
Status: actions_model.StatusSkipped,
Started: 0,
Stopped: 0,
LogLength: 0,
},
want: []*actions_model.ActionTaskStep{
{Name: preStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
{Name: postStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View file

@ -103,7 +103,7 @@ func Int64sToStrings(ints []int64) []string {
func EntryIcon(entry *git.TreeEntry) string {
switch {
case entry.IsLink():
te, err := entry.FollowLink()
te, _, err := entry.FollowLink()
if err != nil {
log.Debug(err.Error())
return "file-symlink-file"

497
modules/cache/mocks.go vendored
View file

@ -1,497 +0,0 @@
// Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package cache
import (
"code.forgejo.org/go-chi/cache"
mock "github.com/stretchr/testify/mock"
)
// NewMockCache creates a new instance of MockCache. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewMockCache(t interface {
mock.TestingT
Cleanup(func())
},
) *MockCache {
mock := &MockCache{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// MockCache is an autogenerated mock type for the Cache type
type MockCache struct {
mock.Mock
}
type MockCache_Expecter struct {
mock *mock.Mock
}
func (_m *MockCache) EXPECT() *MockCache_Expecter {
return &MockCache_Expecter{mock: &_m.Mock}
}
// Decr provides a mock function for the type MockCache
func (_mock *MockCache) Decr(key string) error {
ret := _mock.Called(key)
if len(ret) == 0 {
panic("no return value specified for Decr")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(string) error); ok {
r0 = returnFunc(key)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockCache_Decr_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Decr'
type MockCache_Decr_Call struct {
*mock.Call
}
// Decr is a helper method to define mock.On call
// - key string
func (_e *MockCache_Expecter) Decr(key any) *MockCache_Decr_Call {
return &MockCache_Decr_Call{Call: _e.mock.On("Decr", key)}
}
func (_c *MockCache_Decr_Call) Run(run func(key string)) *MockCache_Decr_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
})
return _c
}
func (_c *MockCache_Decr_Call) Return(err error) *MockCache_Decr_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockCache_Decr_Call) RunAndReturn(run func(key string) error) *MockCache_Decr_Call {
_c.Call.Return(run)
return _c
}
// Delete provides a mock function for the type MockCache
func (_mock *MockCache) Delete(key string) error {
ret := _mock.Called(key)
if len(ret) == 0 {
panic("no return value specified for Delete")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(string) error); ok {
r0 = returnFunc(key)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockCache_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete'
type MockCache_Delete_Call struct {
*mock.Call
}
// Delete is a helper method to define mock.On call
// - key string
func (_e *MockCache_Expecter) Delete(key any) *MockCache_Delete_Call {
return &MockCache_Delete_Call{Call: _e.mock.On("Delete", key)}
}
func (_c *MockCache_Delete_Call) Run(run func(key string)) *MockCache_Delete_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
})
return _c
}
func (_c *MockCache_Delete_Call) Return(err error) *MockCache_Delete_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockCache_Delete_Call) RunAndReturn(run func(key string) error) *MockCache_Delete_Call {
_c.Call.Return(run)
return _c
}
// Flush provides a mock function for the type MockCache
func (_mock *MockCache) Flush() error {
ret := _mock.Called()
if len(ret) == 0 {
panic("no return value specified for Flush")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = returnFunc()
} else {
r0 = ret.Error(0)
}
return r0
}
// MockCache_Flush_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Flush'
type MockCache_Flush_Call struct {
*mock.Call
}
// Flush is a helper method to define mock.On call
func (_e *MockCache_Expecter) Flush() *MockCache_Flush_Call {
return &MockCache_Flush_Call{Call: _e.mock.On("Flush")}
}
func (_c *MockCache_Flush_Call) Run(run func()) *MockCache_Flush_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockCache_Flush_Call) Return(err error) *MockCache_Flush_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockCache_Flush_Call) RunAndReturn(run func() error) *MockCache_Flush_Call {
_c.Call.Return(run)
return _c
}
// Get provides a mock function for the type MockCache
func (_mock *MockCache) Get(key string) any {
ret := _mock.Called(key)
if len(ret) == 0 {
panic("no return value specified for Get")
}
var r0 any
if returnFunc, ok := ret.Get(0).(func(string) any); ok {
r0 = returnFunc(key)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(any)
}
}
return r0
}
// MockCache_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get'
type MockCache_Get_Call struct {
*mock.Call
}
// Get is a helper method to define mock.On call
// - key string
func (_e *MockCache_Expecter) Get(key any) *MockCache_Get_Call {
return &MockCache_Get_Call{Call: _e.mock.On("Get", key)}
}
func (_c *MockCache_Get_Call) Run(run func(key string)) *MockCache_Get_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
})
return _c
}
func (_c *MockCache_Get_Call) Return(v any) *MockCache_Get_Call {
_c.Call.Return(v)
return _c
}
func (_c *MockCache_Get_Call) RunAndReturn(run func(key string) any) *MockCache_Get_Call {
_c.Call.Return(run)
return _c
}
// Incr provides a mock function for the type MockCache
func (_mock *MockCache) Incr(key string) error {
ret := _mock.Called(key)
if len(ret) == 0 {
panic("no return value specified for Incr")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(string) error); ok {
r0 = returnFunc(key)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockCache_Incr_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Incr'
type MockCache_Incr_Call struct {
*mock.Call
}
// Incr is a helper method to define mock.On call
// - key string
func (_e *MockCache_Expecter) Incr(key any) *MockCache_Incr_Call {
return &MockCache_Incr_Call{Call: _e.mock.On("Incr", key)}
}
func (_c *MockCache_Incr_Call) Run(run func(key string)) *MockCache_Incr_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
})
return _c
}
func (_c *MockCache_Incr_Call) Return(err error) *MockCache_Incr_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockCache_Incr_Call) RunAndReturn(run func(key string) error) *MockCache_Incr_Call {
_c.Call.Return(run)
return _c
}
// IsExist provides a mock function for the type MockCache
func (_mock *MockCache) IsExist(key string) bool {
ret := _mock.Called(key)
if len(ret) == 0 {
panic("no return value specified for IsExist")
}
var r0 bool
if returnFunc, ok := ret.Get(0).(func(string) bool); ok {
r0 = returnFunc(key)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockCache_IsExist_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsExist'
type MockCache_IsExist_Call struct {
*mock.Call
}
// IsExist is a helper method to define mock.On call
// - key string
func (_e *MockCache_Expecter) IsExist(key any) *MockCache_IsExist_Call {
return &MockCache_IsExist_Call{Call: _e.mock.On("IsExist", key)}
}
func (_c *MockCache_IsExist_Call) Run(run func(key string)) *MockCache_IsExist_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
run(
arg0,
)
})
return _c
}
func (_c *MockCache_IsExist_Call) Return(b bool) *MockCache_IsExist_Call {
_c.Call.Return(b)
return _c
}
func (_c *MockCache_IsExist_Call) RunAndReturn(run func(key string) bool) *MockCache_IsExist_Call {
_c.Call.Return(run)
return _c
}
// Ping provides a mock function for the type MockCache
func (_mock *MockCache) Ping() error {
ret := _mock.Called()
if len(ret) == 0 {
panic("no return value specified for Ping")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func() error); ok {
r0 = returnFunc()
} else {
r0 = ret.Error(0)
}
return r0
}
// MockCache_Ping_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ping'
type MockCache_Ping_Call struct {
*mock.Call
}
// Ping is a helper method to define mock.On call
func (_e *MockCache_Expecter) Ping() *MockCache_Ping_Call {
return &MockCache_Ping_Call{Call: _e.mock.On("Ping")}
}
func (_c *MockCache_Ping_Call) Run(run func()) *MockCache_Ping_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockCache_Ping_Call) Return(err error) *MockCache_Ping_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockCache_Ping_Call) RunAndReturn(run func() error) *MockCache_Ping_Call {
_c.Call.Return(run)
return _c
}
// Put provides a mock function for the type MockCache
func (_mock *MockCache) Put(key string, val any, timeout int64) error {
ret := _mock.Called(key, val, timeout)
if len(ret) == 0 {
panic("no return value specified for Put")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(string, any, int64) error); ok {
r0 = returnFunc(key, val, timeout)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockCache_Put_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Put'
type MockCache_Put_Call struct {
*mock.Call
}
// Put is a helper method to define mock.On call
// - key string
// - val any
// - timeout int64
func (_e *MockCache_Expecter) Put(key, val, timeout any) *MockCache_Put_Call {
return &MockCache_Put_Call{Call: _e.mock.On("Put", key, val, timeout)}
}
func (_c *MockCache_Put_Call) Run(run func(key string, val any, timeout int64)) *MockCache_Put_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 string
if args[0] != nil {
arg0 = args[0].(string)
}
var arg1 any
if args[1] != nil {
arg1 = args[1].(any)
}
var arg2 int64
if args[2] != nil {
arg2 = args[2].(int64)
}
run(
arg0,
arg1,
arg2,
)
})
return _c
}
func (_c *MockCache_Put_Call) Return(err error) *MockCache_Put_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockCache_Put_Call) RunAndReturn(run func(key string, val any, timeout int64) error) *MockCache_Put_Call {
_c.Call.Return(run)
return _c
}
// StartAndGC provides a mock function for the type MockCache
func (_mock *MockCache) StartAndGC(opt cache.Options) error {
ret := _mock.Called(opt)
if len(ret) == 0 {
panic("no return value specified for StartAndGC")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(cache.Options) error); ok {
r0 = returnFunc(opt)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockCache_StartAndGC_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'StartAndGC'
type MockCache_StartAndGC_Call struct {
*mock.Call
}
// StartAndGC is a helper method to define mock.On call
// - opt cache.Options
func (_e *MockCache_Expecter) StartAndGC(opt any) *MockCache_StartAndGC_Call {
return &MockCache_StartAndGC_Call{Call: _e.mock.On("StartAndGC", opt)}
}
func (_c *MockCache_StartAndGC_Call) Run(run func(opt cache.Options)) *MockCache_StartAndGC_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 cache.Options
if args[0] != nil {
arg0 = args[0].(cache.Options)
}
run(
arg0,
)
})
return _c
}
func (_c *MockCache_StartAndGC_Call) Return(err error) *MockCache_StartAndGC_Call {
_c.Call.Return(err)
return _c
}
func (_c *MockCache_StartAndGC_Call) RunAndReturn(run func(opt cache.Options) error) *MockCache_StartAndGC_Call {
_c.Call.Return(run)
return _c
}

View file

@ -48,8 +48,8 @@ func (follow *ForgeFollow) UnmarshalJSON(data []byte) error {
func (follow ForgeFollow) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(follow.Type, "type")...)
result = append(result, validation.ValidateOneOf(follow.Type, []any{ap.FollowType}, "type")...)
result = append(result, validation.ValidateNotEmpty(string(follow.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(follow.Type), []any{"Follow"}, "type")...)
result = append(result, validation.ValidateIDExists(follow.Actor, "actor")...)
result = append(result, validation.ValidateIDExists(follow.Object, "object")...)

View file

@ -15,7 +15,7 @@ import (
func Test_NewForgeFollowValidation(t *testing.T) {
sut := forgefed.ForgeFollow{}
sut.Type = ap.FollowType
sut.Type = "Follow"
sut.Actor = ap.IRI("example.org/alice")
sut.Object = ap.IRI("example.org/bob")

View file

@ -44,8 +44,8 @@ func (like ForgeLike) IsNewer(compareTo time.Time) bool {
func (like ForgeLike) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(like.Type, "type")...)
result = append(result, validation.ValidateOneOf(like.Type, []any{ap.LikeType}, "type")...)
result = append(result, validation.ValidateNotEmpty(string(like.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(like.Type), []any{"Like"}, "type")...)
if like.Actor == nil {
result = append(result, "Actor should not be nil.")

View file

@ -51,7 +51,7 @@ func Test_LikeMarshalJSON(t *testing.T) {
item: forgefed.ForgeLike{
Activity: ap.Activity{
Actor: ap.IRI("https://repo.prod.meissa.de/api/v1/activitypub/user-id/1"),
Type: ap.LikeType,
Type: "Like",
Object: ap.IRI("https://codeberg.org/api/v1/activitypub/repository-id/1"),
},
},
@ -80,7 +80,7 @@ func Test_LikeUnmarshalJSON(t *testing.T) {
item: []byte(`{"type":"Like","actor":"https://repo.prod.meissa.de/api/activitypub/user-id/1","object":"https://codeberg.org/api/activitypub/repository-id/1"}`),
want: &forgefed.ForgeLike{
Activity: ap.Activity{
Type: ap.LikeType,
Type: "Like",
Actor: ap.IRI("https://repo.prod.meissa.de/api/activitypub/user-id/1"),
Object: ap.IRI("https://codeberg.org/api/activitypub/repository-id/1"),
},
@ -124,7 +124,7 @@ func Test_ForgeLikeValidation(t *testing.T) {
validate := sut.Validate()
assert.Len(t, validate, 2)
assert.Equal(t,
"Field type contains the value <nil>, which is not in allowed subset [Like]",
"Field type contains the value , which is not in allowed subset [Like]",
validate[1])
sut.UnmarshalJSON([]byte(`{"type":"bad-type",

View file

@ -42,8 +42,8 @@ func (undo *ForgeUndoLike) UnmarshalJSON(data []byte) error {
func (undo ForgeUndoLike) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(undo.Type, "type")...)
result = append(result, validation.ValidateOneOf(undo.Type, []any{ap.UndoType}, "type")...)
result = append(result, validation.ValidateNotEmpty(string(undo.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(undo.Type), []any{"Undo"}, "type")...)
if undo.Actor == nil {
result = append(result, "Actor should not be nil.")
@ -61,8 +61,8 @@ func (undo ForgeUndoLike) Validate() []string {
} else if activity, ok := undo.Object.(*ap.Activity); !ok {
result = append(result, "object is not of type Activity")
} else {
result = append(result, validation.ValidateNotEmpty(activity.Type, "type")...)
result = append(result, validation.ValidateOneOf(activity.Type, []any{ap.LikeType}, "type")...)
result = append(result, validation.ValidateNotEmpty(string(activity.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(activity.Type), []any{"Like"}, "type")...)
if activity.Actor == nil {
result = append(result, "Object.Actor should not be nil.")

View file

@ -64,7 +64,7 @@ func Test_UndoLikeMarshalJSON(t *testing.T) {
Activity: ap.Activity{
StartTime: startTime,
Actor: ap.IRI("https://repo.prod.meissa.de/api/v1/activitypub/user-id/1"),
Type: ap.UndoType,
Type: "Undo",
Object: like,
},
},
@ -117,7 +117,7 @@ func Test_UndoLikeUnmarshalJSON(t *testing.T) {
Activity: ap.Activity{
StartTime: startTime,
Actor: ap.IRI("https://repo.prod.meissa.de/api/v1/activitypub/user-id/1"),
Type: ap.UndoType,
Type: "Undo",
Object: like,
},
},

View file

@ -60,8 +60,8 @@ func NewForgeUserActivity(doer *user_model.User, actionID int64, content string)
func (userActivity ForgeUserActivity) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(userActivity.Type, "type")...)
result = append(result, validation.ValidateOneOf(userActivity.Type, []any{ap.CreateType}, "type")...)
result = append(result, validation.ValidateNotEmpty(string(userActivity.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(userActivity.Type), []any{"Create"}, "type")...)
result = append(result, validation.ValidateIDExists(userActivity.Actor, "actor")...)
if len(userActivity.To) == 0 {

View file

@ -15,14 +15,17 @@ import (
func Test_ForgeUserActivityValidation(t *testing.T) {
note := forgefed.ForgeUserActivityNote{}
note.Type = ap.NoteType
note.Type = "Note"
note.Content = ap.NaturalLanguageValues{
ap.NilLangRef: ap.Content("Any Content!"),
{
Ref: ap.NilLangRef,
Value: ap.Content("Any Content!"),
},
}
note.URL = ap.IRI("example.org/user-id/57")
sut := forgefed.ForgeUserActivity{}
sut.Type = ap.CreateType
sut.Type = "Create"
sut.Actor = ap.IRI("example.org/user-id/23")
sut.CC = ap.ItemCollection{
ap.IRI("example.org/registration/public#2nd"),

View file

@ -20,8 +20,6 @@ type PersonID struct {
const (
personIDapiPathV1 = "api/v1/activitypub/user-id"
personIDapiPathV1Latest = "api/activitypub/user-id"
actorIDapiPathV1 = "api/v1/activitypub"
actorIDapiPathLatest = "api/activitypub"
)
// Factory function for PersonID. Created struct is asserted to be valid
@ -90,11 +88,8 @@ func (id PersonID) Validate() []string {
result = append(result, validation.ValidateOneOf(id.Source, []any{"forgejo", "gitea", "mastodon", "gotosocial"}, "Source")...)
if id.Source == "forgejo" {
result = append(result, validation.ValidateNotEmpty(id.Path, "path")...)
lowerPath := strings.ToLower(id.Path)
if lowerPath != personIDapiPathV1 && lowerPath != personIDapiPathV1Latest {
if lowerPath != actorIDapiPathV1 && lowerPath != actorIDapiPathLatest || id.ID != "actor" {
result = append(result, fmt.Sprintf("path: %q has to be a person specific api path", id.Path))
}
if strings.ToLower(id.Path) != personIDapiPathV1 && strings.ToLower(id.Path) != personIDapiPathV1Latest {
result = append(result, fmt.Sprintf("path: %q has to be a person specific api path", id.Path))
}
}
@ -120,8 +115,8 @@ func (s *ForgePerson) UnmarshalJSON(data []byte) error {
func (s ForgePerson) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(s.Type, "Type")...)
result = append(result, validation.ValidateOneOf(s.Type, []any{ap.PersonType}, "Type")...)
result = append(result, validation.ValidateNotEmpty(string(s.Type), "Type")...)
result = append(result, validation.ValidateOneOf(string(s.Type), []any{string(ap.PersonType)}, "Type")...)
result = append(result, validation.ValidateNotEmpty(s.PreferredUsername.String(), "PreferredUsername")...)
return result

View file

@ -159,48 +159,6 @@ func TestPersonIdValidation(t *testing.T) {
result, err = validation.IsValid(sut)
assert.False(t, result)
require.EqualError(t, err, "Validation Error: forgefed.PersonID: Field Source contains the value forgejox, which is not in allowed subset [forgejo gitea mastodon gotosocial]")
sut = forgefed.PersonID{}
sut.ID = "actor"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub"
sut.Host = "example.com"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://example.com/api/v1/activitypub/actor"
result, err = validation.IsValid(sut)
assert.True(t, result)
require.NoError(t, err)
sut = forgefed.PersonID{}
sut.ID = "actor"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "api/activitypub"
sut.Host = "example.com"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://example.com/api/activitypub/actor"
result, err = validation.IsValid(sut)
assert.True(t, result)
require.NoError(t, err)
sut = forgefed.PersonID{}
sut.ID = "1"
sut.Source = "forgejo"
sut.HostSchema = "https"
sut.Path = "api/v1/activitypub"
sut.Host = "example.com"
sut.HostPort = 443
sut.IsPortSupplemented = true
sut.UnvalidatedInput = "https://example.com/api/v1/activitypub/1"
result, err = validation.IsValid(sut)
assert.False(t, result)
require.EqualError(t, err, "Validation Error: forgefed.PersonID: path: \"api/v1/activitypub\" has to be a person specific api path")
}
func TestWebfingerId(t *testing.T) {
@ -236,9 +194,9 @@ func TestShouldThrowErrorOnInvalidInput(t *testing.T) {
func Test_PersonMarshalJSON(t *testing.T) {
sut := forgefed.ForgePerson{}
sut.Type = ap.PersonType
sut.Type = "Person"
sut.PreferredUsername = ap.NaturalLanguageValuesNew()
sut.PreferredUsername.Set(ap.English, ap.Content("MaxMuster"))
sut.PreferredUsername.Set("en", ap.Content("MaxMuster"))
result, _ := sut.MarshalJSON()
assert.JSONEq(t, `{"type":"Person","preferredUsername":"MaxMuster"}`, string(result), "Expected string is not equal")
}
@ -246,9 +204,9 @@ func Test_PersonMarshalJSON(t *testing.T) {
func Test_PersonUnmarshalJSON(t *testing.T) {
expected := &forgefed.ForgePerson{
Actor: ap.Actor{
Type: ap.PersonType,
Type: "Person",
PreferredUsername: ap.NaturalLanguageValues{
ap.English: []byte("MaxMuster"),
ap.LangRefValue{Ref: "en", Value: []byte("MaxMuster")},
},
},
}

View file

@ -1,15 +0,0 @@
// Copyright 2024, 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgefed
import (
ap "github.com/go-ap/activitypub"
)
// ForgeFollow activity data type
// swagger:model
type ForgeInbox struct {
// swagger:ignore
ap.InboxStream
}

View file

@ -35,7 +35,10 @@ func newNote(doer *user_model.User, content, id string, published time.Time) (Fo
note.Type = ap.NoteType
note.AttributedTo = ap.IRI(doer.APActorID())
note.Content = ap.NaturalLanguageValues{
ap.NilLangRef: ap.Content(content),
{
Ref: ap.NilLangRef,
Value: ap.Content(content),
},
}
note.ID = ap.IRI(id)
note.Published = published
@ -56,8 +59,8 @@ func newNote(doer *user_model.User, content, id string, published time.Time) (Fo
func (note ForgeUserActivityNote) Validate() []string {
var result []string
result = append(result, validation.ValidateNotEmpty(note.Type, "type")...)
result = append(result, validation.ValidateOneOf(note.Type, []any{ap.NoteType}, "type")...)
result = append(result, validation.ValidateNotEmpty(string(note.Type), "type")...)
result = append(result, validation.ValidateOneOf(string(note.Type), []any{"Note"}, "type")...)
result = append(result, validation.ValidateNotEmpty(note.Content.String(), "content")...)
result = append(result, validation.ValidateIDExists(note.URL, "url")...)

Some files were not shown because too many files have changed in this diff Show more