Compare commits

..

170 commits

Author SHA1 Message Date
forgejo-backport-action
df982912e8 [v14.0/forgejo] Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.6.0 (forgejo) (#12316)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/12156

Co-authored-by: Renovate Bot <bot@kriese.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12316
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2026-04-29 08:26:50 +02:00
Mathieu Fenniak
3653b34ec7 [v14.0/forgejo] fix: verify PR author has write access to head to support allow maintainers edit (#12294)
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/12294
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
2026-04-29 05:29:23 +02:00
0ko
a8ad367642 merge commit: [v14.0/forgejo] i18n: backport of translations from Codeberg Translate (#12305)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12305
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2026-04-28 20:30:31 +02:00
0ko
79bd2692bb [v14.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v14 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:25:58 +05:00
Renovate Bot
0f6956a3cd Update dependency postcss to v8.5.10 [SECURITY] (v14.0/forgejo) (#12254)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12254
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-04-24 19:45:14 +02:00
Renovate Bot
21692f7cb3 Update module golang.org/x/image to v0.39.0 [SECURITY] (v14.0/forgejo) (#12223)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12223
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2026-04-23 00:15:37 +02:00
Renovate Bot
54d13b309c Update github.com/go-git/go-git/v5 (indirect) to v5.18.0 [SECURITY] (v14.0/forgejo) (#12176)
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:eyJjcmVhdGVkSW5WZXIiOiI0My4xMTEuMCIsInVwZGF0ZWRJblZlciI6IjQzLjExMS4wIiwidGFyZ2V0QnJhbmNoIjoidjE0LjAvZm9yZ2VqbyIsImxhYmVscyI6WyJkZXBlbmRlbmN5LXVwZ3JhZGUiLCJ0ZXN0L25vdC1uZWVkZWQiXX0=-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12176
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:04 +02:00
Renovate Bot
0243a9a1b3 Update module github.com/jackc/pgx/v5 to v5.9.0 [SECURITY] (v14.0/forgejo) (#12133)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) | `v5.7.6` → `v5.9.0` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fjackc%2fpgx%2fv5/v5.9.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fjackc%2fpgx%2fv5/v5.7.6/v5.9.0?slim=true) |

---

### Memory-safety vulnerability in github.com/jackc/pgx/v5.
[CVE-2026-33816](https://nvd.nist.gov/vuln/detail/CVE-2026-33816) / [GHSA-9jj7-4m8r-rfcm](https://github.com/advisories/GHSA-9jj7-4m8r-rfcm) / [GO-2026-4772](https://pkg.go.dev/vuln/GO-2026-4772)

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

#### Details
Memory-safety vulnerability in github.com/jackc/pgx/v5.

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

#### References
- [https://nvd.nist.gov/vuln/detail/CVE-2026-33816](https://nvd.nist.gov/vuln/detail/CVE-2026-33816)
- [https://github.com/jackc/pgx](https://github.com/jackc/pgx)
- [https://pkg.go.dev/vuln/GO-2026-4772](https://pkg.go.dev/vuln/GO-2026-4772)

This data is provided by [OSV](https://osv.dev/vulnerability/GHSA-9jj7-4m8r-rfcm) 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>

---

### CVE-2026-33816 in github.com/jackc/pgx
[CVE-2026-33816](https://nvd.nist.gov/vuln/detail/CVE-2026-33816) / [GHSA-9jj7-4m8r-rfcm](https://github.com/advisories/GHSA-9jj7-4m8r-rfcm) / [GO-2026-4772](https://pkg.go.dev/vuln/GO-2026-4772)

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

#### Details
Memory-safety vulnerability in github.com/jackc/pgx/v5.

#### Severity
Unknown

#### References
No references.

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

---

### Release Notes

<details>
<summary>jackc/pgx (github.com/jackc/pgx/v5)</summary>

### [`v5.9.0`](https://github.com/jackc/pgx/compare/v5.8.0...v5.9.0)

[Compare Source](https://github.com/jackc/pgx/compare/v5.8.0...v5.9.0)

### [`v5.8.0`](https://github.com/jackc/pgx/compare/v5.7.6...v5.8.0)

[Compare Source](https://github.com/jackc/pgx/compare/v5.7.6...v5.8.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 [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMTEuMCIsInVwZGF0ZWRJblZlciI6IjQzLjExMS4wIiwidGFyZ2V0QnJhbmNoIjoidjE0LjAvZm9yZ2VqbyIsImxhYmVscyI6WyJkZXBlbmRlbmN5LXVwZ3JhZGUiLCJ0ZXN0L25vdC1uZWVkZWQiXX0=-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12133
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-17 16:35:07 +02:00
forgejo-backport-action
09aebe33d5 [v14.0/forgejo] fix: make /repos/search?uid=-2 return zero results, no repos with that owner (#12149)
**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/12149
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:40 +02:00
0ko
27c5d9ac0f merge commit: [v14.0/forgejo] i18n: backport of translations from Codeberg Translate (#12039)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12039
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-04-09 15:41:51 +02:00
0ko
69fc06217d [v14.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v14 branch were picked from this commit:
728936ccd9

Changes to strings that are only present in the v15/16 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 v15/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-08 19:27:49 +05:00
0ko
df248fbccd [v14.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v14 branch were picked from this commit:
d4fbbf0ac1

Changes to strings that are only present in the v15 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 v15/v16.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Aindriú Mac Giolla Eoin <aindriu80@noreply.codeberg.org>
Co-authored-by: Atalanttore <atalanttore@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Benniest <benniest@noreply.codeberg.org>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Coral Pink <coral.pink@disr.it>
Co-authored-by: EssGeeEich <essgeeeich@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: Jean-Christian <jean-christian@noreply.codeberg.org>
Co-authored-by: Kenneth Bruen <kenny@kbruen.ro>
Co-authored-by: Kyush <kyush@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: Martini-141 <martini-141@noreply.codeberg.org>
Co-authored-by: Salif Mehmed <mail@salif.eu>
Co-authored-by: Shihfu Juan <xlion@xlion.tw>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: ThinkRoot <thinkroot@noreply.codeberg.org>
Co-authored-by: Ullebe1 <ullebe1@noreply.codeberg.org>
Co-authored-by: Vyxie <kitakita@disroot.org>
Co-authored-by: Wuzzy <wuzzy@disroot.org>
Co-authored-by: adriand <adriand@noreply.codeberg.org>
Co-authored-by: alanmena <alanmena@noreply.codeberg.org>
Co-authored-by: andreuz <andreu@kindspells.dev>
Co-authored-by: anon_ally <anon_ally@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: bertof <bertof@noreply.codeberg.org>
Co-authored-by: bespinas <bespinas@noreply.codeberg.org>
Co-authored-by: daltux <daltux@noreply.codeberg.org>
Co-authored-by: dsonck <dsonck@noreply.codeberg.org>
Co-authored-by: fbausch <fbausch@noreply.codeberg.org>
Co-authored-by: hanklank <hanklank@noreply.codeberg.org>
Co-authored-by: ivanhercaz <ivanhercaz@noreply.codeberg.org>
Co-authored-by: jimkats <jimkats@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: llixon <llixon@noreply.codeberg.org>
Co-authored-by: lxcj <lxcj@noreply.codeberg.org>
Co-authored-by: makmonty <makmonty@noreply.codeberg.org>
Co-authored-by: maydo <maydo@noreply.codeberg.org>
Co-authored-by: minh160302 <minh160302@noreply.codeberg.org>
Co-authored-by: mou7664 <mou7664@noreply.codeberg.org>
Co-authored-by: onkelklo <onkelklo@noreply.codeberg.org>
Co-authored-by: pixelcode <pixelcode@noreply.codeberg.org>
Co-authored-by: pswsm <pswsm@noreply.codeberg.org>
Co-authored-by: recreationalprogamer <recreationalprogamer@noreply.codeberg.org>
Co-authored-by: smlxdesign <smlxdesign@noreply.codeberg.org>
Co-authored-by: sunwoo1524 <sunwoo1524@noreply.codeberg.org>
Co-authored-by: vmtj <vmtj@noreply.codeberg.org>
Co-authored-by: woolkingx <woolkingx@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
Co-authored-by: Кнⷫѧⷷ̈зⷮьⷬ Кропоткинъ <kropotkin@noreply.codeberg.org>
2026-04-08 19:25:59 +05:00
Renovate Bot
9c9485d1df Update dependency go to v1.25.9 (v14.0/forgejo) (#12028)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12028
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:33:48 +02:00
forgejo-backport-action
8634b38383 [v14.0/forgejo] fix: portable error reporting (#11317)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11296

Linux PAM reports "Authentication Failure"
OpenPAM reports "authentication error"

This resulted in forgejo reporting error 500 on FreeBSD when pam
authentication failed.

Add a sentinel error to make this portable: ErrInvalidCredentials

Signed-off-by: Baptiste Daroussin <bapt@FreeBSD.org>
Co-authored-by: Baptiste Daroussin <bapt@FreeBSD.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11317
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-02 03:45:55 +02:00
Renovate Bot
206224aff5 Update github.com/go-git/go-git/v5 (indirect) to v5.17.1 [SECURITY] (v14.0/forgejo) (#11899)
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.16.5` → `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.16.5/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>

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

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

#### What's Changed

- build: Update module github.com/go-git/go-git/v5 to v5.16.5 \[SECURITY] (releases/v5.x) by [@&#8203;go-git-renovate](https://github.com/go-git-renovate)\[bot] in [#&#8203;1839](https://github.com/go-git/go-git/pull/1839)
- git: worktree, optimize infiles function for very large repos by [@&#8203;k-anshul](https://github.com/k-anshul) in [#&#8203;1853](https://github.com/go-git/go-git/pull/1853)
- git: Add strict checks for supported extensions by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;1861](https://github.com/go-git/go-git/pull/1861)
- backport, git: Improve Status() speed with new index.ModTime check by [@&#8203;cedric-appdirect](https://github.com/cedric-appdirect) in [#&#8203;1862](https://github.com/go-git/go-git/pull/1862)
- storage: filesystem, Avoid overwriting loose obj files by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;1864](https://github.com/go-git/go-git/pull/1864)

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

</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:eyJjcmVhdGVkSW5WZXIiOiI0My45OS4xIiwidXBkYXRlZEluVmVyIjoiNDMuOTkuMSIsInRhcmdldEJyYW5jaCI6InYxNC4wL2Zvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11899
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:49:00 +02:00
Renovate Bot
7902524927 Update dependency happy-dom to v20.8.9 [SECURITY] (v14.0/forgejo) (#11885)
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-03-30 01:00:40 +02:00
forgejo-backport-action
a3870d7955 [v14.0/forgejo] fix: out of synchronization error after interrupting a PR merge by user-agent disconnect (#11850)
**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.

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

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/11821): <!--number 11821 --><!--line 0 --><!--description b3V0IG9mIHN5bmNocm9uaXphdGlvbiBlcnJvciBhZnRlciBpbnRlcnJ1cHRpbmcgYSBQUiBtZXJnZSBieSB1c2VyLWFnZW50IGRpc2Nvbm5lY3Q=-->out of synchronization error after interrupting a PR merge by user-agent disconnect<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11850
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 21:19:17 +01:00
Renovate Bot
9cf4962d95 Update dependency happy-dom to v20.8.8 [SECURITY] (v14.0/forgejo) (#11838)
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-03-27 06:48:23 +01:00
Renovate Bot
2c3f0c4250 Update module golang.org/x/net to v0.51.0 [SECURITY] (v14.0/forgejo) (#11828)
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/net](https://pkg.go.dev/golang.org/x/net) | [`v0.50.0` → `v0.51.0`](https://cs.opensource.google/go/x/net/+/refs/tags/v0.50.0...refs/tags/v0.51.0) | ![age](https://developer.mend.io/api/mc/badges/age/go/golang.org%2fx%2fnet/v0.51.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/golang.org%2fx%2fnet/v0.50.0/v0.51.0?slim=true) |

---

### Sending certain HTTP/2 frames can cause a server to panic in golang.org/x/net
[CVE-2026-27141](https://nvd.nist.gov/vuln/detail/CVE-2026-27141) / [GO-2026-4559](https://pkg.go.dev/vuln/GO-2026-4559)

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

#### Details
Due to missing nil check, sending 0x0a-0x0f HTTP/2 frames will cause a running server to panic

#### Severity
Unknown

#### References
- [https://nvd.nist.gov/vuln/detail/CVE-2026-27141](https://nvd.nist.gov/vuln/detail/CVE-2026-27141)
- [https://go.dev/cl/746180](https://go.dev/cl/746180)
- [https://go.dev/issue/77652](https://go.dev/issue/77652)

This data is provided by [OSV](https://osv.dev/vulnerability/GO-2026-4559) 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:eyJjcmVhdGVkSW5WZXIiOiI0My44Ni4wIiwidXBkYXRlZEluVmVyIjoiNDMuODYuMCIsInRhcmdldEJyYW5jaCI6InYxNC4wL2Zvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11828
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
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-26 19:18:15 +01:00
Renovate Bot
ff2cbd6824 Update module golang.org/x/image to v0.38.0 [SECURITY] (v14.0/forgejo) (#11820)
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.36.0` → `v0.38.0`](https://cs.opensource.google/go/x/image/+/refs/tags/v0.36.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.36.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:eyJjcmVhdGVkSW5WZXIiOiI0My44Ni4wIiwidXBkYXRlZEluVmVyIjoiNDMuODYuMCIsInRhcmdldEJyYW5jaCI6InYxNC4wL2Zvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11820
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-26 14:54:24 +01:00
forgejo-backport-action
85e12097a4 [v14.0/forgejo] ci: update tests to run debian trixie, remove manual installation from testing (#11802)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11801

Forgejo CI is currently failing due to changes in debian testing packaging that are not compatible with installing `git` from testing onto a bookworm system (https://codeberg.org/forgejo/forgejo/actions/runs/147815/jobs/2/attempt/1#jobstep-3-144).

Where `git` was being installed from testing it is replaced with just using trixie's `git 2.47.3`.  Where `git-lfs` was being installed, it's been inlined with a simple `update` and `install`.

### 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/11802
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-24 22:46:15 +01:00
forgejo-backport-action
72d35af26a [v14.0/forgejo] fix: comment attachment API is more restrictive than the web UI (#11742)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11623

The permission check for editing the attachments of a comment (adding or removing them) is changed to be the same as when editing the textual body of the comment.

The poster of a comment can always edit it via the web UI, which includes the ability to remove or add attachments. It does not require write permission on the issue or pull unit of the repository.

The API is consistent with the web UI in how it [verifies permissions for editing comments][0] when modifying the textual content. However, when adding or removing the attachments of a comment, it [also requires write permissions][1] on the issue or pull unit, which is inconsistent with the web UI and more restrictive.

[0]: a581059606/routers/api/v1/repo/issue_comment.go (L606)
[1]: a581059606/routers/api/v1/repo/issue_comment_attachment.go (L359)

Co-authored-by: limiting-factor <limiting-factor@posteo.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11742
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-19 04:19:17 +01:00
forgejo-backport-action
eac5cb9a64 [v14.0/forgejo] fix: prevent container registry headers from leaking into other registries (#11737)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11733

https://codeberg.org/forgejo/forgejo/issues/11711 discovered that headers from the container registry are leaking into the other registries. That was introduced by https://codeberg.org/forgejo/forgejo/pulls/11393. This PR fixes the problem and adds a regression test to the Maven repository.

## 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.
  - [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: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11737
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-18 21:48:07 +01:00
forgejo-backport-action
a2f9fb501f [v14.0/forgejo] fix: remove template file from generated repo (#11722)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11691

This PR fixes a bug where the previously-implemented functionality to delete the `.gitea/template` or `.forgejo/template` file when generating a repository from a template was not working. The issue happened because the code was using `util.Remove()` with a relative path, but this resolves against the process working directory instead of the temporary clone directory. The fix was to use `root.Remove()` which is based on an `os.OpenRoot()` anchored at `tmpDir`.

Updated integration tests and verified that they pass with this change and fail without it.

Co-authored-by: Brandon Rothweiler <bdr9@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11722
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-03-18 21:11:52 +01:00
forgejo-backport-action
a1bd21d45e [v14.0/forgejo] Make overflow-menu Web Component scroll / overflow with JS off (#11725)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11614

Closes #11400

## Testing
1. Go to any repository.
2. Turn off javascript.
3. Make viewport width small.
4. Observe that repository menu under the repository header doesn't overflow.

Co-authored-by: Artyom Bologov <git@aartaka.me>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11725
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
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-03-18 17:20:44 +01:00
forgejo-backport-action
2e6fc8aaf0 [v14.0/forgejo] fix: don't trip deleting attachment with missing permission error (#11658)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11642

- Deleting attachments are also seen as updating attachments due to the frontend always sending a field to edit the name even if the name didn't change. This was not reflected in the unit tests.
- Refactor the updating attachment logic to be more flexible if a attachment does not exist, because it was just deleted or because someone is being malicious.
- Resolves forgejo/forgejo#11636

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11658
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-03-12 21:21:02 +01:00
Mathieu Fenniak
62c73cdd8e [v14.0/forgejo] chore(deps): bump xorm to v1.3.9-forgejo.8 (#11626)
**Backport**: #11624

Fixes https://codeberg.org/forgejo/forgejo/issues/11608 via https://code.forgejo.org/xorm/xorm/pulls/81.

(cherry picked from commit 20388a7bee)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11626
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2026-03-11 04:52:00 +01:00
Mathieu Fenniak
c7b4e90106 [v14.0/forgejo]: fix: remove second challenge from WWW-Authenticate header (#11625)
**Backport**: #11616

https://codeberg.org/forgejo/forgejo/pulls/11393 introduced a second challenge, one for HTTP Basic Authentication, to the existing `WWW-Authenticate` header sent by Forgejo's container registry in response to missing or invalid credentials. However, that led to unexpected compatibility issues with some clients. For example, it broke Renovate (see https://github.com/renovatebot/renovate/discussions/41774).

To be extra-safe, the decision was taken to revert that particular change without introducing a second header field (i.e., sending two `WWW-Authenticate` headers). That effectively restores the old behaviour.

```
$ curl -v -u andreas --basic http://192.168.178.62:3000/v2
Enter host password for user 'andreas':
*   Trying 192.168.178.62:3000...
* Connected to 192.168.178.62 (192.168.178.62) port 3000
* using HTTP/1.x
* Server auth using Basic with user 'andreas'
> GET /v2 HTTP/1.1
> Host: 192.168.178.62:3000
> Authorization: Basic *****
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 401 Unauthorized
< Content-Length: 50
< Content-Type: application/json
< Docker-Distribution-Api-Version: registry/2.0
< Www-Authenticate: Bearer realm="http://192.168.178.62:3000/v2/token",service="container_registry",scope="*"
< Date: Tue, 10 Mar 2026 17:00:21 GMT
<
{"errors":[{"code":"UNAUTHORIZED","message":""}]}
```

## 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.
  - [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.

(cherry picked from commit f1a08a7ab1)

Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11625
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-03-11 04:00:09 +01:00
forgejo-backport-action
021d8b198f [v14.0/forgejo] fix: webook/discord: omit empty embeds.footer from the payload for Spacebar compatibility (#11613)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11588

Fixes #11573

### 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.

*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: oliverpool <git@olivier.pfad.fr>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11613
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-10 18:14:24 +01:00
forgejo-backport-action
71df8827a9 [v14.0/forgejo] fix(issue-search): delete issue from indexer on DeleteIssue (#11596)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11585

Previously, issues were deleted from the indexer only when the repository was deleted.
Individually deleting issues would not remove them from the indexer.
Instead, they were merely hidden due to their IDs being absent from the DB.

Co-authored-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11596
Reviewed-by: Shiny Nematoda <snematoda@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-09 22:50:04 +01:00
forgejo-backport-action
3c6b708c0f [v14.0/forgejo] fix: enforce package quota against package owner, not uploader (#11594)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11442

## What is broken

Quota on packages is not enforced when pushing to an organisation.

`enforcePackagesQuota()` calls `EvaluateForUser(ctx.Doer.ID, ...)` — it checks how much space the **uploader** personally owns, not the org being pushed to. Since packages accumulate under `package.owner_id = org_id`, the uploader always shows 0 bytes used and the check always passes.

This also means site admins bypass quota entirely when pushing to orgs (they get the service-layer admin bypass on top of the 0-byte measurement).

OCI/container routes (`/v2/...`) have the same problem but worse — `enforcePackagesQuota()` was not called on them at all.

## Fix

Check quota against `ctx.Package.Owner.ID` instead of `ctx.Doer.ID`. The package owner (the org or user being pushed to) is already available via `ctx.Package.Owner`, populated by `PackageAssignment()` before this middleware runs.

For individual user namespaces nothing changes — `ctx.Package.Owner` is the user themselves.

Also wired `enforcePackagesQuota()` into the missing OCI upload routes: `InitiateUploadBlob`, `UploadBlob`, `EndUploadBlob`, `UploadManifest` — both in the named `/{image}` group and the wildcard `/*` handler.

## Tested

Kind cluster, org `maw2` with 1 GiB quota, 2.6 GiB of container images already pushed:

- pushing a generic package to `maw2` as SA user → was 201, now 413
- pushing a generic package to `maw2` as `gitea_admin` → was 201, now 413
- initiating OCI blob upload to `maw2` as SA user → was 202, now 413
- pushing to own user namespace within quota → still 201

Co-authored-by: wejdross <wejdross@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11594
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-03-09 18:48:29 +01:00
Beowulf
1a3cdde2ed [v14.0/forgejo] fix: Forgejo Security Patches, 2026-03-09 (#11514)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11514
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-by: Beowulf <beowulf@beocode.eu>
2026-03-09 06:35:39 +01:00
0ko
37cbf7f519 [v14.0/forgejo] fix(e2e): use empty user for overflow menu test (from #11337)
Potentially fixes one of the E2E failures that started to occur lately where the last tab (Starred repos) can overflow on user2's profile on CI.

Replaced the user by the one that has no counters on the tabs.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11337
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>
Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-committed-by: 0ko <0ko@noreply.codeberg.org>
(cherry picked from commit 32c6f64f39)
2026-03-09 09:56:33 +05:00
0ko
3c91d267ec [v14.0/forgejo] i18n: revert zh-CN changes in 1452c3ae70 and f602b5f5ed (#11581)
This PR resets files
- `options/locale/locale_zh-CN.ini`
- `options/locale_next/locale_zh-CN.json`

to their state as of commit 197220c2ee, effectively reverting changes to them in commits
- 1452c3ae70
- f602b5f5ed

As this was requested by the Simplified Chinese maintainer in https://codeberg.org/forgejo/forgejo/pulls/11535#issuecomment-11391319 (@xtex is a maintainer per 391e989554/TEAMS.md (localization)), because many changes are not compatible with v14 after https://codeberg.org/forgejo/forgejo/issues/11340 was merged into v15 and breaking changes related to it were applied on Weblate.

https://codeberg.org/forgejo/forgejo/pulls/11340 was merged two days after https://codeberg.org/forgejo/forgejo/pulls/10978, so out of commits backported in https://codeberg.org/forgejo/forgejo/pulls/11535 only one is reverted (1452c3ae70) while the other one stays (197220c2ee).

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11581
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-03-09 05:51:37 +01:00
Gusted
0f2e6034ce chore: add unit test 2026-03-08 20:07:29 -06:00
Gusted
b566753e47 fix: filter recipients for new release mails
Remove recipients that are not active (e.g. done by moderation or
organizational reasons) and those that have the permi ssion to read
releases on that repository.
2026-03-08 20:07:29 -06:00
Gusted
14957b42bc chore: add integration testing 2026-03-08 20:07:29 -06:00
Gusted
c502e2b1e3 chore: add unit tests
Unit tests for model functions
2026-03-08 20:07:29 -06:00
Gusted
d8cba03e16 fix: check owner when changing state of project
It was sufficiently checked for the repostiory case, but for user/org
project it was not checked and you could change the state of any
project by there mere knowledge of a ID.
2026-03-08 20:07:29 -06:00
Nils Philippsen
e7a5e0a82b test: backport from #9906 test data
Required for backport of v15 security fixes w/ test automation, this is
a partial cherry-pick of 5589182c54.

Signed-off-by: Nils Philippsen <nils@redhat.com>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/9906
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Robert Wolff <mahlzahn@posteo.de>
Co-authored-by: Nils Philippsen <nilsph@noreply.codeberg.org>
Co-committed-by: Nils Philippsen <nilsph@noreply.codeberg.org>
2026-03-08 20:07:16 -06:00
0ko
f602b5f5ed [v14.0/forgejo] i18n: backport of hint_with_placeholder translations (#11570)
Backport: https://codeberg.org/forgejo/forgejo/pulls/11344 (additional)
Following original backport: https://codeberg.org/forgejo/forgejo/pulls/11535
In order for v14.0.3 to include strings for https://codeberg.org/forgejo/forgejo/pulls/11413

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11570
Reviewed-by: Beowulf <beowulf@beocode.eu>
Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-committed-by: 0ko <0ko@noreply.codeberg.org>
2026-03-08 17:15:07 +01:00
forgejo-backport-action
d52756b879 [v14.0/forgejo] fix(ui): hardcode sort options in search syntax hint, improve look (#11413)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11381

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

Fix issue reported by @mahlzahn that the string was confusing translators and they translated the part that wasn't meant to be translated

Part of this fix was to replace custom IterWithTr with simple dict iteration to allow for placeholders in strings.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11413
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
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-03-08 06:31:20 +01:00
Andreas Ahlenstorf
a72cffddfa [v14.0/forgejo] fix: extend basic auth to /v2, always include WWW-Authenticate header (#11393) (#11557)
Forgejo's OCI container registry did not enable basic authentication for the top-level endpoint `/v2`. Furthermore, it did not include the `WWW-Authenticate` header when returning the status code 401 as mandated by [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), "Hypertext Transfer Protocol (HTTP/1.1): Authentication", section 3.1. Those deficiencies made it impossible for Apple's [container](https://github.com/apple/container) to log into Forgejo OCI container registry. This has been rectified.

The problem did not occur with most other tools because they do not include credentials when sending the initial request to `/v2`. Forgejo's reply then included `WWW-Authenticate` as expected.

Enabling basic authentication for `/v2` has the side effect that Apple's container uses username and password for all successive requests and not the bearer token. If that is a problem, it's up to Apple to change container's behaviour.

If invalid credentials are passed to `container registry login`, then container enters an infinite loop. The same happens with quay.io, but not ghcr.io (returns 403) or docker.io (returns 401 but _without_ `WWW-Authenticate`). As this is invalid behaviour on container's side, it's up to Apple to change container. Docker and Podman handle it correctly.

Login and pushing have been tested manually with Docker 29.1.3, Podman 5.7.1, and Apple's container 0.9.0.

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

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11557
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
(cherry picked from commit 3e849b4b50)

Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2026-03-08 02:56:44 +01:00
forgejo-backport-action
beed05d2f7 [v14.0/forgejo] fix: modals on small viewport height (#11560)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11547

- For small modals fomantic tried to add a `scrolling` class using a function that was not implemented, this function is now stubbed.
- There's not really a need to conditionally change the behavior of scrolling or not, we can specify `overflow-y: auto` which is more than enough to take care of this. We do add some layout changes to ensure the modal is fully scrollable.
- Refactor to nested CSS.
- Resolves forgejo/forgejo#10991

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11560
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-03-08 02:44:47 +01:00
forgejo-backport-action
9421d22215 [v14.0/forgejo] fix: skip repo avatar upload when no file is selected (#11555)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11335

Submitting the repo avatar form without selecting a file shows a raw Go error: `Avatar.Open: open : no such file or directory.`. The existing `nil` check does not prevent this from happening.

The user avatar handler already guards against this same problem with [`form.Avatar != nil && form.Avatar.Filename != ""`](e1cecbd276/routers/web/user/setting/profile.go (L141)), I've done the same for the repo avatar handler.

Co-authored-by: Bram Hagens <bram@bramh.me>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11555
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-03-07 22:39:20 +01:00
forgejo-backport-action
4123ace6c4 [v14.0/forgejo] fix: RPM registry addrepo instructions (#11552)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11478

The provided instructions for how to add RPM package repo fail on Fedora 43:

```
Unknown argument "--add-repo" for command "config-manager". Add "--help" for more information about the arguments.
```

The [docs](https://forgejo.org/docs/latest/user/packages/rpm/#configuring-the-package-registry-using-dnf5) contain a different command, which does work.

This changes instructions to match docs.
Co-authored-by: sarge <sarge@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11552
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-03-07 20:57:52 +01:00
forgejo-backport-action
211376cd9a [v14.0/forgejo] chore: skip sha256 repo for older git versions (#11551)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11542

- Breaks testing on git versions that don't have SHA256 support.

https://codeberg.org/forgejo-integration/forgejo/actions/runs/16172/jobs/1/attempt/1#jobstep-5-2381

```
// TestLinksLogin
	"2026/03/06 06:15:20 ...ices/context/repo.go:1007:28() [E] GetBranchCommit: length 64 has no matched object format: 473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813",
```

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11551
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-07 19:02:49 +01:00
0ko
164c02b010 merge commit: [v14.0/forgejo] i18n: backport of translations from Codeberg Translate (#11535)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11535
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-03-07 04:12:36 +01:00
0ko
1452c3ae70 [v14.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v14 branch were picked from this commit: 77282e9ca1

Changes to strings that are only present in the v15 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 v15.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@noreply.codeberg.org>
Co-authored-by: Laquin <laquin@noreply.codeberg.org>
Co-authored-by: Salif Mehmed <mail@salif.eu>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Tamil <tamil@noreply.codeberg.org>
Co-authored-by: Vaibhav Sunder <vaibhavswire@gmail.com>
Co-authored-by: Vyxie <kitakita@disroot.org>
Co-authored-by: daltux <daltux@noreply.codeberg.org>
Co-authored-by: hanklank <hanklank@noreply.codeberg.org>
Co-authored-by: hasecilu <hasecilu@noreply.codeberg.org>
Co-authored-by: jimkats <jimkats@noreply.codeberg.org>
Co-authored-by: jlsun <jlsun@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: lanticy <lanticy@noreply.codeberg.org>
Co-authored-by: mahlzahn <mahlzahn@posteo.de>
Co-authored-by: vmtj <vmtj@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
2026-03-07 00:10:19 +05:00
0ko
197220c2ee [v14.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v14 branch were picked from this commit: 0ac16105b8

Changes to strings that are only present in the v15 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 v15.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: AbelFalcon <abelfalcon@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Benniest <benniest@noreply.codeberg.org>
Co-authored-by: Bullbagaren <bullbagaren@noreply.codeberg.org>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Fnurkla <fnurkla@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: IPv6 <ipv6@noreply.codeberg.org>
Co-authored-by: Lzebulon <lzebulon@noreply.codeberg.org>
Co-authored-by: Outbreak2096 <outbreak2096@noreply.codeberg.org>
Co-authored-by: Sagor Islam <sagor_islam@noreply.codeberg.org>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Victor E. Chocho <vechocho@noreply.codeberg.org>
Co-authored-by: Vyxie <kitakita@disroot.org>
Co-authored-by: Wuzzy <wuzzy@disroot.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: bespinas <bespinas@noreply.codeberg.org>
Co-authored-by: butterflyoffire <butterflyoffire@noreply.codeberg.org>
Co-authored-by: daltux <daltux@noreply.codeberg.org>
Co-authored-by: dimiro1 <dimiro1@noreply.codeberg.org>
Co-authored-by: hamburger <hamburger@noreply.codeberg.org>
Co-authored-by: hanklank <hanklank@noreply.codeberg.org>
Co-authored-by: hpcfzl <hpcfzl@noreply.codeberg.org>
Co-authored-by: jimkats <jimkats@noreply.codeberg.org>
Co-authored-by: jrosh <jrosh@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: kdh8219 <kdh8219@monamo.dev>
Co-authored-by: kmpm <kmpm@noreply.codeberg.org>
Co-authored-by: lordwektabyte <lordwektabyte@users.noreply.translate.codeberg.org>
Co-authored-by: lukesnc <lukesnc@noreply.codeberg.org>
Co-authored-by: marlena <marlena@noreply.codeberg.org>
Co-authored-by: nikee <nikee@noreply.codeberg.org>
Co-authored-by: psenakdotsk <psenakdotsk@noreply.codeberg.org>
Co-authored-by: sebastiaanspeck <sebastiaanspeck@noreply.codeberg.org>
Co-authored-by: sieni <sieni@noreply.codeberg.org>
Co-authored-by: sinsky <sinsky@noreply.codeberg.org>
Co-authored-by: sinsky <sinsky@users.noreply.translate.codeberg.org>
Co-authored-by: smlxdesign <smlxdesign@noreply.codeberg.org>
Co-authored-by: stkw0 <stkw0@noreply.codeberg.org>
Co-authored-by: tace16 <tace16@noreply.codeberg.org>
Co-authored-by: thomasboom <thomasboom@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-03-07 00:08:43 +05:00
Gusted
d1d90aa9c1 chore: add integration testing 2026-03-06 11:20:40 -07:00
Gusted
fc57758c87 chore: unit testing 2026-03-06 11:20:40 -07:00
Gusted
f4581e0f23 fix: check the permission of canceling automerge
The API already checked the permission sufficiently if auto merge could
be cancelled by the doer. The web route did not. Consolidate this check
in the function that lives in the services directory.
2026-03-06 11:20:40 -07:00
Gusted
912ffa2dbd fix: consider more risky redirects
After evaluating `..`, it's possible that the resulting path is a risky
redirect, as it might be a "browser" special redirect. Detect this case.
2026-03-06 11:20:40 -07:00
Gusted
e5a4f83bea chore: add unit test 2026-03-06 11:20:40 -07:00
Gusted
fa3073044a chore: add unit test 2026-03-06 11:20:40 -07:00
Gusted
fe55c0e76c fix: check that attachments belong to correct resource
It was possible to hijack attachments during update and create functions
to another owner as permissions to check they weren't already attached
to another resource and wasn't checked if it belonged to the repository
that was being operated on.
2026-03-06 11:20:40 -07:00
Gusted
816a37f576 chore: add integration testing
Modify the existing scopes tests for normal API tokens to OAuth2 tokens.
2026-03-06 11:20:40 -07:00
Gusted
155acecb4b fix: consider scopes for OAuth2 token via basic login
There are two ways to use a OAuth2 token:

Via the Authorization header as a Bearer token.
Via the Authorization header as a Basic login.

For the former the scope was correctly passed through, for the latter it
was not and would mean no scope was checked if you used the token via
this way.
2026-03-06 11:20:40 -07:00
Gusted
2b0ec87644 chore: add integration testing
Build on the test of forgejo/forgejo!8678 to also verify PKCE works for
S256.
2026-03-06 11:20:40 -07:00
Gusted
388436d500 fix: verify code challenge of S256
We do not know for sure, but it is quite likely someone assumed implicit
fallthrough. This meant that if someone used S256 for PKCE, it simply
did not verify the code challenge and always accepted it.

PKCE only started working recently as it was broken for a long time
already, forgejo/forgejo!8678
2026-03-06 11:20:40 -07:00
forgejo-backport-action
ea4f733de8 [v14.0/forgejo] chore: add more diagnostic output to dbfs Stat error (#11528)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11525

@viceice is having problems with runner `UpdateLog` errors like this:

```
2026-03-05T23:50:33.764718938+01:00 time="2026-03-05T22:50:33Z" level=warning msg="ReportLog error: internal: write logs: dbfs Stat \"actions_log/org/infra/99/14233.log.zst\": invalid argument" task_id=14233
2026-03-05T23:50:33.765473314+01:00 time="2026-03-05T22:50:33Z" level=warning msg="ReportLog error: internal: write logs: dbfs Stat \"actions_log/org/infra/98/14232.log.zst\": invalid argument" task_id=14232
```

This seems to be occurring with a bit of a contradiction:
- invalid argument should only occur if the file was absent in the dbfs table
- the file should be created if the offset to be written to is `0`
- the offset should be zero if the actions task has `log_size = 0`
- `log_size != 0` would indicate that the file exists

This PR adds additional details to the dbfs error, primarily to give insight into what the `offset` value is when the error occurs.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11528
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-03-06 07:50:38 +01:00
Renovate Bot
d4bb6cde65 Update dependency go to v1.25.8 (v14.0/forgejo) (#11527)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11527
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-06 06:47:11 +01:00
0ko
cd9ddac459 [v14.0/forgejo] fix(ui/mde): inputs in table/link insertion modals (#11499)
Backport: #11341
Trivial conflict resolution: commit contained changes to org-members.test.e2e not directly related to the fix. The file is exclusive to v15, so these changes were dropped in the backport.

---

Fixes #11268
Fixes regression of #9614

Calling `initDisabledInputs` wasn't effective for template contents, so inputs in MDEs spawned by repo-legacy.js on comment editing were broken. Now repo-legacy.js also calls it when it spawns a new MDE.

Co-authored-by: Gusted <Gusted@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11341
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-committed-by: 0ko <0ko@noreply.codeberg.org>
(cherry picked from commit a0faae2764)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11499
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-03-05 22:01:40 +01:00
Renovate Bot
d9896e4de6 Update dependency svgo to v4.0.1 [SECURITY] (v14.0/forgejo) (#11510)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11510
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-03-05 14:26:18 +01:00
forgejo-backport-action
6ee6dc2eb0 [v14.0/forgejo] fix: prevent panic on gitlab import (releases/issues) (#11484)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11282

It is unfortunately all mixed up, because refreshing the data, means breaking the tests. And changing the code means needing fresh data.

- tests: ignore some more headers and sort the rest when dumping http responses
- code: fixed #10234 by requesting the latest issues first.
- tests: created a new repo to replace the disappeared repo, needed for the skip-numbers test
- refreshed the testdata.
- follow-up fixes to get the tests green.
- including a cherry-pick of https://github.com/go-gitea/gitea/pull/36295 and #11272

Co-authored-by: oliverpool <git@olivier.pfad.fr>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11484
Reviewed-by: Gusted <gusted@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-03-05 03:03:15 +01:00
Renovate Bot
230ccf5276 Update github.com/cloudflare/circl (indirect) to v1.6.3 [SECURITY] (v14.0/forgejo) (#11498)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11498
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-04 18:00:04 +01:00
Renovate Bot
d0dd0928be Update https://data.forgejo.org/actions/setup-forgejo action to v3.1.7 (v14.0/forgejo) (#11475)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11475
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-02 22:59:07 +01:00
Renovate Bot
aca1775dae Update dependency minimatch to v10.2.3 [SECURITY] (v14.0/forgejo) (#11415)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11415
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-03-02 17:01:11 +01:00
Renovate Bot
456be57bb7 Update module code.superseriousbusiness.org/exif-terminator to v0.11.1 (v14.0/forgejo) (#11464)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11464
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2026-03-02 06:10:36 +01:00
Gusted
b72473d114 [v14.0/forgejo] ci: ensure correct node version (#11467)
Backport of forgejo/forgejo!11280

- ensure we use the defined node version on ci, so renovate and ci use same version
- fix lockfile to match npm version
- add some debugging to ci

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11467
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
2026-03-02 05:14:31 +01:00
forgejo-backport-action
dbdbd0f5e6 [v14.0/forgejo] fix: cleanup of multi-platform container images (#11254)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11246

This change fixes an issue that makes Forgejo clean up too many versions of a container package even though it should keep them according to the rules set for the package.

The issue affects multi-platform container images.
Forgejo adds a package version for each platform (for example `linux/amd64`, `linux/arm64`) in addition to the actual tag (for example `0.6.0` or `latest`).

This results in rows in the table `package_version` similar to this (unimportant columns omitted for brevity):

| **lower_version** | **created_unix** |
|---|---|
| `latest` | `1768742887`|
| `0.6.0` | `1768742886` |
| `sha256:038e...` | `1768742886` |
| `sha256:fc38...` | `1768742886` |
| `0.5.0` | `1768742864` |
| `sha256:806d...` | `1768742864` |
| `sha256:0a19...` | `1768742864` |
| `0.4.0` | `1768742848` |
| `...` | `...` |

The code assumes that the first `<keep count>` entries can be ignored and considers every entry after `<keep count>` as eligible for cleanup.
That doesn't work for multi-platform container images because, for `<keep count>=5`, it considers version `0.4.0` as eligible.

## 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

- 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 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.

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

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/11246): <!--number 11246 --><!--line 0 --><!--description Y2xlYW51cCBvZiBtdWx0aS1wbGF0Zm9ybSBjb250YWluZXIgaW1hZ2Vz-->cleanup of multi-platform container images<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: wandhydrant <wandhydrant@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11254
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-02-23 18:49:26 +01:00
Mathieu Fenniak
f4f3a3e0f3 [v14.0/forgejo] chore: bump go-git/v5 indirect dependency for govulncheck (#11412)
Unable to backport to v14 currently due to govulncheck ([example](https://codeberg.org/forgejo/forgejo/actions/runs/138106/jobs/11/attempt/2)).

#11396 was already opened and merged in v11, but v14 is currently blocked.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11412
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2026-02-23 16:27:07 +01:00
Renovate Bot
6b6e9da3cd Update dependency webpack to v5.104.1 [SECURITY] (v14.0/forgejo) (#11398)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11398
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
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-02-22 09:13:22 +01:00
Renovate Bot
41c3c5bb80 Update module github.com/go-chi/chi/v5 to v5.2.4 [SECURITY] (v14.0/forgejo) (#11397)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11397
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-02-22 09:12:34 +01:00
forgejo-backport-action
677de6419b [v14.0/forgejo] fix(ui): prevent label overflow in PR CI checks on mobile (#11327)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11287

Fix #11266

Co-authored-by: panc <pan0xc@foxmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11327
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-02-16 21:40:07 +01:00
Mathieu Fenniak
8ef91fa1cc [v14.0/forgejo] fix: when expanding a dynamic matrix, original 'needs' access was lost (#11166)
**Backport:** #11164

Manual backport required due to conflicts with recent workflow expansion work.

(cherry picked from commit c7d23fa6e8)

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

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/11166): <!--number 11166 --><!--line 0 --><!--description Zml4OiB3aGVuIGV4cGFuZGluZyBhIGR5bmFtaWMgbWF0cml4LCBvcmlnaW5hbCAnbmVlZHMnIGFjY2VzcyB3YXMgbG9zdA==-->fix: when expanding a dynamic matrix, original 'needs' access was lost<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11166
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2026-02-15 23:55:05 +01:00
forgejo-backport-action
b3c7fbcce3 [v14.0/forgejo] fix: improve SQLite "database is locked" errors by increasing default SQLITE_TIMEOUT (#11220)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11179

As noted in https://codeberg.org/forgejo/forgejo/issues/10900#issuecomment-10339634, `TestAPICreateIssueParallel` is failing intermittently in Forgejo CI.  Based upon this intermittent failure, I've made these changes:
- Increase the parallel run of the test from 10 instances to 100, which caused this test to fail consistently and reliably on my dev workstation.  The test execution time at 100 parallel invocations is only ~4 seconds.
- Increase the default `SQLITE_TIMEOUT` from 500ms to 60s, which caused this test to succeed consistently in CI.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11220
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
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-02-14 17:24:37 +01:00
Renovate Bot
3515a9c365 Update module github.com/mattn/go-sqlite3 to v1.14.34 (v14.0/forgejo) (#11245)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11245
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-02-11 18:25:38 +01:00
Renovate Bot
e50f9ff165 Update module code.forgejo.org/forgejo/runner/v12 to v12.6.4 (v14.0/forgejo) (#11244)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11244
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-02-11 17:54:02 +01:00
Mathieu Fenniak
131fc0db9c [v14.0/forgejo] fix: don't abandon Action jobs waiting for approval (#11148)
**Backport:** #11145

(cherry picked from commit 462ad7bb33)

On an open PR that is waiting for job approval, if jobs haven't been approved by the time the abandon timeout occurs they get marked as cancelled.  This doesn't match the expectations of abandoned jobs in my opinion, which is that they were never able to be dispatched to a runner (no matching labels), but these jobs never got a chance.  They should remain valid and blocked until approved.

Discovered while testing #11125, but unrelated to the behaviour fixed there.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11145
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/11148
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-02-07 01:02:56 +01:00
Mathieu Fenniak
382ee8ce34 [v14.0/forgejo]: ensure consistent sort order in TestFeed fixture (#11178)
**Backport**: #11176

(cherry picked from commit a40e81b755)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11176
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: xrstf <git@xrstf.de>
Co-committed-by: xrstf <git@xrstf.de>
Co-authored-by: xrstf <git@xrstf.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11178
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-committed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-02-07 00:50:40 +01:00
Renovate Bot
ce0e17989b Update dependency go to v1.25.7 (v14.0/forgejo) (#11168)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [go](https://go.dev/) ([source](https://github.com/golang/go)) | toolchain | patch | `1.25.6` -> `1.25.7` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), 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:eyJjcmVhdGVkSW5WZXIiOiI0Mi45My4xIiwidXBkYXRlZEluVmVyIjoiNDIuOTMuMSIsInRhcmdldEJyYW5jaCI6InYxNC4wL2Zvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11168
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-02-06 03:48:01 +01:00
forgejo-backport-action
84240ce3a2 [v14.0/forgejo] fix: cancel runs pending approval when a PR is closed (#11135)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11134

Fixes #11125.  When a PR is closed, cancel any action runs associated with the pull request that are not approved so that they do not remain in the Actions list as a blocked action.

## 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

- 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 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: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11135
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-02-03 11:47:28 +01:00
Mathieu Fenniak
a59481d3d9 [v14.0/forgejo] fix: use an absolute URL for compare links in atom feed (#11126)
**Backport:** #10933

(cherry picked from commit 995244895a)

Co-authored-by: xrstf <git@xrstf.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11126
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
2026-02-01 19:46:45 +01:00
forgejo-backport-action
3ad19e7335 [v14.0/forgejo] fix: allow test delivery for webhooks not enabled for push events (#11074)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11073

Webhooks not enabled for push events cannot be tested using the
"Test delivery" button, because the built-in test payload corresponds
to a push event and is therefore filtered out at delivery time if the
webhook isn't configured to trigger for such events.

This fixes it by delivering the payload for a push event regardless
of the webhook's configuration. This has the downside of delivering
a payload which isn't necessarily representative of what the webhook
will deliver for real, but it would be a significant effort to implement
test payloads for all possible event types. We leave this as a follow-up
improvement.

Fixes #7934.

Co-authored-by: Antonin Delpeuch <antonin@delpeuch.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11074
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-01-28 16:09:43 +01:00
Mathieu Fenniak
032b0bbeda [v14.0/forgejo] fix: empty dynamic matrix can leave action run hanging incomplete (#11072)
**Backport:** #11063

Fixes #11030.

When a `strategy.matrix` needs to be evaluated on the output of another job, it can become evaluated into an empty set of jobs.  In this case, and assuming no other jobs in the run are active, the run should reach a settled state.  The logic to check the other jobs in the run and determine if this state has been hit needs to be explicitly added to the job emitter.

To accomplish this change, this action run state logic was extracted out of `UpdateRunJobWithoutNotification` where it could be reused.

(cherry picked from commit c198082975)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11072
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2026-01-27 20:14:04 +01:00
forgejo-backport-action
9347d06de5 [v14.0/forgejo] feat: enable SQLite WAL by default (#11069)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11059

- In order to avoid a database locked message, you either need shared
cache or WAL. Shared cache was disabled in as its deprecrated and could
cause more good than trouble. Enable WAL by default, it's only
non-desirable in very narrow and select situations (NFS filesystem
situation) and is otherwise safe as default.
- Resolves forgejo/forgejo#10900

Docs: forgejo/docs!1717

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

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/11069): <!--number 11069 --><!--line 0 --><!--description ZmVhdDogZW5hYmxlIFNRTGl0ZSBXQUwgYnkgZGVmYXVsdA==-->feat: enable SQLite WAL by default<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11069
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-01-27 16:57:36 +01:00
forgejo-backport-action
7410ef5b9f [v14.0/forgejo] fix: decrease watch count when blocking user (#11060)
Fixes #10881

Call the proper function for each repository the user watches, so adjusting the watch count can be done properly.

Co-authored-by: christopher-besch <mail@chris-besch.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11060
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Reviewed-by: Christopher Besch <mail@chris-besch.com>
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-01-27 13:57:57 +01:00
forgejo-backport-action
8aff5ab18b [v14.0/forgejo] fix: migrations/github: avoid getting the first issues page twice (#11055)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10798

For the previous code with the Page attribute present in
ListCursorOptions for page 1, github would not return an "After" cursor,
such that the request for page 2 would request what effectively is the
content of page 1 a second time.

This would lead to an attempt to insert the same issues twice.

Note that this is not the only reason why this can happen with the
current code base.

We fix this particular issue by not using the Page attribute so github
does return an "After" cursor.

Fixes #10794

Co-authored-by: Nils Goroll <nils.goroll@uplex.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11055
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-01-27 01:45:57 +01:00
forgejo-backport-action
68f39ad66b [v14.0/forgejo] fix NewMockWebServer(): Headers never reached the http client (#11058)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11007

Found while working on https://codeberg.org/forgejo/forgejo/pulls/10798#issuecomment-10083846: The symptom was that the go-github client never returned a `resp.After`, so I tracked down the root cause, which was that, with the mocked http server ...

Mocked headers never reached the calling client, because w.WriteHeader()
was called before the headers were set in the response.

Fix by moving w.WriteHeader() to the right place just before w.Write(),
which writes the body.

Test added which fails without the fix and succeeds with it.

Co-authored-by: Nils Goroll <nils.goroll@uplex.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11058
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-01-26 20:41:29 +01:00
forgejo-backport-action
4bb2d68a10 [v14.0/forgejo] fix: migrations/github: Wait & retry when primary rate limit is hit (#11054)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10846

This is a successor to #10805, which simply did not work. It is also much simpler and basically a one line change to enable an existing feature in [go-github](https://github.com/google/go-github).

Fixes #10845

With this fix and #10798 in place, a migration of a repo with ~3K issues and ~1.3k pull requests finally completed successfully.

## Patch

We use SleepUntilPrimaryRateLimitResetWhenRateLimited to instruct the go-github code to wait until the retry time and retry the request when the primary rate limit gets hit.

## Test case

TestGitHubDownloadRepo() has been modified such that 403 rate limit errors are injected every 7 requests with a retry time of one second, resulting in the rate limit condition being hit twice with the current tests. The test case confirms that the migration code itself is in fact unaffected by the rate limit being hit.

## Scope

This change does not affect secondary rate limits.

If the server is restarted during the wait for the rate limit refresh, the migration likely still fails when retried, because inserts for already present database objects will be attempted.

This approach effectively puts the task's goroutine to sleep until the retry time, which implies that the respective resources stay allocated.

A better approach might be to add the necessary infrastructure to support restarts of migration tasks at a later time, but this is much more involved, because the migration state would need to be saved and/or re-created based on already pulled data. This would also require adding support for database upserts.

Co-authored-by: Nils Goroll <nils.goroll@uplex.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11054
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-01-26 20:05:04 +01:00
forgejo-backport-action
4e1468a1b5 [v14.0/forgejo] fix: detect renames when using diff-tree (#11039)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/11038

Regression of forgejo/forgejo!9587

`git-diff` will always find renames because it is implied by the `diff.renames` configuration option. Specify --find-renames to detect renames again.

Resolves forgejo/forgejo#11032

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11039
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-01-25 16:39:35 +01:00
forgejo-backport-action
ddf0265b5c [v14.0/forgejo] fix(ui): tippy menu styles too broad, affecting switch in PR review (#10996)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10969

The custom styles for tippy-enabled menus had too broad selectors, conflicting with styles of other .item elements in tippy boxes.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10996
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-01-25 14:57:38 +01:00
Mathieu Fenniak
3aaef3b3dd [v14.0/forgejo] fix: don't clobber authorized_keys file during installation (#10948) (#11009)
**Backport**: https://codeberg.org/forgejo/forgejo/pulls/10948

(cherry picked from commit c52ecd2258)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10948
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>

## 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

- 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 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

- [ ] 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.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11009
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
2026-01-23 21:29:47 +01:00
0ko
097680a64d merge commit: [v14.0/forgejo] i18n: backport of translations from Codeberg Translate (#10988)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10988
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-01-23 14:50:26 +01:00
Renovate Bot
bdc7c65173 Update module code.forgejo.org/forgejo/runner/v12 to v12.6.0 (v14.0/forgejo) (#11001)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [code.forgejo.org/forgejo/runner/v12](https://code.forgejo.org/forgejo/runner) | `v12.2.0` -> `v12.6.0` | ![age](https://developer.mend.io/api/mc/badges/age/go/code.forgejo.org%2fforgejo%2frunner%2fv12/v12.6.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/code.forgejo.org%2fforgejo%2frunner%2fv12/v12.2.0/v12.6.0?slim=true) |

---

### Release Notes

<details>
<summary>forgejo/runner (code.forgejo.org/forgejo/runner/v12)</summary>

### [`v12.6.0`](https://code.forgejo.org/forgejo/runner/releases/tag/v12.6.0)

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v12.5.3...v12.6.0)

- [User guide](https://forgejo.org/docs/next/user/actions/overview/)
- [Administrator guide](https://forgejo.org/docs/next/admin/actions/)
- [Container images](https://code.forgejo.org/forgejo/-/packages/container/runner/versions)

Release Notes

***

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

<!--URL:https://code.forgejo.org/forgejo/runner-->

- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1236): <!--number 1236 --><!--line 0 --><!--description ZmVhdDogYWRkICd1c2luZzogZG9ja2VyJyBhY3Rpb24gcHJlIGFuZCBwb3N0LWVudHJ5cG9pbnQgc3VwcG9ydA==-->feat: add 'using: docker' action pre and post-entrypoint support<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1287): <!--number 1287 --><!--line 0 --><!--description Zml4OiBlbGltaW5hdGUgbG9nIGRhdGEgbG9zcyBjYXVzZWQgYnkgTFhDICYgUFRZIGJ1ZmZlcg==-->fix: eliminate log data loss caused by LXC & PTY buffer<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1307): <!--number 1307 --><!--line 0 --><!--description Zml4KGpvYnBhcnNlcik6IGV2YWx1YXRpbmcgbWF0cml4IHZhbHVlcyB3aXRoaW4gcnVucy1vbiByZWZlcmVuY2VzIGZpcnN0IG1hdHJpeCB2YWx1ZSBvbmx5-->fix(jobparser): evaluating matrix values within runs-on references first matrix value only<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1312): <!--number 1312 --><!--line 0 --><!--description dGVzdDogdmVyaWZ5IHRoYXQgY29uZmlndXJhdGlvbiBpcyBsb2FkZWQgY29ycmVjdGx5-->test: verify that configuration is loaded correctly<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1315): <!--number 1315 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9mb3JnZWpvL2Zvcmdlam8tYnVpbGQtcHVibGlzaCBhY3Rpb24gdG8gdjUuNS4x-->Update <https://data.forgejo.org/forgejo/forgejo-build-publish> action to v5.5.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1314): <!--number 1314 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9mb3JnZWpvL2Zvcmdlam8tYnVpbGQtcHVibGlzaCBhY3Rpb24gdG8gdjUuNS4w-->Update <https://data.forgejo.org/forgejo/forgejo-build-publish> action to v5.5.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1290): <!--number 1290 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL21vYnkvZ28tYXJjaGl2ZSB0byB2MC4yLjA=-->Update module github.com/moby/go-archive to v0.2.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1308): <!--number 1308 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL3NldHVwLWZvcmdlam8gYWN0aW9uIHRvIHYzLjEuMQ==-->Update <https://data.forgejo.org/actions/setup-forgejo> action to v3.1.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1306): <!--number 1306 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NpcnVwc2VuL2xvZ3J1cyB0byB2MS45LjQ=-->Update module github.com/sirupsen/logrus to v1.9.4<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1305): <!--number 1305 --><!--line 0 --><!--description VXBkYXRlIGZvcmdlam8tcnVubmVyIHRvIHYxMi41LjM=-->Update forgejo-runner to v12.5.3<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1304): <!--number 1304 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9mb3JnZWpvIERvY2tlciB0YWcgdG8gdjExLjAuMTA=-->Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.10<!--description-->

<!--end release-notes-assistant-->

### [`v12.5.3`](https://code.forgejo.org/forgejo/runner/releases/tag/v12.5.3)

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v12.5.2...v12.5.3)

- [User guide](https://forgejo.org/docs/next/user/actions/overview/)
- [Administrator guide](https://forgejo.org/docs/next/admin/actions/)
- [Container images](https://code.forgejo.org/forgejo/-/packages/container/runner/versions)

Release Notes

***

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

<!--URL:https://code.forgejo.org/forgejo/runner-->

- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1303): <!--number 1303 --><!--line 0 --><!--description Zml4OiBzdXBwb3J0IEZvcmdlam8gcmV0dXJuaW5nIEFkZGl0aW9uYWxUYXNrcyBidXQgbm90IFRhc2s=-->fix: support Forgejo returning AdditionalTasks but not Task<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1293): <!--number 1293 --><!--line 0 --><!--description Zml4OiBvbmx5IHNraXAgZmV0Y2hpbmcgd2hlbiBhIGNvbW1pdCBleGlzdHMgbG9jYWxseQ==-->fix: only skip fetching when a commit exists locally<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1294): <!--number 1294 --><!--line 0 --><!--description Zml4OiB1bmJyZWFrIHRoZSBidWlsZCBmb3IgcGxhdGZvcm1zIHcvbyBkb2NrZXIgc3VwcG9ydA==-->fix: unbreak the build for platforms w/o docker support<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1277): <!--number 1277 --><!--line 0 --><!--description Zml4OiB0cnkgdG8gZW1wdHkgY2xvbmUgZGlyZWN0b3J5IHRoYXQgaXMgbm90IGVtcHR5-->fix: try to empty clone directory that is not empty<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1301): <!--number 1301 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9yZWxlYXNlLW5vdGVzLWFzc2lzdGFudCB0byB2MS41LjE=-->Update dependency forgejo/release-notes-assistant to v1.5.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1299): <!--number 1299 --><!--line 0 --><!--description Y2hvcmU6IGltcHJvdmUgaW50ZXJuYWwgcmVwb3J0ZXIuZ28gbG9nZ2luZw==-->chore: improve internal reporter.go logging<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1298): <!--number 1298 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjUuNg==-->Update dependency go to v1.25.6<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1297): <!--number 1297 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvdGVybSB0byB2MC4zOS4w-->Update module golang.org/x/term to v0.39.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1295): <!--number 1295 --><!--line 0 --><!--description Y2hvcmU6IGJ1aWxkIHVuc3VwcG9ydGVkIHBsYXRmb3Jtcw==-->chore: build unsupported platforms<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1296): <!--number 1296 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvc3lzIHRvIHYwLjQwLjA=-->Update module golang.org/x/sys to v0.40.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1288): <!--number 1288 --><!--line 0 --><!--description VXBkYXRlIGRhdGEuZm9yZ2Vqby5vcmcvb2NpL2FscGluZSBEb2NrZXIgdGFnIHRvIHYzLjIz-->Update data.forgejo.org/oci/alpine Docker tag to v3.23<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1286): <!--number 1286 --><!--line 0 --><!--description dGVzdDogYWRkIGFuIExYQyBlbnZpcm9ubWVudCB0ZXN0-->test: add an LXC environment test<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1261): <!--number 1261 --><!--line 0 --><!--description Y2hvcmU6IGVuc3VyZSBhbGwgdGVzdHMgYXJlIHJ1bg==-->chore: ensure all tests are run<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1279): <!--number 1279 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NwZjEzL2NvYnJhIHRvIHYxLjEwLjI=-->Update module github.com/spf13/cobra to v1.10.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1281): <!--number 1281 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuOC4w-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.8.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1280): <!--number 1280 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby1ydW5uZXItc2VydmljZS15cSB0byB2NC41MC4x-->Update dependency forgejo-runner-service-yq to v4.50.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1284): <!--number 1284 --><!--line 0 --><!--description dGVzdDogcGluZyBob3N0bmFtZSBpbnN0ZWFkIG9mIGxvY2FsaG9zdA==-->test: ping hostname instead of localhost<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1285): <!--number 1285 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgbHhjLW5vZGUgdG8gdjI0-->Update dependency lxc-node to v24<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1283): <!--number 1283 --><!--line 0 --><!--description VXBkYXRlIE5vZGUuanMgdG8gdjI0-->Update Node.js to v24<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1278): <!--number 1278 --><!--line 0 --><!--description VXBkYXRlIGZvcmdlam8tcnVubmVyIHRvIHYxMi41LjI=-->Update forgejo-runner to v12.5.2<!--description-->

<!--end release-notes-assistant-->

### [`v12.5.2`](https://code.forgejo.org/forgejo/runner/releases/tag/v12.5.2)

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v12.5.1...v12.5.2)

- [User guide](https://forgejo.org/docs/next/user/actions/overview/)
- [Administrator guide](https://forgejo.org/docs/next/admin/actions/)
- [Container images](https://code.forgejo.org/forgejo/-/packages/container/runner/versions)

In combination with a runner with capacity > 1, and using Forgejo v14.0.0 or v14.0.1, this release has a known defect [#&#8203;1302](https://github.com/forgejo/runner/issues/1302) that may cause jobs to appear to be stalled in Forgejo.  Please upgrade the runner to v12.5.3 to avoid this issue.

Release Notes

***

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

<!--URL:https://code.forgejo.org/forgejo/runner-->

- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1267): <!--number 1267 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2RvY2tlci9kb2NrZXIgdG8gdjI4LjUuMitpbmNvbXBhdGlibGU=-->Update module github.com/docker/docker to v28.5.2+incompatible<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1275): <!--number 1275 --><!--line 0 --><!--description VXBkYXRlIGZvcmdlam8tcnVubmVyIHRvIHYxMi41LjE=-->Update forgejo-runner to v12.5.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1276): <!--number 1276 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9yZWxlYXNlLW5vdGVzLWFzc2lzdGFudCB0byB2MS41LjA=-->Update dependency forgejo/release-notes-assistant to v1.5.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1272): <!--number 1272 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3JoeXNkL2FjdGlvbmxpbnQgdG8gdjEuNy4xMA==-->Update module github.com/rhysd/actionlint to v1.7.10<!--description-->

<!--end release-notes-assistant-->

### [`v12.5.1`](https://code.forgejo.org/forgejo/runner/releases/tag/v12.5.1)

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v12.5.0...v12.5.1)

- [User guide](https://forgejo.org/docs/next/user/actions/overview/)
- [Administrator guide](https://forgejo.org/docs/next/admin/actions/)
- [Container images](https://code.forgejo.org/forgejo/-/packages/container/runner/versions)

In combination with a runner with capacity > 1, and using Forgejo v14.0.0 or v14.0.1, this release has a known defect [#&#8203;1302](https://github.com/forgejo/runner/issues/1302) that may cause jobs to appear to be stalled in Forgejo.  Please upgrade the runner to v12.5.3 to avoid this issue.

Release Notes

***

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

<!--URL:https://code.forgejo.org/forgejo/runner-->

- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1268): <!--number 1268 --><!--line 0 --><!--description Zml4OiBwcml2YXRlIHJlcG9zaXRvcnkgY2xvbmluZyB3aXRoIGF1dGhlbnRpY2F0aW9uIHRva2Vu-->fix: private repository cloning with authentication token<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1270): <!--number 1270 --><!--line 0 --><!--description Zml4OiBtaW5pbWl6ZSBsb2cgZGF0YSBsb3NzIGNhdXNlZCBieSBMWEMgJiBQVFkgYnVmZmVy-->fix: minimize log data loss caused by LXC & PTY buffer<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1269): <!--number 1269 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLWdpdC9nby1naXQvdjUgdG8gdjUuMTYuNA==-->Update module github.com/go-git/go-git/v5 to v5.16.4<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1266): <!--number 1266 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9mb3JnZWpvIERvY2tlciB0YWcgdG8gdjExLjAuOQ==-->Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.9<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1263): <!--number 1263 --><!--line 0 --><!--description VXBkYXRlIGZvcmdlam8tcnVubmVyIHRvIHYxMi41LjA=-->Update forgejo-runner to v12.5.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1264): <!--number 1264 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL3NldHVwLWZvcmdlam8gYWN0aW9uIHRvIHYzLjEuMA==-->Update <https://data.forgejo.org/actions/setup-forgejo> action to v3.1.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1262): <!--number 1262 --><!--line 0 --><!--description UmVwbGFjZSBOb2RlLmpzIHdpdGggZGF0YS5mb3JnZWpvLm9yZy9vY2kvbm9kZQ==-->Replace Node.js with data.forgejo.org/oci/node<!--description-->

<!--end release-notes-assistant-->

### [`v12.5.0`](https://code.forgejo.org/forgejo/runner/releases/tag/v12.5.0)

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v12.4.0...v12.5.0)

- [User guide](https://forgejo.org/docs/next/user/actions/overview/)
- [Administrator guide](https://forgejo.org/docs/next/admin/actions/)
- [Container images](https://code.forgejo.org/forgejo/-/packages/container/runner/versions)

In combination with a runner with capacity > 1, and using Forgejo v14.0.0 or v14.0.1, this release has a known defect [#&#8203;1302](https://github.com/forgejo/runner/issues/1302) that may cause jobs to appear to be stalled in Forgejo.  Please upgrade the runner to v12.5.3 to avoid this issue.

Release Notes

***

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

<!--URL:https://code.forgejo.org/forgejo/runner-->

- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1259): <!--number 1259 --><!--line 0 --><!--description ZmVhdDogaW50cm9kdWNlIGV4cGVyaW1lbnRhbCBjb21tYW5kIGNvbm5lY3Qgd2l0aCB0b2tlbiBvcHRpb24=-->feat: introduce experimental command connect with token option<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1232): <!--number 1232 --><!--line 0 --><!--description ZmVhdDogYWRkIE9JREMgd29ya2xvYWQgaWRlbnRpdHkgZmVkZXJhdGlvbiBzdXBwb3J0-->feat: add OIDC workload identity federation support<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1249): <!--number 1249 --><!--line 0 --><!--description ZmVhdDogaW5jbHVkZSBhdXRoIHRva2VuIHdoZW4gY2xvbmluZyBhY3Rpb25zIGZyb20gb3duIGluc3RhbmNl-->feat: include auth token when cloning actions from own instance<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1255): <!--number 1255 --><!--line 0 --><!--description Zml4OiBjbG9uZSBhY3Rpb25zIHdpdGggR2l0IGluc3RlYWQgb2YgZ28tZ2l0-->fix: clone actions with Git instead of go-git<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1257): <!--number 1257 --><!--line 0 --><!--description Zml4OiBob3N0LWJhc2VkIGV4ZWN1dG9yLCBjbGFyaWZ5IGVycm9yIG1lc3NhZ2UgZnJvbSBtaXNzaW5nIHdvcmtpbmctZGlyZWN0b3J5-->fix: host-based executor, clarify error message from missing working-directory<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1250): <!--number 1250 --><!--line 0 --><!--description Zml4OiBzdG9wIGNyZWF0aW9uIG9mIGJyYW5jaCBjYWxsZWQgSEVBRCBkdXJpbmcgZmV0Y2g=-->fix: stop creation of branch called HEAD during fetch<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1252): <!--number 1252 --><!--line 0 --><!--description ZG9jczogcmVtb3ZlICdyZXF1aXJlZCcgZmxhZyBmcm9tIHJldXNhYmxlIHdvcmtmbG93ICdydW5zLW9uJyBmaWVsZA==-->docs: remove 'required' flag from reusable workflow 'runs-on' field<!--description-->

<!--end release-notes-assistant-->

### [`v12.4.0`](https://code.forgejo.org/forgejo/runner/releases/tag/v12.4.0)

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v12.3.1...v12.4.0)

- [User guide](https://forgejo.org/docs/next/user/actions/overview/)
- [Administrator guide](https://forgejo.org/docs/next/admin/actions/)
- [Container images](https://code.forgejo.org/forgejo/-/packages/container/runner/versions)

In combination with a runner with capacity > 1, and using Forgejo v14.0.0 or v14.0.1, this release has a known defect [#&#8203;1302](https://github.com/forgejo/runner/issues/1302) that may cause jobs to appear to be stalled in Forgejo.  Please upgrade the runner to v12.5.3 to avoid this issue.

Release Notes

***

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

<!--URL:https://code.forgejo.org/forgejo/runner-->

- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1247): <!--number 1247 --><!--line 0 --><!--description ZmVhdDogaW5jbHVkZSBhbGwgaW50ZWdyYXRpb24gdGVzdHMgaW4gYG1ha2UgaW50ZWdyYXRpb24tdGVzdGA=-->feat: include all integration tests in `make integration-test`<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1238): <!--number 1238 --><!--line 0 --><!--description ZmVhdChkb2NrZXJfcnVuKTogYWRkIHN1cHBvcnQgZm9yIHVzZXIgYW5kIGdyb3VwLWFkZCBqb2Igb3B0aW9ucw==-->feat(docker\_run): add support for user and group-add job options<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1245): <!--number 1245 --><!--line 0 --><!--description ZmVhdDogcmVxdWVzdCB1cCB0byBgY2FwYWNpdHlgIGpvYnMgZnJvbSBGb3JnZWpvIGluIG9uZSBBUEkgY2FsbA==-->feat: request up to `capacity` jobs from Forgejo in one API call<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1240): <!--number 1240 --><!--line 0 --><!--description Zml4OiByZW1vdmUgYGNtZGAgYW5kIGBwb3J0c2AgZnJvbSBjb250YWluZXIgc2NoZW1h-->fix: remove `cmd` and `ports` from container schema<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1244): <!--number 1244 --><!--line 0 --><!--description Zml4OiBldmFsdWF0ZSBqb2JzLjxqb2JfaWQ+LmNvbnRhaW5lci52b2x1bWVz-->fix: evaluate jobs.\<job\_id>.container.volumes<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1251): <!--number 1251 --><!--line 0 --><!--description Zml4OiByZS1wYXJzaW5nIGluY29tcGxldGUgam9icyBtdXN0IHVzZSBvbi53b3JrZmxvd19jYWxsLmlucHV0cywgbm90IGdsb2JhbCBpbnB1dHM=-->fix: re-parsing incomplete jobs must use on.workflow\_call.inputs, not global inputs<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1246): <!--number 1246 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBjb2RlLmZvcmdlam8ub3JnL2Zvcmdlam8vYWN0aW9ucy1wcm90byB0byB2MC42LjA=-->Update module code.forgejo.org/forgejo/actions-proto to v0.6.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1242): <!--number 1242 --><!--line 0 --><!--description VXBkYXRlIGZvcmdlam8tcnVubmVyIHRvIHYxMi4zLjE=-->Update forgejo-runner to v12.3.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1241): <!--number 1241 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjU=-->Update dependency go to v1.25<!--description-->

<!--end release-notes-assistant-->

### [`v12.3.1`](https://code.forgejo.org/forgejo/runner/releases/tag/v12.3.1)

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v12.3.0...v12.3.1)

- [User guide](https://forgejo.org/docs/next/user/actions/overview/)
- [Administrator guide](https://forgejo.org/docs/next/admin/actions/)
- [Container images](https://code.forgejo.org/forgejo/-/packages/container/runner/versions)

Release Notes

***

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

<!--URL:https://code.forgejo.org/forgejo/runner-->

- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1239): <!--number 1239 --><!--line 0 --><!--description ZmVhdChqb2JwYXJzZXIpOiBzZXBhcmF0ZSB0aGUgY29uY2VwdCBvZiBhbiBpbnN0YW5jZSAmIGV4dGVybmFsIHJldXNhYmxlIHdvcmtmbG93-->feat(jobparser): separate the concept of an instance & external reusable workflow<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1237): <!--number 1237 --><!--line 0 --><!--description Zml4OiBzZWNvbmQtbGF5ZXIgcmV1c2FibGUgd29ya2Zsb3dzIGxvc2luZyB0aGVpciBpbnB1dHMgd2hlbiBleHBhbmRlZA==-->fix: second-layer reusable workflows losing their inputs when expanded<!--description-->

<!--end release-notes-assistant-->

### [`v12.3.0`](https://code.forgejo.org/forgejo/runner/releases/tag/v12.3.0)

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v12.2.0...v12.3.0)

- [User guide](https://forgejo.org/docs/next/user/actions/overview/)
- [Administrator guide](https://forgejo.org/docs/next/admin/actions/)
- [Container images](https://code.forgejo.org/forgejo/-/packages/container/runner/versions)

Release Notes

***

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

<!--URL:https://code.forgejo.org/forgejo/runner-->

- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1234): <!--number 1234 --><!--line 0 --><!--description ZmVhdChqb2JwYXJzZXIpOiBleHBvc2UgSm9iIHRvIHJldXNhYmxlIHdvcmtmbG93IGZldGNoZXJz-->feat(jobparser): expose Job to reusable workflow fetchers<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1227): <!--number 1227 --><!--line 0 --><!--description ZmVhdChqb2JwYXJzZXIpOiBhZGQgdHJhY2tpbmcgSURzIGZvciBvdXRlci9pbm5lciBqb2JzIGluIHJldXNhYmxlIHdvcmtmbG93cw==-->feat(jobparser): add tracking IDs for outer/inner jobs in reusable workflows<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1228): <!--number 1228 --><!--line 0 --><!--description ZmVhdChqb2JwYXJzZXIpOiBpZ25vcmUgYF9fbWV0YWRhdGFgIGluIHdvcmtmbG93IHNjaGVtYSB2YWxpZGF0aW9u-->feat(jobparser): ignore `__metadata` in workflow schema validation<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1229): <!--number 1229 --><!--line 0 --><!--description ZmVhdChqb2JwYXJzZXIpOiBleHBvc2UgQVBJIGZvciBgRXZhbHVhdGVXb3JrZmxvd0NhbGxTZWNyZXRzYA==-->feat(jobparser): expose API for `EvaluateWorkflowCallSecrets`<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1210): <!--number 1210 --><!--line 0 --><!--description ZmVhdChydW5uZXIpOiBza2lwIHNlcnZpY2UgY29udGFpbmVycyB3aXRoIGVtcHR5IGltYWdlIGFmdGVyIGludGVycG9sYXRpb24=-->feat(runner): skip service containers with empty image after interpolation<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1235): <!--number 1235 --><!--line 0 --><!--description Zml4KGpvYnBhcnNlcik6IHByZXNlcnZlIHdvcmtmbG93X3BhcmVudF9pZCBvbiByZXBhcnNpbmcgaW5jb21wbGV0ZSB3b3JrZmxvd3M=-->fix(jobparser): preserve workflow\_parent\_id on reparsing incomplete workflows<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1230): <!--number 1230 --><!--line 0 --><!--description Zml4OiBhY2NlcHQgZW52IHJlZmVyZW5jZXMgaW4gc2VydmljZSBkZWZpbml0aW9ucw==-->fix: accept env references in service definitions<!--description-->

<!--end release-notes-assistant-->

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), 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:eyJjcmVhdGVkSW5WZXIiOiI0Mi44NC4yIiwidXBkYXRlZEluVmVyIjoiNDIuODQuMiIsInRhcmdldEJyYW5jaCI6InYxNC4wL2Zvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11001
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-01-23 04:51:52 +01:00
0ko
f9e2ccb108 [v14.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v14 branch were picked from this commit: 5c67663706

Changes to strings that are only present in the v15 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 v15.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Atalanttore <atalanttore@noreply.codeberg.org>
Co-authored-by: BKehayov <bkehayov@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Bullbagaren <bullbagaren@noreply.codeberg.org>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: KWik <kwik@noreply.codeberg.org>
Co-authored-by: Klenje <klenje@noreply.codeberg.org>
Co-authored-by: Lzebulon <lzebulon@noreply.codeberg.org>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@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: aindriu80 <aindriu80@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: atarwn <atarwn@noreply.codeberg.org>
Co-authored-by: bespinas <bespinas@noreply.codeberg.org>
Co-authored-by: hanklank <hanklank@noreply.codeberg.org>
Co-authored-by: hugoalh <hugoalh@noreply.codeberg.org>
Co-authored-by: jimkats <jimkats@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: lanticy <lanticy@noreply.codeberg.org>
Co-authored-by: mahlzahn <mahlzahn@posteo.de>
Co-authored-by: ospalh <ospalh@noreply.codeberg.org>
Co-authored-by: retarded-beast <retarded-beast@noreply.codeberg.org>
Co-authored-by: smlxdesign <smlxdesign@noreply.codeberg.org>
Co-authored-by: tibfulv <tibfulv@noreply.codeberg.org>
Co-authored-by: vmtj <vmtj@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
Co-authored-by: yookoala <yookoala@noreply.codeberg.org>
2026-01-22 17:34:15 +05:00
Renovate Bot
39a5f838c7 Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.5.1 (v14.0/forgejo) (#10983)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10983
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-01-22 11:36:45 +01:00
Renovate Bot
da0df4b5d9 Update https://data.forgejo.org/infrastructure/issue-action action to v1.5.0 (v14.0/forgejo) (#10984)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10984
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-01-22 11:23:52 +01:00
Shiny Nematoda
c3fe2a5e34 [v14.0/forgejo] fix(ui): add missing translation for code search when keyword is empty string (#10970)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10964

- `CodeSearchMode` was is now set when keyword is empty
- The default value for search mode should be exact, use fuzzy ONLY when fuzziness is enabled in settings

(cherry picked from commit da7ce17533)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10970
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
Co-committed-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
2026-01-22 06:05:16 +01:00
forgejo-backport-action
191b309486 [v14.0/forgejo] fix(api): default new release 'title' field to label name, if not provided (#10949)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10925

## 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

- 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 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.
- [ ] 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/10949): <!--number 10949 --><!--line 0 --><!--description Zml4KGFwaSk6IGRlZmF1bHQgbmV3IHJlbGVhc2UgJ3RpdGxlJyBmaWVsZCB0byBsYWJlbCBuYW1lLCBpZiBub3QgcHJvdmlkZWQ=-->fix(api): default new release 'title' field to label name, if not provided<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: emilycares <emilydoescare@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10949
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-01-20 21:13:53 +01:00
forgejo-backport-action
4d7dfe38bf [v14.0/forgejo] fix(ui): improve force-push layout alignment (#10950)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10939

Followup to https://codeberg.org/forgejo/forgejo/pulls/7746
Replaces https://codeberg.org/forgejo/forgejo/pulls/10938

grid layout (desktop): give the Compare button a wrapper with same height as the first text line so it stays aligned to it (and to timeline badge)

inline layout (mobile): give the Compare button left margin so there's a gap between it and the text line

Initial fix for grid was proposed by luisadame.

Co-authored-by: Luis <luis@adame.dev>
Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10950
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-01-20 20:15:15 +01:00
forgejo-backport-action
186664b881 [v14.0/forgejo] fix: remove infinite loop in UpdateRunJobWithoutNotification when run in transaction (#10947)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10945

#10893 introduced a retry loop to manage concurrent updates when updating the state of `action_run` in the function `UpdateRunJobWithoutNotification`.  However, when `UpdateRunJobWithoutNotification` is called from within a transaction, the retry loop continues to read the same data from the DB (due to repeatable read isolation) and loops infinitely.

As #10893 was later identified to not be required to fix the target problem (https://code.forgejo.org/forgejo/runner/issues/1302), this PR reverts the change.  The only retained change is that the error `ErrActionRunOutOfDate` is a constant rather than `errors.New("run has changed")`.

## 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

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
      - [x] Reverted the test added for 10893 after confirming that it is the cause of the problem.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- 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.
- [ ] 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: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10947
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-01-20 18:31:11 +01:00
forgejo-backport-action
1d1a62187a [v14.0/forgejo] feat: strip newlines on og image rendering (#10928)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10914

Replace newlines from the repo description with spaces to match in-app
rendering.

Related issue: #10823

## 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

- 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 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: Enrique Sanchez Cardoso <enriqueesanchz@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10928
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-01-19 19:23:25 +01:00
forgejo-backport-action
ec28d5885d [v14.0/forgejo] fix: don't return AdditionalTasks from FetchTask if there is no Task (#10909)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10899

Possible bug that could cause https://code.forgejo.org/forgejo/runner/issues/1302: by picking more tasks after the first `PickTask` didn't find anything, they'll be returned in `AdditionalTasks`.  But the runner doesn't act upon additional tasks if there is no "first" task.

I can't see a practical way to cover this with an automated test other than mutating the production code to provide a synchronization point between the two operations.

## 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

- 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 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: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10909
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-01-18 02:35:02 +01:00
forgejo-backport-action
f33e2d1efd [v14.0/forgejo] fix: retry ActionRun updates when optimistic-concurrency-control indicates record changed (#10906)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10893

When concurrent updates occur to the `action_run` table, fetching a task via `FetchTask` can result in an error:
```
time="2026-01-16T16:02:30Z" level=error msg="failed to fetch task" error="internal: pick task: CreateTaskForRunner: update run 2358339: run has changed"
```

This is an error with no known harm.  However, this error is correlated with the forgejo/forgejo repo encountering zombie tasks, where they appear as if they are recorded as dispatched to a runner but a runner doesn't pick them up.  I think it would be worthwhile to prevent this error and see if it fixes the zombie tasks, or eliminate it as a potential cause.

See https://code.forgejo.org/forgejo/runner/issues/1302#issuecomment-73859 for a more detailed technical analysis.

## 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

- 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 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

- [ ] 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: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10906
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
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-01-18 02:00:05 +01:00
Renovate Bot
964288a4a8 Update module github.com/klauspost/compress to v1.18.3 (v14.0/forgejo) (#10908)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10908
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-01-18 00:45:41 +01:00
forgejo-backport-action
f3028a7768 [v14.0/forgejo] ci: tie go cache to go version and add Makefile to key hash (#10886)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10883

- tie go cache to go version, so it will cleanup from time to time [see](https://codeberg.org/forgejo/discussions/issues/436)
- Add `Makefile` to cache key hash, because it also has go deps

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10886
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-01-17 22:34:59 +01:00
forgejo-backport-action
16f98ebaec [v14.0/forgejo] fix: use ALTER TABLE in SQLite DropTableColumns(), allowing unexpected database sources to work better in migrations (#10903)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10888

The existing implementation of `DropTableColumns()` came from before SQLite had the ability to `ALTER TABLE ... DROP COLUMN ...`.  It works by parsing the table definition and rewriting it without the columns that are to be dropped, but it will fail to do this correctly if the table definition is not in the exact expected format.  In #10887, a database that had probably come through some migration tool was not exactly formatted the way Forgejo expected, resulting in a migration failure.

This replaces `DropTableColumns()`'s hacky SQLite implementation with a more straightforward implementation.  Affected indexes touching the target fields are dropped, then the field is dropped.

DROP COLUMN is supported on SQLite since [3.35.0, 2021-03-12](https://sqlite.org/releaselog/3_35_0.html).

## 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

- Existing `test-sqlite-migration` coverage is relied upon for this change.  During development it was proven to exercise the affected code -- in other words, multiple iterations of changes were required due to it failing as I worked on it.
- No coverage is added for "database with unexpected schema definition format" as the trigger issue for this change though, a point that can be raised if someone believes it is worthwhile.
- 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 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: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10903
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-01-17 22:34:10 +01:00
Renovate Bot
ca46a3f68b Update dependency @citation-js/plugin-software-formats to v0.6.2 (v14.0/forgejo) (#10876)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10876
Reviewed-by: oliverpool <oliverpool@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-01-16 16:57:25 +01:00
forgejo-backport-action
16ee36b023 [v14.0/forgejo] fix: make concurrency group job cancellation effect runs that are failed (#10871)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10863

When an action's job fails, it marks the entire run as failed.  Concurrency group cancellation was only looking for runs that are in a pending state, and therefore after a single job failed in the run, none of the other jobs in the run could be cancelled by a matching cancel-in-progress job.

Raised in https://codeberg.org/Codeberg/Community/issues/2315.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10871
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-01-16 15:36:58 +01:00
forgejo-backport-action
e147d8d805 [v14.0/forgejo] fix: recreate-tables doesn't work on PostgreSQL with multiple Forgejo schemas (#10870)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10854

Discovered while trying to reproduce #10848 -- when using `forgejo doctor recreate-tables` against a PostgreSQL database with multiple Forgejo schemas in it, it fails.  The reason is that when querying for index and sequence information, it begins to get information from the other schemas.

```
2026/01/15 15:19:15 ...3.6.1/command_run.go:288:run() [I] PING DATABASE postgresschema
2026/01/15 15:19:15 ...igrations/base/db.go:51:func2() [I] Creating temp table: tmp_recreate__external_login_user for Bean: ExternalLoginUser
2026/01/15 15:19:15 ...igrations/base/db.go:108:func2() [I] Copying table external_login_user to temp table tmp_recreate__external_login_user
2026/01/15 15:19:15 ...igrations/base/db.go:120:func2() [I] Dropping existing table external_login_user, and renaming temp table tmp_recreate__external_login_user in its place
2026/01/15 15:19:15 cmd/doctor.go:216:func1() [E] [Error SQL Query] ALTER INDEX "external_login_user_pkey" RENAME TO "external_login_user_pkey" [] - ERROR: relation "external_login_user_pkey" does not exist (SQLSTATE 42P01)
2026/01/15 15:19:15 ...igrations/base/db.go:404:renameTable() [E] Unable to rename external_login_user_pkey to external_login_user_pkey. Error: ERROR: relation "external_login_user_pkey" does not exist (SQLSTATE 42P01)
Command error: migrate: ERROR: relation "external_login_user_pkey" does not exist (SQLSTATE 42P01)
```

This is a very niche use-case that is likely to only affect a developer using PostgreSQL and popping back to older releases often enough to keep them around in different DB schemas.  I don't think it's worth an automated test, which would require creating a secondary DB schema in a specific migration test.  Manually tested on my dev environment.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10870
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-01-16 11:41:57 +01:00
forgejo-backport-action
cd00d61b91 [v14.0/forgejo] fix: use strict-origin as referrer policy (#10858)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10851

- Resolves forgejo/forgejo#10849
- Yes, the referrer policy is causing cross-origin protection to fail.
Why? Because someone really cared about privacy, the referrer policy was
set to no-referrer. So no `Referrer` HTTP header and `Origin` is either
omited or set to `null`, because hey the browser isn't allowed to leak
it via that header either. The new cross-origin protection relies on
Sec-Fetch metadata to determine if the request is same-origin or not.
This metadata is only sent to trustworthy origins, and thus not when
you visit Forgejo on your intranet. But the new protection has a
fallback to compare the Origin to the Host header... but the Origin
header was conviently set to `null` to protect the user's privacy.
- We now set the referrer policy to strict-origin, which means only for
same-origin requests a Origin header is set. For cross-origin the
behavior is unchanged and the user's privacy is preserved.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10858
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-01-16 02:40:53 +01:00
Renovate Bot
0f20b2e51a Update dependency go to v1.25.6 (v14.0/forgejo) (#10853)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [go](https://go.dev/) ([source](https://github.com/golang/go)) | toolchain | patch | `1.25.5` -> `1.25.6` |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), 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:eyJjcmVhdGVkSW5WZXIiOiI0Mi43OC4yIiwidXBkYXRlZEluVmVyIjoiNDIuNzguMiIsInRhcmdldEJyYW5jaCI6InYxNC4wL2Zvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10853
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-01-16 02:12:22 +01:00
forgejo-backport-action
a3a52251ad [v14.0/forgejo] chore: correct spelling error in cleanup-commit-status CLI docs (#10838)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10780

Fixes a typo that prevents the forgejo docs builds from being updated.

## 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

- 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 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

- [ ] 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: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10838
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-01-14 20:11:57 +01:00
0ko
46d0192f5c [v14.0/forgejo]: chore(release): delete previously announced release notes (#10835)
It was already announced in release notes of v13 and v11 point releases and shouldn't be in release notes of v14, which this file is causing.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10835
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-01-14 17:06:35 +01:00
forgejo-backport-action
745134a89f [v14.0/forgejo] fix: proper styling for global time tracker popup (#10831)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10827

- Resolves forgejo/forgejo#10819
- CSS from tippy is overriding the style we are providing, so override
it via `!important` (tippy also uses that hence we lose the priority
race).

## Test
1. Start timer on any issue.
2. See that the styling is okay in the global time tracker popup in the navbar.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10831
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-01-14 12:27:11 +01:00
forgejo-backport-action
04132b338d [v14.0/forgejo] fix(ui): show switch default branch button in branch list only for repo admins (#10826)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10814

The default braunch is configured in the repo settings. Only users with
administrator privileges for the repository can access the repo
settings. When the feature was implemented (72e956b79a),
the button in the branch list was only guarded with a check for repo
write permissions. This means the button is shown to too many users.
If no an user with write, but not admin permissions clicks on the button,
they see just a 404 page. Which is bad UX.

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10826
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-01-14 08:53:35 +01:00
forgejo-backport-action
527c1a4fda [v14.0/forgejo] fix: make lastcommit available for non-signed-in users (#10817)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10815

- Regression of forgejo/forgejo!9830
- `reqSignIn` means it requires sign-in, but it does not require sign-in (can be hit by visiting large repository) so `ignSignIn` is the better option.
- Resulted in behavior of being redirected to `/user/login` when visiting a repository such as comaps or forgejo when not being logged in.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10817
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-01-13 23:41:35 +01:00
forgejo-backport-action
48bb631f20 [v14.0/forgejo] fix: drop sqlite shared cache (#10816)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10812

Use of sqlite shared cache is discouraged and obsolete. wal mode should be used instead.

- https://sqlite.org/sharedcache.html#use_of_shared_cache_is_discouraged

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10816
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-01-13 21:58:23 +01:00
0ko
92ea9b7055 merge commit: [v14.0/forgejo] i18n: backport of translations from Codeberg Translate (#10786)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10786
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2026-01-12 15:18:52 +01:00
forgejo-backport-action
d912a9b21f [v14.0/forgejo] fix: add forgejo doctor cleanup-commit-status command to recover from #10671 (#10781)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10686

```
NAME:
   forgejo doctor cleanup-commit-status - Cleanup extra records in commit_status table

USAGE:
   forgejo doctor cleanup-commit-status

DESCRIPTION:
   Forgejo suffered from a bug which caused the creation of more entries in the
   "commit_status" table than necessary. This operation removes the redundant
   data caused by the bug. Removing this data is almost always safe.
   These reundant records can be accessed by users through the API, making it
   possible, but unlikely, that removing it could have an impact to
   integrating services (API: /repos/{owner}/{repo}/commits/{ref}/statuses).

   It is safe to run while Forgejo is online.

   On very large Forgejo instances, the performance of operation will improve
   if the buffer-size option is used with large values. Approximately 130 MB of
   memory is required for every 100,000 records in the buffer.

   Bug reference: https://codeberg.org/forgejo/forgejo/issues/10671

OPTIONS:
   --help, -h                       show help
   --custom-path string, -C string  Set custom path (defaults to '{WorkPath}/custom')
   --config string, -c string       Set custom config file (defaults to '{WorkPath}/custom/conf/app.ini')
   --work-path string, -w string    Set Forgejo's working path (defaults to the directory of the Forgejo binary)
   --verbose, -V                    Show process details
   --dry-run                        Report statistics from the operation but do not modify the database
   --buffer-size int                Record count per query while iterating records; larger values are typically faster but use more memory (default: 100000)
   --delete-chunk-size int          Number of records to delete per DELETE query (default: 1000)
```

The cleanup effectively performs `SELECT * FROM commit_status ORDER BY repo_id, sha, context, index, id`, and iterates through the records.  Whenever `index, id` changes without the other fields changing, then it's a useless record that can be deleted.  The major complication is doing that at scale without bringing the entire database table into memory, which is performed through a new iteration method `IterateByKeyset`.

Manually tested against a 455,303 record table in PostgreSQL, MySQL, and SQLite, which was reduced to 10,781 records, dropping 97.5% of the records.

## 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

- 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 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.
    - Documentation should be via release notes and automatic CLI documentation updates.
- [ ] I did not document these changes and I do not expect someone else to do it.

### Release notes

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10781
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
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-01-12 13:11:04 +01:00
forgejo-backport-action
b042992694 [v14.0/forgejo] fix: correctly compute required commit status (#10788)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10747

We need to take all matching required status into account to get the desired status because there can be some pending.

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

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/10788): <!--number 10788 --><!--line 0 --><!--description Zml4OiBjb3JyZWN0bHkgY29tcHV0ZSByZXF1aXJlZCBjb21taXQgc3RhdHVz-->fix: correctly compute required commit status<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10788
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-01-12 13:05:58 +01:00
0ko
f962b32177 [v14.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v14 branch were picked from this commit:
f6399a0d25

Changes to strings that are only present in the v15 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 v15.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: Arthur Zamarin <arthurzam@gentoo.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: killawabbit <killawabbit@noreply.codeberg.org>
Co-authored-by: m-casanova <m-casanova@noreply.codeberg.org>
Co-authored-by: nykula <nykula@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
2026-01-12 13:00:58 +05:00
0ko
5c9a2e91f4 [v14.0/forgejo] i18n: backport of translations from Codeberg Translate
Translation updates that were relevant to v14 branch were picked from this commit:
cc11e56483

Changes to strings that are only present in the v15 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 v15.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: AYT04 <ayt04@noreply.codeberg.org>
Co-authored-by: Arthur Zamarin <arthurzam@gentoo.org>
Co-authored-by: Astrak <astrak@noreply.codeberg.org>
Co-authored-by: Baempaieo <baempaieo@noreply.codeberg.org>
Co-authored-by: Benedikt Straub <benedikt-straub@web.de>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-authored-by: Kenneth Bruen <kenny@kbruen.ro>
Co-authored-by: Kyush <kyush@noreply.codeberg.org>
Co-authored-by: Lzebulon <lzebulon@noreply.codeberg.org>
Co-authored-by: Nimplex <nimplex@noreply.codeberg.org>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: Schmerling <schmerling@noreply.codeberg.org>
Co-authored-by: SomeTr <sometr@noreply.codeberg.org>
Co-authored-by: Vyxie <kitakita@disroot.org>
Co-authored-by: WithLithum <withlithum@noreply.codeberg.org>
Co-authored-by: Wuzzy <wuzzy@disroot.org>
Co-authored-by: Zughy <zughy@noreply.codeberg.org>
Co-authored-by: adam <me@adamperkowski.dev>
Co-authored-by: adriand <adriand@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: butterflyoffire <butterflyoffire@noreply.codeberg.org>
Co-authored-by: jimkats <jimkats@noreply.codeberg.org>
Co-authored-by: justbispo <justbispo@noreply.codeberg.org>
Co-authored-by: mahlzahn <mahlzahn@posteo.de>
Co-authored-by: pixelcode <pixelcode@noreply.codeberg.org>
Co-authored-by: vmtj <vmtj@noreply.codeberg.org>
Co-authored-by: xtex <xtexchooser@duck.com>
2026-01-12 12:59:40 +05:00
Renovate Bot
915c436d95 Update CodeMirror (v14.0/forgejo) (#10776)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10776
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-01-11 11:43:36 +01:00
forgejo-backport-action
686f780673 [v14.0/forgejo] chore(ui): cleanup PR checks area (#10772)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10768

Mostly a UI followup to https://codeberg.org/forgejo/forgejo/pulls/9397 with a few fixes.

Co-authored-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10772
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-01-11 09:33:45 +01:00
oliverpool
659f1fc0c6 [v14.0/forgejo] fix: internal server error on a large .gitmodules (#10767)
Backport: #10744

---

Fix #10714 (introduced in #8438) by silently ignoring large .gitmodules files.

Additionally:
- the limit was bumped from 10KB to 64KB (https://github.com/boostorg/boost/blob/master/.gitmodules has 20KB)
- a warning is shown on the .gitmodules view page if this limit is exceeded

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10744
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: oliverpool <git@olivier.pfad.fr>
Co-committed-by: oliverpool <git@olivier.pfad.fr>
(cherry picked from commit 970b0da24d)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10767
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2026-01-11 09:32:09 +01:00
forgejo-backport-action
f87ec19130 [v14.0/forgejo] feat: provide multiple tasks to Runner in one FetchTask when requested (#10751)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10602

Permits the Forgejo to return multiple tasks to the Runner in one API call, if requested.  Fixes #8917.

Related runner PR: https://code.forgejo.org/forgejo/runner/pulls/1245

## 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

- 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 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

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

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

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/10602): <!--number 10602 --><!--line 0 --><!--description cHJvdmlkZSBtdWx0aXBsZSB0YXNrcyB0byBSdW5uZXIgaW4gb25lIEZldGNoVGFzayB3aGVuIHJlcXVlc3RlZA==-->provide multiple tasks to Runner in one FetchTask when requested<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10751
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
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-01-09 21:26:27 +01:00
Renovate Bot
47b9fdc590 Update module code.forgejo.org/forgejo/actions-proto to v0.6.0 (v14.0/forgejo) (#10754)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [code.forgejo.org/forgejo/actions-proto](https://code.forgejo.org/forgejo/actions-proto) | `v0.5.3` -> `v0.6.0` | ![age](https://developer.mend.io/api/mc/badges/age/go/code.forgejo.org%2fforgejo%2factions-proto/v0.6.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/code.forgejo.org%2fforgejo%2factions-proto/v0.5.3/v0.6.0?slim=true) |

---

### Release Notes

<details>
<summary>forgejo/actions-proto (code.forgejo.org/forgejo/actions-proto)</summary>

### [`v0.6.0`](https://code.forgejo.org/forgejo/actions-proto/compare/v0.5.3...v0.6.0)

[Compare Source](https://code.forgejo.org/forgejo/actions-proto/compare/v0.5.3...v0.6.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), 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:eyJjcmVhdGVkSW5WZXIiOiI0Mi43MS4wIiwidXBkYXRlZEluVmVyIjoiNDIuNzEuMCIsInRhcmdldEJyYW5jaCI6InYxNC4wL2Zvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10754
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2026-01-09 20:29:59 +01:00
Michael Kriese
90ab3b1940 [v14.0/forgejo] January 8th security patches (#10720)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10720
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2026-01-08 10:37:46 +01:00
forgejo-backport-action
0b7e6ff363 [v14.0/forgejo] fix(ui): actions list layout breakage with long content (#10723)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10648

Fixes issue #4580

## Context

Fixes the layout of the actions list specifically when an action name is too long to be displayed within the column's constrained width.

I took the opportunity to add some ancillary improvements:
- Center elements vertically
- Space elements consistently: the error badge didn't have the same margin on the left like the disabled badge.

Co-authored-by: Luis <luis@adame.dev>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10723
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-01-07 15:17:15 +01:00
forgejo-backport-action
440f38913e [v14.0/forgejo] fix(ui): improve rendering of commit links (#10613)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10530

This commit changes the commit link rendering (link to a single commit,
a diff, a PR, etc):

1. If it is a link to something on the local instance:
  1.1. If it is to the same org and repo, the link is just e.g. the
  commit hash
  1.2. If it is to another repo, the link is the org/repo/commit hash
2. If the link is to another instance:
  The link is the domain/optional sub path/org/repo/commit hash

This change is made to keep the link as short as possible, while not
hiding that the link may go to an external instance.

Followup to !9146

Closes #10241

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10613
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-01-07 13:51:34 +01:00
Mathieu Fenniak
3556875c51
doc: add release notes for Jan 8 security release 2026-01-06 10:34:13 -07:00
Gusted
f5603d2210 fix: load reviewer for pull review dismiss action notifier
This was implicitly loaded during the mail notifications notifier. If
you disable mail notifications on Forgejo then this will result in the
reviewer not being loaded and NPE.
2026-01-06 10:33:22 -07:00
Gusted
ca3166ddba chore: add integration test
Add a integration test that verifies that only the verified key is shown
in `{user}.gpg`.
2026-01-06 10:33:22 -07:00
Gusted
1ca9cbb7c2 fix: use correct GPG key for export
`GPGKeyToEntity` incorrectly assumed that within a keyring with multiple
keys that the first key is verified and should be exported. Look at all
keys and find the one that matches the verified key ID.
2026-01-06 10:33:22 -07:00
Mathieu Fenniak
590795f592
fix: don't use attachment size as max memory for ParseMultipart 2026-01-06 10:33:22 -07:00
Mathieu Fenniak
168dfbb70b
fix: incorrect whitespace handling on pre&post receive hooks 2026-01-06 10:33:22 -07:00
Mathieu Fenniak
bade14ee69
fix: hide user profile anonymous options on public repo APIs 2026-01-06 10:33:22 -07:00
forgejo-backport-action
8e083c9f3e [v14.0/forgejo] fix: prevent intermittent test failures caused by uncancellable tasks (#10717)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10713

Attempt to fix intermittent test failure noted in #10633, detailed technical notes in https://codeberg.org/forgejo/forgejo/issues/10633#issuecomment-9571199.

- Failure to cancel the previous processes is now a test error that aborts immediately, preventing 2hr long test runs that won't succeed.
- When the process cancellation fails, the stack trace of all goroutines is printed to help diagnose the cause of any failure to cancel tasks.
- `context.Background()` referenced in the actions notifier is corrected when opening git repos, which seems to be a cause of failure to cancel the tasks -- git subprocesses are spawned from the repo context, which is the background context, and that prevents the context registered in the process manager from cancelling them.

## 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

- 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 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] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10717
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-01-06 17:06:22 +01:00
forgejo-backport-action
342a54a142 [v14.0/forgejo] fix: retain Forgejo Action's commit_status entries with distinct descriptions (#10704)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10696

In #10678, I fixed an incorrect codepath that was intended to prevent duplicate redundant entries in `commit_status`.  However, the codepath that was repaired didn't take into account changes in the `description` field -- eg. going from `Waiting to run` to `Has started running` both have the `pending` commit status state but are distinct and should be retained.  This PR fixes the fix so that changes in description do still cause new entries into the `commit_status` table.

This issue was raised due to an end-to-end test failure in the `push-cancel` actions test.  I've manually tested that this fixes the end-to-end test.

Will require manual backport to v11 and v13 top of #10680 and #10681; automated backport to v14.

## 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

- 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 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

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10704
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-01-05 18:20:14 +01:00
Mathieu Fenniak
a53aa04f5d [v14.0/forgejo] fix: in-progress job icon doesn't rotate on repo's action list (#10656) (#10663)
**Backport:** #10656

(cherry picked from commit 0af52cdca2)

In-progress jobs don't have a rotating status icon on `/org/repo/actions`.  Likely a regression from #9444 as the rotation style was in `RepoActionView` which won't be loaded on the action list page.

Manually tested and confirmed that the styling is effective on both `/org/repo/actions` and in the action log page (`.../runs/#/jobs/#/attempt/#`).

Reported-by: limiting-factor
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10656
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10663
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-01-05 15:02:08 +01:00
forgejo-backport-action
40e4f6f354 [v14.0/forgejo] fix(ui): pull request merge menu item clipping the auto merge tip (#10685)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10652

Fixes the auto merge tip not being properly displayed due to an `overflow: hidden` set at the `.item` level. The fix resets that overflow rule if the auto merge button is being hovered and goes back to `hidden` when no longer being hovered.

Fixed also a small misalignment between the tip and the button.

Resolves #4822

### Test

1. Go to a pull request that merges into a protected branch that requires status checks to pass.
2. Go to the merge area of that pull request.
3. Click on the "Create merge commit" button.
4. Hover over the clock icon.
5. Observe that some text appears to the right of that clock icon.

Co-authored-by: Luis <luis@adame.dev>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10685
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-01-05 12:14:35 +01:00
forgejo-backport-action
abab629d90 [v14.0/forgejo] chore(cleanup): move all test blank imports in a single package (#10672)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10662

- create the modules/testimport/import.go to centralize blank import needed for tests (in order to run the init() function)  to simplify maintenance
- remove the imports that are not needed

Co-authored-by: limiting-factor <limiting-factor@posteo.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10672
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-01-05 12:14:11 +01:00
Beowulf
626929eaa3 feat(ui): replace Monaco with CodeMirror (#10559) (#10697)
- Replace the [Monaco Editor](https://microsoft.github.io/monaco-editor/)
with [CodeMirror 6](https://codemirror.net/). This editor is used to
facilitate the 'Add file' and 'Edit file' functionality.
- Rationale:
  - Monaco editor is a great and powerful editor, however for Forgejo's
  purpose it acts more like a small IDE than a code editor and is doing
  too much. In my limited user research the usage of editing files via
  the web UI is largely for small changes that does not need the
  features that Monaco editor provides.
  - Monaco editor has no mobile support, Codemirror is very usable on mobile.
  - Monaco editor pulls in large dependencies (for language support) and
  by replacing it with Codemirror the amount of time that webpack needs
  to build the frontend is reduced by 50% (~30s -> ~15s).
  - The binary of Forgejo (build with `bindata` tag) is reduced by 2MiB.
  - Codemirror is much more lightweight and should be more usable on
  less powerful hardware, most notably the lazy loading is much faster
  as codemirror uses less javascript.
  - Because Codemirror is modular it is much easier to change the
  behavior of the code editor if we wish to.
- Drawbacks:
  - Codemirror is quite modular and as seen in `package.json` and in
  `codeeditor.ts` we have to supply a lot more of its features to have
  feature parity with Monaco editor.
  - Monaco editor has great integrated language support (features that
  an lsp would provide), Codemirror only has such language support to an
  extend.
  - Monaco editor has its famous command palette (known by many as its
  also available in VSCode), this is not available in code mirror.
- Good to note:
  - All features that was added on top of the monaco editor (such as
  dynamically changing language  support depending on the filename)
  still works and the theme is based on the VSCode colors which largely
  resembles the monaco editor.
  - The code editor is still lazy-loaded (this is painfully clear by
  reading how imports are passed around in `codeeditor.ts`).
  - This change was privately tested by a few people, a few bugs were
  found (and fixed) but no major drawbacks were noted for their usage of
  the web editor.
  - There's a "search" button in the top bar, so that search can be used
  on mobile. It is otherwise only accessible via
  <kbd>Ctrl</kbd>+<kbd>f</kbd>.

Co-authored-by: Beowulf <beowulf@beocode.eu>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Beowulf <beowulf@beocode.eu>

(cherry picked from commit 28e0af23fa)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10697
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
2026-01-05 06:26:42 +01:00
forgejo-backport-action
a604f85c60 [v14.0/forgejo] chore: download git-man over TLS (#10694)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10692

- No need to use http when https is available.

Co-authored-by: Gusted <postmaster@gusted.xyz>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10694
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-01-04 05:38:18 +01:00
forgejo-backport-action
ee42a69b3a [v14.0/forgejo] fix: don't duplicate commit status records on workflows with empty name (#10679)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10678

Fixes #10671.

Cleanup for the inflated number of records in this table will come in a near future change.

## 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

- 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 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

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10679
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-01-02 22:10:33 +01:00
forgejo-backport-action
766104acae [v14.0/forgejo] feat: add Forgejo server version to runner context (#10643)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10642

Currently, there's no way for actions runners to know what version of
Forgejo is running on the server side. This makes it
difficult/impossible to know which features are available and can make
maintaining compatibility tricky.

Let's add the Forgejo server version to the context.

See associated PR in the runner repo: https://code.forgejo.org/forgejo/runner/pulls/1249

Co-authored-by: John Moon <john.moon@vts-i.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10643
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
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>
2025-12-31 00:32:51 +01:00
forgejo-backport-action
180ebee6de [v14.0/forgejo] fix: build-release workflow stops its own end-to-end checks when run concurrently (#10635)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10632

`build-release.yml` attempts to run an end-to-end check with a cascading PR, but it doesn't target the currently building branch.  When two releases build simultaneously (eg. `forgejo/v14.0` and `forgejo`), whichever one starts the end-to-end test first is then "cancelled" by the second one as it pushes an update to the same branch.

This will be a bit of an experimental change due to the difficulty in setting up a test environment.  After merge, I intend to watch a v14 and forgejo build and verify that they are independent, and, that both are actually tested with the correct target build.

This introduces a need to backport any changes to `.forgejo/cascading-release-end-to-end` in the future to maintain cascading functionality in all active releases.

## 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

- 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 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] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10635
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>
2025-12-30 04:28:18 +01:00
forgejo-backport-action
400c17e290 [v14.0/forgejo] fix(ui): process dynamically added content via htmx (#10630)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10572

When new content is added via JS and htmx is not used for this change,
htmx need to be informed that DOM changes happened and that it needs to
reprocess the DOM (or at least the changed parts).

When a diff is really large, it is hidden by default. The user can press
a button to load the diff, which then will be added via JS.
The diff contains buttons to expand it, which are using htmx behind the
scenes. Therefore a reprocessing via htmx needs to be triggered after
adding the large diff.

Fixes #10570

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10630
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>
2025-12-30 02:26:44 +01:00
forgejo-backport-action
15f891abd7 [v14.0/forgejo] fix(ui): don't stretch activity top author image (#10628)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10556

This is a followup to !10524.

In addition I changed that the tooltip triggers for the whole height, instead for only the bar height, because otherwise it is esp for small bars nearly impossible to get the tooltip to open.

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10628
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
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>
2025-12-29 22:13:14 +01:00
forgejo-backport-action
8514af643d [v14.0/forgejo] fix: display orphan branches separately in commit graph (#10622)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10484

Fixes #2705.
Fixes #7635.

This PR fixes the commit graph showing false connections for orphan/root commits. Connection lines are now shown only when a parent/child relationship exists. Visible relationships are determined using `git log`'s `%P` output by the new `ComputeGlyphConnectivity` function. The SVG template is adapted to render vertical lines conditionally.

Unit tests for `ComputeGlyphConnectivity` cover regular linear commit history, orphan commits, merge commits, and non-commit glyphs (`|`, `/`, `\`). Unit tests also cover the changes to the `git log` parsing. The SVG template was verified manually.

Co-authored-by: Bram Hagens <bram@bramh.me>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10622
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>
2025-12-29 20:56:20 +01:00
forgejo-backport-action
763547f43f [v14.0/forgejo] migration: update existing foreign key migrations to automatically fix inconsistencies (#10621)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10568

Changes foreign key database inconsistency handling so that inconsistent records are automatically deleted with an administrator warning during migration.  As noted in discussion: https://codeberg.org/forgejo/discussions/issues/385#issuecomment-9175566

Because these migrations are now deleting data, rather than allowing the administrator to do it, all migrations have been covered with an integration test that verifies expected data is deleted.  This is particularly interesting with nullable fields.

## 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

- 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 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

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10621
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>
2025-12-29 03:49:03 +01:00
forgejo-backport-action
a89978a207 [v14.0/forgejo] fix: allow Actions trust management on conflicted PRs (#10600)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10594

Fixes #10589.

![20251226_134200](/attachments/0aac3594-62d7-467f-82f2-2d9063fb5ffb)

## 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

- 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 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

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10600
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>
2025-12-27 17:24:50 +01:00
forgejo-backport-action
c6c51dcde6 [v14.0/forgejo] test: fix intermittent PostgreSQL failure in TestAdminViewRepos (#10592)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10587

Intermittent test failure ([example](https://codeberg.org/forgejo/forgejo/actions/runs/125874/jobs/9/attempt/1)):
```
=== TestAdminViewRepos (tests/test_utils.go:327)
--- FAIL: TestAdminViewRepos (0.39s)
    testlogger.go:411: 2025/12/26 15:21:27 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /workspace/forgejo/forgejo/tests/gitea-lfs-meta
    testlogger.go:411: 2025/12/26 15:21:27 ...eb/routing/logger.go:102:func1() [I] router: completed POST /user/login for test-mock:12345, 303 See Other in 4.7ms @ auth/auth.go:178(auth.SignInPost)
    testlogger.go:411: 2025/12/26 15:21:27 ...eb/routing/logger.go:102:func1() [I] router: completed GET /admin/repos for test-mock:12345, 200 OK in 75.1ms @ admin/repos.go:29(admin.Repos)
    admin_repo_test.go:29:
        	Error Trace:	/workspace/forgejo/forgejo/tests/integration/admin_repo_test.go:29
        	Error:      	Not equal:
        	            	expected: 1
        	            	actual  : 0
        	Test:       	TestAdminViewRepos
    admin_repo_test.go:30:
        	Error Trace:	/workspace/forgejo/forgejo/tests/integration/admin_repo_test.go:30
        	Error:      	Not equal:
        	            	expected: "repo49"
        	            	actual  : ""

        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1 +1 @@
        	            	-repo49
        	            	+
        	Test:       	TestAdminViewRepos
```

Cause: the page is displaying 50 out of 65 repos in the fixture with a default sort of "recently updated"; on PostgreSQL that is occasionally causing the target link not to appear on the first page.  As a fix, I've switched the test to load with reverse alphabetical order which should cause it to consistently appear on the first page.

## 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

- 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 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] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10592
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>
2025-12-27 02:23:25 +01:00
forgejo-backport-action
462fe3819b [v14.0/forgejo] fix: ListTrackedTimes API has no defined record ordering (#10593)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10588

API call `GET /repos/{owner}/{repo}/issues/{index}/times` has no defined ordering implemented in it, causing PostgreSQL to have intermittent test failures on `TestAPIGetTrackedTimes` which expected records to be returned in ID order.  ID order is reasonable enough, so this PR adds that ordering.

Fixes #10577.

## 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

- 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 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

- [ ] I do not want this change to show in the release notes.
- [x] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10593
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>
2025-12-26 23:01:50 +01:00
forgejo-backport-action
8dff8ba7c2 [v14.0/forgejo] port(gitea): Fix password leak in log messages (go-gitea/gitea!35584) (#10555)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10550

Link to original PR: https://github.com/go-gitea/gitea/pull/35584
Original Author: https://github.com/shashank-netapp

Co-authored-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10555
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>
2025-12-23 00:52:58 +01:00
forgejo-backport-action
5a131275c1 [v14.0/forgejo] fix(ui): avatar for dismissed review is stretched if not square (#10540)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10524

The timeline event for a dismissed review didn't used the `AvatarUtils` until now. The `AvatarUtils` also adds classes to the img tag, which makes sure the avatar is correctly styled and not stretched.
This PR replaces the img tag with the expected call to the `AvatarUtils`.

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10540
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>
2025-12-22 23:07:10 +01:00
forgejo-backport-action
6907601529 [v14.0/forgejo] fix(ui): add dynamic aria-label to monospace button in markdown editor (#10543)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/8244

The aria-label now changes dynamically depending on whether
the monospace font is enabled or disabled.

Greetings from GPN :)

Fixes #7669.

Co-authored-by: JohnnyJayJay <johnny@leftfold.tech>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10543
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>
2025-12-22 14:49:27 +01:00
forgejo-backport-action
fcb22b1a47 [v14.0/forgejo] fix: always search for issue posters by user and full name (#10542)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10394

Previously searching for posters would use full name or username depending on the `[ui].DEFAULT_SHOW_FULL_NAME` setting, now it searches for both of them regardless of the setting.

This also a fixes a bug when `[ui].DEFAULT_SHOW_FULL_NAME=true` that users without a full name where not able to searched for.

Co-authored-by: BtbN <btbn@btbn.de>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10542
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>
2025-12-22 13:45:28 +01:00
forgejo-backport-action
650252f851 [v14.0/forgejo] Add to html button in markdown type="button" (#10527)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10520

This is for preventing that a markdown button is recognized as button for submission in a html form.

Buttons can't be stripped from the markdown due to: https://codeberg.org/forgejo/forgejo/pulls/7670#issuecomment-4086608

There is no issue with buttons if they always have `type="button"`, so this should be fine.

This is a "follow-up" to !7670.

Fixes #7656

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10527
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>
2025-12-22 00:29:08 +01:00
forgejo-backport-action
cd0afc4f90 [v14.0/forgejo] fix(ui): add missing space before 'Commit' back (#10526)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10521

Regression from 8039240c26

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10526
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>
2025-12-22 00:28:33 +01:00
forgejo-backport-action
dd75d0957d [v14.0/forgejo] feat(ui): show cancel button until all jobs are finished (#10531)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/9261

Change that the Cancel button is shown until all jobs are finished and do not hide it, when the first job failed.
Additionally the wrapping of the header was changed.

Fixes #8922

Co-authored-by: Beowulf <beowulf@beocode.eu>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10531
Reviewed-by: Beowulf <beowulf@beocode.eu>
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>
2025-12-21 19:18:37 +01:00
forgejo-backport-action
83da3ae68c [v14.0/forgejo] feat(ui): show update time when sorting by recently updated (#10500)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10488

Fixes #4712
Fixes #7783

When filtering issues or PRs by "Recently updated" or "Least recently updated", the last updated time is shown:
![image](/attachments/f8e52a05-6055-42f9-9370-78196a173108)
![image](/attachments/50b63323-fe73-4ca5-8283-79fd6952d318)

Co-authored-by: Bram Hagens <bram@bramh.me>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10500
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>
2025-12-20 16:22:36 +01:00
forgejo-backport-action
44102c47d4 [v14.0/forgejo] fix: ignore private .profile repo on user profile page (#10495)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10486

Fixes #4202

Co-authored-by: Bram Hagens <bram@bramh.me>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10495
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>
2025-12-20 07:06:26 +01:00
forgejo-backport-action
fed7d64861 [v14.0/forgejo] fix(ui): align due date icon in issue list (#10494)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10489

Flattened nested `<span>` tags for the calender icon in the issue list, to fix the vertical alignment

Before:
![image](/attachments/f5049acb-41dc-438e-9256-ef30542e168d)

After:
![image](/attachments/c4d8bc64-0474-4a3e-9061-9e2bca6abff9)
![image](/attachments/0b2c4d9c-7d34-4627-be55-2099ed32dd19)

Co-authored-by: Bram Hagens <bram@bramh.me>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10494
Co-authored-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
Co-committed-by: forgejo-backport-action <forgejo-backport-action@noreply.codeberg.org>
2025-12-20 06:05:54 +01:00
Andreas Ahlenstorf
6df7514417 Revert "feat: add support for ephemeral runners compatible with autoscaling tools (#9409)" (#10463)
Remove the unreleased HTTP API for managing runners that was introduced in https://codeberg.org/forgejo/forgejo/pulls/9409. It needs more time to mature. See also https://codeberg.org/forgejo/forgejo/pulls/10450.

## 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

- 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 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

- [ ] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10463
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Co-authored-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
Co-committed-by: Andreas Ahlenstorf <andreas@ahlenstorf.ch>
2025-12-19 17:24:03 +01:00
forgejo-backport-action
0861a01192 [v14.0/forgejo] feat: allow to add pam source from command line (#10485)
**Backport:** https://codeberg.org/forgejo/forgejo/pulls/10388

The forgejo admin command line allows to deal with all the propose auth mecanism but pam, this PR adds full support for adding and updating pam auth mecanism via the command line without limitation.

Co-authored-by: Baptiste Daroussin <bapt@FreeBSD.org>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10485
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>
2025-12-19 17:00:47 +01:00
1953 changed files with 36737 additions and 90479 deletions

View file

@ -19,10 +19,10 @@ forgejo.org/models/auth
forgejo.org/models/db
TruncateBeans
TruncateBeansCascade
InTransaction
DumpTables
GetTableNames
extendBeansForCascade
IsErrNameActivityPubInvalid
forgejo.org/models/dbfs
file.renameTo
@ -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,6 +1,6 @@
{
"name": "forgejo-dev",
"image": "mcr.microsoft.com/devcontainers/go:1.26-trixie",
"name": "Gitea DevContainer",
"image": "mcr.microsoft.com/devcontainers/go:1.25-trixie",
"features": {
// installs nodejs into container
"ghcr.io/devcontainers/features/node:1": {

View file

@ -30,6 +30,7 @@ insert_final_newline = false
[options/locale/locale_*.ini]
insert_final_newline = false
# Weblate is configured to use one tab for indention
# Weblate JSON output defaults to four spaces
[options/locale_next/locale_*.json]
indent_style = tab
indent_style = space
indent_size = 4

View file

@ -13,18 +13,7 @@ body:
- Please speak English, as this is the language all maintainers can speak and write.
- Be civil, and follow the [Forgejo Code of Conduct](https://codeberg.org/forgejo/code-of-conduct).
- Take a moment to [check if a similar problem has already been discussed in the past.](https://codeberg.org/forgejo/forgejo/issues?q=&type=all&labels=78137). Feel free to add your own experience there, if applicable.
- type: markdown
attributes:
value: |
### New workflow
We are currently experimenting with a new workflow to manage issues and better understand your problems and needs. This is step 1 of the workflow: Please try to focus on explaining the problem you are facing, which could be a bug in the code, a moment of confusion, or a need that you have.
We do not expect anything from Forgejo users after creating a problem report, but we appreciate if you stay responsive to further questions. If you want, you can also participate in a discussion for solutions.
Forgejo contributors will review your report, try to understand how important it is to you and other Forgejo users, and suggest potential solutions. In a next step, solutions can be documented and implemented.
If you want to learn more about the background of our workflow, feel invited to read and participate in [the discussion that led to the current approach](https://codeberg.org/forgejo/discussions/issues/415). We are looking forward to your feedback.
- We are currently experimenting with a new workflow to understand your problems and requests. Please try to focus on explaining the problem you are facing, which could be a bug in the code, a moment of confusion, or a missing feature. We'll think about solutions to the problem at a later step. If you want to learn more about the background of our workflow, feel invited to read and participate in [the discussion that led to the current approach](https://codeberg.org/forgejo/discussions/issues/415). We are looking forward to your feedback.
- type: dropdown
id: can-reproduce
attributes:
@ -41,18 +30,15 @@ body:
- type: textarea
id: environment
attributes:
label: About your usage of Forgejo
label: Your usage of Forgejo
description: |
Please provide a brief description of your usage of Forgejo. There is no clear guideline on how much you need to share here. You can be brief, but we value the insights you provide us to better understand your use case. Thank you very much!
Please provide a description of your usage of Forgejo. To better understand your problem, it will be relevant to know in which environment you use Forgejo and if you have performed specific configuration.
<details><summary>Further instructions</summary>
* When reporting problems with certain functionality, you should include related information. Examples:
* When reporting an issue with setting up an identity provider, it is useful to know if you use Forgejo in a 10-users non-profit / start up, or if you are talking about a school / university with several thousands of users.
* When describing confusion, it will be relevant to know your skill level and background ("New, but used a similar product", "In my role as a project manager ..."), so we know for which target audience we need to design the functionality.
* When reporting workflow issues or needs, it will be useful to know how large your project is, how many team members you have, which skill level we are talking about etc. For example, we might choose a different design depending on whether a feature is only for professional developers or for hobby coders.
* If you want, we always appreciate generic information about your Forgejo usage to help us understand your usage and make better decisions. For example:
* Your personal relation to Forgejo and user role ("I'm new to Forgejo, but used a comparable product called …", "In my role as a designer, …").
* If you already explained your usage of Forgejo elsewhere (e.g. in another issue or in a user research repository), feel free to just drop a link.
* If you report a bug with a certain functionality, it will be relevant to learn about related configuration ("This is how I configured my identity provider", "This is how my Forgejo Actions runner is set up").
* Please elaborate on your personal relation to Forgejo and user role ("I'm new to Forgejo, but used a comparable product called …", "In my role as a designer, …").
* If you feel that Forgejo needs a change in functionality, please describe in which environment you want to use it, so that we can understand for which audience the complexity needs to appeal to ("We're a group of friends with no technical / professional background and use a personal Forgejo instance to prepare our first libre game").
* If you already explained your usage of Forgejo elsewhere (e.g. in another issue or in a user research repository), you can put a link here.
</details>
validations:
@ -62,7 +48,7 @@ body:
attributes:
label: Problem description
description: |
Please describe your problem as a first-hand experience. Try to focus on the problem. You do not have to find a solution, you can leave this to us.
Please describe your problem as a first-hand experience. Try to focus on the problem. Finding a solution will happen in a next step.
<details><summary>Further instructions</summary>
* Start by explaining what you want to achieve ("I wanted to find an issue to work on").
@ -89,7 +75,7 @@ body:
id: forgejo-ver
attributes:
label: Forgejo Version
description: Forgejo version (or commit reference) your instance is running or that you used to reproduce the bug on Forgejo Next.
description: Forgejo version (or commit reference) your instance is running
- type: textarea
id: versions
attributes:
@ -98,10 +84,3 @@ body:
Please include details to help us understand your problem: browser engine and version (for UI issues), operating system and version running Forgejo, database engine and version, deployment methods and relevant third-party packages (e.g. renderers, identity providers)
validations:
required: true
- type: markdown
attributes:
value: |
### Solutions
*Accepted solutions to address this problem will go here*
visible: [content]

View file

@ -1,5 +1,5 @@
name: "Step 2: Enhancement"
description: "[Advanced users only] Suggest a solution to one or multiple problems that have already been reported (see step 1)."
description: Suggest a solution to one or multiple problems that have already been reported (see step 1).
title: "enh: "
labels: ["enhancement/feature"]
body:
@ -8,28 +8,19 @@ body:
value: |
- Please speak English, as this is the language all maintainers can speak and write.
- Be civil, and follow the [Forgejo Code of Conduct](https://codeberg.org/forgejo/code-of-conduct).
- type: markdown
attributes:
value: |
### New workflow
We are currently experimenting with a new workflow to manage issues and better understand your problems and needs. This is step 2 of the workflow, which is intended for Forgejo contributors: If you just want to raise a problem or need you have, please refer to step 1.
This step allows to document a solution to one or multiple problems. It allows developers to focus on actionable implementation tasks without the clutter of previous discussions or triaging work.
If you want to learn more about the background of our workflow, feel invited to read and participate in [the discussion that led to the current approach](https://codeberg.org/forgejo/discussions/issues/415). We are looking forward to your feedback.
- We are currently experimenting with a new workflow to understand your problems and requests. This is step 2 of a two-step-process. The goal is to discuss potential solutions to already-reported problems. If you want to learn more about the background of our workflow, feel invited to read and participate in [the discussion that led to the current approach](https://codeberg.org/forgejo/discussions/issues/415). We are looking forward to your feedback.
- type: textarea
id: problems
attributes:
label: Existing problems this enhancement addresses
description: Only list the issue numbers of the **existing** problems that your proposal addresses. **Do not add new descriptions.** If you haven't previously described a problem, please [complete step one of the workflow](https://codeberg.org/forgejo/forgejo/issues/new?template=.forgejo%2fissue_template%2fproblem.yaml) and describe the problem you'd like to solve first.
description: List the issue numbers of the reported problems that this enhancement addresses. If you haven't previously described a problem, please [complete step one of the workflow](https://codeberg.org/forgejo/forgejo/issues/new?template=.forgejo%2fissue_template%2fproblem.yaml) and describe the problem you'd like to solve first.
validations:
required: true
- type: textarea
id: description
attributes:
label: Enhancement description
description: Describe the changes you suggest for Forgejo and explain how they address the problems.
description: As concisely as possible, describe the changes you suggest for Forgejo and explain how they address the problems.
validations:
required: true
- type: textarea

View file

@ -1,4 +1,3 @@
blank_issues_enabled: false
contact_links:
- name: 🔓 Security Reports
url: mailto:security@forgejo.org

View file

@ -10,22 +10,13 @@ labels:
## 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).
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)
### Tests
- 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
### 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)).
@ -37,9 +28,6 @@ The [contributor guide](https://forgejo.org/docs/next/contributor/) contains inf
### 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.
- [ ] I do not want this change to show in the release notes.
- [ ] I want the title to show in the release notes with a link to this pull request.
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.

View file

@ -3,7 +3,7 @@ runs:
steps:
- run: |
su forgejo -c 'make deps-backend'
- uses: https://data.forgejo.org/actions/cache@v5
- uses: https://data.forgejo.org/actions/cache@v4
id: cache-backend
with:
path: ${{github.workspace}}/gitea

View file

@ -50,7 +50,7 @@ runs:
- name: "Restore Go dependencies from cache or mark for later caching"
id: cache-deps
uses: https://data.forgejo.org/actions/cache@v5
uses: https://data.forgejo.org/actions/cache@v4
with:
key: setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}-${{ steps.go-version.outputs.go_version }}-${{ hashFiles('go.sum', 'go.mod', 'Makefile') }}
restore-keys: |

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

@ -1,9 +1,6 @@
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
on:
push:
paths:
@ -29,14 +26,14 @@ jobs:
if: vars.ROLE == 'forgejo-coding'
runs-on: lxc-bookworm
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- id: forgejo
uses: https://data.forgejo.org/actions/setup-forgejo@v3.1.11
uses: https://data.forgejo.org/actions/setup-forgejo@v3.1.7
with:
user: root
password: admin1234
image-version: ${{ env.FORGEJO_VERSION }}
image-version: 1.21
lxc-ip-prefix: 10.0.9
- name: publish the forgejo release

View file

@ -33,7 +33,7 @@ jobs:
# root is used for testing, allow it
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
with:
fetch-depth: 0
@ -93,7 +93,7 @@ jobs:
- name: cache node_modules
id: node
uses: https://data.forgejo.org/actions/cache@v5
uses: https://data.forgejo.org/actions/cache@v4
with:
path: |
node_modules
@ -227,14 +227,11 @@ jobs:
curl -sS -X DELETE $url/api/v1/repos/forgejo-experimental/forgejo/releases/tags/$tag > /dev/null
curl -sS -X DELETE $url/api/v1/repos/forgejo-experimental/forgejo/tags/$tag > /dev/null
fi
# actions/checkout@v6 sets http.https://codeberg.org/.extraheader with the automatic token. Get rid of it so
# it does not prevent using the token that has write permissions. As of @v6, it is stored in
# $RUNNER_TEMP/git-credentials-(uuid).config and included in the repo via
# includeif.gitdir:...=$RUNNER_TEMP/git-credentials-(uuid).config. Since we don't need these credentials
# anymore we can just remove the generated config file.
rm -f $RUNNER_TEMP/git-credentials-*
# actions/checkout@v3 sets http.https://codeberg.org/.extraheader with the automatic token.
# Get rid of it so it does not prevent using the token that has write permissions
git config --local --unset http.https://codeberg.org/.extraheader
if test -f .git/shallow ; then
echo "unexpected .git/shallow file is present"
echo "unexptected .git/shallow file is present"
echo "it suggests a checkout --depth X was used which may prevent pushing the commit"
echo "it happens when actions/checkout is called without depth: 0"
fi

View file

@ -37,7 +37,7 @@ jobs:
container:
image: data.forgejo.org/oci/node:24-bookworm
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
with:
fetch-depth: '0'
show-progress: 'false'

View file

@ -61,7 +61,7 @@ jobs:
image: registry.redict.io/redict:7.3.6-scratch
options: --tmpfs /data:noatime
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
with:
repository: ${{ inputs.repository }}
ref: ${{ inputs.ref }}
@ -83,7 +83,7 @@ jobs:
TEST_MINIO_ENDPOINT: minio:9000
TEST_LDAP: 1
TEST_REDIS_SERVER: cacher:6379
- uses: https://data.forgejo.org/forgejo/upload-artifact@v5
- uses: https://code.forgejo.org/forgejo/upload-artifact@v4
with:
name: coverage
path: ${{ forge.workspace }}/coverage/merged

View file

@ -41,7 +41,7 @@ jobs:
runs-on: lxc-bookworm
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- name: copy & sign
uses: https://data.forgejo.org/forgejo/forgejo-build-publish/publish@v5.6.0

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.4.1 # renovate: datasource=gitea-releases depName=forgejo/release-notes-assistant registryUrl=https://code.forgejo.org
jobs:
release-notes:
@ -15,9 +15,9 @@ jobs:
container:
image: 'data.forgejo.org/oci/ci:1'
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: https://data.forgejo.org/actions/cache@v5
- uses: https://data.forgejo.org/actions/cache@v4
with:
key: rna-${{ env.RNA_VERSION }}
path: ${{ env.RNA_WORKDIR }}

View file

@ -8,16 +8,16 @@ 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.4.1 # renovate: datasource=gitea-releases depName=forgejo/release-notes-assistant registryUrl=https://code.forgejo.org
jobs:
release-notes:
if: ( vars.ROLE == 'forgejo-coding' ) && contains(github.event.pull_request.labels.*.name, 'worth a release-note')
runs-on: docker
container:
image: 'data.forgejo.org/oci/ci:1'
image: 'data.forgejo.org/oci/node:24-bookworm'
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- name: event
run: |
@ -28,12 +28,17 @@ jobs:
${{ toJSON(github.event) }}
EOF
- name: install release-notes-assistant
- uses: https://data.forgejo.org/actions/setup-go@v6
with:
go-version-file: "go.mod"
cache: false
- name: apt install jq
run: |
set -x
wget -O /usr/local/bin/rna https://code.forgejo.org/forgejo/release-notes-assistant/releases/download/${{ env.RNA_VERSION}}/release-notes-assistant
chmod +x /usr/local/bin/rna
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get -q install -y -qq jq
- name: release-notes-assistant preview
run: |
rna --config .release-notes-assistant.yaml --storage pr --storage-location ${{ github.event.pull_request.number }} --forgejo-url $GITHUB_SERVER_URL --repository $GITHUB_REPOSITORY --token ${{ secrets.RELEASE_NOTES_ASSISTANT_TOKEN }} preview ${{ github.event.pull_request.number }}
go run code.forgejo.org/forgejo/release-notes-assistant@$RNA_VERSION --config .release-notes-assistant.yaml --storage pr --storage-location ${{ github.event.pull_request.number }} --forgejo-url $GITHUB_SERVER_URL --repository $GITHUB_REPOSITORY --token ${{ secrets.RELEASE_NOTES_ASSISTANT_TOKEN }} preview ${{ github.event.pull_request.number }}

View file

@ -0,0 +1,79 @@
#
# Runs every 2 hours, but Renovate is limited to create new PR before 4am.
# See renovate.json for more settings.
# Automerge is enabled for Renovate PR's but need to be approved before.
#
name: renovate
on:
push:
branches:
- renovate/** # self-test updates
paths:
- .forgejo/workflows/renovate.yml
schedule:
- cron: '0 0/2 * * *'
workflow_dispatch:
env:
RENOVATE_DRY_RUN: ${{ (github.event_name != 'schedule' && github.ref_name != github.event.repository.default_branch) && 'full' || '' }}
RENOVATE_REPOSITORIES: ${{ github.repository }}
# fix because 10.0.0-58-7e1df53+gitea-1.22.0 < 10.0.0 for semver
# and codeberg api returns such versions from `git describe --tags`
# RENOVATE_X_PLATFORM_VERSION: 10.0.0+gitea-1.22.0 currently not needed
jobs:
renovate:
if: vars.ROLE == 'forgejo-coding' && secrets.RENOVATE_TOKEN != ''
runs-on: docker
container:
image: data.forgejo.org/renovate/renovate:42.39.2
steps:
- name: Load renovate repo cache
uses: https://data.forgejo.org/actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
with:
path: |
.tmp/cache/renovate/repository
.tmp/cache/renovate/renovate-cache-sqlite
.tmp/osv
key: repo-cache-${{ github.run_id }}
restore-keys: |
repo-cache-
- name: Run renovate
run: renovate
env:
GITHUB_COM_TOKEN: ${{ secrets.RENOVATE_GITHUB_COM_TOKEN }}
LOG_LEVEL: debug
RENOVATE_BASE_DIR: ${{ github.workspace }}/.tmp
RENOVATE_ENDPOINT: ${{ github.server_url }}
RENOVATE_PLATFORM: forgejo
RENOVATE_REPOSITORY_CACHE: 'enabled'
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
RENOVATE_GIT_AUTHOR: 'Renovate Bot <forgejo-renovate-action@forgejo.org>'
RENOVATE_CONFIG_FILE_NAMES: '[".forgejo/renovate.json"]'
RENOVATE_X_SQLITE_PACKAGE_CACHE: true
GIT_AUTHOR_NAME: 'Renovate Bot'
GIT_AUTHOR_EMAIL: 'forgejo-renovate-action@forgejo.org'
GIT_COMMITTER_NAME: 'Renovate Bot'
GIT_COMMITTER_EMAIL: 'forgejo-renovate-action@forgejo.org'
OSV_OFFLINE_ROOT_DIR: ${{ github.workspace }}/.tmp/osv
# use direct connection for these domains for renovate go datasource instead of the go proxy
# allows faster lookups
GONOPROXY: code.forgejo.org
- name: Save renovate repo cache
if: always() && env.RENOVATE_DRY_RUN != 'full'
uses: https://data.forgejo.org/actions/cache/save@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
with:
path: |
.tmp/cache/renovate/repository
.tmp/cache/renovate/renovate-cache-sqlite
.tmp/osv
key: repo-cache-${{ github.run_id }}

View file

@ -34,7 +34,7 @@ jobs:
image: 'data.forgejo.org/oci/node:24-trixie'
options: --tmpfs /tmp:exec,noatime
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
- name: install git 2.34.1 and git-lfs 3.0.2
uses: ./.forgejo/workflows-composite/install-minimum-git-version
@ -53,7 +53,7 @@ jobs:
image: 'data.forgejo.org/oci/node:24-trixie'
options: --tmpfs /tmp:exec,noatime
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
- name: install git 2.34.1 and git-lfs 3.0.2
uses: ./.forgejo/workflows-composite/install-minimum-git-version
@ -85,7 +85,7 @@ jobs:
MARIADB_DATABASE: testgitea
options: --tmpfs /var/lib/mysql:noatime
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
- name: install dependencies
run: apt-get update -qq && apt-get -q install -qq -y git-lfs

View file

@ -22,12 +22,10 @@ jobs:
cat <<'EOF'
${{ toJSON(github) }}
EOF
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
# DO NOT add checks here, but rather in the makefile
- run: su forgejo -c './tools/cimake.sh pr-go'
# this will re-run the backend target also contained in pr-go, but
# a re-build is insignificant
- run: su forgejo -c 'make deps-backend deps-tools'
- run: su forgejo -c 'make --always-make -j$(nproc) lint-backend tidy-check swagger-check lint-swagger fmt-check swagger-validate' # ensure the "go-licenses" make target runs
- uses: ./.forgejo/workflows-composite/build-backend
frontend-checks:
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
@ -36,17 +34,14 @@ jobs:
image: 'data.forgejo.org/oci/node:24-trixie'
options: --tmpfs /tmp:exec,noatime
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: https://data.forgejo.org/actions/setup-node@v6
with:
node-version-file: .node-version
- run: make deps-frontend
- run: make lint-frontend
- run: make checks-frontend
- name: make test-frontend-coverage
run: |
- run: |
# Usage of `dayjs` can be impacted by local system timezone and can be sensitive to DST differences; since
# frontend tests are very short they're run twice with varying DST rules to reduce regression risk.
TZ=Europe/Berlin make test-frontend-coverage
@ -58,8 +53,8 @@ jobs:
run: |
apt-get update -qq
apt-get -q install -qq -y zstd
- name: 'Cache frontend build for playwright testing'
uses: https://data.forgejo.org/actions/cache/save@v5
- name: "Cache frontend build for playwright testing"
uses: https://data.forgejo.org/actions/cache/save@v4
with:
path: ${{github.workspace}}/public/assets
key: frontend-build-${{ github.sha }}
@ -76,7 +71,7 @@ jobs:
options: --tmpfs /bitnami/elasticsearch/data
env:
discovery.type: single-node
ES_JAVA_OPTS: '-Xms512m -Xmx512m'
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
minio:
image: data.forgejo.org/oci/bitnami/minio:2024.8.17
options: >-
@ -86,7 +81,7 @@ jobs:
MINIO_ROOT_USER: 123456
MINIO_ROOT_PASSWORD: 12345678
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
- name: test release-notes-assistant.sh
run: |
@ -109,17 +104,17 @@ jobs:
image: 'data.forgejo.org/oci/playwright:latest'
options: --tmpfs /tmp:exec,noatime
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
with:
fetch-depth: 20
- uses: ./.forgejo/workflows-composite/setup-env
- name: 'Restore frontend build'
uses: https://data.forgejo.org/actions/cache/restore@v5
- name: "Restore frontend build"
uses: https://data.forgejo.org/actions/cache/restore@v4
id: cache-frontend
with:
path: ${{github.workspace}}/public/assets
key: frontend-build-${{ github.sha }}
- name: 'Build frontend (if not cached)'
- name: "Build frontend (if not cached)"
if: steps.cache-frontend.outputs.cache-hit != 'true'
run: |
su forgejo -c 'make deps-frontend frontend'
@ -144,7 +139,7 @@ jobs:
RUN_ALL: ${{steps.run-all.all}}
- name: Upload test artifacts on failure
if: failure()
uses: https://data.forgejo.org/forgejo/upload-artifact@v5
uses: https://data.forgejo.org/forgejo/upload-artifact@v4
with:
name: test-artifacts.zip
path: tests/e2e/test-artifacts/
@ -177,9 +172,9 @@ jobs:
image: ${{ matrix.cacher.image }}
options: ${{ matrix.cacher.options }}
env:
ALLOW_EMPTY_PASSWORD: 'yes' # redis & valkey will immediately shutdown with no defined password unless overridden
ALLOW_EMPTY_PASSWORD: "yes" # redis & valkey will immediately shutdown with no defined password unless overridden
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
- uses: ./.forgejo/workflows-composite/build-backend
- run: |
@ -208,7 +203,7 @@ jobs:
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000 --disable-log-bin
options: --tmpfs /bitnami/mysql/data:noatime
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
- name: install dependencies
run: apt-get update -qq && apt-get -q install -qq -y git-lfs
@ -246,7 +241,7 @@ jobs:
POSTGRESQL_EXTRA_FLAGS: -c full_page_writes=off
options: --tmpfs /bitnami/postgresql
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
- name: install dependencies
run: apt-get update -qq && apt-get -q install -qq -y git-lfs
@ -268,7 +263,7 @@ jobs:
image: 'data.forgejo.org/oci/node:24-trixie'
options: --tmpfs /tmp:exec,noatime
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
- name: install dependencies
run: apt-get update -qq && apt-get -q install -qq -y git-lfs
@ -296,20 +291,7 @@ jobs:
image: 'data.forgejo.org/oci/node:24-trixie'
options: --tmpfs /tmp:exec,noatime
steps:
- uses: https://data.forgejo.org/actions/checkout@v6
- uses: https://data.forgejo.org/actions/checkout@v5
- uses: ./.forgejo/workflows-composite/setup-env
- run: su forgejo -c 'make deps-backend deps-tools'
- run: su forgejo -c 'make security-check'
semgrep:
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
name: semgrep/ci
runs-on: docker
container:
image: 'data.forgejo.org/oci/semgrep:latest'
steps:
- run: apk add nodejs # required for actions/checkout
- uses: https://data.forgejo.org/actions/checkout@v6
- name: self-check semgrep rules
run: semgrep --test .semgrep/tests/ --config .semgrep/config/
- name: semgrep ci
run: semgrep ci --config .semgrep/config/ --metrics=off

1
.gitignore vendored
View file

@ -107,7 +107,6 @@ cpu.out
/.air
/.go-licenses
/.cur-deadcode-out
/.deadcode.diff
# Files and folders that were previously generated
/public/assets/img/webpack

View file

@ -15,7 +15,6 @@ linters:
- govet
- importas
- ineffassign
- modernize
- nakedret
- nolintlint
- revive
@ -26,7 +25,6 @@ linters:
- unused
- usetesting
- wastedassign
- nilnil
settings:
depguard:
rules:
@ -46,25 +44,6 @@ linters:
desc: use forgejo.org/modules/git instead, see https://codeberg.org/forgejo/forgejo/pulls/4941
- pkg: gopkg.in/yaml.v3
desc: use go.yaml.in/yaml instead, see https://codeberg.org/forgejo/forgejo/pulls/8956
migration-isolation:
list-mode: lax
files:
- "**/models/forgejo_migrations/**"
deny:
- pkg: "forgejo.org/models"
desc: >
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.
- pkg: "forgejo.org/services"
desc: >
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.
allow:
- "forgejo.org/models/db"
- "forgejo.org/models/gitea_migrations/base"
- "forgejo.org/models/gitea_migrations/test"
gocritic:
disabled-checks:
- ifElseChain
@ -134,8 +113,6 @@ linters:
disable:
- error-is-as
- go-require
nilnil:
only-two: false
exclusions:
generated: lax
presets:
@ -186,215 +163,6 @@ linters:
- linters:
- staticcheck
text: "(ST1005|ST1003|QF1001):"
# TODO: eventually remove this section entirely
- path: cmd/admin_auth_ldap_test.go
linters:
- nilnil
- path: cmd/admin_auth_oauth_test.go
linters:
- nilnil
- path: cmd/admin_auth_pam_test.go
linters:
- nilnil
- path: cmd/cmd.go
linters:
- nilnil
- path: cmd/forgejo/actions.go
linters:
- nilnil
- path: models/actions/run.go
linters:
- nilnil
- path: models/actions/task.go
linters:
- nilnil
- path: models/activities/action_list.go
linters:
- nilnil
- path: models/asymkey/gpg_key_object_verification.go
linters:
- nilnil
- path: models/auth/oauth2.go
linters:
- nilnil
- path: models/db/collation.go
linters:
- nilnil
- path: models/dbfs/dbfile.go
linters:
- nilnil
- path: models/forgejo_migrations_legacy/v32.go
linters:
- nilnil
- path: models/forgejo_migrations_legacy/v32_test.go
linters:
- nilnil
- path: models/db/context.go
linters:
- nilnil
- path: models/git/branch_list.go
linters:
- nilnil
- path: models/git/lfs_lock.go
linters:
- nilnil
- path: models/git/protected_branch.go
linters:
- nilnil
- path: models/git/protected_tag.go
linters:
- nilnil
- path: models/issues/issue.go
linters:
- nilnil
- path: models/issues/issue_xref.go
linters:
- nilnil
- path: models/issues/review.go
linters:
- nilnil
- path: models/organization/org_user.go
linters:
- nilnil
- path: models/quota/rule.go
linters:
- nilnil
- path: models/repo/archiver.go
linters:
- nilnil
- path: models/repo/fork.go
linters:
- nilnil
- path: models/repo/topic.go
linters:
- nilnil
- path: models/user/email_address.go
linters:
- nilnil
- path: models/user/list.go
linters:
- nilnil
- path: models/user/user.go
linters:
- nilnil
- path: models/repo/repo.go
linters:
- nilnil
- path: modules/git/commit.go
linters:
- nilnil
- path: modules/git/foreachref/parser.go
linters:
- nilnil
- path: modules/git/last_commit_cache.go
linters:
- nilnil
- path: modules/git/log_name_status.go
linters:
- nilnil
- path: modules/graceful/net_unix.go
linters:
- nilnil
- path: modules/indexer/internal/bleve/util.go
linters:
- nilnil
- path: modules/indexer/issues/util.go
linters:
- nilnil
- path: modules/optional/serialization.go
linters:
- nilnil
- path: modules/setting/storage.go
linters:
- nilnil
- path: routers/api/packages/chef/auth.go
linters:
- nilnil
- path: routers/api/packages/container/auth.go
linters:
- nilnil
- path: routers/api/packages/nuget/auth.go
linters:
- nilnil
- path: routers/api/packages/swift/swift.go
linters:
- nilnil
- path: routers/web/auth/oauth.go
linters:
- nilnil
- path: routers/web/repo/compare.go
linters:
- nilnil
- path: routers/web/repo/release.go
linters:
- nilnil
- path: routers/web/repo/setting/runners.go
linters:
- nilnil
- path: routers/web/repo/setting/secrets.go
linters:
- nilnil
- path: routers/web/repo/setting/variables.go
linters:
- nilnil
- path: services/actions/context.go
linters:
- nilnil
- path: services/actions/task.go
linters:
- nilnil
- path: services/actions/trust.go
linters:
- nilnil
- path: services/contexttest/context_tests.go
linters:
- nilnil
- path: services/gitdiff/csv.go
linters:
- nilnil
- path: services/issue/assignee.go
linters:
- nilnil
- path: routers/api/packages/conan/auth.go
linters:
- nilnil
- path: services/issue/commit.go
linters:
- nilnil
- path: services/issue/issue.go
linters:
- nilnil
- path: services/migrations/onedev.go
linters:
- nilnil
- path: services/packages/cargo/index.go
linters:
- nilnil
- path: services/pull/check.go
linters:
- nilnil
- path: services/pull/comment.go
linters:
- nilnil
- path: services/pull/merge.go
linters:
- nilnil
- path: services/pull/review.go
linters:
- nilnil
- path: services/remote/promote.go
linters:
- nilnil
- path: services/repository/archiver/archiver.go
linters:
- nilnil
- path: services/repository/generate_repo_commit.go
linters:
- nilnil
- path: services/repository/repository.go
linters:
- nilnil
paths:
- node_modules
- public

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.12.0

View file

@ -7,8 +7,7 @@ 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'
- 'v7.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,111 +0,0 @@
rules:
- id: forgejo-api-use-resource-SearchRepoOptions
patterns:
- pattern: |
repo_model.SearchRepoOptions{...}
- pattern-not: |
repo_model.SearchRepoOptions{
...,
AuthorizationReducer: ctx.Reducer,
...
}
languages:
- go
message: >
SearchRepoOptions does not take into account fine-grained access token limitations. Include the
AuthorizationReducer field.
severity: ERROR
paths:
include:
- "/routers/api/**/*.go"
- id: forgejo-api-use-resource-SearchRepoOptions
patterns:
- pattern: |
organization.SearchTeamRepoOptions{...}
- pattern-not: |
organization.SearchTeamRepoOptions{
...,
AuthorizationReducer: ctx.Reducer,
...
}
languages:
- go
message: >
SearchTeamRepoOptions does not take into account fine-grained access token limitations. Include the
AuthorizationReducer field.
severity: ERROR
paths:
include:
- "/routers/api/**/*.go"
- id: forgejo-api-use-resource-GetUserRepoPermission
patterns:
- pattern: |
$X.GetUserRepoPermission($CTX, $REPO, $DOER)
- metavariable-type:
metavariable: $CTX
types:
- "*context.APIContext"
languages:
- go
message: >
GetUserRepoPermission does not take into account fine-grained access token limitations. Use
GetUserRepoPermissionWithReducer.
fix: |
$X.GetUserRepoPermissionWithReducer($CTX, $REPO, $DOER, $CTX.Reducer)
severity: ERROR
- id: forgejo-api-suspicious-GetUserRepoPermission
patterns:
- pattern: $X.GetUserRepoPermission($CTX, $REPO, $DOER)
- pattern-not: # don't match if identical to forgejo-api-use-resource-GetUserRepoPermission
patterns:
- pattern: |
$X.GetUserRepoPermission($CTX, $REPO, $DOER)
- metavariable-type:
metavariable: $CTX
types:
- "*context.APIContext"
languages:
- go
message: >
API code is accessing GetUserRepoPermission which does not take into account fine-grained access token
limitations. Should this use GetUserRepoPermissionWithReducer?
severity: ERROR
paths:
include:
- "/routers/api/**/*.go"
- id: forgejo-api-direct-IsAdmin-check
patterns:
- pattern: |
ctx.Doer.IsAdmin
languages:
- go
message: |
ctx.Doer.IsAdmin does not take into account limited API access tokens. Use ctx.IsUserSiteAdmin() instead.
fix: |
ctx.IsUserSiteAdmin()
severity: ERROR
paths:
include:
- "/routers/api/**/*.go"
- id: forgejo-api-direct-repo-Admin-check
patterns:
- pattern: |
ctx.Repo.IsAdmin()
- pattern: |
ctx.Repo.IsOwner()
languages:
- go
message: |
ctx.Repo.IsAdmin/IsOwner() does not take into account limited API access tokens. Use ctx.IsUserRepoAdmin() instead.
fix: |
ctx.IsUserRepoAdmin()
severity: ERROR
paths:
include:
- "/routers/api/**/*.go"

View file

@ -1,18 +0,0 @@
rules:
- id: forgejo-switch-empty-case
pattern-either:
- pattern: |-
switch $_ {
case $_:
}
- patterns:
- pattern: |-
switch {
case $_:
}
languages:
- go
severity: ERROR
message: >
switch has a case block with no content. This is treated as "break" by Go, but developers may confuse it for
"fallthrough". To fix this error, disambiguate by using "break" or "fallthrough".

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,24 +0,0 @@
rules:
- id: xorm-sync-missing-ignore-drop-indices
patterns:
- pattern-either:
- pattern: |
$X.Sync(...)
- pattern: |
$X.SyncWithOptions($OPTS, ...)
- pattern-not: |
$X.SyncWithOptions(xorm.SyncOptions{..., IgnoreDropIndices: true, ...}, ...)
- metavariable-type:
metavariable: $X
types:
- "*xorm.Engine"
- "*xorm.Session"
paths:
exclude:
- /models/gitea_migrations/**/*.go
- /models/forgejo_migrations_legacy/**/*.go
languages:
- go
message: |
xorm Sync operation may drop indices if used on an incomplete bean definition for an existing table. Use SyncWithOptions with IgnoreDropIndices: true instead.
severity: ERROR

View file

@ -1,58 +0,0 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2020 The Gitea Authors.
// SPDX-License-Identifier: MIT
package repo
import (
"net/http"
"forgejo.org/models/db"
access_model "forgejo.org/models/perm/access"
repo_model "forgejo.org/models/repo"
api "forgejo.org/modules/structs"
"forgejo.org/routers/api/v1/utils"
"forgejo.org/services/context"
"forgejo.org/services/convert"
)
// ListForks list a repository's forks
func ListForks(ctx *context.APIContext) {
forks, total, err := repo_model.GetForks(ctx, ctx.Repo.Repository, ctx.Doer, utils.GetListOptions(ctx))
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetForks", err)
return
}
apiForks := make([]*api.Repository, len(forks))
for i, fork := range forks {
// ruleid:forgejo-api-use-resource-GetUserRepoPermission
permission, err := access_model.GetUserRepoPermissionWithReducer(ctx, fork, ctx.Doer, ctx.Reducer)
// ok:forgejo-api-use-resource-GetUserRepoPermission
permission, err := access_model.GetUserRepoPermissionWithReducer(ctx, fork, ctx.Doer, ctx.Reducer)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
return
}
apiForks[i] = convert.ToRepo(ctx, fork, permission)
}
}
// getStarredRepos returns the repos that the user with the specified userID has
// starred
func getStarredRepos(ctx std_context.Context, user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, error) {
starredRepos, err := repo_model.GetStarredRepos(ctx, user.ID, private, listOptions)
if err != nil {
return nil, err
}
repos := make([]*api.Repository, len(starredRepos))
for i, starred := range starredRepos {
// ruleid:forgejo-api-suspicious-GetUserRepoPermission
permission, err := access_model.GetUserRepoPermission(ctx, starred, user)
if err != nil {
return nil, err
}
repos[i] = convert.ToRepo(ctx, starred, permission)
}
return repos, nil
}

View file

@ -1,58 +0,0 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2020 The Gitea Authors.
// SPDX-License-Identifier: MIT
package repo
import (
"net/http"
"forgejo.org/models/db"
access_model "forgejo.org/models/perm/access"
repo_model "forgejo.org/models/repo"
api "forgejo.org/modules/structs"
"forgejo.org/routers/api/v1/utils"
"forgejo.org/services/context"
"forgejo.org/services/convert"
)
// ListForks list a repository's forks
func ListForks(ctx *context.APIContext) {
forks, total, err := repo_model.GetForks(ctx, ctx.Repo.Repository, ctx.Doer, utils.GetListOptions(ctx))
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetForks", err)
return
}
apiForks := make([]*api.Repository, len(forks))
for i, fork := range forks {
// ruleid:forgejo-api-use-resource-GetUserRepoPermission
permission, err := access_model.GetUserRepoPermission(ctx, fork, ctx.Doer)
// ok:forgejo-api-use-resource-GetUserRepoPermission
permission, err := access_model.GetUserRepoPermissionWithReducer(ctx, fork, ctx.Doer, ctx.Reducer)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
return
}
apiForks[i] = convert.ToRepo(ctx, fork, permission)
}
}
// getStarredRepos returns the repos that the user with the specified userID has
// starred
func getStarredRepos(ctx std_context.Context, user *user_model.User, private bool, listOptions db.ListOptions) ([]*api.Repository, error) {
starredRepos, err := repo_model.GetStarredRepos(ctx, user.ID, private, listOptions)
if err != nil {
return nil, err
}
repos := make([]*api.Repository, len(starredRepos))
for i, starred := range starredRepos {
// ruleid:forgejo-api-suspicious-GetUserRepoPermission
permission, err := access_model.GetUserRepoPermission(ctx, starred, user)
if err != nil {
return nil, err
}
repos[i] = convert.ToRepo(ctx, starred, permission)
}
return repos, nil
}

View file

@ -1,44 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"os"
"os/signal"
"strings"
"syscall"
_ "net/http/pprof" // Used for debugging if enabled and a web server is running
"forgejo.org/modules/setting"
)
func setPortEmptyCaseBad(port string) error {
setting.AppURL = strings.Replace(setting.AppURL, setting.HTTPPort, port, 1)
setting.HTTPPort = port
// ruleid:forgejo-switch-empty-case
switch setting.Protocol {
case setting.HTTPUnix:
case setting.FCGI:
case setting.FCGIUnix:
default:
defaultLocalURL := string(setting.Protocol) + "://"
}
// ok:forgejo-switch-empty-case
switch setting.Protocol {
case setting.HTTPUnix:
break
case setting.FCGI:
break
case setting.FCGIUnix:
break
default:
defaultLocalURL := string(setting.Protocol) + "://"
}
return nil
}

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

@ -1,45 +0,0 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package forgejo_migrations
import (
"io/fs"
"forgejo.org/modules/timeutil"
"xorm.io/xorm"
)
type ActionUser struct {
ID int64 `xorm:"pk autoincr"`
UserID int64 `xorm:"INDEX UNIQUE(action_user_index) REFERENCES(user, id)"`
RepoID int64 `xorm:"INDEX UNIQUE(action_user_index) REFERENCES(repository, id)"`
TrustedWithPullRequests bool
LastAccess timeutil.TimeStamp `xorm:"INDEX"`
}
func testSyncBad1(x *xorm.Engine) error {
// ruleid:xorm-sync-missing-ignore-drop-indices
return x.Sync(new(ActionUser))
}
func testSyncBad2(x *xorm.Engine) error {
// ruleid:xorm-sync-missing-ignore-drop-indices
_, err = x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: false}, bean)
return err
}
func testSyncGood1(x *xorm.Engine) error {
// ok:xorm-sync-missing-ignore-drop-indices
_, err = x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, bean)
return err
}
func testSyncGood2(x *fs.File) error {
// ok:xorm-sync-missing-ignore-drop-indices
_, err = x.Sync()
return err
}

View file

@ -51,12 +51,3 @@ modules/structs/.* @Cyborus
routers/api/v1/.* @Cyborus
routers/api/forgejo/.* @Cyborus
tests/integration/api_.* @Cyborus
# Federation code, requires care to be taken with regards to interoperability
# and backwards compatibility due to the way signatures work.
services/federation/.* @famfo @0xllx0
modules/forgefed/.* @famfo @0xllx0
models/forgefed/.* @famfo @0xllx0
routers/api/v1/activitypub/.* @famfo @0xllx0
tests/integration/api_activitypub_.* @famfo @0xllx0
tests/integration/activitypub_.* @famfo @0xllx0

View file

@ -1,6 +1,6 @@
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/xx AS xx
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.26-alpine3.23 AS build-env
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.25-alpine3.23 AS build-env
ARG GOPROXY
ENV GOPROXY=${GOPROXY:-https://proxy.golang.org,direct}

View file

@ -1,6 +1,6 @@
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/xx AS xx
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.26-alpine3.23 AS build-env
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.25-alpine3.23 AS build-env
ARG GOPROXY
ENV GOPROXY=${GOPROXY:-https://proxy.golang.org,direct}
@ -86,8 +86,8 @@ RUN addgroup \
-G git \
git
RUN mkdir -p /var/lib/gitea
RUN chown git:git /var/lib/gitea
RUN mkdir -p /var/lib/gitea /etc/gitea
RUN chown git:git /var/lib/gitea /etc/gitea
COPY --from=build-env /tmp/local /
RUN cd /usr/local/bin ; ln -s gitea forgejo
@ -103,9 +103,13 @@ ENV GITEA_CUSTOM=/var/lib/gitea/custom
ENV GITEA_TEMP=/tmp/gitea
ENV TMPDIR=/tmp/gitea
# Legacy config file for backwards compatibility
# TODO: remove on next major version release
ENV GITEA_APP_INI_LEGACY=/etc/gitea/app.ini
ENV GITEA_APP_INI=${GITEA_CUSTOM}/conf/app.ini
ENV HOME="/var/lib/gitea/git"
VOLUME ["/var/lib/gitea"]
VOLUME ["/var/lib/gitea", "/etc/gitea"]
WORKDIR /var/lib/gitea
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]

View file

@ -37,18 +37,17 @@ endif
XGO_VERSION := go-1.21.x
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.6.1 # renovate: datasource=go
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.6.0 # renovate: datasource=go
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.9.2 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.4 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6.2 # renovate: datasource=go
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.15 # renovate: datasource=go
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.33.2 # renovate: datasource=go
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.33.1 # renovate: datasource=go
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses/v2@v2.0.1 # renovate: datasource=go
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # 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
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
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.39.0 # renovate: datasource=go
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.6.0 # renovate: datasource=go
RENOVATE_NPM_PACKAGE ?= renovate@42.39.2 # 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 +244,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"
@ -323,7 +322,7 @@ git-check:
node-check:
$(eval MIN_NODE_VERSION_STR := $(shell grep -Eo '"node":.*[0-9.]+"' package.json | sed -n 's/.*[^0-9.]\([0-9.]*\)"/\1/p'))
$(eval MIN_NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell echo '$(MIN_NODE_VERSION_STR)' | tr '.' ' ')))
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | cut -c2- | sed 's:-.*::' | tr '.' ' ');))
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | cut -c2- | tr '.' ' ');))
$(eval NPM_MISSING := $(shell hash npm > /dev/null 2>&1 || echo 1))
@if [ "$(NODE_VERSION)" -lt "$(MIN_NODE_VERSION)" -o "$(NPM_MISSING)" = "1" ]; then \
echo "Forgejo requires Node.js $(MIN_NODE_VERSION_STR) or greater and npm to build. You can get it at https://nodejs.org/en/download/"; \
@ -466,7 +465,7 @@ lint-swagger: node_modules
.PHONY: lint-renovate
lint-renovate: node_modules
npx --yes --package $(RENOVATE_NPM_PACKAGE) -- renovate-config-validator --no-global .forgejo/renovate.json > .lint-renovate 2>&1 || true
npx --yes --package $(RENOVATE_NPM_PACKAGE) -- renovate-config-validator > .lint-renovate 2>&1 || true
@if grep --quiet --extended-regexp -e '^( ERROR:)' .lint-renovate ; then cat .lint-renovate ; rm .lint-renovate ; exit 1 ; fi
@rm .lint-renovate
@ -486,23 +485,10 @@ RUN_DEADCODE = $(GO) run $(DEADCODE_PACKAGE) -generated=false -f='{{println .Pat
.PHONY: lint-go
lint-go:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS) \
|| (code=$$?; echo "Please run 'make lint-go-fix' and commit the result"; exit $${code})
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS)
$(RUN_DEADCODE) > .cur-deadcode-out
@$(DIFF) .deadcode-out .cur-deadcode-out >.deadcode.diff || true
@if grep -qE '^[+][^+]' .deadcode.diff ; then \
cat .deadcode.diff ; \
echo "Looks like you added dead code, please evaluate and remove or use it."; \
echo "If you are sure the dead code should stay around, please run 'make lint-go-fix',"; \
echo "commit the result and explain the reason in the commit message / PR description."; \
exit 1; \
fi
@if grep -qE '^[-][^-]' .deadcode.diff ; then \
cat .deadcode.diff ; \
echo "Looks like you removed dead code. Thank you!"; \
echo "Run 'make lint-go-fix' and commit the result to accept."; \
fi
$(GO) run $(ERRORTYPE_PACKAGE) ./...
@$(DIFF) .deadcode-out .cur-deadcode-out \
|| (code=$$?; echo "Please run 'make lint-go-fix' and commit the result"; exit $${code})
.PHONY: lint-go-fix
lint-go-fix:
@ -534,11 +520,6 @@ security-check:
tsc: node_modules
npx tsc --noEmit
# target for PRs to be pushed. Mandatory to succeed in CI
.PHONY: pr-go
pr-go: deps-backend deps-tools lint-backend tidy-check swagger-check lint-swagger fmt-check swagger-validate
TAGS=bindata $(MAKE) backend
###
# Development and testing targets
###
@ -562,12 +543,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 +573,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,13 +949,16 @@ deps-tools:
$(GO) install $(XGO_PACKAGE)
$(GO) install $(GO_LICENSES_PACKAGE)
$(GO) install $(GOVULNCHECK_PACKAGE)
$(GO) install $(ERRORTYPE_PACKAGE)
$(GO) install $(MOCKERY_PACKAGE)
$(GO) install $(GOMOCK_PACKAGE)
node_modules: package-lock.json
npm install --no-save
@touch node_modules
.venv: poetry.lock
poetry install
@touch .venv
.PHONY: fomantic
fomantic:
rm -rf $(FOMANTIC_WORK_DIR)/build
@ -1024,9 +1008,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,39 @@ translation_meta.test
# this also gets instantiated as a Messenger once
repo.migrate.migrating_failed.error
# models/asymkey/gpg_key_object_verification.go: $ObjectVerification.Reason
# unfortunately, it is non-trivial to parse all the occurences
gpg.error.extract_sign
gpg.error.failed_retrieval_gpg_keys
gpg.error.generate_hash
gpg.error.no_committer_account
# 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

@ -15,7 +15,6 @@ import (
"strings"
llu "forgejo.org/build/lint-locale-usage"
lluAsymKey "forgejo.org/models/asymkey/lint-locale-usage"
lluUnit "forgejo.org/models/unit/lint-locale-usage"
lluMigrate "forgejo.org/services/migrations/lint-locale-usage"
)
@ -37,172 +36,142 @@ 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)
}
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
@ -361,7 +302,7 @@ func main() {
if name == "docker" || name == ".git" || name == "node_modules" {
return fs.SkipDir
}
} else if name == "bindata.go" || fpath == "modules/translation/i18n/i18n_test.go" || fpath == "modules/translation/i18n/i18n_ini_test.go" {
} else if name == "bindata.go" || fpath == "modules/translation/i18n/i18n_test.go" {
// skip false positives
} else if strings.HasSuffix(name, ".go") {
onError(HandleGoFile(handler, fpath, nil))

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

@ -60,13 +60,9 @@ func (handler Handler) handleTemplateNode(fset *token.FileSet, node tmplParser.N
case tmplParser.NodeField:
nodeField := nodeCommand.Args[0].(*tmplParser.FieldNode)
if len(nodeField.Ident) != 2 || nodeField.Ident[0] != "locale" {
if len(nodeField.Ident) != 2 || !(nodeField.Ident[0] == "locale" || nodeField.Ident[0] == "Locale") {
return
}
resolvedPos := fset.PositionFor(token.Pos(nodeCommand.Pos), false)
if !strings.Contains(resolvedPos.Filename, "templates/mail/") {
handler.OnWarning(fset, token.Pos(nodeCommand.Pos), "encountered unexpected .locale usage")
}
funcname = nodeField.Ident[1]
case tmplParser.NodeVariable:
@ -150,12 +146,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

@ -205,15 +205,7 @@ func runCreateUser(ctx context.Context, c *cli.Command) error {
// create the access token
if accessTokenScope != "" {
t := &auth_model.AccessToken{
Name: accessTokenName,
UID: u.ID,
Scope: accessTokenScope,
// maintain legacy behaviour until new CLI options are added -- token has access to all resources, is not
// fine-grained
ResourceAllRepos: true,
}
t := &auth_model.AccessToken{Name: accessTokenName, UID: u.ID, Scope: accessTokenScope}
if err := auth_model.NewAccessToken(ctx, t); err != nil {
return err
}

View file

@ -86,10 +86,6 @@ func runGenerateAccessToken(ctx context.Context, c *cli.Command) error {
}
t.Scope = accessTokenScope
// maintain legacy behaviour until new CLI options are added -- token has access to all resources, is not
// fine-grained
t.ResourceAllRepos = true
// create the token
if err := auth_model.NewAccessToken(ctx, t); err != nil {
return err

View file

@ -1,270 +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"),
UI: auth_model.AuthorizedIntegrationUIGeneric,
}
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

@ -150,8 +150,8 @@ func runCert(ctx context.Context, c *cli.Command) error {
BasicConstraintsValid: true,
}
hosts := strings.SplitSeq(c.String("host"), ",")
for h := range hosts {
hosts := strings.Split(c.String("host"), ",")
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {

View file

@ -1,5 +1,4 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
// Package cmd provides subcommands to the gitea binary - such as "web" or
@ -90,9 +89,26 @@ If this is the intended configuration file complete the [database] section.`, se
return nil
}
// installSignals returns a context that's cancelled on the SIGINT and SIGTERM signals or if the passed ctx is cancelled.
func installSignals(ctx context.Context) (context.Context, context.CancelFunc) {
return signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
ctx, cancel := context.WithCancel(ctx)
go func() {
// install notify
signalChannel := make(chan os.Signal, 1)
signal.Notify(
signalChannel,
syscall.SIGINT,
syscall.SIGTERM,
)
select {
case <-signalChannel:
case <-ctx.Done():
}
cancel()
signal.Reset()
}()
return ctx, cancel
}
func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) {

View file

@ -1,39 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cmd
import (
"context"
"fmt"
"runtime"
"syscall"
"testing"
"time"
)
func Test_installSignals(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skipf("Windows does not terminate in an awaitable manner")
return
}
for _, s := range []syscall.Signal{syscall.SIGTERM, syscall.SIGINT} {
t.Run(fmt.Sprintf("Context is terminated on %s", s), func(t *testing.T) {
// Register the signal handler. context.Background() is chosen deliberately,
// because unlike t.Context(), we can be sure that it's not cancelled by a
// different handler.
ctx, cancel := installSignals(context.Background())
t.Cleanup(cancel)
// Send the signal in the background.
go syscall.Kill(syscall.Getpid(), s)
select {
case <-time.Tick(time.Second * 10):
t.Fatalf("Context not cancelled via signal after 10 seconds")
case <-ctx.Done():
t.Logf("Context was cancelled")
}
})
}
}

View file

@ -12,7 +12,6 @@ import (
"os"
"path"
"path/filepath"
"slices"
"strings"
"sync"
"time"
@ -84,9 +83,11 @@ func (o outputType) Join() string {
}
func (o *outputType) Set(value string) error {
if slices.Contains(o.Enum, value) {
o.selected = value
return nil
for _, enum := range o.Enum {
if enum == value {
o.selected = value
return nil
}
}
return fmt.Errorf("allowed values are %s", o.Join())
@ -112,10 +113,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":
@ -252,8 +250,8 @@ func runDump(stdCtx context.Context, ctx *cli.Command) error {
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
} else {
for _, suffix := range outputTypeEnum.Enum {
if before, ok := strings.CutSuffix(fileName, "."+suffix); ok {
fileName = before
if strings.HasSuffix(fileName, "."+suffix) {
fileName = strings.TrimSuffix(fileName, "."+suffix)
break
}
}
@ -332,12 +330,14 @@ func runDump(stdCtx context.Context, ctx *cli.Command) error {
go dumpDatabase(ctx, archiveJobs, &wg, verbose)
if len(setting.CustomConf) > 0 {
wg.Go(func() {
wg.Add(1)
go func() {
defer wg.Done()
log.Info("Adding custom configuration file from %s", setting.CustomConf)
if err := addFile(archiveJobs, "app.ini", setting.CustomConf, verbose); err != nil {
fatal("Failed to include specified app.ini: %v", err)
}
})
}()
}
if ctx.IsSet("skip-custom-dir") && ctx.Bool("skip-custom-dir") {
@ -361,13 +361,15 @@ func runDump(stdCtx context.Context, ctx *cli.Command) error {
if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") {
log.Info("Skipping attachment data")
} else {
wg.Go(func() {
wg.Add(1)
go func() {
defer wg.Done()
if err := storage.Attachments.IterateObjects("", func(objPath string, object storage.Object) error {
return addObject(archiveJobs, object, path.Join("data", "attachments", objPath), verbose)
}); err != nil {
fatal("Failed to dump attachments: %v", err)
}
})
}()
}
if ctx.IsSet("skip-package-data") && ctx.Bool("skip-package-data") {
@ -375,13 +377,15 @@ func runDump(stdCtx context.Context, ctx *cli.Command) error {
} else if !setting.Packages.Enabled {
log.Info("Package registry not enabled - skipping")
} else {
wg.Go(func() {
wg.Add(1)
go func() {
defer wg.Done()
if err := storage.Packages.IterateObjects("", func(objPath string, object storage.Object) error {
return addObject(archiveJobs, object, path.Join("data", "packages", objPath), verbose)
}); err != nil {
fatal("Failed to dump packages: %v", err)
}
})
}()
}
// Doesn't check if LogRootPath exists before processing --skip-log intentionally,
@ -395,11 +399,13 @@ func runDump(stdCtx context.Context, ctx *cli.Command) error {
log.Error("Failed to check if %s exists: %v", setting.Log.RootPath, err)
}
if isExist {
wg.Go(func() {
wg.Add(1)
go func() {
defer wg.Done()
if err := addRecursiveExclude(archiveJobs, "log", setting.Log.RootPath, []string{absFileName}, verbose); err != nil {
fatal("Failed to include log: %v", err)
}
})
}()
}
}

View file

@ -143,8 +143,8 @@ func runDumpRepository(stdCtx context.Context, ctx *cli.Command) error {
opts.PullRequests = true
opts.ReleaseAssets = true
} else {
units := strings.SplitSeq(ctx.String("units"), ",")
for unit := range units {
units := strings.Split(ctx.String("units"), ",")
for _, unit := range units {
switch strings.ToLower(strings.TrimSpace(unit)) {
case "":
continue

View file

@ -102,11 +102,6 @@ func SubcmdActionsRegister(ctx context.Context) *cli.Command {
Value: "",
Usage: "version of the runner (not required since v1.21)",
},
&cli.BoolFlag{
Name: "ephemeral",
Value: false,
Usage: "instruct Forgejo to permanently unregister this runner after it has run one job",
},
},
}
}
@ -177,7 +172,6 @@ func RunRegister(ctx context.Context, cli *cli.Command) error {
scope := cli.String("scope")
name := cli.String("name")
version := cli.String("version")
ephemeral := cli.Bool("ephemeral")
labels, err := getLabels(cli)
if err != nil {
return err
@ -205,7 +199,7 @@ func RunRegister(ctx context.Context, cli *cli.Command) error {
return err
}
runner, err := actions_model.RegisterRunner(ctx, owner, repo, secret, labels, name, version, ephemeral)
runner, err := actions_model.RegisterRunner(ctx, owner, repo, secret, labels, name, version)
if err != nil {
return fmt.Errorf("error while registering runner: %v", err)
}

View file

@ -24,6 +24,7 @@ import (
)
func CmdF3(ctx context.Context) *cli.Command {
ctx = f3_logger.ContextSetLogger(ctx, util.NewF3Logger(nil, log.GetLogger(log.DEFAULT)))
return &cli.Command{
Name: "f3",
Usage: "F3",
@ -37,9 +38,7 @@ func SubcmdF3Mirror(ctx context.Context) *cli.Command {
mirrorCmd := f3_cmd.CreateCmdMirror()
mirrorCmd.Before = prepareWorkPathAndCustomConf(ctx)
f3Action := mirrorCmd.Action
mirrorCmd.Action = func(ctx context.Context, cli *cli.Command) error {
return runMirror(ctx, cli, f3Action)
}
mirrorCmd.Action = func(ctx context.Context, cli *cli.Command) error { return runMirror(ctx, cli, f3Action) }
return mirrorCmd
}
@ -68,8 +67,6 @@ func runMirror(ctx context.Context, c *cli.Command, action cli.ActionFunc) error
if err := models.Init(ctx); err != nil {
return err
}
ctx = f3_logger.ContextSetLogger(ctx, util.NewF3Logger(nil, log.GetLogger(log.DEFAULT)))
}
err := action(ctx, c)

View file

@ -126,9 +126,7 @@ func installSignals(ctx context.Context) (context.Context, context.CancelFunc) {
)
select {
case <-signalChannel:
break
case <-ctx.Done():
break
}
cancel()
signal.Reset()

View file

@ -568,7 +568,7 @@ Forgejo or set your environment appropriately.`, "")
hookOptions.RefFullNames = make([]git.RefName, 0, hookBatchSize)
for {
// note: pktLineTypeUnknown means pktLineTypeFlush and pktLineTypeData all allowed
// note: pktLineTypeUnknow means pktLineTypeFlush and pktLineTypeData all allowed
rs, err = readPktLine(ctx, reader, pktLineTypeUnknown)
if err != nil {
return err

View file

@ -24,10 +24,10 @@ func runSendMail(ctx context.Context, c *cli.Command) error {
}
subject := c.String("title")
confirmSkipped := c.Bool("force")
confirmSkiped := c.Bool("force")
body := c.String("content")
if !confirmSkipped {
if !confirmSkiped {
if len(body) == 0 {
fmt.Print("warning: Content is empty")
}

View file

@ -80,6 +80,7 @@ func appGlobalFlags() []cli.Flag {
func prepareSubcommandWithConfig(command *cli.Command, globalFlags func() []cli.Flag) {
command.Flags = append(globalFlags(), command.Flags...)
command.Action = prepareWorkPathAndCustomConf(command.Action)
command.HideHelp = true
if command.Name != "help" {
command.Commands = append(command.Commands, cmdHelp())
}
@ -198,6 +199,7 @@ func innerNewMainApp(version, versionExtra string, subCmdsStandaloneArgs, subCmd
}
app.Flags = append(app.Flags, cli.VersionFlag)
app.Flags = append(app.Flags, globalFlags()...)
app.HideHelp = true // use our own help action to show helps (with more information like default config)
app.Before = PrepareConsoleLoggerLevel(log.INFO)
for i := range subCmdWithConfig {
prepareSubcommandWithConfig(subCmdWithConfig[i], globalFlags)

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")
@ -114,11 +108,6 @@ func TestCliCmd(t *testing.T) {
cmd: "./gitea test-cmd --config /tmp/app-other.ini",
exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/app-other.ini"),
},
{
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
cmd: "./gitea forgejo-cli --help",
exp: "(subcommand help template)",
},
}
for _, c := range cases {

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")
@ -276,11 +278,8 @@ func setPort(port string) error {
switch setting.Protocol {
case setting.HTTPUnix:
break
case setting.FCGI:
break
case setting.FCGIUnix:
break
default:
defaultLocalURL := string(setting.Protocol) + "://"
if setting.HTTPAddr == "0.0.0.0" {

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 =
;;
@ -420,8 +417,8 @@ DB_TYPE = sqlite3
;; Database connection max idle time, 0 prevents closing due to idle time.
;CONN_MAX_IDLETIME = 0
;;
;; Database maximum number of open connections. Ensure you only increase the value if your database server is configured to handle the amount of open connections accordingly.
;MAX_OPEN_CONNS = 30
;; Database maximum number of open connections, default is 100 which is the lowest default from Postgres (MariaDB + MySQL default to 151). Ensure you only increase the value if you configured your database server accordingly.
;MAX_OPEN_CONNS = 100
;;
;; Whether execute database models migrations automatically
;AUTO_MIGRATION = true
@ -460,7 +457,7 @@ INTERNAL_TOKEN =
;GLOBAL_TWO_FACTOR_REQUIREMENT = none
;;
;; Name of cookie used to store authentication information.
;COOKIE_REMEMBER_NAME = persistent
;COOKIE_REMEMBER_NAME = gitea_incredible
;;
;; Reverse proxy authentication header name of user name, email, and full name
;REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
@ -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
@ -1066,7 +1062,7 @@ LEVEL = Info
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; List of file extensions for which lines should be wrapped in the CodeMirror editor
;; List of file extensions for which lines should be wrapped in the Monaco editor
;; Separate extensions with a comma. To line wrap files without an extension, just put a comma
;LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,.livemd,
@ -1136,6 +1132,9 @@ LEVEL = Info
;; If an squash commit's comment should be populated with the commit messages of the squashed commits
;POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES = false
;;
;; Add co-authored-by and co-committed-by trailers if committer does not match author
;ADD_CO_COMMITTER_TRAILERS = true
;;
;; Retarget child pull requests to the parent pull request branch target on merge of parent pull request. It only works on merged PRs where the head and base branch target the same repo.
;RETARGET_CHILDREN_ON_MERGE = true
@ -1562,17 +1561,15 @@ LEVEL = Info
;DEFAULT_EMAIL_NOTIFICATIONS = enabled
;; Send an email to all admins when a new user signs up to inform the admins about this act. Options: true, false
;SEND_NOTIFICATION_EMAIL_ON_NEW_USER = false
;; Disabled features for users, could be "deletion", "manage_ssh_keys","manage_gpg_keys", "manage_password" more features can be disabled in future
;; Disabled features for users, could be "deletion", "manage_ssh_keys","manage_gpg_keys" more features can be disabled in future
;; - deletion: a user cannot delete their own account
;; - manage_ssh_keys: a user cannot configure ssh keys
;; - manage_gpg_keys: a user cannot configure gpg keys
;; - manage_password: a user cannot configure their password
;USER_DISABLED_FEATURES =
;; Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`, `manage_password`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior.
;; Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior.
;; - deletion: a user cannot delete their own account
;; - manage_ssh_keys: a user cannot configure ssh keys
;; - manage_gpg_keys: a user cannot configure gpg keys
;; - manage_password: a user cannot configure their password
;;EXTERNAL_USER_DISABLE_FEATURES =
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -1899,7 +1896,7 @@ LEVEL = Info
;PROVIDER_CONFIG = data/sessions ; Relative paths will be made absolute against _`AppWorkPath`_.
;;
;; Session cookie name
;COOKIE_NAME = session
;COOKIE_NAME = i_like_gitea
;;
;; If you use session in https only: true or false. If not set, it defaults to `true` if the ROOT_URL is an HTTPS URL.
;COOKIE_SECURE =
@ -2459,15 +2456,6 @@ LEVEL = Info
;; Enable/Disable RSS/Atom feed
;ENABLE_FEED = true
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[pwa]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Enable standalone mode; this allows PWA enabled browsers to "install" the website as an progressive web app,
;; by setting the https://developer.mozilla.org/en-US/docs/Web/Manifest/display property to "standalone".
;STANDALONE = false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[markup]
@ -2555,7 +2543,7 @@ LEVEL = Info
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[f3]
;[F3]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@ -2788,21 +2776,12 @@ LEVEL = Info
;ABANDONED_JOB_TIMEOUT = 24h
;; Strings committers can place inside a commit message or PR title to skip executing the corresponding actions workflow
;SKIP_WORKFLOW_STRINGS = [skip ci],[ci skip],[no ci],[skip actions],[actions skip]
;; Limit on inputs for manual / workflow_dispatch triggers, default is 100
;LIMIT_DISPATCH_INPUTS = 100
;; Limit on inputs for manual / workflow_dispatch triggers, default is 10
;LIMIT_DISPATCH_INPUTS = 10
;; Support queuing workflow jobs, by setting `concurrency.group` & `concurrency.cancel-in-progress: false`, can increase
;; 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.
;; 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
;; Private key file path used to sign ID tokens. The path is relative to APP_DATA_PATH.
;; The file must contain an RSA or ECDSA private key in the PKCS8 format. If no key exists, a key will be created for you.
;ID_TOKEN_SIGNING_PRIVATE_KEY_FILE = actions_id_token/private.pem
;; Lifetime of ID tokens generated by the actions `/idtoken` endpoint in seconds.
;ID_TOKEN_EXPIRATION_TIME = 3600
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -2823,30 +2802,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

View file

@ -13,5 +13,10 @@ fi
if [ $# -gt 0 ]; then
exec "$@"
else
# TODO: remove on next major version release
# Honour legacy config file if existing
if [ -f ${GITEA_APP_INI_LEGACY} ]; then
GITEA_APP_INI=${GITEA_APP_INI_LEGACY}
fi
exec /usr/local/bin/gitea -c ${GITEA_APP_INI} web
fi

View file

@ -11,10 +11,22 @@ mkdir -p ${GITEA_CUSTOM} && chmod 0700 ${GITEA_CUSTOM}
mkdir -p ${GITEA_TEMP} && chmod 0700 ${GITEA_TEMP}
if [ ! -w ${GITEA_TEMP} ]; then echo "${GITEA_TEMP} is not writable"; exit 1; fi
# Prepare config file
# TODO: remove on next major version release
# Honour legacy config file if existing, but inform the user
if [ -f ${GITEA_APP_INI_LEGACY} ] && [ ${GITEA_APP_INI} != ${GITEA_APP_INI_LEGACY} ]; then
GITEA_APP_INI_DEFAULT=/var/lib/gitea/custom/conf/app.ini
echo -e \
"\033[33mWARNING\033[0m: detected configuration file in deprecated default path ${GITEA_APP_INI_LEGACY}." \
"The new default is ${GITEA_APP_INI_DEFAULT}. To remove this warning, choose one of the options:\n" \
"* Move ${GITEA_APP_INI_LEGACY} to ${GITEA_APP_INI_DEFAULT} (or to \$GITEA_APP_INI if you want to override this variable)\n" \
"* Explicitly override GITEA_APP_INI=${GITEA_APP_INI_LEGACY} in the container environment"
GITEA_APP_INI=${GITEA_APP_INI_LEGACY}
fi
#Prepare config file
if [ ! -f ${GITEA_APP_INI} ]; then
# Prepare config file folder
#Prepare config file folder
GITEA_APP_INI_DIR=$(dirname ${GITEA_APP_INI})
mkdir -p ${GITEA_APP_INI_DIR} && chmod 0700 ${GITEA_APP_INI_DIR}
if [ ! -w ${GITEA_APP_INI_DIR} ]; then echo "${GITEA_APP_INI_DIR} is not writable"; exit 1; fi

View file

@ -9,7 +9,7 @@
# And place the original in /usr/lib/gitea with working files in /data/gitea
GITEA="/app/gitea/gitea"
WORK_DIR="/var/lib/gitea"
APP_INI="/var/lib/gitea/custom/conf/app.ini"
APP_INI="/etc/gitea/app.ini"
APP_INI_SET=""
for i in "$@"; do

View file

@ -1145,7 +1145,6 @@ export default tseslint.config(
'playwright/prefer-comparison-matcher': [2],
'playwright/prefer-equality-matcher': [2],
'playwright/prefer-locator': [0],
'playwright/prefer-native-locators': [2],
'playwright/prefer-to-contain': [2],
'playwright/prefer-to-have-length': [2],

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": {

194
go.mod
View file

@ -1,37 +1,37 @@
module forgejo.org
go 1.26.0
go 1.25.0
toolchain go1.26.3
toolchain go1.25.9
require (
code.forgejo.org/f3/gof3/v3 v3.11.15
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20260301104140-add494e31dab
code.forgejo.org/forgejo/actions-proto v0.7.0
code.forgejo.org/f3/gof3/v3 v3.11.1
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251
code.forgejo.org/forgejo/actions-proto v0.6.0
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.6.4
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.2
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/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0
github.com/alecthomas/chroma/v2 v2.23.1
github.com/ProtonMail/go-crypto v1.3.0
github.com/PuerkitoBio/goquery v1.10.3
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
github.com/alecthomas/chroma/v2 v2.20.0
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.6.0
github.com/blevesearch/bleve/v2 v2.5.6
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,77 +41,78 @@ 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/chi/v5 v5.2.4
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.2
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-openapi/spec v0.22.1
github.com/go-sql-driver/mysql v1.9.3
github.com/go-webauthn/webauthn v0.14.0
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-jwt/jwt/v5 v5.3.0
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/go-version v1.7.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/jackc/pgx/v5 v5.9.2
github.com/inbucket/html2text v0.9.0
github.com/jackc/pgx/v5 v5.9.0
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/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/klauspost/compress v1.18.3
github.com/klauspost/cpuid/v2 v2.2.11
github.com/markbates/goth v1.80.0
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-sqlite3 v1.14.34
github.com/meilisearch/meilisearch-go v0.34.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.95
github.com/msteinert/pam/v2 v2.1.0
github.com/niklasfasching/go-org v1.9.1
github.com/olivere/elastic/v7 v7.0.32
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.1
github.com/pquerna/otp v1.5.0
github.com/pquerna/otp v1.4.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.2
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.9.0
github.com/valyala/fastjson v1.6.10
github.com/urfave/cli/v3 v3.5.0
github.com/valyala/fastjson v1.6.7
github.com/yohcop/openid-go v1.0.1
github.com/yuin/goldmark v1.8.2
github.com/yuin/goldmark v1.7.13
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/oauth2 v0.36.0
golang.org/x/crypto v0.49.0
golang.org/x/image v0.39.0
golang.org/x/net v0.52.0
golang.org/x/oauth2 v0.34.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.42.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
mvdan.cc/xurls/v2 v2.6.0
mvdan.cc/xurls/v2 v2.5.0
xorm.io/builder v0.3.13
xorm.io/xorm v1.3.9
)
@ -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.7 // 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,32 +167,35 @@ 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
github.com/go-openapi/swag/conv v0.25.4 // indirect
github.com/go-openapi/swag/jsonname v0.25.4 // indirect
github.com/go-openapi/swag/jsonutils v0.25.4 // indirect
github.com/go-openapi/swag/loading v0.25.4 // indirect
github.com/go-openapi/swag/stringutils v0.25.4 // indirect
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-openapi/jsonpointer v0.22.3 // indirect
github.com/go-openapi/jsonreference v0.21.3 // indirect
github.com/go-openapi/swag/conv v0.25.3 // indirect
github.com/go-openapi/swag/jsonname v0.25.3 // indirect
github.com/go-openapi/swag/jsonutils v0.25.3 // indirect
github.com/go-openapi/swag/loading v0.25.3 // indirect
github.com/go-openapi/swag/stringutils v0.25.3 // indirect
github.com/go-openapi/swag/typeutils v0.25.3 // indirect
github.com/go-openapi/swag/yamlutils v0.25.3 // indirect
github.com/go-webauthn/x v0.1.25 // indirect
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/go-tpm v0.9.8 // indirect
github.com/google/go-tpm v0.9.5 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/securecookie v1.1.2 // indirect
@ -200,21 +204,23 @@ 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/crc64nvme v1.0.2 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minlz v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // 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,27 @@ 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.3.0 // 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/time v0.15.0 // indirect
golang.org/x/tools v0.44.0 // indirect
golang.org/x/mod v0.34.0 // indirect
golang.org/x/time v0.14.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 +273,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.8

402
go.sum
View file

@ -16,12 +16,12 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
code.forgejo.org/f3/gof3/v3 v3.11.15 h1:/EzJWRQUhVVia1EmCWRZHCuW8qdAX1DEXY0M1n0mECc=
code.forgejo.org/f3/gof3/v3 v3.11.15/go.mod h1:k99wl7QiI9LjS3qEd1RXLdcZPE3wZP5gkVhy8/WhzJ4=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20260301104140-add494e31dab h1:g/uf/tNOvCdGL9EuYV9EJQglEH8n572P1ZwH4lBBkjI=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20260301104140-add494e31dab/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
code.forgejo.org/forgejo/actions-proto v0.7.0 h1:0UA8AIOIWEiMLQvBbnZ6GQ9reh6BbM15Ep8x+oeTCY8=
code.forgejo.org/forgejo/actions-proto v0.7.0/go.mod h1:+444hHBs9/qDh5X/AedaTv0Egj3vd/EXP93vg9zFV2E=
code.forgejo.org/f3/gof3/v3 v3.11.1 h1:c0vE8XvqpbXuSv8gzttn96k5T2FQi0u9bYnux46qSAs=
code.forgejo.org/f3/gof3/v3 v3.11.1/go.mod h1:1p2UKrqZiwxKneQF2DKrMnc403YIgR/lfcfvadZtmDs=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
code.forgejo.org/forgejo/actions-proto v0.6.0 h1:dw1Dogk9A4V/yrLVkhe9dSZPsqNAIkI1kCXPSqG3tZA=
code.forgejo.org/forgejo/actions-proto v0.6.0/go.mod h1:+444hHBs9/qDh5X/AedaTv0Egj3vd/EXP93vg9zFV2E=
code.forgejo.org/forgejo/go-rpmutils v1.0.0 h1:RZGGeKt70p/WaIEL97pyT6uiiEIoN8/aLmS5Z6WmX0M=
code.forgejo.org/forgejo/go-rpmutils v1.0.0/go.mod h1:cg+VbgLXfrDPza9T+kBsMb3TVmmzPN4XseT6gDGLSUk=
code.forgejo.org/forgejo/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:RArF5AsF9LH4nEoJxqRxcP5r8hhRfWcId84G82YbqzA=
@ -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.6.4 h1:nhYj2wSj5BVKxcF0bRtMt/A9iGkxHPFJiIui+T/4mrc=
code.forgejo.org/forgejo/runner/v12 v12.6.4/go.mod h1:34ATLtcxtOgjAJiINaJvBoNJiKpL1hGn0kt+gk+zdyk=
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.2 h1:pG+AXre9L9VXJmTaADXkmeEPuRalhmBXyv6tG2Rvjcc=
code.forgejo.org/go-chi/session v1.0.2/go.mod h1:HnEGyBny7WPzCiVLP2vzL5ssma+3gCSl/vLpuVNYrqc=
code.forgejo.org/xorm/xorm v1.3.9-forgejo.8 h1:dsSKm2nus0NhHsqYxeuB3Gldk6TtlusD1CBGV6V1SS0=
code.forgejo.org/xorm/xorm v1.3.9-forgejo.8/go.mod h1:A7sFd3BFmRp20h6drSsCXgQRQdF8Vz8HuCSrzFS3m90=
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=
@ -73,24 +71,24 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
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/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y=
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=
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0/go.mod h1:1HmmMEVsr+0R1QWahSeMJkjSkq6CYAZu1aIbYSpfJ4o=
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2 h1:cSXom2MoKJ9KPPw29RoZtHvUETY4F4n/kXl8m9btnQ0=
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2/go.mod h1:JitQWJ8JuV4Y87l8VsHiiwhb3cgdyn68mX40s7NT6PA=
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY=
github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw=
github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA=
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg=
github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e h1:4dAU9FXIyQktpoUAgOJK3OTFc/xug0PCXYCqU0FgDKI=
github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
@ -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.6 h1:YdixQmOUuZHojQRe8Te7BY2cRirbzpbcpybAFs0m2DI=
github.com/blevesearch/bleve/v2 v2.5.6/go.mod h1:t5WoESS5TDteTdnjhhvpA1BpLYErOBX2IQViTMLK7wo=
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.7 h1:xcgFRa7f/tQXOwApVq7JWgPYSlzyUMmkuYa54tMDuR0=
github.com/blevesearch/zapx/v16 v16.2.7/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,29 +249,28 @@ 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=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
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.2 h1:giOQAtCgBX08kosrX818DCQJTCNtKwoPBGu0qb6nKTY=
github.com/go-enry/go-enry/v2 v2.9.2/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,51 +280,53 @@ 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=
github.com/go-openapi/jsonpointer v0.22.4/go.mod h1:elX9+UgznpFhgBuaMQ7iu4lvvX1nvNsesQ3oxmYTw80=
github.com/go-openapi/jsonreference v0.21.4 h1:24qaE2y9bx/q3uRK/qN+TDwbok1NhbSmGjjySRCHtC8=
github.com/go-openapi/jsonreference v0.21.4/go.mod h1:rIENPTjDbLpzQmQWCj5kKj3ZlmEh+EFVbz3RTUh30/4=
github.com/go-openapi/spec v0.22.3 h1:qRSmj6Smz2rEBxMnLRBMeBWxbbOvuOoElvSvObIgwQc=
github.com/go-openapi/spec v0.22.3/go.mod h1:iIImLODL2loCh3Vnox8TY2YWYJZjMAKYyLH2Mu8lOZs=
github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4=
github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU=
github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI=
github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag=
github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA=
github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM=
github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s=
github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE=
github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8=
github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0=
github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw=
github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE=
github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw=
github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc=
github.com/go-openapi/jsonpointer v0.22.3 h1:dKMwfV4fmt6Ah90zloTbUKWMD+0he+12XYAsPotrkn8=
github.com/go-openapi/jsonpointer v0.22.3/go.mod h1:0lBbqeRsQ5lIanv3LHZBrmRGHLHcQoOXQnf88fHlGWo=
github.com/go-openapi/jsonreference v0.21.3 h1:96Dn+MRPa0nYAR8DR1E03SblB5FJvh7W6krPI0Z7qMc=
github.com/go-openapi/jsonreference v0.21.3/go.mod h1:RqkUP0MrLf37HqxZxrIAtTWW4ZJIK1VzduhXYBEeGc4=
github.com/go-openapi/spec v0.22.1 h1:beZMa5AVQzRspNjvhe5aG1/XyBSMeX1eEOs7dMoXh/k=
github.com/go-openapi/spec v0.22.1/go.mod h1:c7aeIQT175dVowfp7FeCvXXnjN/MrpaONStibD2WtDA=
github.com/go-openapi/swag/conv v0.25.3 h1:PcB18wwfba7MN5BVlBIV+VxvUUeC2kEuCEyJ2/t2X7E=
github.com/go-openapi/swag/conv v0.25.3/go.mod h1:n4Ibfwhn8NJnPXNRhBO5Cqb9ez7alBR40JS4rbASUPU=
github.com/go-openapi/swag/jsonname v0.25.3 h1:U20VKDS74HiPaLV7UZkztpyVOw3JNVsit+w+gTXRj0A=
github.com/go-openapi/swag/jsonname v0.25.3/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag=
github.com/go-openapi/swag/jsonutils v0.25.3 h1:kV7wer79KXUM4Ea4tBdAVTU842Rg6tWstX3QbM4fGdw=
github.com/go-openapi/swag/jsonutils v0.25.3/go.mod h1:ILcKqe4HC1VEZmJx51cVuZQ6MF8QvdfXsQfiaCs0z9o=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.3 h1:/i3E9hBujtXfHy91rjtwJ7Fgv5TuDHgnSrYjhFxwxOw=
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.3/go.mod h1:8kYfCR2rHyOj25HVvxL5Nm8wkfzggddgjZm6RgjT8Ao=
github.com/go-openapi/swag/loading v0.25.3 h1:Nn65Zlzf4854MY6Ft0JdNrtnHh2bdcS/tXckpSnOb2Y=
github.com/go-openapi/swag/loading v0.25.3/go.mod h1:xajJ5P4Ang+cwM5gKFrHBgkEDWfLcsAKepIuzTmOb/c=
github.com/go-openapi/swag/stringutils v0.25.3 h1:nAmWq1fUTWl/XiaEPwALjp/8BPZJun70iDHRNq/sH6w=
github.com/go-openapi/swag/stringutils v0.25.3/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0=
github.com/go-openapi/swag/typeutils v0.25.3 h1:2w4mEEo7DQt3V4veWMZw0yTPQibiL3ri2fdDV4t2TQc=
github.com/go-openapi/swag/typeutils v0.25.3/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE=
github.com/go-openapi/swag/yamlutils v0.25.3 h1:LKTJjCn/W1ZfMec0XDL4Vxh8kyAnv1orH5F2OREDUrg=
github.com/go-openapi/swag/yamlutils v0.25.3/go.mod h1:Y7QN6Wc5DOBXK14/xeo1cQlq0EA0wvLoSv13gDQoCao=
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4=
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.14.0 h1:ZLNPUgPcDlAeoxe+5umWG/tEeCoQIDr7gE2Zx2QnhL0=
github.com/go-webauthn/webauthn v0.14.0/go.mod h1:QZzPFH3LJ48u5uEPAu+8/nWJImoLBWM7iAH/kSVSo6k=
github.com/go-webauthn/x v0.1.25 h1:g/0noooIGcz/yCVqebcFgNnGIgBlJIccS+LYAa+0Z88=
github.com/go-webauthn/x v0.1.25/go.mod h1:ieblaPY1/BVCV0oQTsA/VAo08/TWayQuJuo5Q+XxmTY=
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=
@ -340,8 +340,10 @@ github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7w
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JPCjlxoJd6K8ALZqSDDhk2ymieAZOVaDg0=
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU=
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
@ -367,12 +369,12 @@ 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=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -386,10 +388,8 @@ github.com/google/go-github/v81 v81.0.0 h1:hTLugQRxSLD1Yei18fk4A5eYjOGLUBKAl/VCq
github.com/google/go-github/v81 v81.0.0/go.mod h1:upyjaybucIbBIuxgJS7YLOZGziyvvJ92WX6WEBNE3sM=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/go-tpm-tools v0.3.13-0.20230620182252-4639ecce2aba h1:qJEJcuLzH5KDR0gKc0zcktin6KSAwL7+jWKBYceddTc=
github.com/google/go-tpm-tools v0.3.13-0.20230620182252-4639ecce2aba/go.mod h1:EFYHy8/1y2KfgTAsx7Luu7NGhoxtuVHnNo8jE7FikKc=
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -398,8 +398,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,16 +439,18 @@ 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=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
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/pgx/v5 v5.9.0 h1:T/dI+2TvmI2H8s/KH1/lXIbz1CUFk3gn5oTjr0/mBsE=
github.com/jackc/pgx/v5 v5.9.0/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,14 +477,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.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
github.com/klauspost/compress v1.18.3/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/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM=
github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw=
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/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -497,49 +497,49 @@ 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=
github.com/markbates/going v1.0.3 h1:mY45T5TvW+Xz5A6jY7lf4+NLg9D8+iuStIHyR7M8qsE=
github.com/markbates/going v1.0.3/go.mod h1:fQiT6v6yQar9UD6bd/D4Z5Afbk9J6BBVBtLiyY4gp2o=
github.com/markbates/goth v1.82.0 h1:8j/c34AjBSTNzO7zTsOyP5IYCQCMBTRBHAbBt/PI0bQ=
github.com/markbates/goth v1.82.0/go.mod h1:/DRlcq0pyqkKToyZjsL2KgiA1zbF1HIjE7u2uC79rUk=
github.com/markbates/goth v1.80.0 h1:NnvatczZDzOs1hn9Ug+dVYf2Viwwkp/ZDX5K+GLjan8=
github.com/markbates/goth v1.80.0/go.mod h1:4/GYHo+W6NWisrMPZnq0Yr2Q70UntNLn7KXEFhrIdAY=
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.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk=
github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/meilisearch/meilisearch-go v0.34.0 h1:P+Ohdx4/PCxXaoI5wNi0LMwPkuiNrF/kGIzBrKYS4tw=
github.com/meilisearch/meilisearch-go v0.34.0/go.mod h1:cUVJZ2zMqTvvwIMEEAdsWH+zrHsrLpAw6gm8Lt1MXK0=
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/crc64nvme v1.0.2 h1:6uO1UxGAD+kwqWWp7mBFsi5gAse66C4NXO8cmcVculg=
github.com/minio/crc64nvme v1.0.2/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.95 h1:ywOUPg+PebTMTzn9VDsoFJy32ZuARN9zhB+K3IYEvYU=
github.com/minio/minio-go/v7 v7.0.95/go.mod h1:wOOX3uxS334vImCNRVyIDdXX9OsXDm89ToynKgqUKlo=
github.com/minio/minlz v1.0.1 h1:OUZUzXcib8diiX+JYxyRLIdomyZYzHct6EShOKtQY2A=
github.com/minio/minlz v1.0.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -595,8 +595,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
github.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -606,8 +606,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.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI=
github.com/redis/go-redis/v9 v9.17.2/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,15 +655,16 @@ 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.3.0 h1:ULuf7GPooDaIlbyvgAxBV/FI7ynli6LZ1/nVUNu+0ww=
github.com/tinylib/msgp v1.3.0/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
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.9.0 h1:AV9lIiPv3ukYnxunaCUsHnEozptYmDN2F0+yWqLMn/c=
github.com/urfave/cli/v3 v3.9.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
github.com/urfave/cli/v3 v3.5.0 h1:qCuFMmdayTF3zmjG8TSsoBzrDqszNrklYg2x3g4MSgw=
github.com/urfave/cli/v3 v3.5.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/valyala/fastjson v1.6.7 h1:ZE4tRy0CIkh+qDc5McjatheGX2czdn8slQjomexVpBM=
github.com/valyala/fastjson v1.6.7/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
@ -673,8 +674,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.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
github.com/yuin/goldmark v1.7.13/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 +684,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 +701,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 +722,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.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
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=
@ -733,12 +732,12 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
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 +759,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,15 +791,15 @@ 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.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
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=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -850,8 +849,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.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.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 +860,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.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
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,12 +875,12 @@ 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=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -911,8 +910,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 +972,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 +983,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,16 +993,16 @@ 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.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI=
modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE=
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=
mvdan.cc/xurls/v2 v2.6.0 h1:3NTZpeTxYVWNSokW3MKeyVkz/j7uYXYiMtXRUfmjbgI=
mvdan.cc/xurls/v2 v2.6.0/go.mod h1:bCvEZ1XvdA6wDnxY7jPPjEmigDtvtvPXAD/Exa9IMSk=
modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU=
modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View file

@ -1,36 +0,0 @@
-
id: 100
attempt: 3
runner_id: 12345678
status: 5 # StatusWaiting
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
is_fork_pull_request: false
token_hash: a1
token_salt: eeeeeeee
token_last_eight: eeeeeeee
log_filename: artifact-test2/2f/47.log
log_in_storage: true
log_length: 707
log_size: 90179
log_expired: false
runner_request_key: 0a7e017d-4201-4b34-8cf4-de0f431893a4
-
id: 101
attempt: 3
runner_id: 12345678
status: 5 # StatusWaiting
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
is_fork_pull_request: false
token_hash: a2
token_salt: eeeeeeee
token_last_eight: eeeeeeee
log_filename: artifact-test2/2f/47.log
log_in_storage: true
log_length: 707
log_size: 90179
log_expired: false
runner_request_key: 0a7e017d-4201-4b34-8cf4-de0f431893a4

View file

@ -1,45 +0,0 @@
- id: 719931
uuid: "9e0eb762-cbdf-4725-9c90-4298568a2a77"
name: "runner-1"
version: "dev"
owner_id: 3 # Owned by org3
repo_id: 0
description: "A superb runner"
agent_labels: ["debian", "gpu"]
deleted: 0
- id: 719932
uuid: "b0a0a168-1b08-4365-95dd-e65040ca384d"
name: "runner-2"
version: "11.3.1"
owner_id: 2 # Owned by user2
repo_id: 0
description: "An exclusive runner"
agent_labels: ["docker"]
deleted: 0
- id: 719933
uuid: "974f9caf-ee64-4022-a56b-67b28ea06a0d"
name: "runner-3"
version: "12.2.0"
owner_id: 0
repo_id: 0
description: "A runner for everyone"
agent_labels: ["docker"]
deleted: 0
- id: 719934
uuid: "022650a8-e999-4a3d-afb0-21f75233798b"
name: "runner-4"
version: "12.1.0"
owner_id: 0
repo_id: 32 # owned by org3
description: ""
agent_labels: ["debian"]
deleted: 0
- id: 719935
uuid: "f3031695-87ea-41cf-8d48-21948e83ee17"
name: "runner-5"
version: "12.7.0"
owner_id: 0
repo_id: 36 # owned by user2
description: ""
agent_labels: ["arch"]
deleted: 0

View file

@ -1,36 +0,0 @@
- id: 719931
uuid: "9e0eb762-cbdf-4725-9c90-4298568a2a77"
name: "runner-1"
version: "dev"
owner_id: 3 # Owned by org3
repo_id: 0
description: "A superb runner"
agent_labels: ["debian", "gpu"]
deleted: 0
- id: 719932
uuid: "b0a0a168-1b08-4365-95dd-e65040ca384d"
name: "runner-2"
version: "11.3.1"
owner_id: 2 # Owned by user2
repo_id: 0
description: "An exclusive runner"
agent_labels: ["docker"]
deleted: 0
- id: 719933
uuid: "974f9caf-ee64-4022-a56b-67b28ea06a0d"
name: "runner-3"
version: "12.2.0"
owner_id: 0
repo_id: 0
description: "A runner for everyone"
agent_labels: ["docker"]
deleted: 0
- id: 719934
uuid: "022650a8-e999-4a3d-afb0-21f75233798b"
name: "runner-4"
version: "12.1.0"
owner_id: 0
repo_id: 32
description: ""
agent_labels: ["debian"]
deleted: 0

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

@ -14,7 +14,7 @@ import (
gouuid "github.com/google/uuid"
)
func RegisterRunner(ctx context.Context, ownerID, repoID int64, token string, labels *[]string, name, version string, ephemeral bool) (*ActionRunner, error) {
func RegisterRunner(ctx context.Context, ownerID, repoID int64, token string, labels *[]string, name, version string) (*ActionRunner, error) {
uuid, err := gouuid.FromBytes([]byte(token[:16]))
if err != nil {
return nil, fmt.Errorf("gouuid.FromBytes %v", err)
@ -60,12 +60,11 @@ func RegisterRunner(ctx context.Context, ownerID, repoID int64, token string, la
//
name, _ = util.SplitStringAtByteN(name, 255)
cols := []string{"name", "owner_id", "repo_id", "version", "ephemeral"}
cols := []string{"name", "owner_id", "repo_id", "version"}
runner.Name = name
runner.OwnerID = ownerID
runner.RepoID = repoID
runner.Version = version
runner.Ephemeral = ephemeral
if labels != nil {
runner.AgentLabels = *labels
cols = append(cols, "agent_labels")

View file

@ -22,11 +22,9 @@ func TestActions_RegisterRunner_Token(t *testing.T) {
labels := []string{}
name := "runner"
version := "v1.2.3"
ephemeral := true
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, &labels, name, version, ephemeral)
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, &labels, name, version)
require.NoError(t, err)
assert.Equal(t, name, runner.Name)
assert.True(t, runner.Ephemeral)
assert.Equal(t, 1, subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))), "the token cannot be verified with the same method as routers/api/actions/runner/interceptor.go as of 8228751c55d6a4263f0fec2932ca16181c09c97d")
}
@ -46,7 +44,7 @@ func TestActions_RegisterRunner_TokenUpdate(t *testing.T) {
"the initial token should match the runner's secret",
)
RegisterRunner(db.DefaultContext, before.OwnerID, before.RepoID, newToken, nil, before.Name, before.Version, false)
RegisterRunner(db.DefaultContext, before.OwnerID, before.RepoID, newToken, nil, before.Name, before.Version)
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
@ -68,11 +66,10 @@ func TestActions_RegisterRunner_CreateWithLabels(t *testing.T) {
token := "0123456789012345678901234567890123456789"
name := "runner"
version := "v1.2.3"
ephemeral := true
labels := []string{"woop", "doop"}
labelsCopy := labels // labels may be affected by the tested function so we copy them
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, &labels, name, version, ephemeral)
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, &labels, name, version)
require.NoError(t, err)
// Check that the returned record has been updated, except for the labels
@ -81,7 +78,6 @@ func TestActions_RegisterRunner_CreateWithLabels(t *testing.T) {
assert.Equal(t, name, runner.Name)
assert.Equal(t, version, runner.Version)
assert.Equal(t, labelsCopy, runner.AgentLabels)
assert.Equal(t, ephemeral, runner.Ephemeral)
// Check that whatever is in the DB has been updated, except for the labels
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: runner.ID})
@ -90,7 +86,6 @@ func TestActions_RegisterRunner_CreateWithLabels(t *testing.T) {
assert.Equal(t, name, after.Name)
assert.Equal(t, version, after.Version)
assert.Equal(t, labelsCopy, after.AgentLabels)
assert.Equal(t, ephemeral, after.Ephemeral)
}
func TestActions_RegisterRunner_CreateWithoutLabels(t *testing.T) {
@ -100,9 +95,8 @@ func TestActions_RegisterRunner_CreateWithoutLabels(t *testing.T) {
token := "0123456789012345678901234567890123456789"
name := "runner"
version := "v1.2.3"
ephemeral := true
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, nil, name, version, ephemeral)
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, nil, name, version)
require.NoError(t, err)
// Check that the returned record has been updated, except for the labels
@ -111,7 +105,6 @@ func TestActions_RegisterRunner_CreateWithoutLabels(t *testing.T) {
assert.Equal(t, name, runner.Name)
assert.Equal(t, version, runner.Version)
assert.Equal(t, []string{}, runner.AgentLabels)
assert.Equal(t, ephemeral, runner.Ephemeral)
// Check that whatever is in the DB has been updated, except for the labels
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: runner.ID})
@ -120,7 +113,6 @@ func TestActions_RegisterRunner_CreateWithoutLabels(t *testing.T) {
assert.Equal(t, name, after.Name)
assert.Equal(t, version, after.Version)
assert.Equal(t, []string{}, after.AgentLabels)
assert.Equal(t, ephemeral, after.Ephemeral)
}
func TestActions_RegisterRunner_UpdateWithLabels(t *testing.T) {
@ -133,11 +125,10 @@ func TestActions_RegisterRunner_UpdateWithLabels(t *testing.T) {
newRepoID := int64(1)
newName := "rennur"
newVersion := "v4.5.6"
ephemeral := true
newLabels := []string{"warp", "darp"}
labelsCopy := newLabels // labels may be affected by the tested function so we copy them
runner, err := RegisterRunner(db.DefaultContext, newOwnerID, newRepoID, token, &newLabels, newName, newVersion, ephemeral)
runner, err := RegisterRunner(db.DefaultContext, newOwnerID, newRepoID, token, &newLabels, newName, newVersion)
require.NoError(t, err)
// Check that the returned record has been updated
@ -146,7 +137,6 @@ func TestActions_RegisterRunner_UpdateWithLabels(t *testing.T) {
assert.Equal(t, newName, runner.Name)
assert.Equal(t, newVersion, runner.Version)
assert.Equal(t, labelsCopy, runner.AgentLabels)
assert.Equal(t, ephemeral, runner.Ephemeral)
// Check that whatever is in the DB has been updated
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
@ -155,7 +145,6 @@ func TestActions_RegisterRunner_UpdateWithLabels(t *testing.T) {
assert.Equal(t, newName, after.Name)
assert.Equal(t, newVersion, after.Version)
assert.Equal(t, labelsCopy, after.AgentLabels)
assert.Equal(t, ephemeral, after.Ephemeral)
}
func TestActions_RegisterRunner_UpdateWithoutLabels(t *testing.T) {
@ -168,9 +157,8 @@ func TestActions_RegisterRunner_UpdateWithoutLabels(t *testing.T) {
newRepoID := int64(1)
newName := "rennur"
newVersion := "v4.5.6"
ephemeral := true
runner, err := RegisterRunner(db.DefaultContext, newOwnerID, newRepoID, token, nil, newName, newVersion, ephemeral)
runner, err := RegisterRunner(db.DefaultContext, newOwnerID, newRepoID, token, nil, newName, newVersion)
require.NoError(t, err)
// Check that the returned record has been updated, except for the labels
@ -179,7 +167,6 @@ func TestActions_RegisterRunner_UpdateWithoutLabels(t *testing.T) {
assert.Equal(t, newName, runner.Name)
assert.Equal(t, newVersion, runner.Version)
assert.Equal(t, before.AgentLabels, runner.AgentLabels)
assert.Equal(t, ephemeral, runner.Ephemeral)
// Check that whatever is in the DB has been updated, except for the labels
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
@ -188,5 +175,4 @@ func TestActions_RegisterRunner_UpdateWithoutLabels(t *testing.T) {
assert.Equal(t, newName, after.Name)
assert.Equal(t, newVersion, after.Version)
assert.Equal(t, before.AgentLabels, after.AgentLabels)
assert.Equal(t, ephemeral, after.Ephemeral)
}

View file

@ -26,11 +26,6 @@ const (
ErrorCodeIncompleteRunsOnMissingOutput
ErrorCodeIncompleteRunsOnMissingMatrixDimension
ErrorCodeIncompleteRunsOnUnknownCause
ErrorCodeIncompleteWithMissingJob
ErrorCodeIncompleteWithMissingOutput
ErrorCodeIncompleteWithMissingMatrixDimension
ErrorCodeIncompleteWithUnknownCause
ErrorCodeUnknownJobInNeeds
)
func TranslatePreExecutionError(lang translation.Locale, run *ActionRun) string {
@ -62,16 +57,6 @@ func TranslatePreExecutionError(lang translation.Locale, run *ActionRun) string
return lang.TrString("actions.workflow.incomplete_runson_missing_matrix_dimension", run.PreExecutionErrorDetails...)
case ErrorCodeIncompleteRunsOnUnknownCause:
return lang.TrString("actions.workflow.incomplete_runson_unknown_cause", run.PreExecutionErrorDetails...)
case ErrorCodeIncompleteWithMissingJob:
return lang.TrString("actions.workflow.incomplete_with_missing_job", run.PreExecutionErrorDetails...)
case ErrorCodeIncompleteWithMissingOutput:
return lang.TrString("actions.workflow.incomplete_with_missing_output", run.PreExecutionErrorDetails...)
case ErrorCodeIncompleteWithMissingMatrixDimension:
return lang.TrString("actions.workflow.incomplete_with_missing_matrix_dimension", run.PreExecutionErrorDetails...)
case ErrorCodeIncompleteWithUnknownCause:
return lang.TrString("actions.workflow.incomplete_with_unknown_cause", run.PreExecutionErrorDetails...)
case ErrorCodeUnknownJobInNeeds:
return lang.TrString("actions.workflow.unknown_job_in_needs", run.PreExecutionErrorDetails...)
}
return fmt.Sprintf("<unsupported error: code=%v details=%#v", run.PreExecutionErrorCode, run.PreExecutionErrorDetails)
}

View file

@ -60,7 +60,7 @@ func TestTranslatePreExecutionError(t *testing.T) {
PreExecutionErrorCode: ErrorCodeIncompleteMatrixMissingOutput,
PreExecutionErrorDetails: []any{"blocked_job", "other_job", "some_output"},
},
expected: "Unable to evaluate `strategy.matrix` of job blocked_job: job other_job is missing output some_output.",
expected: "Unable to evaluate `strategy.matrix` of job blocked_job: job other_job does not have an output some_output.",
},
{
name: "ErrorCodeIncompleteMatrixMissingJob",
@ -84,7 +84,7 @@ func TestTranslatePreExecutionError(t *testing.T) {
PreExecutionErrorCode: ErrorCodeIncompleteRunsOnMissingOutput,
PreExecutionErrorDetails: []any{"blocked_job", "other_job", "some_output"},
},
expected: "Unable to evaluate `runs-on` of job blocked_job: job other_job is missing output some_output.",
expected: "Unable to evaluate `runs-on` of job blocked_job: job other_job does not have an output some_output.",
},
{
name: "ErrorCodeIncompleteRunsOnMissingJob",
@ -110,38 +110,6 @@ func TestTranslatePreExecutionError(t *testing.T) {
},
expected: "Unable to evaluate `runs-on` of job blocked_job: unknown error.",
},
{
name: "ErrorCodeIncompleteWithMissingOutput",
run: &ActionRun{
PreExecutionErrorCode: ErrorCodeIncompleteWithMissingOutput,
PreExecutionErrorDetails: []any{"blocked_job", "other_job", "some_output"},
},
expected: "Unable to evaluate `with` of job blocked_job: job other_job is missing output some_output.",
},
{
name: "ErrorCodeIncompleteWithMissingJob",
run: &ActionRun{
PreExecutionErrorCode: ErrorCodeIncompleteWithMissingJob,
PreExecutionErrorDetails: []any{"blocked_job", "other_job", "needs-1, needs-2"},
},
expected: "Unable to evaluate `with` of job blocked_job: job other_job is not in the `needs` list of job blocked_job (needs-1, needs-2).",
},
{
name: "ErrorCodeIncompleteWithMissingMatrixDimension",
run: &ActionRun{
PreExecutionErrorCode: ErrorCodeIncompleteWithMissingMatrixDimension,
PreExecutionErrorDetails: []any{"blocked_job", "platfurm"},
},
expected: "Unable to evaluate `with` of job blocked_job: matrix dimension platfurm does not exist.",
},
{
name: "ErrorCodeIncompleteWithUnknownCause",
run: &ActionRun{
PreExecutionErrorCode: ErrorCodeIncompleteWithUnknownCause,
PreExecutionErrorDetails: []any{"blocked_job"},
},
expected: "Unable to evaluate `with` of job blocked_job: unknown error.",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View file

@ -104,21 +104,6 @@ func (run *ActionRun) Link() string {
return fmt.Sprintf("%s/actions/runs/%d", run.Repo.Link(), run.Index)
}
func (run *ActionRun) CommitLink() string {
if run.Repo == nil {
return ""
}
return fmt.Sprintf("%s/commit/%s", run.Repo.Link(), run.CommitSHA)
}
// WorkflowPath returns the path in the git repo to the workflow file that this run was based on
func (run *ActionRun) WorkflowPath() string {
if run.WorkflowDirectory == "" {
return run.WorkflowID
}
return run.WorkflowDirectory + "/" + run.WorkflowID
}
// RefLink return the url of run's ref
func (run *ActionRun) RefLink() string {
refName := git.RefName(run.Ref)
@ -153,9 +138,7 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error {
if run.TriggerUser == nil {
u, err := user_model.GetPossibleUserByID(ctx, run.TriggerUserID)
if user_model.IsErrUserNotExist(err) {
u = user_model.NewGhostUser()
} else if err != nil {
if err != nil {
return err
}
run.TriggerUser = u
@ -225,65 +208,6 @@ func (run *ActionRun) SetDefaultConcurrencyGroup() {
))
}
func (run *ActionRun) FindOuterWorkflowCall(ctx context.Context, innerCall *ActionRunJob) (*ActionRunJob, error) {
allJobs, err := GetRunJobsByRunID(ctx, run.ID)
if err != nil {
return nil, fmt.Errorf("failure to get run jobs: %w", err)
}
if innerCall.workflowPayloadDecoded == nil || innerCall.workflowPayloadDecoded.Metadata.WorkflowCallParent == "" {
return nil, errors.New("invalid state for FindOuterWorkflowCall")
}
parent := innerCall.workflowPayloadDecoded.Metadata.WorkflowCallParent
for _, job := range allJobs {
if job.ID == innerCall.ID {
continue
}
swf, err := job.DecodeWorkflowPayload()
if err != nil {
return nil, err
}
if swf.Metadata.WorkflowCallID == parent {
return job, nil
}
}
return nil, fmt.Errorf("no workflow call with ID %s found in run %d", parent, run.ID)
}
func (run *ActionRun) IsScheduledRun() bool {
return run.TriggerEvent == "schedule"
}
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 {
return run.PreExecutionErrorCode == 0 && run.PreExecutionError == ""
}
// CanBeRerun indicates whether this ActionRun can be rerun.
func (run *ActionRun) CanBeRerun() bool {
if !run.IsValid() {
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)
}
@ -347,7 +271,7 @@ func UpdateRunApprovalByID(ctx context.Context, id int64, approval ApprovalType,
func GetRunsNotDoneByRepoIDAndPullRequestPosterID(ctx context.Context, repoID, pullRequestPosterID int64) ([]*ActionRun, error) {
var runs []*ActionRun
// performance relies on indexes on repo_id and status
if err := db.GetEngine(ctx).Where("repo_id=? AND pull_request_poster_id=?", repoID, pullRequestPosterID).And(builder.In("status", PendingStatuses())).Find(&runs); err != nil {
if err := db.GetEngine(ctx).Where("repo_id=? AND pull_request_poster_id=?", repoID, pullRequestPosterID).And(builder.In("status", []Status{StatusUnknown, StatusWaiting, StatusRunning, StatusBlocked})).Find(&runs); err != nil {
return nil, err
}
return runs, nil
@ -356,7 +280,7 @@ func GetRunsNotDoneByRepoIDAndPullRequestPosterID(ctx context.Context, repoID, p
func GetRunsNotDoneByRepoIDAndPullRequestID(ctx context.Context, repoID, pullRequestID int64) ([]*ActionRun, error) {
var runs []*ActionRun
// performance relies on indexes on repo_id and status
if err := db.GetEngine(ctx).Where("repo_id=? AND pull_request_id=?", repoID, pullRequestID).And(builder.In("status", PendingStatuses())).Find(&runs); err != nil {
if err := db.GetEngine(ctx).Where("repo_id=? AND pull_request_id=?", repoID, pullRequestID).And(builder.In("status", []Status{StatusUnknown, StatusWaiting, StatusRunning, StatusBlocked})).Find(&runs); err != nil {
return nil, err
}
return runs, nil
@ -366,11 +290,11 @@ func GetRunsNotDoneByRepoIDAndPullRequestID(ctx context.Context, repoID, pullReq
// The title will be cut off at 255 characters if it's longer than 255 characters.
// We don't have to send the ActionRunNowDone notification here because there are no runs that start in a not done status.
func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWorkflow) error {
ctx, committer, err := db.TxContext(ctx)
ctx, commiter, err := db.TxContext(ctx)
if err != nil {
return err
}
defer committer.Close()
defer commiter.Close()
index, err := db.GetNextResourceIndex(ctx, "action_run_index", run.RepoID)
if err != nil {
@ -397,7 +321,7 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
return err
}
return committer.Commit()
return commiter.Commit()
}
// Adds `ActionRunJob` instances from `SingleWorkflows` to an existing ActionRun.
@ -418,7 +342,7 @@ func InsertRunJobs(ctx context.Context, run *ActionRun, jobs []*jobparser.Single
}
payload, _ = v.Marshal()
if len(needs) > 0 || run.NeedApproval || v.IncompleteMatrix || v.IncompleteRunsOn || v.IncompleteWith {
if len(needs) > 0 || run.NeedApproval || v.IncompleteMatrix || v.IncompleteRunsOn {
status = StatusBlocked
} else {
status = StatusWaiting
@ -427,8 +351,7 @@ func InsertRunJobs(ctx context.Context, run *ActionRun, jobs []*jobparser.Single
name, _ = util.SplitStringAtByteN(job.Name, 255)
runsOn = job.RunsOn()
}
runJob := &ActionRunJob{
runJobs = append(runJobs, &ActionRunJob{
RunID: run.ID,
RepoID: run.RepoID,
OwnerID: run.OwnerID,
@ -439,12 +362,8 @@ func InsertRunJobs(ctx context.Context, run *ActionRun, jobs []*jobparser.Single
JobID: id,
Needs: needs,
RunsOn: runsOn,
}
if err := runJob.PrepareNextAttempt(status); err != nil {
return err
}
runJobs = append(runJobs, runJob)
Status: status,
})
}
if len(runJobs) > 0 {
@ -612,11 +531,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

@ -15,7 +15,6 @@ import (
"forgejo.org/modules/util"
"code.forgejo.org/forgejo/runner/v12/act/jobparser"
gouuid "github.com/google/uuid"
"go.yaml.in/yaml/v3"
"xorm.io/builder"
)
@ -31,7 +30,6 @@ type ActionRunJob struct {
IsForkPullRequest bool
Name string `xorm:"VARCHAR(255)"`
Attempt int64
Handle string `xorm:"unique"`
WorkflowPayload []byte
JobID string `xorm:"VARCHAR(255)"` // job id in workflow, not job's id
Needs []string `xorm:"JSON TEXT"`
@ -110,12 +108,6 @@ func (job *ActionRunJob) LoadAttributes(ctx context.Context) error {
return job.Run.LoadAttributes(ctx)
}
// IsRequestedByRunner returns true if this attempt of this ActionRunJob was explicitly requested by the runner or if
// the runner expressed no preference.
func (job *ActionRunJob) IsRequestedByRunner(handle *string) bool {
return handle == nil || job.Handle == *handle
}
func (job *ActionRunJob) ItRunsOn(labels []string) bool {
if len(labels) == 0 || len(job.RunsOn) == 0 {
return false
@ -125,34 +117,6 @@ func (job *ActionRunJob) ItRunsOn(labels []string) bool {
return labelSet.IsSubset(job.RunsOn)
}
func (job *ActionRunJob) PrepareNextAttempt(initialStatus Status) error {
if job.Status != StatusUnknown && !job.Status.IsDone() {
return fmt.Errorf("cannot prepare next attempt because job %d is active: %s", job.ID, job.Status.String())
}
job.Attempt++
job.Started = 0
job.Stopped = 0
job.TaskID = 0
job.Handle = gouuid.New().String()
job.Status = initialStatus
return nil
}
// 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)
}
if !job.Run.IsValid() {
return false, nil
}
return job.Status.IsDone(), nil
}
func GetRunJobByID(ctx context.Context, id int64) (*ActionRunJob, error) {
var job ActionRunJob
has, err := db.GetEngine(ctx).Where("id=?", id).Get(&job)
@ -270,9 +234,7 @@ var AggregateJobStatus = func(jobs []*ActionRunJob) Status {
}
}
// Retrieves the parsed workflow for this specific job. This field is often accessed multiple times in succession, so
// the parsed content is cached in-memory on the `ActionRunJob` instance.
func (job *ActionRunJob) DecodeWorkflowPayload() (*jobparser.SingleWorkflow, error) {
func (job *ActionRunJob) decodeWorkflowPayload() (*jobparser.SingleWorkflow, error) {
if job.workflowPayloadDecoded != nil {
return job.workflowPayloadDecoded, nil
}
@ -296,8 +258,8 @@ func (job *ActionRunJob) ClearCachedWorkflowPayload() {
// Checks whether the target job is an `(incomplete matrix)` job that will be blocked until the matrix is complete, and
// then regenerated and deleted. If it is incomplete, and if the information is available, the specific job and/or
// output that causes it to be incomplete will be returned as well.
func (job *ActionRunJob) HasIncompleteMatrix() (bool, *jobparser.IncompleteNeeds, error) {
jobWorkflow, err := job.DecodeWorkflowPayload()
func (job *ActionRunJob) IsIncompleteMatrix() (bool, *jobparser.IncompleteNeeds, error) {
jobWorkflow, err := job.decodeWorkflowPayload()
if err != nil {
return false, nil, fmt.Errorf("failure decoding workflow payload: %w", err)
}
@ -306,69 +268,10 @@ func (job *ActionRunJob) HasIncompleteMatrix() (bool, *jobparser.IncompleteNeeds
// Checks whether the target job has a `runs-on` field with an expression that requires an input from another job. The
// job will be blocked until the other job is complete, and then regenerated and deleted.
func (job *ActionRunJob) HasIncompleteRunsOn() (bool, *jobparser.IncompleteNeeds, *jobparser.IncompleteMatrix, error) {
jobWorkflow, err := job.DecodeWorkflowPayload()
func (job *ActionRunJob) IsIncompleteRunsOn() (bool, *jobparser.IncompleteNeeds, *jobparser.IncompleteMatrix, error) {
jobWorkflow, err := job.decodeWorkflowPayload()
if err != nil {
return false, nil, nil, fmt.Errorf("failure decoding workflow payload: %w", err)
}
return jobWorkflow.IncompleteRunsOn, jobWorkflow.IncompleteRunsOnNeeds, jobWorkflow.IncompleteRunsOnMatrix, nil
}
// Check whether the target job was generated as a result of expanding a reusable workflow.
func (job *ActionRunJob) IsWorkflowCallInnerJob() (bool, error) {
jobWorkflow, err := job.DecodeWorkflowPayload()
if err != nil {
return false, fmt.Errorf("failure decoding workflow payload: %w", err)
}
return jobWorkflow.Metadata.WorkflowCallParent != "", nil
}
// Check whether this job is a caller of a reusable workflow -- in other words, the real work done in this job is in
// spawned child jobs, not this job.
func (job *ActionRunJob) IsWorkflowCallOuterJob() (bool, error) {
jobWorkflow, err := job.DecodeWorkflowPayload()
if err != nil {
return false, fmt.Errorf("failure decoding workflow payload: %w", err)
}
return jobWorkflow.Metadata.WorkflowCallID != "", nil
}
// Checks whether the target job has a `with` field with an expression that requires an input from another job. The job
// will be blocked until the other job is complete, and then regenerated and deleted.
func (job *ActionRunJob) HasIncompleteWith() (bool, *jobparser.IncompleteNeeds, *jobparser.IncompleteMatrix, error) {
jobWorkflow, err := job.DecodeWorkflowPayload()
if err != nil {
return false, nil, nil, fmt.Errorf("failure decoding workflow payload: %w", err)
}
return jobWorkflow.IncompleteWith, jobWorkflow.IncompleteWithNeeds, jobWorkflow.IncompleteWithMatrix, nil
}
// EnableOpenIDConnect checks whether the job allows for ID token generation.
func (job *ActionRunJob) EnableOpenIDConnect() (bool, error) {
jobWorkflow, err := job.DecodeWorkflowPayload()
if err != nil {
return false, fmt.Errorf("failure decoding workflow payload: %w", err)
}
return jobWorkflow.EnableOpenIDConnect, nil
}
// AllNeedsExist checks whether this ActionRunJob's Needs can theoretically be met by comparing them with the supplied
// list of all job IDs that part of a particular workflow run. Returns the list of unknown job IDs found in Needs
// alongside an indicator whether the check was successful.
func (job *ActionRunJob) AllNeedsExist(allExistingJobIDs container.Set[string]) ([]string, bool) {
unknownJobIDs := []string{}
for _, need := range job.Needs {
if !allExistingJobIDs.Contains(need) {
unknownJobIDs = append(unknownJobIDs, need)
}
}
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

@ -22,14 +22,6 @@ func (jobs ActionJobList) GetRunIDs() []int64 {
})
}
func (jobs ActionJobList) GetJobIDs() container.Set[string] {
jobIDs := container.SetOf[string]()
for _, job := range jobs {
jobIDs.Add(job.JobID)
}
return jobIDs
}
func (jobs ActionJobList) LoadRuns(ctx context.Context, withRepo bool) error {
runIDs := jobs.GetRunIDs()
runs := make(map[int64]*ActionRun, len(runIDs))
@ -63,6 +55,8 @@ type FindRunJobOptions struct {
CommitSHA string
Statuses []Status
UpdatedBefore timeutil.TimeStamp
Events []string // []webhook_module.HookEventType
RunNumber int64
RunNeedsApproval optional.Option[bool]
}
@ -74,7 +68,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 != "" {
@ -86,10 +80,16 @@ func (opts FindRunJobOptions) ToConds() builder.Cond {
if opts.UpdatedBefore > 0 {
cond = cond.And(builder.Lt{"updated": opts.UpdatedBefore})
}
if has, value := opts.RunNeedsApproval.Get(); has {
if len(opts.Events) > 0 {
cond = cond.And(builder.In("event", opts.Events))
}
if opts.RunNumber > 0 {
cond = cond.And(builder.Eq{"`index`": opts.RunNumber})
}
if opts.RunNeedsApproval.Has() {
cond = cond.And(builder.Exists(builder.Select("id").From("action_run", "outer_run").
Where(builder.Eq{
"outer_run.need_approval": value,
"outer_run.need_approval": opts.RunNeedsApproval.Value(),
"outer_run.id": builder.Expr("run_id"),
})))
}

View file

@ -1,21 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package actions
import (
"testing"
"forgejo.org/modules/container"
"github.com/stretchr/testify/assert"
)
func TestActionJobList_GetJobIDs(t *testing.T) {
jobs := ActionJobList{
&ActionRunJob{JobID: "job 1"},
&ActionRunJob{JobID: "job 2"},
}
assert.Equal(t, container.SetOf("job 2", "job 1"), jobs.GetJobIDs())
}

View file

@ -8,8 +8,6 @@ import (
"forgejo.org/models/db"
"forgejo.org/models/unittest"
"forgejo.org/modules/container"
"forgejo.org/modules/timeutil"
"code.forgejo.org/forgejo/runner/v12/act/jobparser"
"github.com/stretchr/testify/assert"
@ -74,7 +72,7 @@ func TestActionRunJob_HTMLURL(t *testing.T) {
}
}
func TestActionRunJob_HasIncompleteMatrix(t *testing.T) {
func TestActionRunJob_IsIncompleteMatrix(t *testing.T) {
tests := []struct {
name string
job ActionRunJob
@ -102,7 +100,7 @@ func TestActionRunJob_HasIncompleteMatrix(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
isIncomplete, needs, err := tt.job.HasIncompleteMatrix()
isIncomplete, needs, err := tt.job.IsIncompleteMatrix()
if tt.errContains != "" {
assert.ErrorContains(t, err, tt.errContains)
} else {
@ -114,7 +112,7 @@ func TestActionRunJob_HasIncompleteMatrix(t *testing.T) {
}
}
func TestActionRunJob_HasIncompleteRunsOn(t *testing.T) {
func TestActionRunJob_IsIncompleteRunsOn(t *testing.T) {
tests := []struct {
name string
job ActionRunJob
@ -149,129 +147,7 @@ func TestActionRunJob_HasIncompleteRunsOn(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
isIncomplete, needs, matrix, err := tt.job.HasIncompleteRunsOn()
if tt.errContains != "" {
assert.ErrorContains(t, err, tt.errContains)
} else {
require.NoError(t, err)
assert.Equal(t, tt.isIncomplete, isIncomplete)
assert.Equal(t, tt.needs, needs)
assert.Equal(t, tt.matrix, matrix)
}
})
}
}
func TestActionRunJob_IsWorkflowCallOuterJob(t *testing.T) {
tests := []struct {
name string
job ActionRunJob
isWorkflowCallOuterJob bool
errContains string
}{
{
name: "normal workflow",
job: ActionRunJob{WorkflowPayload: []byte("name: workflow")},
isWorkflowCallOuterJob: false,
},
{
name: "workflow_call outer job",
job: ActionRunJob{WorkflowPayload: []byte("name: test\njobs:\n job:\n if: false\n__metadata:\n workflow_call_id: b5a9f46f1f2513d7777fde50b169d323a6519e349cc175484c947ac315a209ed\n")},
isWorkflowCallOuterJob: true,
},
{
name: "unparseable workflow",
job: ActionRunJob{WorkflowPayload: []byte("name: []\nincomplete_runs_on: true")},
errContains: "failure unmarshaling WorkflowPayload to SingleWorkflow: yaml: unmarshal errors",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
isWorkflowCallOuterJob, err := tt.job.IsWorkflowCallOuterJob()
if tt.errContains != "" {
assert.ErrorContains(t, err, tt.errContains)
} else {
require.NoError(t, err)
assert.Equal(t, tt.isWorkflowCallOuterJob, isWorkflowCallOuterJob)
}
})
}
}
func TestActionRunJob_IsWorkflowCallInnerJob(t *testing.T) {
tests := []struct {
name string
job ActionRunJob
isWorkflowCallInnerJob bool
errContains string
}{
{
name: "normal workflow",
job: ActionRunJob{WorkflowPayload: []byte("on: [workflow_dispatch]\nname: workflow")},
isWorkflowCallInnerJob: false,
},
{
name: "inner job",
job: ActionRunJob{WorkflowPayload: []byte("on:\n workflow_call:\nname: workflow\n__metadata:\n workflow_call_parent: b5a9f46f1f2513d7777fde50b169d323a6519e349cc175484c947ac315a209ed\n")},
isWorkflowCallInnerJob: true,
},
{
name: "unparseable workflow",
job: ActionRunJob{WorkflowPayload: []byte("name: []\nincomplete_runs_on: true")},
errContains: "failure unmarshaling WorkflowPayload to SingleWorkflow: yaml: unmarshal errors",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
isWorkflowCallInnerJob, err := tt.job.IsWorkflowCallInnerJob()
if tt.errContains != "" {
assert.ErrorContains(t, err, tt.errContains)
} else {
require.NoError(t, err)
assert.Equal(t, tt.isWorkflowCallInnerJob, isWorkflowCallInnerJob)
}
})
}
}
func TestActionRunJob_HasIncompleteWith(t *testing.T) {
tests := []struct {
name string
job ActionRunJob
isIncomplete bool
needs *jobparser.IncompleteNeeds
matrix *jobparser.IncompleteMatrix
errContains string
}{
{
name: "normal workflow",
job: ActionRunJob{WorkflowPayload: []byte("name: workflow")},
isIncomplete: false,
},
{
name: "incomplete_with workflow",
job: ActionRunJob{WorkflowPayload: []byte("name: workflow\nincomplete_with: true\nincomplete_with_needs: { job: abc }")},
needs: &jobparser.IncompleteNeeds{Job: "abc"},
isIncomplete: true,
},
{
name: "incomplete_with workflow",
job: ActionRunJob{WorkflowPayload: []byte("name: workflow\nincomplete_with: true\nincomplete_with_matrix: { dimension: abc }")},
matrix: &jobparser.IncompleteMatrix{Dimension: "abc"},
isIncomplete: true,
},
{
name: "unparseable workflow",
job: ActionRunJob{WorkflowPayload: []byte("name: []\nincomplete_with: true")},
errContains: "failure unmarshaling WorkflowPayload to SingleWorkflow: yaml: unmarshal errors",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
isIncomplete, needs, matrix, err := tt.job.HasIncompleteWith()
isIncomplete, needs, matrix, err := tt.job.IsIncompleteRunsOn()
if tt.errContains != "" {
assert.ErrorContains(t, err, tt.errContains)
} else {
@ -303,202 +179,3 @@ func TestRunHasOtherJobs(t *testing.T) {
require.NoError(t, err)
assert.False(t, has)
}
func TestActionRunJobPrepareNextAttempt(t *testing.T) {
lastHandle := "original-handle"
job := ActionRunJob{ID: 46, Handle: lastHandle}
err := job.PrepareNextAttempt(StatusWaiting)
require.NoError(t, err)
assert.NotEqual(t, lastHandle, job.Handle)
assert.NotEmpty(t, job.Handle)
assert.Equal(t, int64(1), job.Attempt)
assert.Zero(t, job.Started)
assert.Zero(t, job.Stopped)
assert.Zero(t, job.TaskID)
assert.Equal(t, StatusWaiting, job.Status)
lastHandle = job.Handle
job.Started = timeutil.TimeStampNow()
job.Stopped = timeutil.TimeStampNow()
job.TaskID = int64(59)
job.Status = StatusFailure
err = job.PrepareNextAttempt(StatusBlocked)
require.NoError(t, err)
assert.NotEqual(t, lastHandle, job.Handle)
assert.NotEmpty(t, job.Handle)
assert.Equal(t, int64(2), job.Attempt)
assert.Zero(t, job.Started)
assert.Zero(t, job.Stopped)
assert.Zero(t, job.TaskID)
assert.Equal(t, StatusBlocked, job.Status)
lastHandle = job.Handle
// The job hasn't finished yet. Preparing a next attempt should not be possible. It should be left untouched.
err = job.PrepareNextAttempt(StatusWaiting)
require.ErrorContains(t, err, "cannot prepare next attempt because job 46 is active: blocked")
assert.Equal(t, lastHandle, job.Handle)
assert.Equal(t, int64(2), job.Attempt)
assert.Zero(t, job.Started)
assert.Zero(t, job.Stopped)
assert.Zero(t, job.TaskID)
assert.Equal(t, StatusBlocked, job.Status)
}
func TestIsRequestedByRunner(t *testing.T) {
sameHandle := "4a1ca0be-4470-486d-8504-89b4a5ac00cf"
differentHandle := "88423da3-67af-4f2d-9a92-a0db822697e9"
emptyHandle := ""
job := &ActionRunJob{ID: 422, Attempt: 5, Handle: sameHandle}
assert.True(t, job.IsRequestedByRunner(nil))
assert.True(t, job.IsRequestedByRunner(&sameHandle))
assert.False(t, job.IsRequestedByRunner(&differentHandle))
assert.False(t, job.IsRequestedByRunner(&emptyHandle))
// Old jobs that were created before the introduction of Handle do not have one.
emptyHandleJob := &ActionRunJob{ID: 422, Attempt: 5, Handle: ""}
assert.True(t, emptyHandleJob.IsRequestedByRunner(nil))
assert.True(t, emptyHandleJob.IsRequestedByRunner(&emptyHandle))
assert.False(t, emptyHandleJob.IsRequestedByRunner(&differentHandle))
}
func TestAllNeedsExist(t *testing.T) {
testCases := []struct {
name string
job ActionRunJob
existingJobIDs container.Set[string]
expectedUnknownIDs []string
ok bool
}{
{
name: "no needs",
job: ActionRunJob{Needs: nil},
existingJobIDs: container.Set[string]{},
expectedUnknownIDs: []string{},
ok: true,
},
{
name: "empty needs",
job: ActionRunJob{Needs: []string{}},
existingJobIDs: container.Set[string]{},
expectedUnknownIDs: []string{},
ok: true,
},
{
name: "satisfied needs",
job: ActionRunJob{Needs: []string{"job1", "job2"}},
existingJobIDs: container.SetOf("job2", "job1"),
expectedUnknownIDs: []string{},
ok: true,
},
{
name: "unsatisfied needs",
job: ActionRunJob{Needs: []string{"unknown", "job2"}},
existingJobIDs: container.SetOf("job2", "job1"),
expectedUnknownIDs: []string{"unknown"},
ok: false,
},
{
name: "comparison is case-sensitive",
job: ActionRunJob{Needs: []string{"Job1", "job2"}},
existingJobIDs: container.SetOf("job2", "job1"),
expectedUnknownIDs: []string{"Job1"},
ok: false,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
unknownIDs, ok := testCase.job.AllNeedsExist(testCase.existingJobIDs)
assert.Equal(t, testCase.ok, ok)
assert.Equal(t, testCase.expectedUnknownIDs, unknownIDs)
})
}
}
func TestActionRunJob_CanBeRerun(t *testing.T) {
testCases := []struct {
name string
job ActionRunJob
canBeRerun bool
expectedError string
}{
{
name: "job with unknown status",
job: ActionRunJob{Run: &ActionRun{Status: StatusSuccess}, Status: StatusUnknown},
canBeRerun: false,
},
{
name: "successful job",
job: ActionRunJob{Run: &ActionRun{Status: StatusSuccess}, Status: StatusSuccess},
canBeRerun: true,
},
{
name: "failed job",
job: ActionRunJob{Run: &ActionRun{Status: StatusSuccess}, Status: StatusFailure},
canBeRerun: true,
},
{
name: "cancelled job",
job: ActionRunJob{Run: &ActionRun{Status: StatusSuccess}, Status: StatusCancelled},
canBeRerun: true,
},
{
name: "skipped job",
job: ActionRunJob{Run: &ActionRun{Status: StatusSuccess}, Status: StatusSkipped},
canBeRerun: true,
},
{
name: "waiting job",
job: ActionRunJob{Run: &ActionRun{Status: StatusSuccess}, Status: StatusWaiting},
canBeRerun: false,
},
{
name: "blocked job",
job: ActionRunJob{Run: &ActionRun{Status: StatusSuccess}, Status: StatusBlocked},
canBeRerun: false,
},
{
name: "ActionRun is nil",
job: ActionRunJob{ID: 12, Run: nil, Status: StatusSuccess},
expectedError: "cannot load run 0 of job 12",
},
{
name: "with busy run but completed job",
job: ActionRunJob{Run: &ActionRun{Status: StatusRunning}, Status: StatusSuccess},
canBeRerun: true,
},
{
name: "with run that cannot be run",
job: ActionRunJob{
Run: &ActionRun{Status: StatusRunning, PreExecutionErrorCode: ErrorCodeEventDetectionError},
Status: StatusSuccess,
},
canBeRerun: false,
},
}
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)
})
}
}

View file

@ -5,7 +5,6 @@ package actions
import (
"context"
"slices"
"forgejo.org/models/db"
repo_model "forgejo.org/models/repo"
@ -14,8 +13,6 @@ import (
"forgejo.org/modules/translation"
webhook_module "forgejo.org/modules/webhook"
"golang.org/x/text/collate"
"golang.org/x/text/language"
"xorm.io/builder"
)
@ -75,9 +72,6 @@ type FindRunOptions struct {
TriggerEvent webhook_module.HookEventType
Approved bool // not util.OptionalBool, it works only when it's true
Status []Status
Events []string // []webhook_module.HookEventType
RunNumber int64
CommitSHA string
}
func (opts FindRunOptions) ToConds() builder.Cond {
@ -85,7 +79,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 != "" {
@ -106,15 +100,6 @@ func (opts FindRunOptions) ToConds() builder.Cond {
if opts.TriggerEvent != "" {
cond = cond.And(builder.Eq{"trigger_event": opts.TriggerEvent})
}
if len(opts.Events) > 0 {
cond = cond.And(builder.In("event", opts.Events))
}
if opts.RunNumber > 0 {
cond = cond.And(builder.Eq{"`index`": opts.RunNumber})
}
if opts.CommitSHA != "" {
cond = cond.And(builder.Eq{"commit_sha": opts.CommitSHA})
}
return cond
}
@ -130,18 +115,14 @@ type StatusInfo struct {
// GetStatusInfoList returns a slice of StatusInfo
func GetStatusInfoList(ctx context.Context, lang translation.Locale) []StatusInfo {
// same as those in aggregateJobStatus
allStatus := []Status{StatusBlocked, StatusCancelled, StatusFailure, StatusRunning, StatusSkipped, StatusSuccess, StatusWaiting}
statusInfoList := make([]StatusInfo, 0, 7)
allStatus := []Status{StatusSuccess, StatusFailure, StatusWaiting, StatusRunning}
statusInfoList := make([]StatusInfo, 0, 4)
for _, s := range allStatus {
statusInfoList = append(statusInfoList, StatusInfo{
Status: int(s),
DisplayedStatus: s.LocaleString(lang),
})
}
collator := collate.New(language.Und, collate.IgnoreCase)
slices.SortFunc(statusInfoList, func(a, b StatusInfo) int {
return collator.CompareString(a.DisplayedStatus, b.DisplayedStatus)
})
return statusInfoList
}

View file

@ -1,37 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package actions
import (
"testing"
"forgejo.org/models/unittest"
"forgejo.org/modules/translation"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestActionStatusList(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
translation.InitLocales(t.Context())
statusInfoList := GetStatusInfoList(t.Context(), translation.NewLocale("en-US"))
assert.Len(t, statusInfoList, 7)
statuses := []string{"Blocked", "Canceled", "Failure", "Running", "Skipped", "Success", "Waiting"}
statusInts := []int{7, 3, 2, 6, 4, 1, 5}
for i, statusString := range statuses {
assert.Equal(t, statusInfoList[i].Status, statusInts[i])
assert.Equal(t, statusInfoList[i].DisplayedStatus, statusString)
}
statusInfoList = GetStatusInfoList(t.Context(), translation.NewLocale("de-DE"))
assert.Len(t, statusInfoList, 7)
statuses = []string{"Abgebrochen", "Blockiert", "Erfolg", "Fehler", "Laufend", "Übersprungen", "Wartend"}
statusInts = []int{3, 7, 1, 2, 6, 4, 5}
for i, statusString := range statuses {
assert.Equal(t, statusInfoList[i].Status, statusInts[i])
assert.Equal(t, statusInfoList[i].DisplayedStatus, statusString)
}
}

View file

@ -11,14 +11,15 @@ import (
repo_model "forgejo.org/models/repo"
"forgejo.org/models/unittest"
"forgejo.org/modules/cache"
"forgejo.org/modules/setting"
"forgejo.org/modules/test"
"code.forgejo.org/forgejo/runner/v12/act/jobparser"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetRunBefore(t *testing.T) {
}
func TestSetConcurrencyGroup(t *testing.T) {
run := ActionRun{}
run.SetConcurrencyGroup("abc123")
@ -44,135 +45,6 @@ func TestSetDefaultConcurrencyGroup(t *testing.T) {
assert.Equal(t, "refs/heads/main_testing_pull_request__auto", run.ConcurrencyGroup)
}
func TestGetWorkflowPath(t *testing.T) {
run := ActionRun{
WorkflowID: "ci.yml",
WorkflowDirectory: ".some/path/to/workflows",
}
assert.Equal(t, ".some/path/to/workflows/ci.yml", run.WorkflowPath())
}
func TestGetCommitLink(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
run := ActionRun{
Repo: repo,
CommitSHA: "a356d1f1f82945a039cd16d4ce0137bd55284e77",
}
assert.Equal(t, "/sub/user2/repo1/commit/a356d1f1f82945a039cd16d4ce0137bd55284e77", run.CommitLink())
}
func TestIsScheduledRun(t *testing.T) {
scheduledRun := ActionRun{
CommitSHA: "a356d1f1f82945a039cd16d4ce0137bd55284e77",
TriggerEvent: "schedule",
}
pushRun := ActionRun{
CommitSHA: "8f9b5c6ab342eb11d7422deecef7195b18058b90",
TriggerEvent: "push",
}
assert.True(t, scheduledRun.IsScheduledRun())
assert.False(t, pushRun.IsScheduledRun())
}
func TestIsManualRun(t *testing.T) {
manualRunRun := ActionRun{
CommitSHA: "a356d1f1f82945a039cd16d4ce0137bd55284e77",
TriggerEvent: "workflow_dispatch",
}
pushRun := ActionRun{
CommitSHA: "8f9b5c6ab342eb11d7422deecef7195b18058b90",
TriggerEvent: "push",
}
assert.True(t, manualRunRun.IsDispatchedRun())
assert.False(t, pushRun.IsDispatchedRun())
}
func TestActionRun_IsValid(t *testing.T) {
testCases := []struct {
name string
run ActionRun
isValid bool
}{
{
name: "valid run",
run: ActionRun{},
isValid: true,
},
{
name: "with pre-execution error",
run: ActionRun{PreExecutionErrorCode: ErrorCodeIncompleteRunsOnMissingOutput},
isValid: false,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
assert.Equal(t, testCase.isValid, testCase.run.IsValid())
})
}
}
func TestActionRun_CanBeRerun(t *testing.T) {
testCases := []struct {
name string
run ActionRun
canBeRerun bool
}{
{
name: "run with unknown status",
run: ActionRun{Status: StatusUnknown},
canBeRerun: false,
},
{
name: "successful run",
run: ActionRun{Status: StatusSuccess},
canBeRerun: true,
},
{
name: "failed run",
run: ActionRun{Status: StatusFailure},
canBeRerun: true,
},
{
name: "cancelled run",
run: ActionRun{Status: StatusCancelled},
canBeRerun: true,
},
{
name: "skipped run",
run: ActionRun{Status: StatusSkipped},
canBeRerun: true,
},
{
name: "waiting run",
run: ActionRun{Status: StatusWaiting},
canBeRerun: false,
},
{
name: "blocked run",
run: ActionRun{Status: StatusBlocked},
canBeRerun: false,
},
{
name: "with pre-execution error",
run: ActionRun{PreExecutionErrorCode: ErrorCodeIncompleteRunsOnMissingOutput, Status: StatusSuccess},
canBeRerun: false,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
assert.Equal(t, testCase.canBeRerun, testCase.run.CanBeRerun())
})
}
}
func TestRepoNumOpenActions(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
err := cache.Init()
@ -401,109 +273,6 @@ jobs:
assert.Equal(t, StatusBlocked, job.Status)
}
func TestActionRun_FindOuterWorkflowCall(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
pullRequestPosterID := int64(4)
repoID := int64(10)
pullRequestID := int64(2)
run := &ActionRun{
RepoID: repoID,
PullRequestID: pullRequestID,
PullRequestPosterID: pullRequestPosterID,
}
workflowRaw := []byte(`
jobs:
outer-job:
uses: ./.forgejo/workflows/reusable.yml
`)
workflows, err := jobparser.Parse(workflowRaw, false,
jobparser.WithJobOutputs(map[string]map[string]string{}),
jobparser.ExpandLocalReusableWorkflows(func(job *jobparser.Job, path string) ([]byte, error) {
return []byte(`
on:
workflow_call:
jobs:
inner-job-1:
runs-on: debian
steps: []
inner-job-2:
runs-on: debian
steps: []
`), nil
}))
require.NoError(t, err)
require.NoError(t, InsertRun(t.Context(), run, workflows))
jobs, err := db.Find[ActionRunJob](t.Context(), FindRunJobOptions{RunID: run.ID})
require.NoError(t, err)
require.Len(t, jobs, 3)
for _, j := range jobs {
t.Run(j.Name, func(t *testing.T) {
_, err := j.DecodeWorkflowPayload()
require.NoError(t, err)
outer, err := run.FindOuterWorkflowCall(t.Context(), j)
if j.Name == "outer-job" {
require.ErrorContains(t, err, "invalid state for FindOuterWorkflowCall")
} else {
require.NoError(t, err)
require.NotNil(t, outer)
assert.Equal(t, "outer-job", outer.Name)
}
})
}
}
func TestActionRun_IncompleteWith(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
pullRequestPosterID := int64(4)
repoID := int64(10)
pullRequestID := int64(2)
runDoesNotNeedApproval := &ActionRun{
RepoID: repoID,
PullRequestID: pullRequestID,
PullRequestPosterID: pullRequestPosterID,
}
workflowRaw := []byte(`
jobs:
outer-job:
with:
some_input: ${{ needs.other-job.outputs.some-output }}
uses: ./.forgejo/workflows/reusable.yml
`)
workflows, err := jobparser.Parse(workflowRaw, false,
jobparser.WithJobOutputs(map[string]map[string]string{}),
jobparser.ExpandLocalReusableWorkflows(func(job *jobparser.Job, path string) ([]byte, error) {
return []byte(`
on:
workflow_call:
inputs:
some_input:
type: string
jobs:
inner-job:
runs-on: debian
steps: []
`), nil
}))
require.NoError(t, err)
require.True(t, workflows[0].IncompleteWith) // must be set for this test scenario to be valid
require.NoError(t, InsertRun(t.Context(), runDoesNotNeedApproval, workflows))
jobs, err := db.Find[ActionRunJob](t.Context(), FindRunJobOptions{RunID: runDoesNotNeedApproval.ID})
require.NoError(t, err)
require.Len(t, jobs, 1)
job := jobs[0]
// Expect job with an incomplete with to be StatusBlocked:
assert.Equal(t, StatusBlocked, job.Status)
}
func TestComputeRunStatus(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
@ -622,73 +391,3 @@ func TestComputeRunStatus(t *testing.T) {
assert.Contains(t, columns, "stopped")
})
}
func TestInsertRunJobs(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
pullRequestPosterID := int64(4)
repoID := int64(10)
pullRequestID := int64(2)
actionRun := &ActionRun{
RepoID: repoID,
PullRequestID: pullRequestID,
PullRequestPosterID: pullRequestPosterID,
CommitSHA: "1421f75bc5474c69fdb1dc176bcb96d381f935dd",
}
workflowRaw := []byte(`
jobs:
build:
runs-on: fedora
test:
runs-on: debian
steps: []
`)
jobs, err := jobparser.Parse(workflowRaw, false)
require.NoError(t, err)
require.NoError(t, InsertRun(t.Context(), actionRun, jobs))
insertedJobs, err := db.Find[ActionRunJob](t.Context(), FindRunJobOptions{RunID: actionRun.ID})
require.NoError(t, err)
require.Len(t, insertedJobs, 2)
assert.Equal(t, actionRun.ID, insertedJobs[0].RunID)
assert.Equal(t, actionRun.RepoID, insertedJobs[0].RepoID)
assert.Equal(t, actionRun.OwnerID, insertedJobs[0].OwnerID)
assert.Equal(t, actionRun.CommitSHA, insertedJobs[0].CommitSHA)
assert.Equal(t, actionRun.IsForkPullRequest, insertedJobs[0].IsForkPullRequest)
assert.Equal(t, "build", insertedJobs[0].Name)
assert.Equal(t, "build", insertedJobs[0].JobID)
assert.Empty(t, insertedJobs[0].Needs)
assert.Equal(t, []string{"fedora"}, insertedJobs[0].RunsOn)
assert.Equal(t, int64(1), insertedJobs[0].Attempt)
assert.Zero(t, insertedJobs[0].Started)
assert.Zero(t, insertedJobs[0].Stopped)
assert.Zero(t, insertedJobs[0].TaskID)
assert.Equal(t, StatusWaiting, insertedJobs[0].Status)
assert.Equal(t, actionRun.ID, insertedJobs[1].RunID)
assert.Equal(t, actionRun.RepoID, insertedJobs[1].RepoID)
assert.Equal(t, actionRun.OwnerID, insertedJobs[1].OwnerID)
assert.Equal(t, actionRun.CommitSHA, insertedJobs[1].CommitSHA)
assert.Equal(t, actionRun.IsForkPullRequest, insertedJobs[1].IsForkPullRequest)
assert.Equal(t, "test", insertedJobs[1].Name)
assert.Equal(t, "test", insertedJobs[1].JobID)
assert.Empty(t, insertedJobs[1].Needs)
assert.Equal(t, []string{"debian"}, insertedJobs[1].RunsOn)
assert.Equal(t, int64(1), insertedJobs[1].Attempt)
assert.Zero(t, insertedJobs[1].Started)
assert.Zero(t, insertedJobs[1].Stopped)
assert.Zero(t, insertedJobs[1].TaskID)
assert.Equal(t, StatusWaiting, insertedJobs[1].Status)
}
func TestActionRunLoadAttributes(t *testing.T) {
run := &ActionRun{
RepoID: 10,
TriggerUserID: 1000,
}
require.NoError(t, run.LoadAttributes(t.Context()))
assert.Equal(t, "ghost", run.TriggerUser.LowerName)
}

View file

@ -61,8 +61,6 @@ type ActionRunner struct {
// Store labels defined in state file (default: .runner file) of `act_runner`
AgentLabels []string `xorm:"TEXT"`
// Store if this is a runner that only ever get one single job assigned
Ephemeral bool `xorm:"ephemeral NOT NULL DEFAULT false"`
Created timeutil.TimeStamp `xorm:"created"`
Updated timeutil.TimeStamp `xorm:"updated"`
@ -127,18 +125,6 @@ func (r *ActionRunner) IsOnline() bool {
return false
}
func (r *ActionRunner) IsActive() bool {
return r.Status() == runnerv1.RunnerStatus_RUNNER_STATUS_ACTIVE
}
func (r *ActionRunner) IsIdle() bool {
return r.Status() == runnerv1.RunnerStatus_RUNNER_STATUS_IDLE
}
func (r *ActionRunner) IsOffline() bool {
return r.Status() == runnerv1.RunnerStatus_RUNNER_STATUS_OFFLINE
}
// Editable checks if the runner is editable by the user
func (r *ActionRunner) Editable(ownerID, repoID int64) bool {
if ownerID == 0 && repoID == 0 {
@ -152,7 +138,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)
@ -197,12 +182,12 @@ func init() {
type FindRunnerOptions struct {
db.ListOptions
RepoID int64
OwnerID int64 // it will be ignored if RepoID is set
Sort string
Filter string
IsOnline optional.Option[bool]
WithVisible bool // include all runners that are visible to the repository, owner, or instance
RepoID int64
OwnerID int64 // it will be ignored if RepoID is set
Sort string
Filter string
IsOnline optional.Option[bool]
WithAvailable bool // not only runners belong to, but also runners can be used
}
func (opts FindRunnerOptions) ToConds() builder.Cond {
@ -210,27 +195,25 @@ func (opts FindRunnerOptions) ToConds() builder.Cond {
if opts.RepoID > 0 {
c := builder.NewCond().And(builder.Eq{"repo_id": opts.RepoID})
if opts.WithVisible {
if opts.WithAvailable {
c = c.Or(builder.Eq{"owner_id": builder.Select("owner_id").From("repository").Where(builder.Eq{"id": opts.RepoID})})
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 {
if opts.WithAvailable {
c = c.Or(builder.Eq{"repo_id": 0, "owner_id": 0})
}
cond = cond.And(c)
} else if !opts.WithVisible {
cond = cond.And(builder.Eq{"repo_id": 0, "owner_id": 0})
}
if opts.Filter != "" {
cond = cond.And(builder.Like{"name", opts.Filter}).Or(builder.Like{"uuid", opts.Filter})
cond = cond.And(builder.Like{"name", opts.Filter})
}
if has, value := opts.IsOnline.Get(); has {
if value {
if opts.IsOnline.Has() {
if opts.IsOnline.Value() {
cond = cond.And(builder.Gt{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
} else {
cond = cond.And(builder.Lte{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
@ -281,31 +264,6 @@ func GetRunnerByID(ctx context.Context, id int64) (*ActionRunner, error) {
return &runner, nil
}
// GetVisibleRunnerByID is like GetRunnerByID, but it only finds the runner if it is visible to the given owner or
// repository. If it is not, util.ErrNotExist will be returned even if the runner exists.
func GetVisibleRunnerByID(ctx context.Context, id, ownerID, repoID int64) (*ActionRunner, error) {
query := db.GetEngine(ctx).Where("id=?", id)
if repoID > 0 {
cond := builder.NewCond().And(builder.Eq{"repo_id": repoID})
cond = cond.Or(builder.Eq{"owner_id": builder.Select("owner_id").From("repository").Where(builder.Eq{"id": repoID})})
cond = cond.Or(builder.Eq{"repo_id": 0, "owner_id": 0})
query = query.And(cond)
} else if ownerID > 0 { // ownerID is ignored if repoID is set
cond := builder.NewCond().And(builder.Eq{"owner_id": ownerID}).Or(builder.Eq{"repo_id": 0, "owner_id": 0})
query = query.And(cond)
}
var runner ActionRunner
has, err := query.Get(&runner)
if err != nil {
return nil, err
} else if !has {
return nil, fmt.Errorf("runner with ID %d: %w", id, util.ErrNotExist)
}
return &runner, nil
}
// UpdateRunner updates runner's information.
func UpdateRunner(ctx context.Context, r *ActionRunner, cols ...string) error {
e := db.GetEngine(ctx)
@ -396,13 +354,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

@ -10,7 +10,6 @@ import (
auth_model "forgejo.org/models/auth"
"forgejo.org/models/db"
"forgejo.org/models/repo"
"forgejo.org/models/unittest"
"forgejo.org/modules/timeutil"
@ -141,400 +140,3 @@ func TestDeleteOfflineRunnersErrorOnInvalidOlderThanValue(t *testing.T) {
defer timeutil.MockUnset()
require.Error(t, DeleteOfflineRunners(db.DefaultContext, timeutil.TimeStampNow(), false))
}
func TestRunnerEditable(t *testing.T) {
testCases := []struct {
name string
runner *ActionRunner
ownerID int64
repoID int64
editable bool
}{
{
name: "admin-can-edit-global-runner",
runner: &ActionRunner{Name: "global-runner", OwnerID: 0, RepoID: 0},
ownerID: 0,
repoID: 0,
editable: true,
},
{
name: "admin-can-edit-user-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 36, RepoID: 0},
ownerID: 0,
repoID: 0,
editable: true,
},
{
name: "admin-can-edit-repository-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 0, RepoID: 110},
ownerID: 0,
repoID: 0,
editable: true,
},
{
name: "user-can-edit-its-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 469, RepoID: 0},
ownerID: 469,
repoID: 0,
editable: true,
},
{
name: "user-cannot-edit-global-runner",
runner: &ActionRunner{Name: "global-runner", OwnerID: 0, RepoID: 0},
ownerID: 469,
repoID: 0,
editable: false,
},
{
name: "user-cannot-edit-other-users-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 892, RepoID: 0},
ownerID: 469,
repoID: 0,
editable: false,
},
{
name: "user-cannot-edit-repo-runner",
runner: &ActionRunner{Name: "repo-runner", OwnerID: 0, RepoID: 151},
ownerID: 469,
repoID: 0,
editable: false,
},
{
name: "repo-can-edit-its-runner",
runner: &ActionRunner{Name: "repo-runner", OwnerID: 0, RepoID: 693},
ownerID: 0,
repoID: 693,
editable: true,
},
{
name: "repo-cannot-edit-other-repo-runner",
runner: &ActionRunner{Name: "repo-runner", OwnerID: 0, RepoID: 519},
ownerID: 0,
repoID: 693,
editable: false,
},
{
name: "repo-cannot-edit-global-runner",
runner: &ActionRunner{Name: "global-runner", OwnerID: 0, RepoID: 0},
ownerID: 0,
repoID: 693,
editable: false,
},
{
name: "repo-cannot-edit-user-runner",
runner: &ActionRunner{Name: "user-runner", OwnerID: 6, RepoID: 0},
ownerID: 0,
repoID: 693,
editable: false,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
result := testCase.runner.Editable(testCase.ownerID, testCase.repoID)
assert.Equal(t, testCase.editable, result)
})
}
}
func TestRunner_GetVisibleRunnerByID(t *testing.T) {
defer unittest.OverrideFixtures("models/actions/TestRunner_GetVisibleRunnerByID")()
require.NoError(t, unittest.PrepareTestDatabase())
repository32 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 32, OwnerID: 3})
repository1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1, OwnerID: 2})
runner1 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719931, OwnerID: 3, RepoID: 0}) // Owned by org3
runner2 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719932, OwnerID: 2, RepoID: 0}) // Owned by user2
runner3 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719933, OwnerID: 0, RepoID: 0})
runner4 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719934, OwnerID: 0, RepoID: repository32.ID})
testCases := []struct {
name string
runner *ActionRunner
ownerID int64
repoID int64
expectedError string
}{
{
name: "Organization runner",
runner: runner1,
ownerID: 3,
repoID: 0,
expectedError: "",
},
{
name: "Organization runner visible to admins",
runner: runner1,
ownerID: 0,
repoID: 0,
expectedError: "",
},
{
name: "Organization runner invisible to different owner",
runner: runner1,
ownerID: 2,
repoID: 0,
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner1.ID),
},
{
name: "Organization runner visible to its repositories",
runner: runner1,
ownerID: 0,
repoID: repository32.ID,
expectedError: "",
},
{
name: "Organization runner invisible to repositories owned by somebody else",
runner: runner1,
ownerID: 0,
repoID: repository1.ID,
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner1.ID),
},
{
name: "User runner",
runner: runner2,
ownerID: 2,
repoID: 0,
expectedError: "",
},
{
name: "User runner invisible to different user",
runner: runner2,
ownerID: 1,
repoID: 0,
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner2.ID),
},
{
name: "User runner visible to repository owned by user",
runner: runner2,
ownerID: 0,
repoID: repository1.ID,
expectedError: "",
},
{
name: "User runner invisible to repository owned by different user",
runner: runner2,
ownerID: 0,
repoID: repository32.ID,
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner2.ID),
},
{
name: "Global runner",
runner: runner3,
ownerID: 0,
repoID: 0,
expectedError: "",
},
{
name: "Global runner is visible to any user",
runner: runner3,
ownerID: 2,
repoID: 0,
expectedError: "",
},
{
name: "Global runner is visible to any repository",
runner: runner3,
ownerID: 0,
repoID: repository32.ID,
expectedError: "",
},
{
name: "Repository runner",
runner: runner4,
ownerID: 0,
repoID: repository32.ID,
expectedError: "",
},
{
name: "Repository runner is visible to admins",
runner: runner4,
ownerID: 0,
repoID: 0,
expectedError: "",
},
{
name: "Repository runner is invisible to repository owner",
runner: runner4,
ownerID: repository32.OwnerID,
repoID: 0,
expectedError: fmt.Sprintf("runner with ID %d: resource does not exist", runner4.ID),
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
_, err := GetVisibleRunnerByID(t.Context(), testCase.runner.ID, testCase.ownerID, testCase.repoID)
if testCase.expectedError == "" {
require.NoError(t, err)
} else {
assert.ErrorContains(t, err, testCase.expectedError)
}
})
}
}
func TestRunner_FindRunnerOptionsToConds(t *testing.T) {
defer unittest.OverrideFixtures("models/actions/TestRunner_FindRunnerOptionsToConds")()
require.NoError(t, unittest.PrepareTestDatabase())
runner1 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719931, OwnerID: 3, RepoID: 0}) // Owned by org3
runner2 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719932, OwnerID: 2, RepoID: 0}) // Owned by user2
runner3 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719933, OwnerID: 0, RepoID: 0})
runner4 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719934, OwnerID: 0, RepoID: 32})
runner5 := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: 719935, OwnerID: 0, RepoID: 36})
testCases := []struct {
name string
opts FindRunnerOptions
expectedRunners RunnerList
unexpectedRunners RunnerList
}{
{
name: "Only runners owned by instance",
opts: FindRunnerOptions{OwnerID: 0, RepoID: 0, WithVisible: false},
expectedRunners: RunnerList{runner3},
unexpectedRunners: RunnerList{runner1, runner2, runner4, runner5},
},
{
name: "All runners on instance",
opts: FindRunnerOptions{OwnerID: 0, RepoID: 0, WithVisible: true},
expectedRunners: RunnerList{runner1, runner2, runner3, runner4, runner5},
unexpectedRunners: RunnerList{},
},
{
name: "Only runners owned by organization",
opts: FindRunnerOptions{OwnerID: 3, RepoID: 0, WithVisible: false},
expectedRunners: RunnerList{runner1},
unexpectedRunners: RunnerList{runner2, runner3, runner4, runner5},
},
{
name: "Runners available to organization",
opts: FindRunnerOptions{OwnerID: 3, RepoID: 0, WithVisible: true},
expectedRunners: RunnerList{runner1, runner3},
unexpectedRunners: RunnerList{runner2, runner4, runner5},
},
{
name: "Only runners owned by user",
opts: FindRunnerOptions{OwnerID: 2, RepoID: 0, WithVisible: false},
expectedRunners: RunnerList{runner2},
unexpectedRunners: RunnerList{runner1, runner3, runner4, runner5},
},
{
name: "Runners available to user",
opts: FindRunnerOptions{OwnerID: 2, RepoID: 0, WithVisible: true},
expectedRunners: RunnerList{runner2, runner3},
unexpectedRunners: RunnerList{runner1, runner4, runner5},
},
{
name: "Only runners owned by organization repository",
opts: FindRunnerOptions{OwnerID: 0, RepoID: 32, WithVisible: false},
expectedRunners: RunnerList{runner4},
unexpectedRunners: RunnerList{runner1, runner2, runner3, runner5},
},
{
name: "Runners available to organization repository",
opts: FindRunnerOptions{OwnerID: 0, RepoID: 32, WithVisible: true},
expectedRunners: RunnerList{runner1, runner3, runner4},
unexpectedRunners: RunnerList{runner2, runner5},
},
{
name: "Only runners owned by user repository",
opts: FindRunnerOptions{OwnerID: 0, RepoID: 36, WithVisible: false},
expectedRunners: RunnerList{runner5},
unexpectedRunners: RunnerList{runner1, runner2, runner3, runner4},
},
{
name: "Runners available to user repository",
opts: FindRunnerOptions{OwnerID: 0, RepoID: 36, WithVisible: true},
expectedRunners: RunnerList{runner2, runner3, runner5},
unexpectedRunners: RunnerList{runner1, runner4},
},
{
name: "Runners with partially matching name",
opts: FindRunnerOptions{Filter: "er-3"},
expectedRunners: RunnerList{runner3},
unexpectedRunners: RunnerList{runner1, runner2, runner4, runner5},
},
{
name: "Runners with partially matching UUID",
opts: FindRunnerOptions{Filter: "21f75233798b"},
expectedRunners: RunnerList{runner4},
unexpectedRunners: RunnerList{runner1, runner2, runner3, runner5},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
runners, err := db.Find[ActionRunner](t.Context(), testCase.opts)
require.NoError(t, err)
for _, expectedRunner := range testCase.expectedRunners {
assert.Contains(t, runners, expectedRunner)
}
for _, unexpectedRunner := range testCase.unexpectedRunners {
assert.NotContains(t, runners, unexpectedRunner)
}
})
}
}
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

@ -10,11 +10,8 @@ import (
"forgejo.org/models/db"
repo_model "forgejo.org/models/repo"
user_model "forgejo.org/models/user"
"forgejo.org/modules/optional"
"forgejo.org/modules/timeutil"
"forgejo.org/modules/util"
"xorm.io/builder"
)
// ActionRunnerToken represents runner tokens
@ -32,14 +29,15 @@ import (
type ActionRunnerToken struct {
ID int64
Token string `xorm:"UNIQUE"`
OwnerID optional.Option[int64] `xorm:"index REFERENCES(user, id)"`
OwnerID int64 `xorm:"index"`
Owner *user_model.User `xorm:"-"`
RepoID optional.Option[int64] `xorm:"index REFERENCES(repository, id)"`
RepoID int64 `xorm:"index"`
Repo *repo_model.Repository `xorm:"-"`
IsActive bool // true means it can be used
Created timeutil.TimeStamp `xorm:"created"`
Updated timeutil.TimeStamp `xorm:"updated"`
Deleted timeutil.TimeStamp `xorm:"deleted"`
}
func init() {
@ -72,11 +70,11 @@ func UpdateRunnerToken(ctx context.Context, r *ActionRunnerToken, cols ...string
// NewRunnerToken creates a new active runner token and invalidate all old tokens
// ownerID will be ignored and treated as 0 if repoID is non-zero.
func NewRunnerToken(ctx context.Context, ownerID, repoID optional.Option[int64]) (*ActionRunnerToken, error) {
if ownerID.Has() && repoID.Has() {
func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
if ownerID != 0 && repoID != 0 {
// It's trying to create a runner token that belongs to a repository, but OwnerID has been set accidentally.
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
ownerID = optional.None[int64]()
ownerID = 0
}
token := util.CryptoRandomString(util.RandomStringHigh)
@ -88,7 +86,7 @@ func NewRunnerToken(ctx context.Context, ownerID, repoID optional.Option[int64])
}
return runnerToken, db.WithTx(ctx, func(ctx context.Context) error {
if _, err := db.GetEngine(ctx).Where(runnerTokenCond(ownerID, repoID)).Cols("is_active").Update(&ActionRunnerToken{
if _, err := db.GetEngine(ctx).Where("owner_id =? AND repo_id = ?", ownerID, repoID).Cols("is_active").Update(&ActionRunnerToken{
IsActive: false,
}); err != nil {
return err
@ -99,32 +97,16 @@ func NewRunnerToken(ctx context.Context, ownerID, repoID optional.Option[int64])
})
}
func runnerTokenCond(ownerID, repoID optional.Option[int64]) builder.Cond {
var condOwnerID builder.Cond
if has, value := ownerID.Get(); !has {
condOwnerID = builder.IsNull{"owner_id"}
} else {
condOwnerID = builder.Eq{"owner_id": value}
}
var condRepoID builder.Cond
if has, value := repoID.Get(); !has {
condRepoID = builder.IsNull{"repo_id"}
} else {
condRepoID = builder.Eq{"repo_id": value}
}
return builder.And(condOwnerID, condRepoID)
}
// GetLatestRunnerToken returns the latest runner token
func GetLatestRunnerToken(ctx context.Context, ownerID, repoID optional.Option[int64]) (*ActionRunnerToken, error) {
if ownerID.Has() && repoID.Has() {
// It's trying to create a runner token that belongs to a repository, but OwnerID has been set accidentally.
func GetLatestRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
if ownerID != 0 && repoID != 0 {
// It's trying to get a runner token that belongs to a repository, but OwnerID has been set accidentally.
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
ownerID = optional.None[int64]()
ownerID = 0
}
var runnerToken ActionRunnerToken
has, err := db.GetEngine(ctx).Where(runnerTokenCond(ownerID, repoID)).
has, err := db.GetEngine(ctx).Where("owner_id=? AND repo_id=?", ownerID, repoID).
OrderBy("id DESC").Get(&runnerToken)
if err != nil {
return nil, err

View file

@ -8,7 +8,6 @@ import (
"forgejo.org/models/db"
"forgejo.org/models/unittest"
"forgejo.org/modules/optional"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -17,16 +16,16 @@ import (
func TestGetLatestRunnerToken(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
token := unittest.AssertExistsAndLoadBean(t, &ActionRunnerToken{ID: 3})
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, optional.Some[int64](1), optional.None[int64]())
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
require.NoError(t, err)
assert.Equal(t, expectedToken, token)
}
func TestNewRunnerToken(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
token, err := NewRunnerToken(db.DefaultContext, optional.Some[int64](1), optional.None[int64]())
token, err := NewRunnerToken(db.DefaultContext, 1, 0)
require.NoError(t, err)
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, optional.Some[int64](1), optional.None[int64]())
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
require.NoError(t, err)
assert.Equal(t, expectedToken, token)
}
@ -35,8 +34,8 @@ func TestUpdateRunnerToken(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
token := unittest.AssertExistsAndLoadBean(t, &ActionRunnerToken{ID: 3})
token.IsActive = true
require.NoError(t, UpdateRunnerToken(db.DefaultContext, token, "is_active"))
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, optional.Some[int64](1), optional.None[int64]())
require.NoError(t, UpdateRunnerToken(db.DefaultContext, token))
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
require.NoError(t, err)
assert.Equal(t, expectedToken, token)
}

View file

@ -5,6 +5,7 @@ package actions
import (
"context"
"time"
"forgejo.org/models/db"
repo_model "forgejo.org/models/repo"
@ -20,7 +21,7 @@ import (
type ActionSchedule struct {
ID int64
Title string
Specs []*ActionScheduleSpec `xorm:"-"`
Specs []string
RepoID int64 `xorm:"index"`
Repo *repo_model.Repository `xorm:"-"`
OwnerID int64 `xorm:"index"`
@ -72,12 +73,25 @@ func CreateScheduleTask(ctx context.Context, rows []*ActionSchedule) error {
return err
}
// Loop through each schedule spec and create a new spec row
now := time.Now()
for _, spec := range row.Specs {
spec.ScheduleID = row.ID
spec.RepoID = row.RepoID
specRow := &ActionScheduleSpec{
RepoID: row.RepoID,
ScheduleID: row.ID,
Spec: spec,
}
// Parse the spec and check for errors
schedule, err := specRow.Parse()
if err != nil {
continue // skip to the next spec if there's an error
}
specRow.Next = timeutil.TimeStamp(schedule.Next(now).Unix())
// Insert the new schedule spec row
if err = db.Insert(ctx, spec); err != nil {
if err = db.Insert(ctx, specRow); err != nil {
return err
}
}
@ -116,7 +130,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

@ -10,10 +10,9 @@ import (
"forgejo.org/models/db"
repo_model "forgejo.org/models/repo"
"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
@ -28,58 +27,36 @@ type ActionScheduleSpec struct {
// started or this entry's schedule is unsatisfiable
Next timeutil.TimeStamp `xorm:"index"`
// Prev is the last time this job was run, or the zero time if never.
Prev timeutil.TimeStamp
Spec string
TimeZone optional.Option[string]
Prev timeutil.TimeStamp
Spec string
Created timeutil.TimeStamp `xorm:"created"`
Updated timeutil.TimeStamp `xorm:"updated"`
}
func NewActionScheduleSpec(cron string, tz optional.Option[string], referenceTime time.Time) (*ActionScheduleSpec, error) {
spec := &ActionScheduleSpec{
Spec: cron,
TimeZone: tz,
}
cronSchedule, err := spec.Parse()
if err != nil {
return nil, err
}
spec.Next = timeutil.TimeStamp(cronSchedule.Next(referenceTime).Unix())
return spec, nil
}
// 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)
if err != nil {
return nil, err
}
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
}
// If `timezone` is not defined in the workflow, but the spec includes a timezone, use it.
if !s.TimeZone.Has() && (strings.HasPrefix(s.Spec, "TZ=") || strings.HasPrefix(s.Spec, "CRON_TZ=")) {
// If the spec has specified a timezone, use it
if strings.HasPrefix(s.Spec, "TZ=") || strings.HasPrefix(s.Spec, "CRON_TZ=") {
return schedule, nil
}
var location *time.Location
if present, tz := s.TimeZone.Get(); present {
location, err = time.LoadLocation(tz)
if err != nil {
return nil, err
}
} else {
// UTC is the default time zone.
location = time.UTC
specSchedule, ok := schedule.(*cron.SpecSchedule)
// If it's not a spec schedule, like "@every 5m", timezone is not relevant
if !ok {
return schedule, nil
}
return schedule.WithLocation(location), nil
// Set the timezone to UTC
specSchedule.Location = time.UTC
return specSchedule, nil
}
func init() {

View file

@ -7,50 +7,10 @@ import (
"testing"
"time"
"forgejo.org/modules/optional"
"github.com/stretchr/testify/assert"
"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
@ -61,105 +21,50 @@ func TestActionScheduleSpec_Parse(t *testing.T) {
}()
time.Local = tz
now, err := time.Parse(time.RFC3339, "2024-07-31T15:47:55+08:00")
require.NoError(t, err)
tests := []struct {
name string
refTime time.Time
spec string
timeZone string
want string
wantErr assert.ErrorAssertionFunc
name string
spec string
want string
wantErr assert.ErrorAssertionFunc
}{
{
name: "regular",
refTime: time.Date(2024, 7, 31, 15, 47, 55, 0, time.Local),
spec: "0 10 * * *",
want: "2024-07-31T10:00:00Z",
wantErr: assert.NoError,
},
{
name: "invalid",
refTime: time.Date(2024, 7, 31, 15, 47, 55, 0, time.Local),
spec: "0 10 * *",
want: "",
wantErr: assert.Error,
},
{
name: "with TZ in cron schedule",
refTime: time.Date(2024, 7, 31, 15, 47, 55, 0, time.Local),
name: "with timezone",
spec: "TZ=America/New_York 0 10 * * *",
want: "2024-07-31T14:00:00Z",
wantErr: assert.NoError,
},
{
name: "with CRON_TZ in cron schedule",
refTime: time.Date(2024, 7, 31, 15, 47, 55, 0, time.Local),
spec: "CRON_TZ=America/New_York 0 10 * * *",
want: "2024-07-31T14:00:00Z",
wantErr: assert.NoError,
},
{
name: "with separate time zone",
refTime: time.Date(2024, 7, 31, 15, 47, 55, 0, time.Local),
spec: "0 10 * * *",
timeZone: "America/New_York",
want: "2024-07-31T14:00:00Z",
wantErr: assert.NoError,
},
{
name: "separate time zone takes precedence over inlined time zone",
refTime: time.Date(2024, 7, 31, 15, 47, 55, 0, time.Local),
spec: "CRON_TZ=Europe/Berlin 0 10 * * *",
timeZone: "America/New_York",
want: "2024-07-31T14:00:00Z",
wantErr: assert.NoError,
},
{
name: "time zone irrelevant",
refTime: time.Date(2024, 7, 31, 15, 47, 55, 0, time.Local),
name: "timezone irrelevant",
spec: "@every 5m",
want: "2024-07-31T07:52:55Z",
wantErr: assert.NoError,
},
{
// The various cron implementations handle the DST jump forwards differently. The most popular approaches
// are (a) scheduling all jobs at 3 o'clock that were supposed to run between 2 and 3 o'clock, or (b)
// 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.
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.
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.
timeZone: "Europe/Berlin",
want: "2025-10-26T01:10:00Z",
wantErr: assert.NoError,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &ActionScheduleSpec{
Spec: tt.spec,
TimeZone: optional.FromNonDefault(tt.timeZone),
Spec: tt.spec,
}
got, err := s.Parse()
tt.wantErr(t, err)
if err == nil {
assert.Equal(t, tt.want, got.Next(tt.refTime).UTC().Format(time.RFC3339))
assert.Equal(t, tt.want, got.Next(now).UTC().Format(time.RFC3339))
}
})
}

View file

@ -1,102 +0,0 @@
// Copyright 2026 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package actions
import (
"testing"
"time"
"forgejo.org/models/db"
"forgejo.org/models/repo"
"forgejo.org/models/unittest"
"forgejo.org/models/user"
"forgejo.org/modules/optional"
"forgejo.org/modules/timeutil"
"forgejo.org/modules/webhook"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestScheduleCreateScheduleTask(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
user2 := unittest.AssertExistsAndLoadBean(t, &user.User{ID: 2})
repo62 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 62, Name: "test_workflows", OwnerID: user2.ID})
content := `
on:
push:
schedule:
- cron: "2 13 * * *"
- cron: "03 13 * * *"
timezone: Europe/Paris
jobs:
test:
runs-on: debian
steps:
- run: |
echo "OK"
`
referenceTime := time.Date(2026, 3, 27, 17, 41, 21, 0, time.UTC)
specWithoutTZ, err := NewActionScheduleSpec("2 13 * * *", optional.None[string](), referenceTime)
require.NoError(t, err)
specWithTZ, err := NewActionScheduleSpec("3 13 * * *", optional.Some("Europe/Paris"), referenceTime)
require.NoError(t, err)
schedule := &ActionSchedule{
Title: ".forgejo/workflows/test.yaml",
Specs: []*ActionScheduleSpec{specWithoutTZ, specWithTZ},
RepoID: repo62.ID,
OwnerID: user2.ID,
WorkflowID: "test.yaml",
WorkflowDirectory: ".forgejo/workflows",
TriggerUserID: -2,
Ref: "main",
CommitSHA: "6af834a5bc97c1a337eb3a21d26903c5cdceca0c",
Event: webhook.HookEventPush,
EventPayload: "{\"action\":\"schedule\"}",
Content: []byte(content),
}
err = CreateScheduleTask(t.Context(), []*ActionSchedule{schedule})
require.NoError(t, err)
schedules, err := db.Find[ActionSchedule](t.Context(), FindScheduleOptions{OwnerID: user2.ID, RepoID: repo62.ID})
require.NoError(t, err)
require.Len(t, schedules, 1)
assert.NotZero(t, schedules[0].ID)
assert.Equal(t, ".forgejo/workflows/test.yaml", schedules[0].Title)
assert.Equal(t, "test.yaml", schedules[0].WorkflowID)
assert.Equal(t, ".forgejo/workflows", schedules[0].WorkflowDirectory)
assert.Equal(t, int64(-2), schedules[0].TriggerUserID)
assert.Equal(t, "main", schedules[0].Ref)
assert.Equal(t, "6af834a5bc97c1a337eb3a21d26903c5cdceca0c", schedules[0].CommitSHA)
assert.Equal(t, webhook.HookEventPush, schedules[0].Event)
assert.JSONEq(t, "{\"action\":\"schedule\"}", schedules[0].EventPayload)
assert.Equal(t, []byte(content), schedules[0].Content)
specs, total, err := FindSpecs(t.Context(), FindSpecOptions{RepoID: repo62.ID})
require.NoError(t, err)
assert.Equal(t, int64(2), total)
assert.NotZero(t, specs[0].ID)
assert.Equal(t, schedules[0].ID, specs[0].ScheduleID)
assert.Equal(t, timeutil.TimeStamp(1774699380), specs[0].Next)
assert.Equal(t, "3 13 * * *", specs[0].Spec)
assert.Equal(t, optional.Some("Europe/Paris"), specs[0].TimeZone)
assert.Zero(t, specs[0].Prev)
assert.NotZero(t, specs[1].ID)
assert.Equal(t, schedules[0].ID, specs[1].ScheduleID)
assert.Equal(t, timeutil.TimeStamp(1774702920), specs[1].Next)
assert.Equal(t, "2 13 * * *", specs[1].Spec)
assert.Equal(t, optional.None[string](), specs[1].TimeZone)
assert.Zero(t, specs[1].Prev)
}

View file

@ -4,8 +4,6 @@
package actions
import (
"slices"
"forgejo.org/modules/translation"
runnerv1 "code.forgejo.org/forgejo/actions-proto/runner/v1"
@ -109,7 +107,12 @@ func (s Status) IsBlocked() bool {
// In returns whether s is one of the given statuses
func (s Status) In(statuses ...Status) bool {
return slices.Contains(statuses, s)
for _, v := range statuses {
if s == v {
return true
}
}
return false
}
func (s Status) AsResult() runnerv1.Result {

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