mirror of
https://gitea.com/gitea/act_runner
synced 2026-05-06 01:37:57 +02:00
594c9ade7cccf7be6cd0f1cd18ae8d28bba878c2
1610 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
594c9ade7c |
Align step failure log output with GitHub Actions (#927)
Fixes #926. Before: <img src="/attachments/a5ae9221-eee2-410a-964e-6103ce126df4" alt="image.png" width="400"> After: <img width="400" alt="image.png" src="attachments/2f2d67c4-6080-4ec3-9ae5-df33e6479920"> Also gets rid of a bunch of emojis in the logging and the obsolete link to `nektos/act` and align some other error messages. --- This PR was written with the help of Claude Opus 4.7 --------- Co-authored-by: Nicolas <bircni@icloud.com> Reviewed-on: https://gitea.com/gitea/runner/pulls/927 Reviewed-by: Nicolas <bircni@icloud.com> Co-authored-by: silverwind <me@silverwind.io> Co-committed-by: silverwind <me@silverwind.io>v1.0.0 |
||
|
|
2a4d56c650 |
feat: add startup janitor for stale bind-workdir task workspaces (#870)
- Add idle-time cleanup for stale bind-workdir task directories instead of cleaning them on the task execution path. - Make cleanup behavior configurable with `runner.startup_cleanup_age` as the stale-age threshold (default: `24h`) and `runner.idle_cleanup_interval` as the idle cleanup cadence (default: `10m`). - Restrict cleanup scope to numeric task directory names only, to avoid touching operator-managed folders. - Document the cleanup settings in `config.example.yaml` and `README.md`. - Add tests for stale-directory cleanup, idle cleanup throttling, and config default/override parsing. ## Why When a runner or host crashes, normal per-task cleanup may not run, leaving stale task directories under the bind-workdir root. Running this cleanup only while the runner is idle recovers that disk space without adding overhead to active job execution. If you want, I can also tighten the wording around `startup_cleanup_age`, since the key name now reads a bit misleadingly relative to the actual behavior. --------- Co-authored-by: silverwind <me@silverwind.io> Reviewed-on: https://gitea.com/gitea/runner/pulls/870 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> |
||
|
|
a22119cf88 |
fix(host): correct host workspace cleanup on Windows (#883)
## Summary - Fix host-mode cleanup to remove the job **workspace** directory after a run (instead of leaving checkouts behind). - On Windows, track step process PIDs and terminate remaining process trees during teardown before attempting workspace deletion (prevents file-lock failures). - Skip workspace deletion when `bind_workdir` is enabled to avoid conflicting with runner-level task directory cleanup. ## Implementation details - `HostEnvironment` now records PIDs for started commands and best-effort terminates them on Windows during `Remove()`. - Workspace removal uses a small retry loop on Windows to handle transient locks. - `BindWorkdir` is propagated into `HostEnvironment` so cleanup behavior matches runner configuration. --------- Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: silverwind <2021+silverwind@noreply.gitea.com> Reviewed-on: https://gitea.com/gitea/runner/pulls/883 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> |
||
|
|
b68ecf2580 |
chore(deps): update crazy-max/ghaction-import-gpg action to v7 (#923)
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg) | action | major | `v6` → `v7` | --- ### Release Notes <details> <summary>crazy-max/ghaction-import-gpg (crazy-max/ghaction-import-gpg)</summary> ### [`v7`](https://github.com/crazy-max/ghaction-import-gpg/compare/v7.0.0...v7.0.0) [Compare Source](https://github.com/crazy-max/ghaction-import-gpg/compare/v7.0.0...v7.0.0) ### [`v7.0.0`](https://github.com/crazy-max/ghaction-import-gpg/releases/tag/v7.0.0) [Compare Source](https://github.com/crazy-max/ghaction-import-gpg/compare/v6.3.0...v7.0.0) - Node 24 as default runtime (requires [Actions Runner v2.327.1](https://github.com/actions/runner/releases/tag/v2.327.1) or later) by [@​crazy-max](https://github.com/crazy-max) in [#​241](https://github.com/crazy-max/ghaction-import-gpg/pull/241) - Switch to ESM and update config/test wiring by [@​crazy-max](https://github.com/crazy-max) in [#​239](https://github.com/crazy-max/ghaction-import-gpg/pull/239) - Bump [@​actions/core](https://github.com/actions/core) from 1.11.1 to 3.0.0 in [#​232](https://github.com/crazy-max/ghaction-import-gpg/pull/232) - Bump [@​actions/exec](https://github.com/actions/exec) from 1.1.1 to 3.0.0 in [#​242](https://github.com/crazy-max/ghaction-import-gpg/pull/242) - Bump brace-expansion from 1.1.11 to 1.1.12 in [#​221](https://github.com/crazy-max/ghaction-import-gpg/pull/221) - Bump minimatch from 3.1.2 to 3.1.5 in [#​240](https://github.com/crazy-max/ghaction-import-gpg/pull/240) - Bump openpgp from 6.1.0 to 6.3.0 in [#​233](https://github.com/crazy-max/ghaction-import-gpg/pull/233) **Full Changelog**: <https://github.com/crazy-max/ghaction-import-gpg/compare/v6.3.0...v7.0.0> ### [`v6.3.0`](https://github.com/crazy-max/ghaction-import-gpg/releases/tag/v6.3.0) [Compare Source](https://github.com/crazy-max/ghaction-import-gpg/compare/v6.2.0...v6.3.0) - Bump openpgp from 5.11.2 to 6.1.0 in [#​215](https://github.com/crazy-max/ghaction-import-gpg/pull/215) - Bump cross-spawn from 7.0.3 to 7.0.6 in [#​212](https://github.com/crazy-max/ghaction-import-gpg/pull/212) **Full Changelog**: <https://github.com/crazy-max/ghaction-import-gpg/compare/v6.2.0...v6.3.0> ### [`v6.2.0`](https://github.com/crazy-max/ghaction-import-gpg/releases/tag/v6.2.0) [Compare Source](https://github.com/crazy-max/ghaction-import-gpg/compare/v6.1.0...v6.2.0) - Bump [@​actions/core](https://github.com/actions/core) from 1.10.1 to 1.11.1 in [#​209](https://github.com/crazy-max/ghaction-import-gpg/pull/209) - Bump braces from 3.0.2 to 3.0.3 in [#​203](https://github.com/crazy-max/ghaction-import-gpg/pull/203) - Bump ip from 2.0.0 to 2.0.1 in [#​196](https://github.com/crazy-max/ghaction-import-gpg/pull/196) - Bump micromatch from 4.0.4 to 4.0.8 in [#​207](https://github.com/crazy-max/ghaction-import-gpg/pull/207) - Bump openpgp from 5.11.0 to 5.11.2 in [#​205](https://github.com/crazy-max/ghaction-import-gpg/pull/205) - Bump tar from 6.1.14 to 6.2.1 in [#​198](https://github.com/crazy-max/ghaction-import-gpg/pull/198) **Full Changelog**: <https://github.com/crazy-max/ghaction-import-gpg/compare/v6.1.0...v6.2.0> ### [`v6.1.0`](https://github.com/crazy-max/ghaction-import-gpg/releases/tag/v6.1.0) [Compare Source](https://github.com/crazy-max/ghaction-import-gpg/compare/v6...v6.1.0) - Bump [@​actions/core](https://github.com/actions/core) from 1.10.0 to 1.10.1 in [#​186](https://github.com/crazy-max/ghaction-import-gpg/pull/186) - Bump [@​babel/traverse](https://github.com/babel/traverse) from 7.17.3 to 7.23.2 in [#​191](https://github.com/crazy-max/ghaction-import-gpg/pull/191) - Bump debug from 4.1.1 to 4.3.4 in [#​190](https://github.com/crazy-max/ghaction-import-gpg/pull/190) - Bump openpgp from 5.10.1 to 5.11.0 in [#​192](https://github.com/crazy-max/ghaction-import-gpg/pull/192) **Full Changelog**: <https://github.com/crazy-max/ghaction-import-gpg/compare/v6.0.0...v6.1.0> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuNiIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC42IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/runner/pulls/923 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
d1434237c2 |
fix(deps): update module golang.org/x/term to v0.42.0 (#920)
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/term](https://pkg.go.dev/golang.org/x/term) | [`v0.41.0` → `v0.42.0`](https://cs.opensource.google/go/x/term/+/refs/tags/v0.41.0...refs/tags/v0.42.0) |  |  | --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [x] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuNCIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/runner/pulls/920 Reviewed-by: Nicolas <bircni@icloud.com> Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
35c65e2b14 |
chore(deps): update actions/hello-world-docker-action action to v2 (#921)
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [actions/hello-world-docker-action](https://github.com/actions/hello-world-docker-action) | action | major | `v1` → `v2` | --- ### Release Notes <details> <summary>actions/hello-world-docker-action (actions/hello-world-docker-action)</summary> ### [`v2`](https://github.com/actions/hello-world-docker-action/releases/tag/v2): Version v2 [Compare Source](https://github.com/actions/hello-world-docker-action/compare/v1...v2) Update action to use the new environment file method for setting outputs. </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuNCIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/runner/pulls/921 Reviewed-by: Nicolas <bircni@icloud.com> Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
c45a4e6d32 |
ci: Fix triggers (#882)
Currently on a branch a workflow got triggered 2x one time on push and one time as its a PR Now it only gets triggered on PR and on push onto main Reviewed-on: https://gitea.com/gitea/runner/pulls/882 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Nicolas <bircni@icloud.com> Co-committed-by: Nicolas <bircni@icloud.com> |
||
|
|
68d9fc45c9 |
chore(deps): update dependency @vercel/ncc to ^0.38.0 (#881)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@vercel/ncc](https://github.com/vercel/ncc) | [`^0.24.1` → `^0.38.0`](https://renovatebot.com/diffs/npm/@vercel%2fncc/0.24.1/0.38.4) |  |  | --- ### Release Notes <details> <summary>vercel/ncc (@​vercel/ncc)</summary> ### [`v0.38.4`](https://github.com/vercel/ncc/releases/tag/0.38.4) [Compare Source](https://github.com/vercel/ncc/compare/0.38.3...0.38.4) ##### Bug Fixes - **cjs-build:** enable evaluating import.meta in cjs build ([#​1236](https://github.com/vercel/ncc/issues/1236)) ([e72d34d]( |
||
|
|
b1c873a66b |
chore(deps): update dependency @actions/core to v1.11.1 (#880)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@actions/core](https://github.com/actions/toolkit/tree/main/packages/core) ([source](https://github.com/actions/toolkit/tree/HEAD/packages/core)) | [`1.10.0` → `1.11.1`](https://renovatebot.com/diffs/npm/@actions%2fcore/1.10.0/1.11.1) |  |  | --- ### Release Notes <details> <summary>actions/toolkit (@​actions/core)</summary> ### [`v1.11.1`](https://github.com/actions/toolkit/blob/HEAD/packages/core/RELEASES.md#1111) - Fix uses of `crypto.randomUUID` on Node 18 and earlier [#​1842](https://github.com/actions/toolkit/pull/1842) ##### 1.11.0 - Add platform info utilities [#​1551](https://github.com/actions/toolkit/pull/1551) - Remove dependency on `uuid` package [#​1824](https://github.com/actions/toolkit/pull/1824) ##### 1.10.1 - Fix error message reference in oidc utils [#​1511](https://github.com/actions/toolkit/pull/1511) ##### 1.10.0 - `saveState` and `setOutput` now use environment files if available [#​1178](https://github.com/actions/toolkit/pull/1178) - `getMultilineInput` now correctly trims whitespace by default [#​1185](https://github.com/actions/toolkit/pull/1185) ##### 1.9.1 - Randomize delimiter when calling `core.exportVariable` ##### 1.9.0 - Added `toPosixPath`, `toWin32Path` and `toPlatformPath` utilities [#​1102](https://github.com/actions/toolkit/pull/1102) ##### 1.8.2 - Update to v2.0.1 of `@actions/http-client` [#​1087](https://github.com/actions/toolkit/pull/1087) ##### 1.8.1 - Update to v2.0.0 of `@actions/http-client` ##### 1.8.0 - Deprecate `markdownSummary` extension export in favor of `summary` - [#​1072](https://github.com/actions/toolkit/pull/1072) - [#​1073](https://github.com/actions/toolkit/pull/1073) ##### 1.7.0 - [Added `markdownSummary` extension](https://github.com/actions/toolkit/pull/1014) ##### 1.6.0 - [Added OIDC Client function `getIDToken`](https://github.com/actions/toolkit/pull/919) - [Added `file` parameter to `AnnotationProperties`](https://github.com/actions/toolkit/pull/896) ##### 1.5.0 - [Added support for notice annotations and more annotation fields](https://github.com/actions/toolkit/pull/855) ##### 1.4.0 - [Added the `getMultilineInput` function](https://github.com/actions/toolkit/pull/829) ##### 1.3.0 - [Added the trimWhitespace option to getInput](https://github.com/actions/toolkit/pull/802) - [Added the getBooleanInput function](https://github.com/actions/toolkit/pull/725) ##### 1.2.7 - [Prepend newline for set-output](https://github.com/actions/toolkit/pull/772) ##### 1.2.6 - [Update `exportVariable` and `addPath` to use environment files](https://github.com/actions/toolkit/pull/571) ##### 1.2.5 - [Correctly bundle License File with package](https://github.com/actions/toolkit/pull/548) ##### 1.2.4 - [Be more lenient in accepting non-string command inputs](https://github.com/actions/toolkit/pull/405) - [Add Echo commands](https://github.com/actions/toolkit/pull/411) ##### 1.2.3 - [IsDebug logging](README.md#logging) ##### 1.2.2 - [Fix escaping for runner commands](https://github.com/actions/toolkit/pull/302) ##### 1.2.1 - [Remove trailing comma from commands](https://github.com/actions/toolkit/pull/263) - [Add "types" to package.json](https://github.com/actions/toolkit/pull/221) ##### 1.2.0 - saveState and getState functions for wrapper tasks (on finally entry points that run post job) ##### 1.1.3 - setSecret added to register a secret with the runner to be masked from the logs - exportSecret which was not implemented and never worked was removed after clarification from product. ##### 1.1.1 - Add support for action input variables with multiple spaces [#​127](https://github.com/actions/toolkit/issues/127) - Switched ## commands to :: commands (should have no noticeable impact) \[[#​110](https://github.com/actions/toolkit/issues/110))([#​110](https://github.com/actions/toolkit/pull/110)) ##### 1.1.0 - Added helpers for `group` and `endgroup` [#​98](https://github.com/actions/toolkit/pull/98) ##### 1.0.0 - Initial release ### [`v1.11.0`](https://github.com/actions/toolkit/blob/HEAD/packages/core/RELEASES.md#1110) - Add platform info utilities [#​1551](https://github.com/actions/toolkit/pull/1551) - Remove dependency on `uuid` package [#​1824](https://github.com/actions/toolkit/pull/1824) ### [`v1.10.1`](https://github.com/actions/toolkit/blob/HEAD/packages/core/RELEASES.md#1101) - Fix error message reference in oidc utils [#​1511](https://github.com/actions/toolkit/pull/1511) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNTAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjE1MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/runner/pulls/880 Reviewed-by: Nicolas <bircni@icloud.com> Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
1d6e7879c8 |
fix(deps): update module github.com/rhysd/actionlint to v1.7.12 (#873)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/rhysd/actionlint](https://github.com/rhysd/actionlint) | `v1.7.11` → `v1.7.12` |  |  | --- ### Release Notes <details> <summary>rhysd/actionlint (github.com/rhysd/actionlint)</summary> ### [`v1.7.12`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v1712---2026-03-30) [Compare Source](https://github.com/rhysd/actionlint/compare/v1.7.11...v1.7.12) - Support the [`timezone` configuration in `on.schedule`](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#onschedule) with checks for IANA timezone string. See the [documentation](https://github.com/rhysd/actionlint/blob/main/docs/checks.md#check-cron-syntax-and-timezone) for more details. Note that actionlint starts to embed the timezone database in the executables from this version so the binary sizes slightly increase. ([#​641](https://github.com/rhysd/actionlint/issues/641), thanks [@​martincostello](https://github.com/martincostello)) ```yaml on: schedule: # ERROR: The timezone is not a valid IANA timezone string - cron: '*/5 * * * *' timezone: 'Asia/Somewhere' ``` - Support the [`jobs.<job_name>.environment.deployment` configuration](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/control-deployments#using-environments-without-deployments). ([#​639](https://github.com/rhysd/actionlint/issues/639), thanks [@​springmeyer](https://github.com/springmeyer)) - Support the [`macos-26-intel` runner label](https://github.blog/changelog/2026-02-26-macos-26-is-now-generally-available-for-github-hosted-runners/). ([#​629](https://github.com/rhysd/actionlint/issues/629), thanks [@​hugovk](https://github.com/hugovk)) - Fix the [table of webhook activity types](https://github.com/rhysd/actionlint/blob/main/all_webhooks.go) are outdated by rebuilding the [script to scrape the table](https://github.com/rhysd/actionlint/tree/main/scripts/generate-webhook-events) from scratch. - Support Go 1.26 and drop the support for Go 1.24. Now supported versions are 1.25 and 1.26. - Tests are run on arm64 Windows in CI. - Update the popular actions data set to the latest. \[Changes]\[v1.7.12] <a id="v1.7.11"></a> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNTAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjE1MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Reviewed-on: https://gitea.com/gitea/runner/pulls/873 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
13dc9386fe |
Rename act_runner to runner (#850)
## Consumer-facing breaking changes
- **Go module path**: `gitea.com/gitea/act_runner` → `gitea.com/gitea/runner`. Anything importing `act/...` or `internal/...` packages (notably Gitea itself) must update imports.
- **Binary name**: `act_runner` → `gitea-runner`. Wrapper scripts, systemd units, init scripts, and documentation referencing the binary by `act_runner` will break.
- **Docker image**: `gitea/act_runner` → `gitea/runner` (incl. `*-dind-rootless` variants). Users pulling `gitea/act_runner:nightly` etc. will get stale images. Note: the image name is `gitea/runner`, not `gitea/gitea-runner`.
- **Release artifact paths**: S3 directory `act_runner/{{.Version}}` → `gitea-runner/{{.Version}}`, and artifact filenames change with the new project name. Existing download URLs break.
- **Metrics namespace**: changed from `act_runner` to `gitea_runner` (e.g. `act_runner_jobs_total` → `gitea_runner_jobs_total`); existing monitors/dashboards must be updated.
- **ldflags version path**: `gitea.com/gitea/act_runner/internal/pkg/ver.version` → `gitea.com/gitea/runner/internal/pkg/ver.version`. Affects anyone building with custom ldflags.
- **Kubernetes example resource names**: `act-runner` / `act-runner-vol` → `runner` / `runner-vol`. Users who copied the manifests verbatim will see resource churn on apply.
- **s6 service name**: `scripts/s6/act_runner/` → `scripts/s6/gitea-runner/` (image-internal; only matters for downstream image overrides).
Unchanged: YAML config field names, env vars (`GITEA_*`), CLI flags/subcommands, registration file format.
---------
Co-authored-by: silverwind <me@silverwind.io>
Reviewed-on: https://gitea.com/gitea/runner/pulls/850
Reviewed-by: Zettat123 <39446+zettat123@noreply.gitea.com>
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
Reviewed-by: Nicolas <bircni@icloud.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-committed-by: Lunny Xiao <xiaolunwen@gmail.com>
|
||
|
|
8e6b3be96a |
docs: Update docs (#872)
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/872 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Nicolas <bircni@icloud.com> Co-committed-by: Nicolas <bircni@icloud.com> |
||
|
|
e5e53c732e |
perf(config): lower default fetch_interval_max from 60s to 5s (#875)
## Summary - Lower the default `fetch_interval_max` from 60s to 5s to reduce job pickup latency for common single-runner deployments - PR #819 optimized defaults for 200-runner fleets, regressing single-runner pickup time from ~2s to ~65s - Most deployments use few runners; large fleets can still tune this value higher in their config ## Impact | `fetch_interval_max` | 1 runner pickup | 200 runners idle | | -------------------- | --------------- | ---------------- | | 60s (previous) | up to **65s** | 3.3 req/s | | **5s (new default)** | up to **5s** | 40 req/s | Closes https://gitea.com/gitea/act_runner/issues/869 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/875 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com> Co-committed-by: Bo-Yi Wu <appleboy.tw@gmail.com>v0.6.1 |
||
|
|
2516573592 |
chore: clean up nolint directives in act package (#864)
Removes 88 `nolint` directives (386 → 298) via mechanical, zero-regression cleanups: - **38 `bodyclose`** in `act/artifactcache/handler_test.go`: replaced by `defer resp.Body.Close()` after each HTTP call. - **21 dead directives** (`gocyclo`, `dogsled`, `contextcheck`): none of these linters are enabled in `.golangci.yml`, so the directives were doing nothing. - **29 `testifylint`** directives whose underlying issues were addressed by mechanical rewrites: - `assert.Nil(t, err)` → `assert.NoError(t, err)` - `assert.NotNil(t, err)` → `assert.Error(t, err)` - `assert.Equal(t, true/false, x)` → `assert.True/False(t, x)` - `assert.Equal(t, 0, len(x))` → `assert.Empty(t, x)` - `assert.Equal(t, N, len(x))` → `assert.Len(t, x, N)` - `assert.Len(t, x, 0)` → `assert.Empty(t, x)` Many `testifylint` directives still apply because they flag `require-error` (i.e. testifylint wants `require.NoError` instead of `assert.NoError` for early bail-out). That's a behavior change (fail-fast vs continue) and out of scope for this purely mechanical cleanup — those can be addressed in a follow-up. Same for `expected-actual`, `equal-values`, `error-is-as`, and the remaining `nilnil` / `unparam` / `forbidigo` / `staticcheck` / `goheader` / `dupl` directives. `golangci-lint run` is clean. Tests pass for all touched packages. --- This PR was written with the help of Claude Opus 4.7 Reviewed-on: https://gitea.com/gitea/act_runner/pulls/864 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: silverwind <2021+silverwind@noreply.gitea.com> Co-committed-by: silverwind <2021+silverwind@noreply.gitea.com> |
||
|
|
35834bf817 |
fix(deps): update module github.com/moby/patternmatcher to v0.6.1 (#868)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/moby/patternmatcher](https://github.com/moby/patternmatcher) | `v0.6.0` → `v0.6.1` |  |  | --- ### Release Notes <details> <summary>moby/patternmatcher (github.com/moby/patternmatcher)</summary> ### [`v0.6.1`](https://github.com/moby/patternmatcher/releases/tag/v0.6.1) [Compare Source](https://github.com/moby/patternmatcher/compare/v0.6.0...v0.6.1) #### What's Changed - fix panic / nil pointer dereference on invalid patterns [#​9](https://github.com/moby/patternmatcher/pull/9) - ci: update actions and test against "oldest", "oldstable" and "stable" [#​8](https://github.com/moby/patternmatcher/pull/8) **Full Changelog**: <https://github.com/moby/patternmatcher/compare/v0.6.0...v0.6.1> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjQzLjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/868 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
11a5dc8936 |
fix(deps): update module github.com/docker/docker to v25.0.15+incompatible (#867)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/docker/docker](https://github.com/docker/docker) | `v25.0.14+incompatible` → `v25.0.15+incompatible` |  |  | --- ### Release Notes <details> <summary>docker/docker (github.com/docker/docker)</summary> ### [`v25.0.15+incompatible`](https://github.com/docker/docker/compare/v25.0.14...v25.0.15) [Compare Source](https://github.com/docker/docker/compare/v25.0.14...v25.0.15) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjQzLjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/867 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
f09fafcb0a |
Clone different git repos in parallel via per-directory locks (#866)
Old `cloneLock` is a package-level `sync.Mutex` that serialized every action clone across all goroutines, regardless of target directory. This PR replaces it with a `sync.Map` of per-directory mutexes keyed by `input.Dir`. Same-directory operations still serialize; different directories now clone in parallel. Reviewed-on: https://gitea.com/gitea/act_runner/pulls/866 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Zettat123 <zettat123@gmail.com> Co-committed-by: Zettat123 <zettat123@gmail.com>v0.6.0 |
||
|
|
801e5cf4d5 |
fix: avoid 'filename too long' on matrix jobs by hashing container names (#853)
## Bug fixes
- Fixed "file name too long" errors when running matrix jobs with many or
long-valued matrix parameters. Docker volume and container names are now
bounded to a safe length by hashing the full name with SHA-256, keeping
the result well within the filesystem `NAME_MAX` limit (255 bytes) even
after Docker appends its own suffixes (`-env`, `-network`, etc.).
## Upgrade notes
This change renames the Docker containers, volumes and networks created by
the runner. Resources created by a previous version will **not** be cleaned
up automatically after upgrade and will become orphans.
After upgrading, you can remove the legacy resources with:
```sh
# volumes
docker volume ls -q | grep -E '^GITEA-ACTIONS-TASK-[0-9]+_' | xargs -r docker volume rm
# networks
docker network ls --format '{{.Name}}' | grep -E '^GITEA-ACTIONS-TASK-[0-9]+_.*-network$' | xargs -r docker network rm
```
> **Note:** If multiple act_runner instances share the same Docker daemon,
> make sure no runner using the old version is running before executing the
> cleanup commands above.
Fixes #686
---------
Co-authored-by: Nicolas <bircni@icloud.com>
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/853
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
Co-authored-by: Morgan Peyre <195218+peyremorgan@noreply.gitea.com>
Co-committed-by: Morgan Peyre <195218+peyremorgan@noreply.gitea.com>
|
||
|
|
3f05040438 |
fix(deps): update module github.com/mattn/go-isatty to v0.0.22 (#863)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/mattn/go-isatty](https://github.com/mattn/go-isatty) | `v0.0.20` → `v0.0.22` |  |  | --- ### Release Notes <details> <summary>mattn/go-isatty (github.com/mattn/go-isatty)</summary> ### [`v0.0.22`](https://github.com/mattn/go-isatty/compare/v0.0.21...v0.0.22) [Compare Source](https://github.com/mattn/go-isatty/compare/v0.0.21...v0.0.22) ### [`v0.0.21`](https://github.com/mattn/go-isatty/compare/v0.0.20...v0.0.21) [Compare Source](https://github.com/mattn/go-isatty/compare/v0.0.20...v0.0.21) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNiIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS42IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/863 Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
59d90bff26 |
fix(deps): update module github.com/docker/docker to v25.0.14+incompatible (#862)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/docker/docker](https://github.com/docker/docker) | `v25.0.13+incompatible` → `v25.0.14+incompatible` |  |  | --- ### Release Notes <details> <summary>docker/docker (github.com/docker/docker)</summary> ### [`v25.0.14+incompatible`](https://github.com/docker/docker/compare/v25.0.13...v25.0.14) [Compare Source](https://github.com/docker/docker/compare/v25.0.13...v25.0.14) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNiIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS42IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/862 Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
5edc4ba550 |
Authenticate cache requests via ACTIONS_RUNTIME_TOKEN and scope by repo (#849)
Closes #848. Addresses [GHSA-82g9-637c-2fx2](https://github.com/go-gitea/gitea/security/advisories/GHSA-82g9-637c-2fx2) and the follow-up points raised by @ChristopherHX and @haroutp in that thread. The change is breaking only for `cache.external_server` which uses auth via a pre-shared secret. ## How auth works now 1. **Runner starts** → opens the embedded cache server on `:port`. Loads / creates a 32-byte HMAC signing key in `<cache-dir>/.secret`. 2. **Runner receives a task** → calls `handler.RegisterJob(ACTIONS_RUNTIME_TOKEN, repository)` before the job runs, defers a revoker that removes the credential on completion. Registrations are reference-counted so a stray re-register cannot revoke a live job. 3. **Job container runs `actions/cache`** → the toolkit sends `Authorization: Bearer $ACTIONS_RUNTIME_TOKEN` on every management call (`reserve`, `upload`, `commit`, `find`, `clean`). The cache server's middleware looks the token up in the registered-jobs map: miss → 401; hit → the job's repository is injected into the request context. 4. **Repository scoping** — every cache entry is stamped with `Repo` on reserve; `find`, `upload`, `commit` all verify the caller's repo matches. A job in repo A cannot see or poison a cache entry owned by repo B, even when both reach the server over the same docker bridge. GC dedup also groups by `(Repo, Key, Version)` so one repo can't age out another. 5. **Archive downloads** — `@actions/cache` does not attach Authorization when downloading `archiveLocation`, so the `find` response is a short-lived HMAC-signed URL: `…/artifacts/:id?exp=<unix>&sig=<hmac>`, 10-minute TTL, signature binds `cacheID:exp`. Tampered, expired, or foreign-secret URLs get 401. 6. **Defence-in-depth** — `ACTIONS_RUNTIME_TOKEN` is added to `task.Secrets` so the runner's log masker scrubs it from step output. ## `cache.external_server` (standalone `act_runner cache-server`) Operators set `cache.external_secret` to the same value on the runner config and the `act_runner cache-server` config. The `cache-server` then runs with bearer auth on the cache API and exposes a control-plane at `POST /_internal/{register,revoke}` (gated by the shared secret). The runner pre-registers each task's `ACTIONS_RUNTIME_TOKEN` with the remote server before the job runs and revokes it on completion. Same per-job auth + repo scoping as the embedded handler, just over the network. `cache-server` refuses to start without `cache.external_secret`; runner config load also fails when `cache.external_server` is set without `cache.external_secret`. ## User-facing changes - **One-time cache miss after upgrade.** Pre-existing entries in `bolt.db` have no `Repo` stamp and won't match any job — they'll be evicted by the normal GC. First job per cache key rebuilds its cache. - **`cache.external_server` deployments must add `cache.external_secret`.** Breaking change for anyone running a standalone `act_runner cache-server`: set the same `cache.external_secret` in both the runner config and the cache-server config. Without it neither side starts. - **No config changes required for the default setup.** Runners using the embedded cache server (the common case) keep working without any yaml edits; the auth mechanism is invisible to workflows. --- This PR was written with the help of Claude Opus 4.7 --------- Co-authored-by: Nicolas <bircni@icloud.com> Co-authored-by: Christopher Homberger <christopher.homberger@web.de> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/849 Reviewed-by: ChristopherHX <38043+christopherhx@noreply.gitea.com> |
||
|
|
547a0ff297 |
feat: show run command, shell and env in collapsible group before step output (#847)
## Summary
Mirrors the GitHub Actions runner behaviour where each `run:` step shows a collapsible **"Run \<command\>"** section containing the script, shell command, and environment variables before the actual step output.
### What changes
- **`pkg/runner/step_run.go`**: In `stepRun.main()`, two new executors are added to the pipeline:
1. `logRunGroupHeader()` — runs after `setupShellCommandExecutor()` (so `sr.cmdline` is already resolved). Emits a `::group::Run <step>` log entry followed by the interpolated script, the full shell command line, and the step's env vars (sorted, internal vars filtered out).
2. The existing execution function now has `defer rawLogger.Infof("::endgroup::")` so the group is closed after the step finishes, regardless of success or failure.
### Env var filtering
Internal runner vars are hidden (`GITHUB_*`, `GITEA_*`, `RUNNER_*`, `INPUT_*`, `PATH`, `HOME`) — only user-relevant vars are shown, matching what GitHub Actions displays.
### Example output
```
▼ Run cargo build
cargo build
shell: bash --noprofile --norc -e -o pipefail {0}
env:
CARGO_HOME: /home/runner/.cargo
CARGO_INCREMENTAL: 0
CARGO_TERM_COLOR: always
<actual build output>
```
---------
Co-authored-by: silverwind <2021+silverwind@noreply.gitea.com>
Co-authored-by: silverwind <me@silverwind.io>
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/847
Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com>
Reviewed-by: ChristopherHX <38043+christopherhx@noreply.gitea.com>
|
||
|
|
f2b4dbf05f |
run docker step in host mode (#857)
## Problem
In host executor mode, uses: docker://<image> step actions fail because
act/runner/step_docker.go always attaches the step container to the job
container's network namespace, which doesn't exist in host mode.
### Example
Run following job in host runner
```yaml
jobs:
test:
runs-on: ubuntu-latest-host
steps:
- uses: docker://alpine:3.20
with:
args: echo hello
```
```
Error:
failed to start container: Error response from daemon:
joining network namespace of container:
No such container: xxxxxx
```
This pr allows the docker step in the host mode
## Testing
I tested following steps on host runner and it worked
```yaml
- name: Test azure cli action in host mode
uses: azure/cli@v2
env:
RUNNER_OS: Linux
with:
inlineScript: echo "hello from azure cli"
- uses: docker://alpine:3.20
with:
args: echo hello
```
---------
Co-authored-by: Nicolas <bircni@icloud.com>
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/857
Reviewed-by: Nicolas <bircni@icloud.com>
Co-authored-by: Mirko Sekulic <misha.sekulic@gmail.com>
Co-committed-by: Mirko Sekulic <misha.sekulic@gmail.com>
|
||
|
|
bad4239d18 |
chore(deps): drop unused distribution/reference replace directive (#858)
The `replace github.com/distribution/reference v0.6.0 => v0.5.0` was added defensively in [ |
||
|
|
589db33e70 |
fix(deps): update module github.com/docker/cli to v25.0.7+incompatible (#855)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [github.com/docker/cli](https://github.com/docker/cli) | `v25.0.3+incompatible` → `v25.0.7+incompatible` |  |  | --- ### Release Notes <details> <summary>docker/cli (github.com/docker/cli)</summary> ### [`v25.0.7+incompatible`](https://github.com/docker/cli/compare/v25.0.6...v25.0.7) [Compare Source](https://github.com/docker/cli/compare/v25.0.6...v25.0.7) ### [`v25.0.6+incompatible`](https://github.com/docker/cli/compare/v25.0.5...v25.0.6) [Compare Source](https://github.com/docker/cli/compare/v25.0.5...v25.0.6) ### [`v25.0.5+incompatible`](https://github.com/docker/cli/compare/v25.0.4...v25.0.5) [Compare Source](https://github.com/docker/cli/compare/v25.0.4...v25.0.5) ### [`v25.0.4+incompatible`](https://github.com/docker/cli/compare/v25.0.3...v25.0.4) [Compare Source](https://github.com/docker/cli/compare/v25.0.3...v25.0.4) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/855 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com>v0.5.0 |
||
|
|
1032f857a1 |
fix(deps): update module connectrpc.com/connect to v1.19.2 (#854)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [connectrpc.com/connect](https://github.com/connectrpc/connect-go) | `v1.19.1` → `v1.19.2` |  |  | --- ### Release Notes <details> <summary>connectrpc/connect-go (connectrpc.com/connect)</summary> ### [`v1.19.2`](https://github.com/connectrpc/connect-go/releases/tag/v1.19.2) [Compare Source](https://github.com/connectrpc/connect-go/compare/v1.19.1...v1.19.2) #### What's Changed ##### Governance - Add [@​timostamm](https://github.com/timostamm) as a maintainer in [#​905](https://github.com/connectrpc/connect-go/pull/905) 🎉 ##### Bugfixes - Use 'deadline\_exceeded' instead of 'canceled' on HTTP/2 cancelation when appropriate by [@​jhump](https://github.com/jhump) in [#​904](https://github.com/connectrpc/connect-go/pull/904) - Fix nil pointer deref in duplexHTTPCall under concurrent Send + CloseAndReceive by [@​simonferquel](https://github.com/simonferquel) in [#​919](https://github.com/connectrpc/connect-go/pull/919) ##### Other changes - Refactor memhttptest to work with Go 1.25 synctest by [@​codefromthecrypt](https://github.com/codefromthecrypt) in [#​881](https://github.com/connectrpc/connect-go/pull/881) - Doc clarifications by [@​emcfarlane](https://github.com/emcfarlane) ([#​911](https://github.com/connectrpc/connect-go/issues/911), [#​912](https://github.com/connectrpc/connect-go/issues/912)) and [@​stefanvanburen](https://github.com/stefanvanburen) ([#​906](https://github.com/connectrpc/connect-go/issues/906)) #### New Contributors - [@​codefromthecrypt](https://github.com/codefromthecrypt) made their first contribution in [#​881](https://github.com/connectrpc/connect-go/pull/881) - [@​simonferquel](https://github.com/simonferquel) made their first contribution in [#​919](https://github.com/connectrpc/connect-go/pull/919) **Full Changelog**: </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuNSIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/854 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: Renovate Bot <renovate-bot@gitea.com> Co-committed-by: Renovate Bot <renovate-bot@gitea.com> |
||
|
|
e56b984c04 |
fix: wait for docker supervise dir before s6-svwait (#851)
`s6-svscan` starts services in parallel, so `act_runner/run` could invoke `s6-svwait` before s6 had created the docker service's `supervise/` directory, failing with `s6-svwait: fatal: unable to s6_svstatus_read: No such file or directory`. Poll for the directory before waiting. Fixes #760 --- This PR was written with the help of Claude Opus 4.7 Reviewed-on: https://gitea.com/gitea/runner/pulls/851 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: silverwind <me@silverwind.io> Co-committed-by: silverwind <me@silverwind.io> |
||
|
|
fa5334eb24 |
fix: Heartbeat ReportState for long-running silent jobs (#852)
Fixes #826.
Regressed in
|
||
|
|
7c6f1261d4 |
fix: fetch when other refs get force-pushed (#846)
Due to `NewGitCloneExecutor` fetching all the refs (rather than `GoGitActionCache`), if any refs move in a non-fast-forward fashion, this causes the entire action update to fail. As GitHub has special refs like `pull/N/merge` which are guaranteed to move in a non-fast-forward fashion, this leads actions from GitHub usually failing to update. ``` ☁ git clone 'https://github.com/Mic92/update-flake-inputs-gitea' # ref=main cloning https://github.com/Mic92/update-flake-inputs-gitea to /var/lib/gitea-runner/nix0/.cache/act/9b0155f2957ac84c749f9ecc8afaec823af5ef2e67a104ac655623aee12ca5b2 Non-terminating error while running 'git clone': some refs were not updated ``` With the repo https://github.com/Mic92/update-flake-inputs-gitea, you can notice that it only has a `main` branch that moves in a fast-forward fashion and no tags that could've been force pushed. Fixes #726 --------- Co-authored-by: Michael Hoang <enzime@users.noreply.github.com> Reviewed-on: https://gitea.com/gitea/runner/pulls/846 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Reviewed-by: Nicolas <bircni@icloud.com> Co-authored-by: Michael Hoang <194829+enzime@noreply.gitea.com> Co-committed-by: Michael Hoang <194829+enzime@noreply.gitea.com> |
||
|
|
fbd6316928 |
Merge pull request 'Align root files with gitea' (#844) from silverwind/act_runner:align-makefile-gitea into main
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/844 Reviewed-by: Bo-Yi Wu (吳柏毅) <appleboy.tw@gmail.com> |
||
|
|
ade5b8202e | Merge branch 'main' into align-makefile-gitea | ||
|
|
a31f3962c0 |
Add .dockerignore and align .editorconfig
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com> |
||
|
|
04244fc3f7 |
Add AGENTS.md and CLAUDE.md
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com> |
||
|
|
cb58492678 |
Merge pull request 'upgrade go git and yaml' (#842) from lunny/upgrade_dep into main
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/842 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> |
||
|
|
9faadad0ce |
Add help target and target descriptions
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com> |
||
|
|
352096c5bf |
Align Makefile with gitea
- Fix `GXZ_PAGAGE` typo to `GXZ_PACKAGE`. - Move `gxz`/`xgo` tool installs from `deps-backend` to `deps-tools` and add `golangci-lint` there; `deps-backend` is just `go mod download`. - Use `--color=always` + `printf` in `tidy-check` to match `fmt-check`. - Use STATIC-gated `EXTLDFLAGS` instead of a uname-based toggle, and move `-s -w` out of `EXTLDFLAGS` to match gitea's `-ldflags` layout. - Pass `-s -w -linkmode external -extldflags "-static"` explicitly for release-linux / release-windows; add `-s -w` to release-darwin. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com> |
||
|
|
b5c50bb3ab | upgrade go git | ||
|
|
8af9a2b47a |
Merge gitea/act into act/ folder' (#827)
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/827 Reviewed-by: ChristopherHX <38043+christopherhx@noreply.gitea.com> |
||
|
|
fab2d6ae04 |
Merge gitea/act into act/
Merges the `gitea.com/gitea/act` fork into this repository as the `act/` directory and consumes it as a local package. The `replace github.com/nektos/act => gitea.com/gitea/act` directive is removed; act's dependencies are merged into the root `go.mod`. - Imports rewritten: `github.com/nektos/act/pkg/...` → `gitea.com/gitea/act_runner/act/...` (flattened — `pkg/` boundary dropped to match the layout forgejo-runner adopted). - Dropped act's CLI (`cmd/`, `main.go`) and all upstream project files; kept the library tree + `LICENSE`. - Added `// Copyright <year> The Gitea Authors ...` / `// Copyright <year> nektos` headers to 104 `.go` files. - Pre-existing act lint violations annotated inline with `//nolint:<linter> // pre-existing issue from nektos/act`. `.golangci.yml` is unchanged vs `main`. - Makefile test target: `-race -short` (matches forgejo-runner). - Pre-existing integration test failures fixed: race in parallel executor (atomic counters); TestSetupEnv / command_test / expression_test / run_context_test updated to match gitea fork runtime; TestJobExecutor and TestActionCache gated on `testing.Short()`. Full `gitea/act` commit history is reachable via the second parent. Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com> |
||
|
|
15dd63a839 |
feat: Add support for Dynamic Matrix Strategies with Job Outputs (#149)
# Matrix Strategy: Support for Scalar Values and Template Expressions ## 🎯 Overview This Pull Request implements support for **scalar values and template expressions** in matrix strategies. Previously, every matrix value had to be declared as a YAML array — a bare scalar like `os: ubuntu-latest` or `version: ${{ fromJSON(...) }}` caused silent failures. Now, scalars are automatically wrapped into single-element arrays, enabling the `${{ fromJSON(...) }}` pattern that is commonly used in GitHub Actions workflows for dynamic matrix generation. ## ⚠️ Semantic Changes Two subtle behavior changes are introduced that are worth understanding: ### 1. Scalar matrix values now produce a 1-element matrix expansion **Before this PR:** A scalar value like ```yaml strategy: matrix: os: ubuntu-latest # no brackets ``` failed to decode as `map[string][]interface{}`, so `Matrix()` returned `nil`. The job ran **once, without any matrix context** (`matrix.os` was undefined). **After this PR:** The same input is wrapped to `["ubuntu-latest"]`. The job runs **one matrix iteration** with `matrix.os = "ubuntu-latest"` set. > **Impact on existing workflows:** Workflows that accidentally used bare scalars instead of arrays will now run with a matrix context where they previously did not. The functional result is usually the same, but `matrix.*` variables are now populated. This is considered an improvement, but is a semantic change. --- ### 2. Unevaluated template expressions fall back to a literal string value The actual resolution of `${{ fromJSON(needs.job1.outputs.versions) }}` into an array happens **before** `Matrix()` is called — in `EvaluateYamlNode` inside `pkg/runner/runner.go`. This PR does not change that evaluation path. If evaluation succeeds → the YAML node already contains a proper array → `Matrix()` decodes it normally. If evaluation **fails or is skipped** (e.g., expression not yet resolved) → the scalar string is now wrapped as `["${{ fromJSON(...) }}"]` → the job runs **one iteration with the literal unexpanded string** as the matrix value. > **Note:** The test `TestJobMatrix/matrix_with_template_expression` covers this fallback path, not the successful resolution path. The literal-wrap behavior is the fallback, not the primary mechanism for template expression support. --- ## 🔑 Key Changes ### 1. Flexible Matrix Decoding (`pkg/model/workflow.go`) #### New Helper Function: `normalizeMatrixValue` ```go func normalizeMatrixValue(key string, val interface{}) ([]interface{}, error) ``` - Converts a single matrix value to the expected array format - Handles three cases: 1. **Arrays**: Pass through unchanged 2. **Scalars**: Wrap in single-element array (including template expressions) 3. **Invalid types** (maps, etc.): Return error to detect misconfigurations early **Supported scalar types:** - `string` — including unevaluated template expressions - `int`, `float64` — numeric values - `bool` — boolean values - `nil` — null values #### Enhanced `Matrix()` Method **Before:** ```go func (j *Job) Matrix() map[string][]interface{} { if j.Strategy.RawMatrix.Kind == yaml.MappingNode { var val map[string][]interface{} if !decodeNode(j.Strategy.RawMatrix, &val) { return nil } return val } return nil } ``` **After:** ```go func (j *Job) Matrix() map[string][]interface{} { if j.Strategy == nil || j.Strategy.RawMatrix.Kind != yaml.MappingNode { return nil } // First decode to flexible map[string]interface{} to handle scalars and arrays var flexVal map[string]interface{} err := j.Strategy.RawMatrix.Decode(&flexVal) if err != nil { // If that fails, try the strict array format var val map[string][]interface{} if !decodeNode(j.Strategy.RawMatrix, &val) { return nil } return val } // Convert flexible format to expected format with validation val := make(map[string][]interface{}) for k, v := range flexVal { normalized, err := normalizeMatrixValue(k, v) if err != nil { log.Errorf("matrix validation error: %v", err) return nil } val[k] = normalized } return val } ``` **Key improvements:** - Handles unevaluated template expressions as scalar strings - Automatic conversion to array format for consistent processing - Validation to catch nested maps and invalid configurations - Fallback to strict array format decoding for backward compatibility - Early nil check for strategy to prevent nil pointer panics --- ## 🎁 Use Cases ### Example 1: Template Expression in Matrix (primary motivation) ```yaml jobs: setup: runs-on: ubuntu-latest outputs: versions: ${{ steps.version-map.outputs.versions }} steps: - id: version-map run: echo "versions=[\"1.17\",\"1.18\",\"1.19\"]" >> $GITHUB_OUTPUT test: needs: setup strategy: matrix: # EvaluateYamlNode resolves this to an array before Matrix() is called version: ${{ fromJSON(needs.setup.outputs.versions) }} runs-on: ubuntu-latest steps: - run: echo "Testing version ${{ matrix.version }}" ``` ### Example 2: Mixed Scalar and Array Values ```yaml jobs: build: strategy: matrix: os: [ubuntu-latest, windows-latest] # Array — unchanged go-version: 1.19 # Scalar — wrapped to [1.19] node: [14, 16, 18] # Array — unchanged runs-on: ${{ matrix.os }} ``` ### Example 3: Single Value Matrix ```yaml jobs: deploy: strategy: matrix: environment: production # Scalar — wrapped to ["production"] runs-on: ubuntu-latest ``` --- ## ✅ Benefits - ✨ **Feature Parity with GitHub Actions**: Supports template expressions in matrix strategies - 🔒 **Robust Validation**: Detects misconfigured matrices (nested maps) early - 🔄 **Backward Compatible**: Existing array-based workflows continue to work - 📝 **Clear Error Messages**: Helpful validation messages for debugging - 🛡️ **Type Safety**: Handles all YAML scalar types correctly --- ## 🚀 Breaking Changes **Technically none in a strictly backward-incompatible sense**, but two semantic changes exist (see [⚠️ Semantic Changes](#️-semantic-changes-read-before-merging) above): 1. Scalar matrix values now iterate (previously they caused a `nil` matrix / no iteration) 2. Unevaluated template strings now produce a literal iteration instead of skipping Both changes are improvements in practice, but downstream users should be aware. --- ## 📚 Related Work - Related Gitea Server PR: [go-gitea/gitea#36564](https://github.com/go-gitea/gitea/pull/36564) - Enables dynamic matrix generation from job outputs - Supports advanced CI/CD patterns used in GitHub Actions ## 🔗 References - [GitHub Actions: Matrix strategies](https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs) - [GitHub Actions: Expression syntax](https://docs.github.com/en/actions/learn-github-actions/expressions) - [GitHub Actions: `fromJSON` in matrix context](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix) Reviewed-on: https://gitea.com/gitea/act/pulls/149 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: Pascal Zimmermann <pascal.zimmermann@theiotstudio.com> Co-committed-by: Pascal Zimmermann <pascal.zimmermann@theiotstudio.com> |
||
|
|
9aafec169b |
perf: use single poller with semaphore-based capacity control (#822)
## Background #819 replaced the shared `rate.Limiter` with per-worker exponential backoff counters to add jitter and adaptive polling. Before #819, the poller used: ```go limiter := rate.NewLimiter(rate.Every(p.cfg.Runner.FetchInterval), 1) ``` This limiter was **shared across all N polling goroutines with burst=1**, effectively serializing their `FetchTask` calls — so even with `capacity=60`, the runner issued roughly one `FetchTask` per `FetchInterval` total. #819 replaced this with independent per-worker `consecutiveEmpty` / `consecutiveErrors` counters. Each goroutine now backs off **independently**, which inadvertently removed the cross-worker serialization. With `capacity=N`, the runner now has N goroutines each polling on their own schedule — a regression from the pre-#819 baseline for any runner with `capacity > 1`. (Thanks to @ChristopherHX for catching this in review.) ## Problem With the post-#819 code: - `capacity=N` maintains **N persistent polling goroutines**, each calling `FetchTask` independently - At idle, N goroutines each wake up and send a `FetchTask` RPC per `FetchInterval` - At full load, N goroutines **continue polling** even though no slot is available to run a new task — every one of those RPCs is wasted - The `Shutdown()` timeout branch has a pre-existing bug: the "non-blocking check" is actually a blocking receive, so `shutdownJobs()` is never reached on timeout ## Real-World Impact: 3 Runners × capacity=60 Current production environment: 3 runners each with `capacity=60`. | Metric | Post-#819 (current) | This PR | Reduction | |--------|---------------------|---------|-----------| | Polling goroutines (total) | 3 × 60 = **180** | 3 × 1 = **3** | **98.3%** (177 fewer) | | FetchTask RPCs per poll cycle (idle) | **180** | **3** | **98.3%** | | FetchTask RPCs per poll cycle (full load) | **180** (all wasted) | **0** (blocked on semaphore) | **100%** | | Concurrent connections to Gitea | **180** | **3** | **98.3%** | | Backoff state objects | 180 (per-worker) | 3 (one per runner) | Simplified | ### Idle scenario All 180 goroutines wake up every `FetchInterval`, each sending a `FetchTask` RPC that returns empty. Server handles 180 RPCs per cycle for zero useful work. After this PR: **3 RPCs per cycle** — one per runner. > Note: pre-#819 idle behavior was already ~3 RPCs/cycle due to the shared `rate.Limiter`. This PR restores that property while also addressing the full-load case below. ### Full-load scenario (all 180 slots occupied) All 180 goroutines **continue polling** even though no slot is available. Every RPC is wasted. After this PR: all 3 pollers are **blocked on the semaphore** — **zero RPCs** until a task completes. > This is a scenario neither the pre-#819 shared limiter nor the post-#819 per-worker backoff handles — both still issue `FetchTask` RPCs when no slot is free. The semaphore is the only approach of the three that ties polling to available capacity. ## Why Not Just Revert to `rate.Limiter`? Reverting would restore the serialized behavior but is not the right long-term fix: - **`rate.Limiter` has no concept of available capacity.** At full load it still hands out tokens and issues `FetchTask` RPCs that can't be acted on. The semaphore blocks polling entirely in that case — zero wasted RPCs. - **It composes poorly with adaptive backoff from #819.** A shared limiter and per-worker backoff pull in different directions. - **N goroutines serializing on a shared limiter means N-1 of them exist only to wait in line.** A single poller expresses the same behavior more directly. The semaphore approach ties polling to capacity explicitly: `acquire slot → fetch → dispatch → release`. That invariant becomes structural rather than emergent from a rate limiter. ## Solution Replace N polling goroutines with a **single polling loop** that uses a buffered channel as a semaphore to control concurrent task execution: ```go // New: poller.go Poll() sem := make(chan struct{}, p.cfg.Runner.Capacity) for { select { case sem <- struct{}{}: // Acquire slot (blocks at capacity) case <-p.pollingCtx.Done(): return } task, ok := p.fetchTask(...) // Single FetchTask RPC if !ok { <-sem // Release slot on empty response // backoff... continue } go func(t *runnerv1.Task) { // Dispatch task defer func() { <-sem }() // Release slot when done p.runTaskWithRecover(p.jobsCtx, t) }(task) } ``` The exponential backoff and jitter from #819 are preserved — just driven by a single `workerState` instead of N per-worker states. ## Shutdown Bug Fix Fixed a pre-existing bug in `Shutdown()` where the timeout branch could never force-cancel running jobs: ```go // Before (BROKEN): blocking receive, shutdownJobs() never reached _, ok := <-p.done // blocks until p.done is closed if !ok { return nil } p.shutdownJobs() // dead code when jobs are still running // After (FIXED): proper non-blocking check select { case <-p.done: return nil default: } p.shutdownJobs() // now correctly reached on timeout ``` ## Code Changes | Area | Detail | |------|--------| | `Poller.runner` | `*run.Runner` → `TaskRunner` interface (enables mock-based testing) | | `Poll()` | N goroutines → single loop with buffered-channel semaphore | | `PollOnce()` | Inlined from removed `pollOnce()` | | `waitBackoff()` | New helper, eliminates duplicated backoff logic | | `resetBackoff()` | New method on `workerState`, also resets stale `lastBackoff` metric | | `Shutdown()` | Fixed blocking receive → proper non-blocking select | | Removed | `poll()`, `pollOnce()` private methods (-2 methods, -42 lines) | ## Test Coverage Added `TestPoller_ConcurrencyLimitedByCapacity` which verifies: - With `capacity=3`, at most 3 tasks execute concurrently (`maxConcurrent <= 3`) - Tasks actually overlap in execution (`maxConcurrent >= 2`) - `FetchTask` is never called concurrently — confirms single poller (`maxFetchConcur == 1`) - All 6 tasks complete successfully (`totalCompleted == 6`) - Mock runner respects context cancellation, enabling shutdown path verification ``` === RUN TestPoller_ConcurrencyLimitedByCapacity --- PASS: TestPoller_ConcurrencyLimitedByCapacity (0.10s) PASS ok gitea.com/gitea/act_runner/internal/app/poll 0.59s ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://gitea.com/gitea/act_runner/pulls/822 Reviewed-by: silverwind <2021+silverwind@noreply.gitea.com> Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com> Co-committed-by: Bo-Yi Wu <appleboy.tw@gmail.com>v0.4.1 |
||
|
|
f923badec7 |
Use golangci-lint fmt to format code (#163)
Use `golangci-lint fmt` to format code, upgrading `.golangci.yml` to v2 and mirroring the linter configuration used by https://github.com/go-gitea/gitea. `gci` now handles import ordering into standard, project-local, blank, and default groups. Mirrors https://github.com/go-gitea/gitea/pull/37194. Changes: - Upgrade `.golangci.yml` to v2 format with the same linter set as gitea (minus `prealloc`, `unparam`, `testifylint`, `nilnil` which produced too many pre-existing issues) - Add path-based exclusions (`bodyclose`, `gosec` in tests; `gosec:G115`/`G117` globally) - Run lint via `make lint-go` in CI instead of `golangci/golangci-lint-action`, matching the pattern used by other Gitea repos - Apply safe auto-fixes (`modernize`, `perfsprint`, `usetesting`, etc.) - Add explanations to existing `//nolint` directives - Remove dead code (unused `newRemoteReusableWorkflow` and `networkName`), duplicate imports, and shadowed `max` builtins - Replace deprecated `docker/distribution/reference` with `distribution/reference` - Fix `Deprecated:` comment casing and simplify nil/len checks --- This PR was written with the help of Claude Opus 4.7 Reviewed-on: https://gitea.com/gitea/act/pulls/163 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: silverwind <me@silverwind.io> Co-committed-by: silverwind <me@silverwind.io> |
||
|
|
48944e136c |
Use golangci-lint fmt to format code (#823)
Use `golangci-lint fmt` to format code, replacing the previous gofumpt-based formatter. https://github.com/daixiang0/gci is used to order the imports. Also drops the `gitea-vet` dependency since `gci` now handles import ordering. Mirrors https://github.com/go-gitea/gitea/pull/37194. --- This PR was written with the help of Claude Opus 4.7 Reviewed-on: https://gitea.com/gitea/act_runner/pulls/823 Reviewed-by: Nicolas <173651+bircni@noreply.gitea.com> Co-authored-by: silverwind <me@silverwind.io> Co-committed-by: silverwind <me@silverwind.io> |
||
|
|
40dcee0991 |
chore(deps): upgrade golangci-lint from v2.10.1 to v2.11.4 (#821)
## Summary - Bump golangci-lint from v2.10.1 to v2.11.4 - Remove unused `//nolint:revive` directive on metrics package declaration (detected by stricter nolintlint in new version) ## Changes between v2.10.1 and v2.11.4 - **v2.11.0** — Multiple linter dependency upgrades, Go 1.26 support - **v2.11.2** — Bug fix for `fmt` with path - **v2.11.3** — gosec update - **v2.11.4** — Dependency updates (sqlclosecheck, noctx, etc.) No breaking changes. Reviewed-on: https://gitea.com/gitea/act_runner/pulls/821 Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com> Co-committed-by: Bo-Yi Wu <appleboy.tw@gmail.com>v0.4.0 |
||
|
|
f33e5a6245 |
feat: add Prometheus metrics endpoint for runner observability (#820)
## What
Add an optional Prometheus `/metrics` HTTP endpoint to `act_runner` so operators can observe runner health, polling behavior, job outcomes, and RPC latency without scraping logs.
New surface:
- `internal/pkg/metrics/metrics.go` — metric definitions, custom `Registry`, static Go/process collectors, label constants, `ResultToStatusLabel` helper.
- `internal/pkg/metrics/server.go` — hardened `http.Server` serving `/metrics` and `/healthz` with Slowloris-safe timeouts (`ReadHeaderTimeout` 5s, `ReadTimeout`/`WriteTimeout` 10s, `IdleTimeout` 60s) and a 5s graceful shutdown.
- `daemon.go` wires it up behind `cfg.Metrics.Enabled` (disabled by default).
- `poller.go` / `reporter.go` / `runner.go` instrument their existing hot paths with counters/histograms/gauges — no behavior change.
Metrics exported (namespace `act_runner_`):
| Subsystem | Metric | Type | Labels |
|---|---|---|---|
| — | `info` | Gauge | `version`, `name` |
| — | `capacity`, `uptime_seconds` | Gauge | — |
| `poll` | `fetch_total`, `client_errors_total` | Counter | `result` / `method` |
| `poll` | `fetch_duration_seconds`, `backoff_seconds` | Histogram / Gauge | — |
| `job` | `total` | Counter | `status` |
| `job` | `duration_seconds`, `running`, `capacity_utilization_ratio` | Histogram / GaugeFunc | — |
| `report` | `log_total`, `state_total` | Counter | `result` |
| `report` | `log_duration_seconds`, `state_duration_seconds` | Histogram | — |
| `report` | `log_buffer_rows` | Gauge | — |
| — | `go_*`, `process_*` | standard collectors | — |
All label values are predefined constants — **no high-cardinality labels** (no task IDs, repo URLs, branches, tokens, or secrets) so scraping is safe and bounded.
## Why
Teams self-hosting Gitea + `act_runner` at scale need to answer basic SRE questions that are currently invisible:
- How often are RPCs failing? Which RPC? (`act_runner_client_errors_total`)
- Are runners saturated? (`act_runner_job_capacity_utilization_ratio`, `act_runner_job_running`)
- How long do jobs take? (`act_runner_job_duration_seconds`)
- Is polling backing off? (`act_runner_poll_backoff_seconds`, `act_runner_poll_fetch_total{result=\"error\"}`)
- Are log/state reports slow? (`act_runner_report_{log,state}_duration_seconds`)
- Is the log buffer draining? (`act_runner_report_log_buffer_rows`)
Today operators have to grep logs. This PR makes all of the above first-class metrics so they can feed dashboards and alerts (`rate(act_runner_client_errors_total[5m]) > 0.1`, capacity saturation alerts, etc.).
The endpoint is **disabled by default** and binds to `127.0.0.1:9101` when enabled, so it's opt-in and safe for existing deployments.
## How
### Config
```yaml
metrics:
enabled: false # opt-in
addr: 127.0.0.1:9101 # change to 0.0.0.0:9101 only behind a reverse proxy
```
`config.example.yaml` documents both fields plus a security note about binding externally without auth.
### Wiring
1. `daemon.go` calls `metrics.Init()` (guarded by `sync.Once`), sets `act_runner_info`, `act_runner_capacity`, registers uptime + running-jobs GaugeFuncs, then starts the server goroutine with the daemon context — it shuts down cleanly on `ctx.Done()`.
2. `poller.fetchTask` observes RPC latency / result / error counters. `DeadlineExceeded` (long-poll idle) is treated as an empty result and **not** observed into the histogram so the 5s timeout doesn't swamp the buckets.
3. `poller.pollOnce` reports `poll_backoff_seconds` using the pre-jitter base interval (the true backoff level), and only when it changes — prevents noisy no-op gauge updates at the `FetchIntervalMax` plateau.
4. `reporter.ReportLog` / `ReportState` record duration histograms and success/error counters; `log_buffer_rows` is updated only when the value changes, guarded by the already-held `clientM`.
5. `runner.Run` observes `job_duration_seconds` and increments `job_total` by outcome via `metrics.ResultToStatusLabel`.
### Safety / security review
- All timeouts set; Slowloris-safe.
- Custom `prometheus.NewRegistry()` — no global registration side-effects.
- No sensitive data in labels (reviewed every instrumentation site).
- Single new dependency: `github.com/prometheus/client_golang v1.23.2`.
- Endpoint is unauthenticated by design and documented as such; default localhost bind mitigates exposure. Operators exposing externally should front it with a reverse proxy.
## Verification
### Unit tests
\`\`\`bash
go build ./...
go vet ./...
go test ./...
\`\`\`
### Manual smoke test
1. Enable metrics in `config.yaml`:
\`\`\`yaml
metrics:
enabled: true
addr: 127.0.0.1:9101
\`\`\`
2. Start the runner against a Gitea instance: \`./act_runner daemon\`.
3. Scrape the endpoint:
\`\`\`bash
curl -s http://127.0.0.1:9101/metrics | grep '^act_runner_'
curl -s http://127.0.0.1:9101/healthz # → ok
\`\`\`
4. Confirm the static series appear immediately: \`act_runner_info\`, \`act_runner_capacity\`, \`act_runner_uptime_seconds\`, \`act_runner_job_running\`, \`act_runner_job_capacity_utilization_ratio\`.
5. Trigger a workflow and confirm counters increment: \`act_runner_poll_fetch_total{result=\"task\"}\`, \`act_runner_job_total{status=\"success\"}\`, \`act_runner_report_log_total{result=\"success\"}\`.
6. Leave the runner idle and confirm \`act_runner_poll_backoff_seconds\` settles (and does **not** churn on every poll).
7. Ctrl-C and confirm a clean \"metrics server shutdown\" log line (no port-in-use error on restart within 5s).
### Prometheus integration
Add to \`prometheus.yml\`:
\`\`\`yaml
scrape_configs:
- job_name: act_runner
static_configs:
- targets: ['127.0.0.1:9101']
\`\`\`
Sample alert to try:
\`\`\`
sum(rate(act_runner_client_errors_total[5m])) by (method) > 0.1
\`\`\`
## Out of scope (follow-ups)
- TLS and auth on the metrics endpoint (mitigated today by localhost default; add when operators need external scraping).
- Per-task labels (intentionally avoided for cardinality safety).
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/820
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com>
Co-committed-by: Bo-Yi Wu <appleboy.tw@gmail.com>
|
||
|
|
f2d545565f |
perf: reduce runner-to-server connection load with adaptive reporting and polling (#819)
## Summary Many teams self-host Gitea + Act Runner at scale. The current runner design causes excessive HTTP requests to the Gitea server, leading to high server load. This PR addresses three root causes: aggressive fixed-interval polling, per-task status reporting every 1 second regardless of activity, and unoptimized HTTP client configuration. ## Problem The original architecture has these issues: **1. Fixed 1-second reporting interval (RunDaemon)** - Every running task calls ReportLog + ReportState every 1 second (2 HTTP requests/sec/task) - These requests are sent even when there are no new log rows or state changes - With 200 runners × 3 tasks each = **1,200 req/sec just for status reporting** **2. Fixed 2-second polling interval (no backoff)** - Idle runners poll FetchTask every 2 seconds forever, even when no jobs are queued - No exponential backoff or jitter — all runners can synchronize after network recovery (thundering herd) - 200 idle runners = **100 req/sec doing nothing useful** **3. HTTP client not tuned** - Uses http.DefaultClient with MaxIdleConnsPerHost=2, causing frequent TCP/TLS reconnects - Creates two separate http.Client instances (one for Ping, one for Runner service) instead of sharing **Total: ~1,300 req/sec for 200 runners with 3 tasks each** ## Solution ### Adaptive Event-Driven Log Reporting Replace the recursive `time.AfterFunc(1s)` pattern in RunDaemon with a goroutine-based select event loop using three trigger mechanisms: | Trigger | Default | Purpose | |---------|---------|---------| | `log_report_max_latency` | 3s | Guarantee even a single log line is delivered within this time | | `log_report_interval` | 5s | Periodic sweep — steady-state cadence | | `log_report_batch_size` | 100 rows | Immediate flush during bursty output (e.g., npm install) | **Key design**: `log_report_max_latency` (3s) must be less than `log_report_interval` (5s) so the max-latency timer fires before the periodic ticker for single-line scenarios. State reporting is decoupled to its own `state_report_interval` (default 5s), with immediate flush on step transitions (start/stop) via a stateNotify channel for responsive frontend UX. Additionally: - Skip ReportLog when `len(rows) == 0` (no pending log rows) - Skip ReportState when `stateChanged == false && len(outputs) == 0` (nothing changed) - Move expensive `proto.Clone` after the early-return check to avoid deep copies on no-op paths ### Polling Backoff with Jitter Replace fixed `rate.Limiter` with adaptive exponential backoff: - Track `consecutiveEmpty` and `consecutiveErrors` counters - Interval doubles with each empty/error response: `base × 2^(n-1)`, capped at `fetch_interval_max` (default 60s) - Add ±20% random jitter to prevent thundering herd - Fetch first, sleep after ��� preserves burst=1 behavior for immediate first fetch on startup and after task completion ### HTTP Client Tuning - Configure custom `http.Transport` with `MaxIdleConnsPerHost=10` (was 2) - Share a single `http.Client` between PingService and RunnerService - Add `IdleConnTimeout=90s` for clean connection lifecycle ## Load Reduction For 200 runners × 3 tasks (70% with active log output): | Component | Before | After | Reduction | |-----------|--------|-------|-----------| | Polling (idle) | 100 req/s | ~3.4 req/s | 97% | | Log reporting | 420 req/s | ~84 req/s | 80% | | State reporting | 126 req/s | ~25 req/s | 80% | | **Total** | **~1,300 req/s** | **~113 req/s** | **~91%** | ## Frontend UX Impact | Scenario | Before | After | Notes | |----------|--------|-------|-------| | Continuous output (npm install) | ~1s | ~5s | Periodic ticker sweep | | Single line then silence | ~1s | ≤3s | maxLatencyTimer guarantee | | Bursty output (100+ lines) | ~1s | <1s | Batch size immediate flush | | Step start/stop | ~1s | <1s | stateNotify immediate flush | | Job completion | ~1s | ~1s | Close() retry unchanged | ## New Configuration Options All have safe defaults — existing config files need no changes: ```yaml runner: fetch_interval_max: 60s # Max backoff interval when idle log_report_interval: 5s # Periodic log flush interval log_report_max_latency: 3s # Max time a log row waits (must be < log_report_interval) log_report_batch_size: 100 # Immediate flush threshold state_report_interval: 5s # State flush interval (step transitions are always immediate) ``` Config validation warns on invalid combinations: - `fetch_interval_max < fetch_interval` → auto-corrected - `log_report_max_latency >= log_report_interval` → warning (timer would be redundant) ## Test Plan - [x] `go build ./...` passes - [x] `go test ./...` passes (all existing + 3 new tests) - [x] `golangci-lint run` — 0 issues - [x] TestReporter_MaxLatencyTimer — verifies single log line flushed by maxLatencyTimer before logTicker - [x] TestReporter_BatchSizeFlush — verifies batch size threshold triggers immediate flush - [x] TestReporter_StateNotifyFlush — verifies step transition triggers immediate state flush - [x] TestReporter_EphemeralRunnerDeletion — verifies Close/RunDaemon race safety - [x] TestReporter_RunDaemonClose_Race — verifies concurrent Close safety Reviewed-on: https://gitea.com/gitea/act_runner/pulls/819 Reviewed-by: Nicolas <173651+bircni@noreply.gitea.com> Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com> Co-committed-by: Bo-Yi Wu <appleboy.tw@gmail.com> |
||
|
|
90c1275f0e |
Upgrade yaml (#816)
~wait https://gitea.com/gitea/act/pulls/157~ Reviewed-on: https://gitea.com/gitea/act_runner/pulls/816 Reviewed-by: Zettat123 <39446+zettat123@noreply.gitea.com> |
||
|
|
3232358e71 |
downgrade yaml from rc.4 to rc.3 and upgrade action lint (#158)
Reviewed-on: https://gitea.com/gitea/act/pulls/158 Reviewed-by: Zettat123 <39446+zettat123@noreply.gitea.com> |
||
|
|
2e98baa34a |
Upgrade yaml (#157)
Reviewed-on: https://gitea.com/gitea/act/pulls/157 Reviewed-by: Zettat123 <39446+zettat123@noreply.gitea.com> |
||
|
|
505907eb2a |
Add run_attempt to context (#632)
Blocked by https://gitea.com/gitea/act/pulls/126 Fix https://github.com/go-gitea/gitea/issues/33135 --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Reviewed-on: https://gitea.com/gitea/act_runner/pulls/632 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Zettat123 <zettat123@gmail.com> Co-committed-by: Zettat123 <zettat123@gmail.com>v0.3.1 |