Compare commits

...

65 commits

Author SHA1 Message Date
d97839cd90
fix(workflow): point to correct repo
Some checks failed
cascade / debug (push) Failing after 0s
cascade / forgejo (push) Failing after 0s
checks / build and test (push) Failing after 1s
checks / validate mocks (push) Failing after 0s
checks / validate pre-commit-hooks file (push) Failing after 0s
ci / goreleaser (push) Successful in 5m40s
checks / runner integration tests (push) Has been cancelled
example / docker-build-push-action-in-lxc (push) Has been cancelled
/ example-docker-compose (push) Has been cancelled
/ example-lxc-systemd (push) Has been cancelled
checks / integration tests (push) Has been cancelled
checks / runner exec tests (push) Has been cancelled
Build release / release (push) Has been cancelled
publish / publish (push) Has been cancelled
2025-10-30 09:09:10 +00:00
1f8217d99b
fix(workflow): remove go generate from goreleaser
Some checks failed
example / docker-build-push-action-in-lxc (push) Waiting to run
/ example-docker-compose (push) Waiting to run
/ example-lxc-systemd (push) Waiting to run
cascade / forgejo (push) Failing after 0s
checks / build and test (push) Failing after 0s
cascade / debug (push) Failing after 0s
checks / validate mocks (push) Failing after 0s
checks / validate pre-commit-hooks file (push) Failing after 0s
ci / goreleaser (push) Failing after 5m37s
checks / integration tests (push) Has been cancelled
checks / runner exec tests (push) Has been cancelled
checks / runner integration tests (push) Has been cancelled
Build release / release (push) Has been cancelled
publish / publish (push) Has been cancelled
2025-10-30 08:57:37 +00:00
cd83c525c8
chore(workflow): set up simpler build pipeline
Some checks failed
example / docker-build-push-action-in-lxc (push) Waiting to run
/ example-docker-compose (push) Waiting to run
/ example-lxc-systemd (push) Waiting to run
cascade / debug (push) Failing after 0s
cascade / forgejo (push) Failing after 0s
checks / build and test (push) Failing after 0s
checks / validate mocks (push) Failing after 0s
checks / validate pre-commit-hooks file (push) Failing after 0s
ci / goreleaser (push) Failing after 3m59s
checks / integration tests (push) Has been cancelled
checks / runner exec tests (push) Has been cancelled
checks / runner integration tests (push) Has been cancelled
Build release / release (push) Has been cancelled
publish / publish (push) Has been cancelled
2025-10-30 08:48:02 +00:00
88e6654a6c feat(runner): Added waiting for a job arrival in the one-job command. 2025-10-29 11:12:12 +01:00
Renovate Bot
10a9ab9001
Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.7 (#1113)
Some checks are pending
Build release / release (push) Waiting to run
publish / publish (push) Waiting to run
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [code.forgejo.org/forgejo/forgejo](https://forgejo.org) ([source](https://codeberg.org/forgejo/forgejo)) | patch | `11.0.6` -> `11.0.7` |

---

### Release Notes

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

### [`v11.0.7`](https://codeberg.org/forgejo/forgejo/releases/tag/v11.0.7)

[Compare Source](https://codeberg.org/forgejo/forgejo/compare/v11.0.6...v11.0.7)

See <https://codeberg.org/forgejo/forgejo/src/branch/forgejo/release-notes-published/11.0.7.md>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNTIuOSIsInVwZGF0ZWRJblZlciI6IjQxLjE1Mi45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1113
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-27 07:33:24 +00:00
volkmnv
ea961a70c3
fix: windows compilation (#1101)
Original pull request: https://code.forgejo.org/forgejo/runner/pulls/987
Fixes https://code.forgejo.org/forgejo/runner/issues/1032

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1101): <!--number 1101 --><!--line 0 --><!--description Zml4OiB3aW5kb3dzIGNvbXBpbGF0aW9u-->fix: windows compilation<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1101
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: volkmnv <volkmnv@noreply.code.forgejo.org>
Co-committed-by: volkmnv <volkmnv@noreply.code.forgejo.org>
2025-10-24 07:00:43 +00:00
Renovate Bot
8a98a8a512
Update data.forgejo.org/oci/golang Docker tag to v1.25 (#1110)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [data.forgejo.org/oci/golang](https://hub.docker.com/_/golang) ([source](https://github.com/docker-library/golang)) | stage | minor | `1.24-alpine3.22` -> `1.25-alpine3.22` |

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNTIuOSIsInVwZGF0ZWRJblZlciI6IjQxLjE1Mi45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1110
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-24 06:37:56 +00:00
Earl Warren
2301db6f85
fix: ${{ env.VAR }} is allowed in container (#1108)
Resolves forgejo/forgejo-actions-feature-requests#62

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1108): <!--number 1108 --><!--line 0 --><!--description Zml4OiAke3sgZW52LlZBUiB9fSBpcyBhbGxvd2VkIGluIGNvbnRhaW5lcg==-->fix: ${{ env.VAR }} is allowed in container<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1108
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-10-22 06:31:45 +00:00
Renovate Bot
aab9e22819 Update dependency forgejo/lxc-helpers to v1.1.3 (#1106)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [forgejo/lxc-helpers](https://code.forgejo.org/forgejo/lxc-helpers) | patch | `1.1.1` -> `1.1.3` |

---

### Release Notes

<details>
<summary>forgejo/lxc-helpers (forgejo/lxc-helpers)</summary>

### [`v1.1.3`](https://code.forgejo.org/forgejo/lxc-helpers/compare/v1.1.2...v1.1.3)

[Compare Source](https://code.forgejo.org/forgejo/lxc-helpers/compare/v1.1.2...v1.1.3)

### [`v1.1.2`](https://code.forgejo.org/forgejo/lxc-helpers/compare/v1.1.1...v1.1.2)

[Compare Source](https://code.forgejo.org/forgejo/lxc-helpers/compare/v1.1.1...v1.1.2)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNTIuOSIsInVwZGF0ZWRJblZlciI6IjQxLjE1Mi45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1106
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-21 03:21:33 +00:00
Earl Warren
403489591e
Revert "chore(cleanup): lxc-helpers does not need a global lock (#1047)" (#1103)
This reverts commit 996ac343ee.

The lock is still needed to guard against the following scenario.

d92a892ece/act/runner/run_context.go (L225-L236)

- two or more jobs start
- one of them creates the act template (`lxc_build_template $(lxc_template_release) $name`) - lxc-helpers now has transactions and they won't race against each other
- once it is built all jobs will then try to install node in the container that was just built and race against each other

with a global lock only the first one will build and populate the act template. The other will then do nothing because it already exists.

The bug can trivially be reproduced with:

```yaml
on:
  pull_request:

jobs:
  test1:
    runs-on: lxc
    steps:
      - run: echo OK1
  test2:
    runs-on: lxc
    steps:
      - run: echo OK2
  test3:
    runs-on: lxc
    steps:
      - run: echo OK3
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1103): <!--number 1103 --><!--line 0 --><!--description UmV2ZXJ0ICJjaG9yZShjbGVhbnVwKTogbHhjLWhlbHBlcnMgZG9lcyBub3QgbmVlZCBhIGdsb2JhbCBsb2NrICgjMTA0Nyki-->Revert "chore(cleanup): lxc-helpers does not need a global lock (#1047)"<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1103
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: limiting-factor <limiting-factor@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-10-20 21:05:05 +00:00
cascading-pr
8034eaaabb
fix: lxc_exists_and_apt_not_old must be in a transaction (#1104)
cascading-pr from https://code.forgejo.org/forgejo/lxc-helpers/pulls/52

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1104): <!--number 1104 --><!--line 0 --><!--description Zml4OiBseGNfZXhpc3RzX2FuZF9hcHRfbm90X29sZCBtdXN0IGJlIGluIGEgdHJhbnNhY3Rpb24=-->fix: lxc_exists_and_apt_not_old must be in a transaction<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: cascading-pr <cascading-pr@example.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1104
Reviewed-by: limiting-factor <limiting-factor@noreply.code.forgejo.org>
Co-authored-by: cascading-pr <cascading-pr@noreply.code.forgejo.org>
Co-committed-by: cascading-pr <cascading-pr@noreply.code.forgejo.org>
2025-10-20 21:03:14 +00:00
Earl Warren
44f4557005
chore(ci): use code.forgejo.org/oci/alpine:latest (#1100)
The current AWS outage revealed one location still using docker.io instead of the code.forgejo.org mirror:

```
2025-10-20T09:22:44.6442259Z [actions-with-environment-and-context-tests/check] [DEBUG] Head "https://registry-1.docker.io/v2/library/alpine/manifests/3": received unexpected HTTP status: 503 Service Unavailable
```

https://code.forgejo.org/forgejo/runner/actions/runs/11442/jobs/2/attempt/3#jobstep-5-56398

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1100): <!--number 1100 --><!--line 0 --><!--description Y2hvcmUoY2kpOiB1c2UgY29kZS5mb3JnZWpvLm9yZy9vY2kvYWxwaW5lOmxhdGVzdA==-->chore(ci): use code.forgejo.org/oci/alpine:latest<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1100
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-10-20 15:18:52 +00:00
cascading-pr
d92a892ece
fix: enforce LXC bootstrap locks (#1098)
cascading-pr from https://code.forgejo.org/forgejo/lxc-helpers/pulls/51

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1098): <!--number 1098 --><!--line 0 --><!--description Zml4OiBlbmZvcmNlIExYQyBib290c3RyYXAgbG9ja3M=-->fix: enforce LXC bootstrap locks<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: cascading-pr <cascading-pr@example.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1098
Co-authored-by: cascading-pr <cascading-pr@noreply.code.forgejo.org>
Co-committed-by: cascading-pr <cascading-pr@noreply.code.forgejo.org>
2025-10-20 11:55:59 +00:00
Andrew Cassidy
a7487dadd7
fix: use automatic IP detection instead of cache proxy host config value for internal cache server (#1088)
The description for the `cache.host` config value is

```
  # The IP or hostname (195.84.20.30 or example.com) to use when constructing
  # ACTIONS_CACHE_URL which is the URL of the cache proxy.
```

however the internal cache *server* was being started using that value, despite it clearly stating its for the *proxy*.

While the address used to contact the cache proxy from the job is *usually* the same as the address for the cache proxy to contact the server, that is not the case with custom /etc/hosts entries, like what is used for the `host.containers.internal` address, which is needed for contacting the cache proxy on rootless podman (see #1075).

Since the cache proxy and internal cache server are always running on the same host (or container), it's safe to use localhost for the server address instead.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1088): <!--number 1088 --><!--line 0 --><!--description Zml4OiB1c2UgYXV0b21hdGljIElQIGRldGVjdGlvbiBpbnN0ZWFkIG9mIGNhY2hlIHByb3h5IGhvc3QgY29uZmlnIHZhbHVlIGZvciBpbnRlcm5hbCBjYWNoZSBzZXJ2ZXI=-->fix: use automatic IP detection instead of cache proxy host config value for internal cache server<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1088
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Reviewed-by: Kwonunn <kwonunn@noreply.code.forgejo.org>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Andrew Cassidy <drewcassidy@me.com>
Co-committed-by: Andrew Cassidy <drewcassidy@me.com>
2025-10-16 07:42:36 +00:00
Renovate Bot
aa6eef94fd
Update module golang.org/x/time to v0.14.0 (#1094)
This PR contains the following updates:

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

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDYuMCIsInVwZGF0ZWRJblZlciI6IjQxLjE0Ni4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1094
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-16 07:40:55 +00:00
Renovate Bot
f31a1b031e
Update module github.com/avast/retry-go/v4 to v4.7.0 (#1092)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/avast/retry-go/v4](https://github.com/avast/retry-go) | `v4.6.1` -> `v4.7.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2favast%2fretry-go%2fv4/v4.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2favast%2fretry-go%2fv4/v4.6.1/v4.7.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>avast/retry-go (github.com/avast/retry-go/v4)</summary>

### [`v4.7.0`](https://github.com/avast/retry-go/releases/tag/v4.7.0)

[Compare Source](https://github.com/avast/retry-go/compare/4.6.1...4.7.0)

#### What's Changed

- support context cancel cause by [@&#8203;NivKeidan](https://github.com/NivKeidan) in [#&#8203;117](https://github.com/avast/retry-go/pull/117)
- Bump github.com/stretchr/testify from 1.10.0 to 1.11.1 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;136](https://github.com/avast/retry-go/pull/136)
- Add FullJitterBackoffDelay  by [@&#8203;amirrezafahimi](https://github.com/amirrezafahimi) in [#&#8203;128](https://github.com/avast/retry-go/pull/128)
- No delay after final retry on max attempts by [@&#8203;StounhandJ](https://github.com/StounhandJ) in [#&#8203;129](https://github.com/avast/retry-go/pull/129)
- BackOffDelay multiplies attempts from zero by [@&#8203;StounhandJ](https://github.com/StounhandJ) in [#&#8203;130](https://github.com/avast/retry-go/pull/130)
- add Go version 1.25 to test matrix for expanded compatibility testing by [@&#8203;JaSei](https://github.com/JaSei) in [#&#8203;142](https://github.com/avast/retry-go/pull/142)

#### New Contributors

- [@&#8203;NivKeidan](https://github.com/NivKeidan) made their first contribution in [#&#8203;117](https://github.com/avast/retry-go/pull/117)
- [@&#8203;amirrezafahimi](https://github.com/amirrezafahimi) made their first contribution in [#&#8203;128](https://github.com/avast/retry-go/pull/128)
- [@&#8203;StounhandJ](https://github.com/StounhandJ) made their first contribution in [#&#8203;129](https://github.com/avast/retry-go/pull/129)

**Full Changelog**: <https://github.com/avast/retry-go/compare/4.6.1...v4.7.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDYuMCIsInVwZGF0ZWRJblZlciI6IjQxLjE0Ni4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1092
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-15 06:54:17 +00:00
Andrew Cassidy
2de7e57e08
chore: log reason reverse proxy can't be started (#1089)
Following on to #1065, the reason that the reverse proxy cannot be started (such as an invalid cache server URL) wasn't being logged.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1089): <!--number 1089 --><!--line 0 --><!--description Y2hvcmU6IGxvZyByZWFzb24gcmV2ZXJzZSBwcm94eSBjYW4ndCBiZSBzdGFydGVk-->chore: log reason reverse proxy can't be started<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1089
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Andrew Cassidy <drewcassidy@me.com>
Co-committed-by: Andrew Cassidy <drewcassidy@me.com>
2025-10-14 08:08:03 +00:00
Renovate Bot
05795ee286
Update dependency go to v1.24.9 (#1087)
This PR contains the following updates:

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDYuMCIsInVwZGF0ZWRJblZlciI6IjQxLjE0Ni4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1087
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-14 08:07:05 +00:00
Roman K.
f48e9b3ba6 fix: prevent premature token revocation in reusable workflows (#1081)
## Problem

When using reusable workflows, the Forgejo runner prematurely revokes `GITHUB_TOKEN` after the first step completes, causing subsequent steps to fail with authentication errors.

### Reproduction

When the reusable workflow contains multiple steps that require authentication:
1. First step (e.g., checkout) completes successfully
2. Reporter receives completion banner from child workflow
3. Token is revoked prematurely
4. Second step fails with authentication error

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1081): <!--number 1081 --><!--line 0 --><!--description Zml4OiBwcmV2ZW50IHByZW1hdHVyZSB0b2tlbiByZXZvY2F0aW9uIGluIHJldXNhYmxlIHdvcmtmbG93cw==-->fix: prevent premature token revocation in reusable workflows<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1081
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Roman K. <devops@syncstack.net>
Co-committed-by: Roman K. <devops@syncstack.net>
2025-10-14 01:45:54 +00:00
Renovate Bot
4d685c129c
Update module golang.org/x/term to v0.36.0 (#1086)
This PR contains the following updates:

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

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzUuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzNS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1086
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-13 15:43:53 +00:00
Andrew Cassidy
2d359067f6
fix: don't prepend server URL with https:// if it's an empty string (#1083)
An attempt to address #1074 in a way that makes everyone happy

Right now, any server URL that doesnt start with `http://` or `https://` automatically gets `https://` prepended to it. When no instance is set while running `forgejo-runner exec` this results in the `{FORGEJO,GITHUB}_SERVER_URL` environment variables being set to simply "https://". Any action using the GitHub actions toolkit chokes on this as an invalid URL and fails the run with a nondescript error. This PR instead leaves empty strings alone, which the actions toolkit seems much happier with

Alternate fixes:
* default the `--forgejo-instance` flag to a valid but unresolved url like 'http://example.com' so the actions don't crash
* don't set the environment variables at all when the server URL is an empty string. This causes the actions toolkit to assume GitHub.com as a fallback

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1083): <!--number 1083 --><!--line 0 --><!--description Zml4OiBkb24ndCBwcmVwZW5kIHNlcnZlciBVUkwgd2l0aCBodHRwczovLyBpZiBpdCdzIGFuIGVtcHR5IHN0cmluZw==-->fix: don't prepend server URL with https:// if it's an empty string<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1083
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Andrew Cassidy <drewcassidy@me.com>
Co-committed-by: Andrew Cassidy <drewcassidy@me.com>
2025-10-12 08:53:45 +00:00
Renovate Bot
e25d6b3c91
Update module github.com/docker/docker to v28.5.1+incompatible (#1085)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/docker/docker](https://github.com/docker/docker) | `v28.4.0+incompatible` -> `v28.5.1+incompatible` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fdocker%2fdocker/v28.5.1+incompatible?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fdocker%2fdocker/v28.4.0+incompatible/v28.5.1+incompatible?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>docker/docker (github.com/docker/docker)</summary>

### [`v28.5.1+incompatible`](https://github.com/docker/docker/compare/v28.5.0...v28.5.1)

[Compare Source](https://github.com/docker/docker/compare/v28.5.0...v28.5.1)

### [`v28.5.0+incompatible`](https://github.com/docker/docker/compare/v28.4.0...v28.5.0)

[Compare Source](https://github.com/docker/docker/compare/v28.4.0...v28.5.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzUuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzNS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1085
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-12 06:53:05 +00:00
Renovate Bot
08723cf623 Update module github.com/rhysd/actionlint to v1.7.8 (#1084)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/rhysd/actionlint](https://github.com/rhysd/actionlint) | `v1.7.7` -> `v1.7.8` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2frhysd%2factionlint/v1.7.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2frhysd%2factionlint/v1.7.7/v1.7.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>rhysd/actionlint (github.com/rhysd/actionlint)</summary>

### [`v1.7.8`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v178---2025-10-11)

[Compare Source](https://github.com/rhysd/actionlint/compare/v1.7.7...v1.7.8)

- Support `models` permission in `permissions` section. ([#&#8203;531](https://github.com/rhysd/actionlint/issues/531), thanks [@&#8203;muzimuzhi](https://github.com/muzimuzhi))
- Support `job.check_run_id` property. ([#&#8203;576](https://github.com/rhysd/actionlint/issues/576), thanks [@&#8203;muzimuzhi](https://github.com/muzimuzhi) for fixing the type at [#&#8203;577](https://github.com/rhysd/actionlint/issues/577))
- Support `node24` runtime at `using` section in action metadata. ([#&#8203;561](https://github.com/rhysd/actionlint/issues/561), thanks [@&#8203;salmanmkc](https://github.com/salmanmkc))
- Add support for the following runner labels
  - [`macos-26` and `macos-26-large`](https://github.blog/changelog/2025-09-11-actions-macos-26-image-now-in-public-preview/) ([#&#8203;572](https://github.com/rhysd/actionlint/issues/572), thanks [@&#8203;muzimuzhi](https://github.com/muzimuzhi))
  - [`macos-15`](https://github.blog/changelog/2025-09-19-github-actions-macos-13-runner-image-is-closing-down/#what-you-need-to-do) ([#&#8203;572](https://github.com/rhysd/actionlint/issues/572), thanks [@&#8203;muzimuzhi](https://github.com/muzimuzhi))
- Drop support for the following runner labels.
  - [`ubuntu-20.04`](https://github.com/actions/runner-images/issues/11101) ([#&#8203;534](https://github.com/rhysd/actionlint/issues/534), thanks [@&#8203;shogo82148](https://github.com/shogo82148))
  - [`windows-2019`](https://github.blog/changelog/2025-04-15-upcoming-breaking-changes-and-releases-for-github-actions/#windows-server-2019-is-closing-down) ([#&#8203;572](https://github.com/rhysd/actionlint/issues/572), thanks [@&#8203;muzimuzhi](https://github.com/muzimuzhi))
- Support [`deprecationMessage`](https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax#inputsinput_iddeprecationmessage) in action inputs. ([#&#8203;540](https://github.com/rhysd/actionlint/issues/540), thanks [@&#8203;saansh45](https://github.com/saansh45))
- Support [`windows-11-arm` runner](https://github.blog/changelog/2025-04-14-windows-arm64-hosted-runners-now-available-in-public-preview/). ([#&#8203;542](https://github.com/rhysd/actionlint/issues/542), thanks [@&#8203;trim21](https://github.com/trim21))
- Handle `ubuntu-latest` runner label as `ubuntu-24.04` and `macos-latest` runner label as `macos-15`.
- Report mixing Intel Mac labels and Arm Mac labels as error.
- Add new types to `issues` and `pull_request_target` webhooks.
- Update the popular actions data set to the latest and add more actions to it (thanks [@&#8203;sethvargo](https://github.com/sethvargo) for fixing the `go generate` scripts)
  - `actions/create-github-app-token`
  - `actions/attest-sbom`
  - `actions/ai-inference`
  - `peter-evans/create-or-update-comment`
  - `release-drafter/release-drafter`
  - `SamKirkland/FTP-Deploy-Action`
- Fix the version value in `actionlint -version` can be empty.
- Fix outdated URL links in some error messages and documents.
- [Homebrew formula in this repository](https://github.com/rhysd/actionlint/blob/main/HomebrewFormula/actionlint.rb) is deprecated and [Homebrew cask](https://github.com/rhysd/actionlint/blob/main/Casks/actionlint.rb) is newly added instead because [GoReleaser no longer supports Homebrew formula update](https://goreleaser.com/deprecations/#brews). Note that Homebrew's official `actionlint` formula is still maintained. Please read the [documentation](https://github.com/rhysd/actionlint/blob/main/docs/install.md#homebrew) for more details.
- Drop support for Go 1.23 and earlier because they are no longer maintained officially. Go 1.24 and later are supported to build actionlint.
- Replace [`go-yaml/yaml@v3`](https://github.com/go-yaml/yaml) package with [`yaml/go-yaml@v4`](https://github.com/yaml/go-yaml) package. `go-yaml/yaml` was used for parsing workflow files however it was unmaintained. `yaml/go-yaml` is a successor of the library officially maintained by YAML organization. ([#&#8203;575](https://github.com/rhysd/actionlint/issues/575))
- Improve error messages on parsing workflow and action metadata files.

\[Changes]\[v1.7.8]

<a id="v1.7.7"></a>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzUuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzNS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1084
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-12 01:47:52 +00:00
Andrew Cassidy
c80a40023c
feat: disambiguate cloud emoji (#1076)
Many emoji technically have two forms, the colorful form and the monochrome text form. For some reason, on macOS, ☁️ defaults to the latter, which is also really tiny for some reason?. Adding the invisible emoji variant selector (U+FE0F) causes it to always render as the colorful full-width graphic

Before:

![Screenshot 2025-10-08 at 22.53.36](/attachments/beaeea4a-d355-4db6-9cca-2425a62b6ea9)

After:

![Screenshot 2025-10-08 at 22.53.14](/attachments/dd670d38-fed6-41dc-a0c2-421846bc26bd)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1076): <!--number 1076 --><!--line 0 --><!--description ZGlzYW1iaWd1YXRlIGNsb3VkIGVtb2pp-->disambiguate cloud emoji<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1076
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Andrew Cassidy <drewcassidy@me.com>
Co-committed-by: Andrew Cassidy <drewcassidy@me.com>
2025-10-11 09:23:28 +00:00
Renovate Bot
21d451085f
Update module code.forgejo.org/forgejo/actions-proto to v0.5.3 (#1082)
This PR contains the following updates:

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

---

### Release Notes

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

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

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

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzUuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzNS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1082
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-11 09:02:22 +00:00
Mathieu Fenniak
02247b852a fix: allow mapping into env variable INPUT_N from ${{ inputs.n }} (#1080)
When using a reusable workflow such as:
```yaml
name: "use-inputs-impl"

on:
  workflow_call:
    inputs:
      image:
        description: "Image to be used in job"
        type: string
        required: false
        default: "docker.io/alpine:3.22"
      condition:
        description: "Only run a job if this is true"
        type: string
        required: false
        default: false

jobs:
  works:
    runs-on: docker
    container:
      image: alpine:3.22
    env:
      INPUT_IMAGE: ${{ inputs.image }}
      INPUT_CONDITION: ${{ inputs.condition }}
    steps:
      - run: echo "Hello world from Alpine"
      - run: cat /etc/alpine-release
      - run: echo "INPUT_IMAGE=$INPUT_IMAGE"
      - run: echo "INPUT_CONDITION=$INPUT_CONDITION"
```

The runner will currently output un-evaluated expressions:
```
INPUT_IMAGE=${{ inputs.image }}
INPUT_CONDITION=${{ inputs.condition }}
```

Internally, the workflow is using `INPUT_...` environment variables to transfer data into local reusable workflows, and the order of evaluation in `getEvaluatorInputs` was preferring to use the un-evaluated value, over the evaluated value.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1080): <!--number 1080 --><!--line 0 --><!--description Zml4OiBhbGxvdyBtYXBwaW5nIGludG8gZW52IHZhcmlhYmxlIElOUFVUX04gZnJvbSAke3sgaW5wdXRzLm4gfX0=-->fix: allow mapping into env variable INPUT_N from ${{ inputs.n }}<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1080
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-10-10 21:55:08 +00:00
Earl Warren
66a7e82c43
feat: allow --memory in workflow container options (#1079)
First hand experience to implement this feature can be found at https://codeberg.org/forgejo/forgejo/issues/9406. In a nutshell it is a service container in the CI that randomly uses massive amounts of memory (>50GB RSS) but normally less than 100MB.

---

See also the [matching documentation pull request](https://codeberg.org/forgejo/docs/pulls/1539).

---

It is already possible to limit the memory used by all containers in the config file:

```yaml
container:
  options: --memory 200M
```

This limit can be further reduced (but not increased) by the same option in a job:

```yaml
jobs:
  job:
    runs-on: docker
    container:
      image: code.forgejo.org/oci/node:20-bookworm
      options: --memory 200M
    steps:
      - run: echo OK
```

or a service container:

```yaml
job:
  my-job:
    runs-on: docker
    services:
      pgsql:
        image: postgres:15
        options: --memory 1G
```

Refs https://docs.docker.com/engine/containers/resource_constraints/#limit-a-containers-access-to-memory

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1079): <!--number 1079 --><!--line 0 --><!--description ZmVhdDogYWxsb3cgLS1tZW1vcnkgaW4gd29ya2Zsb3cgY29udGFpbmVyIG9wdGlvbnM=-->feat: allow --memory in workflow container options<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1079
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-10-10 14:33:07 +00:00
Renovate Bot
44b8b91540
Update module connectrpc.com/connect to v1.19.1 (#1078)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [connectrpc.com/connect](https://github.com/connectrpc/connect-go) | `v1.18.1` -> `v1.19.1` | [![age](https://developer.mend.io/api/mc/badges/age/go/connectrpc.com%2fconnect/v1.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/connectrpc.com%2fconnect/v1.18.1/v1.19.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>connectrpc/connect-go (connectrpc.com/connect)</summary>

### [`v1.19.1`](https://github.com/connectrpc/connect-go/releases/tag/v1.19.1)

[Compare Source](https://github.com/connectrpc/connect-go/compare/v1.19.0...v1.19.1)

<!-- Release notes generated using configuration in .github/release.yml at main -->

#### What's Changed

##### Bugfixes

- Fix bounds check on envelope for 32-bit archs by [@&#8203;emcfarlane](https://github.com/emcfarlane) in [#&#8203;887](https://github.com/connectrpc/connect-go/issues/887)
- Fix CallInfo header/trailer propagation on error responses by [@&#8203;emcfarlane](https://github.com/emcfarlane) in [#&#8203;892](https://github.com/connectrpc/connect-go/issues/892)

**Full Changelog**: <https://github.com/connectrpc/connect-go/compare/v1.19.0...v1.19.1>

### [`v1.19.0`](https://github.com/connectrpc/connect-go/releases/tag/v1.19.0)

[Compare Source](https://github.com/connectrpc/connect-go/compare/v1.18.1...v1.19.0)

This release introduces the highly requested "simple" flag for code generation, making Connect significantly more ergonomic for everyday RPC development.

The new simple flag in protoc-gen-connect-go generates cleaner, more intuitive client and handler interfaces that eliminate request/response wrappers for most use cases. This addresses community feedback about verbosity and provides a more straightforward API. When enabled, metadata (headers/trailers) can be passed through context instead of explicit wrapper objects, optimizing for the common case where developers don't need direct access to HTTP headers.

#### What's Changed

##### Enhancements

- Add simple flag for more ergonomic generated code by [@&#8203;bufdev](https://github.com/bufdev) and [@&#8203;smaye81](https://github.com/smaye81) in [#&#8203;851](https://github.com/connectrpc/connect-go/pull/851)
- Update Go to v1.24 and document http.Protocol use removing the dependency on `golang.org/x/net/http2` by [@&#8203;maxbrunet](https://github.com/maxbrunet) in [#&#8203;873](https://github.com/connectrpc/connect-go/pull/873), [#&#8203;877](https://github.com/connectrpc/connect-go/pull/877)
- Add support for Edition 2024 by [@&#8203;emcfarlane](https://github.com/emcfarlane) in [#&#8203;878](https://github.com/connectrpc/connect-go/pull/878)

##### Bugfixes

- Include valid spec and headers when calling recover handler for streaming RPCs by [@&#8203;jhump](https://github.com/jhump) in [#&#8203;817](https://github.com/connectrpc/connect-go/pull/817)

##### Other changes

- Go version support updated to latest two instead of three by [@&#8203;jhump](https://github.com/jhump) in [#&#8203;837](https://github.com/connectrpc/connect-go/pull/837)
- CI testing improvements by [@&#8203;pkwarren](https://github.com/pkwarren) and [@&#8203;jhump](https://github.com/jhump) in [#&#8203;838](https://github.com/connectrpc/connect-go/pull/838), [#&#8203;839](https://github.com/connectrpc/connect-go/pull/839)
- Code quality improvements by [@&#8203;mattrobenolt](https://github.com/mattrobenolt) and [@&#8203;bufdev](https://github.com/bufdev) in [#&#8203;841](https://github.com/connectrpc/connect-go/pull/841), [#&#8203;867](https://github.com/connectrpc/connect-go/pull/867)
- Documentation improvements by [@&#8203;adlion](https://github.com/adlion) and [@&#8203;stefanvanburen](https://github.com/stefanvanburen) in [#&#8203;821](https://github.com/connectrpc/connect-go/pull/821),
  [#&#8203;880](https://github.com/connectrpc/connect-go/pull/880)

#### New Contributors

- [@&#8203;adlion](https://github.com/adlion) made their first contribution in [#&#8203;821](https://github.com/connectrpc/connect-go/pull/821)
- [@&#8203;maxbrunet](https://github.com/maxbrunet) made their first contribution in [#&#8203;873](https://github.com/connectrpc/connect-go/pull/873)
- [@&#8203;stefanvanburen](https://github.com/stefanvanburen) made their first contribution in [#&#8203;880](https://github.com/connectrpc/connect-go/pull/880)

**Full Changelog**: <https://github.com/connectrpc/connect-go/compare/v1.18.1...v1.19.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzUuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzNS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1078
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-10 13:39:56 +00:00
Renovate Bot
bda2295f71
Update module github.com/docker/cli to v28.5.1+incompatible (#1072)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/docker/cli](https://github.com/docker/cli) | `v28.5.0+incompatible` -> `v28.5.1+incompatible` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fdocker%2fcli/v28.5.1+incompatible?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fdocker%2fcli/v28.5.0+incompatible/v28.5.1+incompatible?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>docker/cli (github.com/docker/cli)</summary>

### [`v28.5.1+incompatible`](https://github.com/docker/cli/compare/v28.5.0...v28.5.1)

[Compare Source](https://github.com/docker/cli/compare/v28.5.0...v28.5.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzUuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzNS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1072
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-09 08:55:16 +00:00
Renovate Bot
b17b1f00b3
Update dependency go to v1.24.8 (#1069)
This PR contains the following updates:

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzUuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzNS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1069
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-08 09:42:15 +00:00
Mathieu Fenniak
3f52c56d1e feat: improve readability of error messages from ParseRawOn (#1063)
With https://codeberg.org/forgejo/forgejo/pulls/9530, the error messages from `ParseRawOn` are user-facing and need a pass to improve their meaning.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1063): <!--number 1063 --><!--line 0 --><!--description ZmVhdDogaW1wcm92ZSByZWFkYWJpbGl0eSBvZiBlcnJvciBtZXNzYWdlcyBmcm9tIFBhcnNlUmF3T24=-->feat: improve readability of error messages from ParseRawOn<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1063
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-10-07 14:41:55 +00:00
Renovate Bot
041524d663
Update module github.com/docker/cli to v28.5.0+incompatible (#1066)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/docker/cli](https://github.com/docker/cli) | `v28.4.0+incompatible` -> `v28.5.0+incompatible` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fdocker%2fcli/v28.5.0+incompatible?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fdocker%2fcli/v28.4.0+incompatible/v28.5.0+incompatible?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>docker/cli (github.com/docker/cli)</summary>

### [`v28.5.0+incompatible`](https://github.com/docker/cli/compare/v28.4.0...v28.5.0)

[Compare Source](https://github.com/docker/cli/compare/v28.4.0...v28.5.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzUuNSIsInVwZGF0ZWRJblZlciI6IjQxLjEzNS41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1066
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-07 08:13:23 +00:00
Mathieu Fenniak
a3d46d7597
chore: add additional logging to cacheproxy (#1065)
In support of diagnosing #1064, I hope.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1065): <!--number 1065 --><!--line 0 --><!--description Y2hvcmU6IGFkZCBhZGRpdGlvbmFsIGxvZ2dpbmcgdG8gY2FjaGVwcm94eQ==-->chore: add additional logging to cacheproxy<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1065
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-10-07 08:12:16 +00:00
Mathieu Fenniak
0a0b25d886
fix: don't panic on cacheproxy startup failure (#1067)
In #1064 I theorized that a failure to start up the cache proxy server might cause it to still be registered as `ACTIONS_CACHE_URL`.  It turns out to not be the case as it will just panic, since `cacheProxy` is `nil`.  But regardless, it seems better to not panic and crash if the intent here is "cache will be disabled" as documented in the log message.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1067): <!--number 1067 --><!--line 0 --><!--description Zml4OiBkb24ndCBwYW5pYyBvbiBjYWNoZXByb3h5IHN0YXJ0dXAgZmFpbHVyZQ==-->fix: don't panic on cacheproxy startup failure<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1067
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-10-07 08:09:14 +00:00
Renovate Bot
a22c5a2e65
Update module github.com/go-git/go-git/v5 to v5.16.3 (#1062)
This PR contains the following updates:

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

---

### Release Notes

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

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

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

#### What's Changed

- internal: Expand regex to fix build \[5.x] by [@&#8203;baloo](https://github.com/baloo) in [#&#8203;1644](https://github.com/go-git/go-git/pull/1644)
- build: raise timeouts for windows CI tests and disable CIFuzz \[5.x] by [@&#8203;baloo](https://github.com/baloo) in [#&#8203;1646](https://github.com/go-git/go-git/pull/1646)
- plumbing: support commits extra headers, support jujutsu signed commit \[5.x] by [@&#8203;baloo](https://github.com/baloo) in [#&#8203;1633](https://github.com/go-git/go-git/pull/1633)

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

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzEuOSIsInVwZGF0ZWRJblZlciI6IjQxLjEzMS45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1062
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-06 04:22:26 +00:00
Andrew Cassidy
e68940619c
chore(docs): clarify the behavior of [container].docker_host (#1059)
The description of `container.docker_host` was misleading (and IMO the setting itself does too many things, see forgejo/forgejo-actions-feature-requests#58). I clarified the comments in the example config to clearly explain that it will mount the specified socket inside the job container, and give some example values

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1059): <!--number 1059 --><!--line 0 --><!--description Q2xhcmlmeSB0aGUgYmVoYXZpb3Igb2YgYGNvbnRhaW5lci5kb2NrZXJfaG9zdGA=-->Clarify the behavior of `container.docker_host`<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1059
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Andrew Cassidy <drewcassidy@me.com>
Co-committed-by: Andrew Cassidy <drewcassidy@me.com>
2025-10-06 03:51:19 +00:00
Mathieu Fenniak
ba1beb08f4
fix: log error for why cache couldn't be started (#1057)
Example, `cache.port` set to `22`:
```
time="2025-10-04T09:27:42-06:00" level=error msg="Could not start the cache server, cache will be disabled: listen tcp :22: bind: permission denied" func="[setupCache]" file="[runner.go:126]"
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1057): <!--number 1057 --><!--line 0 --><!--description Zml4OiBsb2cgZXJyb3IgZm9yIHdoeSBjYWNoZSBjb3VsZG4ndCBiZSBzdGFydGVk-->fix: log error for why cache couldn't be started<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1057
Reviewed-by: limiting-factor <limiting-factor@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-10-05 07:40:06 +00:00
Renovate Bot
4010e61165
Update module google.golang.org/protobuf to v1.36.10 (#1058)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) | `v1.36.9` -> `v1.36.10` | [![age](https://developer.mend.io/api/mc/badges/age/go/google.golang.org%2fprotobuf/v1.36.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/google.golang.org%2fprotobuf/v1.36.9/v1.36.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>protocolbuffers/protobuf-go (google.golang.org/protobuf)</summary>

### [`v1.36.10`](https://github.com/protocolbuffers/protobuf-go/releases/tag/v1.36.10)

[Compare Source](https://github.com/protocolbuffers/protobuf-go/compare/v1.36.9...v1.36.10)

**Full Changelog**: <https://github.com/protocolbuffers/protobuf-go/compare/v1.36.9...v1.36.10>

Bug fixes:
[CL/704415](https://go-review.googlesource.com/c/protobuf/+/704415): reflect/protodesc: edition-2024-specific properties should not be lost when converting FileDescriptorProto to protoreflect.FileDescriptor

Maintenance:
[CL/708555](https://go-review.googlesource.com/c/protobuf/+/708555): internal/race\_test: add missing impl.LazyEnabled() t.Skip
[CL/703295](https://go-review.googlesource.com/c/protobuf/+/703295): proto: add more invalid group encoding test cases
[CL/703276](https://go-review.googlesource.com/c/protobuf/+/703276): internal/impl: verify lazy unmarshal on Deterministic encoding
[CL/703275](https://go-review.googlesource.com/c/protobuf/+/703275): internal/impl: stop using deprecated .Field in lazy\_test.go
[CL/702795](https://go-review.googlesource.com/c/protobuf/+/702795): all: update to latest github.com/google/go-cmp

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzEuOSIsInVwZGF0ZWRJblZlciI6IjQxLjEzMS45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1058
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-05 07:39:29 +00:00
Earl Warren
5f3ff3d2e2
chore: teach renovate about example-lxc-systemd.yml (#1053)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1053
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-10-04 11:16:16 +00:00
Renovate Bot
2bccbec3ae
Update forgejo-runner to v11.1.2 (#1055)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [code.forgejo.org/forgejo/runner](https://forgejo.org) ([source](https://code.forgejo.org/forgejo/runner)) | patch | `11.1.1` -> `11.1.2` |
| [forgejo/runner](https://code.forgejo.org/forgejo/runner) | patch | `11.1.1` -> `11.1.2` |

---

### Release Notes

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

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v11.1.1...v11.1.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)

Release Notes

***

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

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

- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1026): <!--number 1026 --><!--line 0 --><!--description ZmVhdDogc3VwcG9ydCBldmFsdWF0aW5nIHdvcmtmbG93LWxldmVsIGNvbmN1cnJlbmN5IGJsb2NrcyBpbiBqb2JwYXJzZXI=-->feat: support evaluating workflow-level concurrency blocks in jobparser<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1051): <!--number 1051 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogYSBtdWx0aWxpbmUgc2VjcmV0IG1heSBiZSBmb3VuZCBpbiBhIHNpbmdsZSBsb2cgZW50cnk=-->fix(security): a multiline secret may be found in a single log entry<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1048): <!--number 1048 --><!--line 0 --><!--description Zml4OiBpbXByb3ZlIGxvZ2dpbmcgdG8gZGlhZ25vc2UgbXlzdGVyeSBqb2IgdGVybWluYXRpb25z-->fix: improve logging to diagnose mystery job terminations<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1043): <!--number 1043 --><!--line 0 --><!--description Zml4OiBtb2RpZnlpbmcgYSBjYWNoZSBzZWNyZXQgZG9lcyBub3QgaW52YWxpZGF0ZSBjYWNoZWQgZW50cmllcw==-->fix: modifying a cache secret does not invalidate cached entries<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1040): <!--number 1040 --><!--line 0 --><!--description Zml4OiBhbGxvdyBHQyAmIGNhY2hlIG9wZXJhdGlvbnMgdG8gb3BlcmF0ZSBjb25jdXJyZW50bHk=-->fix: allow GC & cache operations to operate concurrently<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1037): <!--number 1037 --><!--line 0 --><!--description Zml4OiBkbyBub3QgYXR0ZW1wdCB0byBydW4gdGhlIExYQyBzdG9wIHNjcmlwdCB3aXRoIHNlbGYtaG9zdGVk-->fix: do not attempt to run the LXC stop script with self-hosted<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1031): <!--number 1031 --><!--line 0 --><!--description Zml4OiBldmVudC5wdWxsX3JlcXVlc3QuYWN0aW9uID09IGNsb3NlZCBjYW4gdXNlIHRoZSBjYWNoZSBvZiB0aGUgYmFzZSByZXBvc2l0b3J5-->fix: event.pull\_request.action == closed can use the cache of the base repository<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1027): <!--number 1027 --><!--line 0 --><!--description Zml4OiBDb3JyZWN0bHkgb3ZlcnJpZGUgdGhlIHZhbHVlIG9mIGBGb3JnZWpvLUNhY2hlLUhvc3RgIHdoZW4gQUNUSU9OU19DQUNIRV9VUkwgaXMgb3ZlcnJpZGRlbi4=-->fix: Correctly override the value of `Forgejo-Cache-Host` when ACTIONS\_CACHE\_URL is overridden.<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1019): <!--number 1019 --><!--line 0 --><!--description Zml4OiBhIGNvbXBvc2l0ZSBhY3Rpb24gbXVzdCBub3QgY2hhbmdlIHRoZSByZXN1bHQgb2YgdGhlIGNhbGxpbmcgc3RlcCBiZWZvcmUgaXQgY29tcGxldGVz-->fix: a composite action must not change the result of the calling step before it completes<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1033): <!--number 1033 --><!--line 0 --><!--description Y2hvcmU6IHRlc3Q6IGV4ZXJjaXNlIGNvbnRleHRzIGluIG1hdHJpeCB3aGVuIHZhbGlkYXRpbmcgd29ya2Zsb3dz-->chore: test: exercise contexts in matrix when validating workflows<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1029): <!--number 1029 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBjb25uZWN0cnBjLmNvbS9jb25uZWN0IHRvIHYxLjE5LjA=-->Update module connectrpc.com/connect to v1.19.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1025): <!--number 1025 --><!--line 0 --><!--description Y2hvcmU6IGZpeCB0eXBvIGluIHRoZSBkb2N1bWVudGF0aW9u-->chore: fix typo in the documentation<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1023): <!--number 1023 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuNS4w-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.5.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1022): <!--number 1022 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9mb3JnZWpvIERvY2tlciB0YWcgdG8gdjExLjAuNg==-->Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.6<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1020): <!--number 1020 --><!--line 0 --><!--description Y2hvcmU6IHVwZ3JhZGUgTFhDIGV4YW1wbGUgdG8gRGViaWFuIEdOVS9MaW51eCB0cml4aWU=-->chore: upgrade LXC example to Debian GNU/Linux trixie<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1021): <!--number 1021 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL3NldHVwLWZvcmdlam8gYWN0aW9uIHRvIHYzLjAuNA==-->Update <https://data.forgejo.org/actions/setup-forgejo> action to v3.0.4<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1018): <!--number 1018 --><!--line 0 --><!--description VXBkYXRlIGZvcmdlam8tcnVubmVyIHRvIHYxMS4xLjE=-->Update forgejo-runner to v11.1.1<!--description-->

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

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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 these updates 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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzEuOSIsInVwZGF0ZWRJblZlciI6IjQxLjEzMS45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1055
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-04 11:15:31 +00:00
limiting-factor
996ac343ee
chore(cleanup): lxc-helpers does not need a global lock (#1047)
- https://code.forgejo.org/forgejo/lxc-helpers/src/tag/v1.1.1 has  locking and atomicity
- this lock was only good for when two release templates are  populated simultaneously and not when it was interrupted

Refs forgejo/lxc-helpers#8

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1047): <!--number 1047 --><!--line 0 --><!--description V0lQOiBjaG9yZShjbGVhbnVwKTogbHhjLWhlbHBlcnMgZG9lcyBub3QgbmVlZCBhIGdsb2JhbCBsb2Nr-->WIP: chore(cleanup): lxc-helpers does not need a global lock<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1047
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: limiting-factor <limiting-factor@posteo.com>
Co-committed-by: limiting-factor <limiting-factor@posteo.com>
2025-10-03 16:15:43 +00:00
Earl Warren
413a52605d
fix: remove LXC backend leftovers when the job completes (#1054)
- remove the root of the LXC container after destroying it, with sudo as it may contain files owned by root while the runner id is not root
- os.RemoveAll only for native host runs, it is no longer needed for the LXC backend
- remove the CleanUp function that is an indirection with no use

Resolves forgejo/runner#442

When running the test from a non-root user and without this fix, it fails as follow:

```
go test -v -count=1 -run='TestRunnerLXC' ./internal/app/run
=== RUN   TestRunnerLXC
...
time="2025-10-03T15:05:12+02:00" level=debug msg=stopHostEnvironment
time="2025-10-03T15:05:13+02:00" level=debug msg="HostEnvironment.Remove /tmp/TestRunnerLXC1841090130/001/d29c1256e2912892/hostexecutor"
time="2025-10-03T15:05:13+02:00" level=error msg="Error while stop job container FORGEJO-ACTIONS-TASK-0_WORKFLOW-3ede81fbc69d42e6db70bef5820490fc3e7dc4d9dcbfb64981f2d00f08a30d6e_JOB-job: unlinkat /tmp/TestRunnerLXC1841090130/001/d29c1256e2912892/hostexecutor/some/directory/owned/by/root: permission denied"
=== NAME  TestRunnerLXC
    runner_test.go:469:
        	Error Trace:	/home/earl-warren/software/runner/internal/app/run/runner_test.go:469
        	            				/home/earl-warren/software/runner/internal/app/run/runner_test.go:496
        	Error:      	Received unexpected error:
        	            	Error occurred running finally: unlinkat /tmp/TestRunnerLXC1841090130/001/d29c1256e2912892/hostexecutor/some/directory/owned/by/root: permission denied (original error: <nil>)
        	Test:       	TestRunnerLXC
        	Messages:   	OK
=== NAME  TestRunnerLXC/OK
    testing.go:1679: test executed panic(nil) or runtime.Goexit: subtest may have called FailNow on a parent test
=== NAME  TestRunnerLXC
    testing.go:1267: TempDir RemoveAll cleanup: unlinkat /tmp/TestRunnerLXC1841090130/001/d29c1256e2912892/hostexecutor/some/directory/owned/by/root: permission denied
--- FAIL: TestRunnerLXC (6.84s)
    --- FAIL: TestRunnerLXC/OK (6.84s)
FAIL
FAIL	code.forgejo.org/forgejo/runner/v11/internal/app/run	6.847s
FAIL
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1054): <!--number 1054 --><!--line 0 --><!--description Zml4OiByZW1vdmUgTFhDIGJhY2tlbmQgbGVmdG92ZXJzIHdoZW4gdGhlIGpvYiBjb21wbGV0ZXM=-->fix: remove LXC backend leftovers when the job completes<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1054
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-10-03 16:14:08 +00:00
cascading-pr
a980acd936
fix: make the creation of LXC templates atomic so they cannot be interrupted while building (#1049)
cascading-pr from https://code.forgejo.org/forgejo/lxc-helpers/pulls/49

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1049): <!--number 1049 --><!--line 0 --><!--description Y2FzY2FkaW5nLXByIGZyb20gaHR0cHM6Ly9jb2RlLmZvcmdlam8ub3JnL2Zvcmdlam8vbHhjLWhlbHBlcnMgcmVmcy9wdWxsLzQ5L2hlYWQgdG8gZm9yZ2Vqby9seGMtaGVscGVycy00OQ==-->cascading-pr from https://code.forgejo.org/forgejo/lxc-helpers refs/pull/49/head to forgejo/lxc-helpers-49<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: cascading-pr <cascading-pr@example.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1049
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: cascading-pr <cascading-pr@noreply.code.forgejo.org>
Co-committed-by: cascading-pr <cascading-pr@noreply.code.forgejo.org>
2025-10-03 09:09:29 +00:00
Renovate Bot
1fa156c7e4
Update dependency forgejo/lxc-helpers to v1.1.1 (#1050)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [forgejo/lxc-helpers](https://code.forgejo.org/forgejo/lxc-helpers) | patch | `1.1.0` -> `1.1.1` |

---

### Release Notes

<details>
<summary>forgejo/lxc-helpers (forgejo/lxc-helpers)</summary>

### [`v1.1.1`](https://code.forgejo.org/forgejo/lxc-helpers/compare/v1.1.0...v1.1.1)

[Compare Source](https://code.forgejo.org/forgejo/lxc-helpers/compare/v1.1.0...v1.1.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzEuOSIsInVwZGF0ZWRJblZlciI6IjQxLjEzMS45IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1050
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-10-03 09:03:32 +00:00
Earl Warren
b772be7131
fix(security): a multiline secret may be found in a single log entry (#1051)
With secrets.MULTILINE set to

```
ABC
DEF
GHI
```

the following is logged in debug mode:

```
2025-09-18T10:54:04.4656189Z expression '${{ secrets.MULTILINE }}' rewritten to 'format('{0}', secrets.MULTILINE)'
2025-09-18T10:54:04.4656426Z evaluating expression 'format('{0}', secrets.MULTILINE)'
2025-09-18T10:54:04.4656797Z expression 'format('{0}', secrets.MULTILINE)' evaluated to '%!t(string=ABC\nDEF\nGHI)'
```

Although it is displayed with \ followed by n, it is a single line entry displayed with the secret verbatim and must also be redacted.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1051): <!--number 1051 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogYSBtdWx0aWxpbmUgc2VjcmV0IG1heSBiZSBmb3VuZCBpbiBhIHNpbmdsZSBsb2cgZW50cnk=-->fix(security): a multiline secret may be found in a single log entry<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1051
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-10-03 08:22:06 +00:00
Mathieu Fenniak
63351343ba
fix: improve logging to diagnose mystery job terminations (#1048)
Additional logging to support #1044.

Manual testing only.  Cases tested:

Cancel a job from Forgejo UI; this seems like the most likely missing piece in #1044 as two jobs were simultaneously marked as "Failed".  There are codepaths in Forgejo that can set this state to both cancelled and failed, but the runner didn't provide log output indicating that's why a job was stopping:
```
time="2025-10-02T13:22:53-06:00" level=info msg="UpdateTask returned task result RESULT_CANCELLED for a task that was in local state RESULT_UNSPECIFIED - beginning local task termination" func="[ReportState]" file="[reporter.go:410]"
```

Host-based executor hits step timeout in exec, or, is cancelled.  This occurred but only logged the `err` from `exec`, not the context error indicating whether it was a timeout or a cancellation:
```
[Test Action/job1] this step has been cancelled: ctx: context deadline exceeded, exec: RUN signal: killed
[Test Action/job1] this step has been cancelled: ctx: context canceled, exec: RUN signal: killed
```

Unable to `ReportState` due to Forgejo inaccessible.  If the runner isn't able to update state to Forgejo a job could be considered a zombie; this would trigger one of the codepaths where the job would be marked as failed.  If connectivity was later restored, then the runner could identify it was marked as failed and cancel the job context.  (This combination doesn't seem likely, but, I think it's reasonable to consider these failures as warnings because there may be unexpected errors here that we're not aware of).
```
time="2025-10-02T13:27:19-06:00" level=warning msg="ReportState error: unavailable: 502 Bad Gateway" func="[RunDaemon]" file="[reporter.go:207]"
```

Runner shutdown logging; just changed up to `Info` level:
```
time="2025-10-02T13:31:36-06:00" level=info msg="forcing the jobs to shutdown" func="[Shutdown]" file="[poller.go:93]"
[Test Action/job1]     Failure - Main sleep 120
[Test Action/job1] this step has been cancelled: ctx: context canceled, exec: RUN signal: killed
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1048): <!--number 1048 --><!--line 0 --><!--description Zml4OiBpbXByb3ZlIGxvZ2dpbmcgdG8gZGlhZ25vc2UgbXlzdGVyeSBqb2IgdGVybWluYXRpb25z-->fix: improve logging to diagnose mystery job terminations<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1048
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-10-02 22:43:50 +00:00
Earl Warren
01766ff4e2
fix: modifying a cache secret does not invalidate cached entries (#1043)
Resolves forgejo/runner#1041

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1043): <!--number 1043 --><!--line 0 --><!--description Zml4OiBtb2RpZnlpbmcgYSBjYWNoZSBzZWNyZXQgZG9lcyBub3QgaW52YWxpZGF0ZSBjYWNoZWQgZW50cmllcw==-->fix: modifying a cache secret does not invalidate cached entries<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1043
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-10-01 16:38:38 +00:00
Mathieu Fenniak
d79d043696
fix: allow GC & cache operations to operate concurrently (#1040)
Fixes #1039.

Rather than opening and closing the Bolt DB instance constantly, the cache now maintains one open `*bolthold.Store` for its lifetime, allowing GC, cache read, and cache write operations to occur concurrently.

The major risk is this change is, "is it safe to use one Bolt instance across goroutines concurrently?"  [Bolt does document its concurrency requirements](https://github.com/boltdb/bolt?tab=readme-ov-file#transactions), and an analysis of our DB interactions looks to me like it introduces very little risk.

Most of the cache operations perform multiple touches to the database; for example `useCache` performs a read to fetch a cache object, and then an update to set its `UsedAt` timestamp.  If we wanted to ensure consistency in these operations, they should use a Bolt ReadWrite transaction -- but concurrent access would just be setting the field to the same value anyway.

The `gcCache` is the complex operation where a transaction might be warranted -- but doing so would also cause the same bug that #1039 indicates.  I believe it is safe to run without a transaction because it is protected by an application-level mutex (to prevent multiple concurrent GCs), it is the only code that performs deletes from the database -- these should guarantee that all its delete attempts are successful.  In the event of unexpected failure to do the DB write, `gcCache` deletes from the storage before deleting from the DB, so it should just attempt to cleanup again next run.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1040): <!--number 1040 --><!--line 0 --><!--description Zml4OiBhbGxvdyBHQyAmIGNhY2hlIG9wZXJhdGlvbnMgdG8gb3BlcmF0ZSBjb25jdXJyZW50bHk=-->fix: allow GC & cache operations to operate concurrently<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1040
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-09-30 19:12:45 +00:00
Earl Warren
7f90c8acb2
fix: do not attempt to run the LXC stop script with self-hosted (#1037)
The test is covered by TestRunnerLXC which verifies the script actually runs on LXC.

Resolves forgejo/runner#1035

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1037): <!--number 1037 --><!--line 0 --><!--description Zml4OiBkbyBub3QgYXR0ZW1wdCB0byBydW4gdGhlIExYQyBzdG9wIHNjcmlwdCB3aXRoIHNlbGYtaG9zdGVk-->fix: do not attempt to run the LXC stop script with self-hosted<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1037
Reviewed-by: fnetX <fnetx@noreply.code.forgejo.org>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-28 14:49:45 +00:00
2franix
ea824bde1c
chore: test: exercise contexts in matrix when validating workflows (#1033)
After realizing my mistake on my proposed fixes in #1028, I figured I could at least propose another test covering the use of contexts in `jobs.<job-id>.strategy.matrix`.

The specification for available contexts is [here](https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#context-availability):

| Workflow key | Context |
| -------------------- | ----------- |
| `jobs.<job_id>.strategy` | `github`, `needs`, `vars`, `inputs` |

In Forgejo, the `forge` and `forgejo` contexts are supported in addition to `github`.

The new test covers a matrix with [`include`](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstrategymatrixinclude), [`exclude`](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstrategymatrixexclude) and custom properties. Both available and unavailable contexts are tested.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1033): <!--number 1033 --><!--line 0 --><!--description Y2hvcmU6IHRlc3Q6IGV4ZXJjaXNlIGNvbnRleHRzIGluIG1hdHJpeCB3aGVuIHZhbGlkYXRpbmcgd29ya2Zsb3dz-->chore: test: exercise contexts in matrix when validating workflows<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: 2franix <code@c.defx.fr>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1033
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: 2franix <2franix@noreply.code.forgejo.org>
Co-committed-by: 2franix <2franix@noreply.code.forgejo.org>
2025-09-28 07:15:51 +00:00
Earl Warren
46a955d1ff
Revert "Update module connectrpc.com/connect to v1.19.0 (#1029)"
This reverts commit 9c09ca3f56.
2025-09-27 07:55:28 +02:00
Mathieu Fenniak
56ef60060b
feat: support evaluating workflow-level concurrency blocks in jobparser (#1026)
- Changes `EvaluateConcurrency` to `EvaluateWorkflowConcurrency`, which has no job-related arguments
- Changes gitContext to be sent as an object rather than a map
- Allows `nil` to be returned for `cancelInProgress`, which indicates that the value wasn't specified in the input yaml -- required for distinguishing the `cancel-in-progress: false` case from not being specified at all.

ReadWorkflowRawConcurrency & EvaluateWorkflowConcurrency were never used in forgejo yet, so this shouldn't break the forgejo build.

Prerequisite for https://codeberg.org/forgejo/forgejo/pulls/9434.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1026): <!--number 1026 --><!--line 0 --><!--description ZmVhdDogc3VwcG9ydCBldmFsdWF0aW5nIHdvcmtmbG93LWxldmVsIGNvbmN1cnJlbmN5IGJsb2NrcyBpbiBqb2JwYXJzZXI=-->feat: support evaluating workflow-level concurrency blocks in jobparser<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1026
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-09-27 04:37:36 +00:00
Earl Warren
014b4ba5f6
fix: event.pull_request.action == closed can use the cache of the base repository (#1031)
It was tested locally with https://code.forgejo.org/forgejo/end-to-end/pulls/1062/files.

## Before

![image](/attachments/26890572-08ba-4904-b6a5-f01762141a51)

## After

![image](/attachments/56352930-99a3-4011-b921-b12217c5fa54)

---

When the "closed" action of a pull request event was triggered by a merge, it effectively runs in the context of the base repository. It was merged by a user with write access to the base repository. It is authorized to write the base repository cache.

Resolves forgejo/runner#1030

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1031): <!--number 1031 --><!--line 0 --><!--description Zml4OiBldmVudC5wdWxsX3JlcXVlc3QuYWN0aW9uID09IGNsb3NlZCBjYW4gdXNlIHRoZSBjYWNoZSBvZiB0aGUgYmFzZSByZXBvc2l0b3J5-->fix: event.pull_request.action == closed can use the cache of the base repository<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1031
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-26 20:01:46 +00:00
Renovate Bot
9c09ca3f56
Update module connectrpc.com/connect to v1.19.0 (#1029)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [connectrpc.com/connect](https://github.com/connectrpc/connect-go) | `v1.18.1` -> `v1.19.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/connectrpc.com%2fconnect/v1.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/connectrpc.com%2fconnect/v1.18.1/v1.19.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>connectrpc/connect-go (connectrpc.com/connect)</summary>

### [`v1.19.0`](https://github.com/connectrpc/connect-go/releases/tag/v1.19.0)

[Compare Source](https://github.com/connectrpc/connect-go/compare/v1.18.1...v1.19.0)

This release introduces the highly requested "simple" flag for code generation, making Connect significantly more ergonomic for everyday RPC development.

The new simple flag in protoc-gen-connect-go generates cleaner, more intuitive client and handler interfaces that eliminate request/response wrappers for most use cases. This addresses community feedback about verbosity and provides a more straightforward API. When enabled, metadata (headers/trailers) can be passed through context instead of explicit wrapper objects, optimizing for the common case where developers don't need direct access to HTTP headers.

#### What's Changed

##### Enhancements

- Add simple flag for more ergonomic generated code by [@&#8203;bufdev](https://github.com/bufdev) and [@&#8203;smaye81](https://github.com/smaye81) in [#&#8203;851](https://github.com/connectrpc/connect-go/pull/851)
- Update Go to v1.24 and document http.Protocol use removing the dependency on `golang.org/x/net/http2` by [@&#8203;maxbrunet](https://github.com/maxbrunet) in [#&#8203;873](https://github.com/connectrpc/connect-go/pull/873), [#&#8203;877](https://github.com/connectrpc/connect-go/pull/877)
- Add support for Edition 2024 by [@&#8203;emcfarlane](https://github.com/emcfarlane) in [#&#8203;878](https://github.com/connectrpc/connect-go/pull/878)

##### Bugfixes

- Include valid spec and headers when calling recover handler for streaming RPCs by [@&#8203;jhump](https://github.com/jhump) in [#&#8203;817](https://github.com/connectrpc/connect-go/pull/817)

##### Other changes

- Go version support updated to latest two instead of three by [@&#8203;jhump](https://github.com/jhump) in [#&#8203;837](https://github.com/connectrpc/connect-go/pull/837)
- CI testing improvements by [@&#8203;pkwarren](https://github.com/pkwarren) and [@&#8203;jhump](https://github.com/jhump) in [#&#8203;838](https://github.com/connectrpc/connect-go/pull/838), [#&#8203;839](https://github.com/connectrpc/connect-go/pull/839)
- Code quality improvements by [@&#8203;mattrobenolt](https://github.com/mattrobenolt) and [@&#8203;bufdev](https://github.com/bufdev) in [#&#8203;841](https://github.com/connectrpc/connect-go/pull/841), [#&#8203;867](https://github.com/connectrpc/connect-go/pull/867)
- Documentation improvements by [@&#8203;adlion](https://github.com/adlion) and [@&#8203;stefanvanburen](https://github.com/stefanvanburen) in [#&#8203;821](https://github.com/connectrpc/connect-go/pull/821),
  [#&#8203;880](https://github.com/connectrpc/connect-go/pull/880)

#### New Contributors

- [@&#8203;adlion](https://github.com/adlion) made their first contribution in [#&#8203;821](https://github.com/connectrpc/connect-go/pull/821)
- [@&#8203;maxbrunet](https://github.com/maxbrunet) made their first contribution in [#&#8203;873](https://github.com/connectrpc/connect-go/pull/873)
- [@&#8203;stefanvanburen](https://github.com/stefanvanburen) made their first contribution in [#&#8203;880](https://github.com/connectrpc/connect-go/pull/880)

**Full Changelog**: <https://github.com/connectrpc/connect-go/compare/v1.18.1...v1.19.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMjIuMyIsInVwZGF0ZWRJblZlciI6IjQxLjEyMi4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1029
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-26 07:10:58 +00:00
Kwonunn
6bdb7ed9c7
fix: Correctly override the value of Forgejo-Cache-Host when ACTIONS_CACHE_URL is overridden. (#1027)
This fixes a bug currently preventing use of an external cache server in the Codeberg runner setup.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1027): <!--number 1027 --><!--line 0 --><!--description Zml4OiBDb3JyZWN0bHkgb3ZlcnJpZGUgdGhlIHZhbHVlIG9mIGBGb3JnZWpvLUNhY2hlLUhvc3RgIHdoZW4gQUNUSU9OU19DQUNIRV9VUkwgaXMgb3ZlcnJpZGRlbi4=-->fix: Correctly override the value of `Forgejo-Cache-Host` when ACTIONS_CACHE_URL is overridden.<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Vivian <me@vivstuff.gay>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1027
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Kwonunn <kwonunn@noreply.code.forgejo.org>
Co-committed-by: Kwonunn <kwonunn@noreply.code.forgejo.org>
2025-09-26 07:02:45 +00:00
Gusted
8debbe699e
chore: fix typo in the documentation (#1025)
Ref: forgejo/docs#1506

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1025): <!--number 1025 --><!--line 0 --><!--description Rml4IHR5cG8=-->Fix typo<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1025
Reviewed-by: Beowulf <beowulf@noreply.code.forgejo.org>
Co-authored-by: Gusted <gusted@noreply.code.forgejo.org>
Co-committed-by: Gusted <gusted@noreply.code.forgejo.org>
2025-09-23 06:41:07 +00:00
Renovate Bot
fb1a38b840
Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.5.0 (#1023)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/golangci/golangci-lint/v2/cmd/golangci-lint](https://github.com/golangci/golangci-lint) | `v2.4.0` -> `v2.5.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgolangci%2fgolangci-lint%2fv2%2fcmd%2fgolangci-lint/v2.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fgolangci%2fgolangci-lint%2fv2%2fcmd%2fgolangci-lint/v2.4.0/v2.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>golangci/golangci-lint (github.com/golangci/golangci-lint/v2/cmd/golangci-lint)</summary>

### [`v2.5.0`](https://github.com/golangci/golangci-lint/blob/HEAD/CHANGELOG.md#v250)

[Compare Source](https://github.com/golangci/golangci-lint/compare/v2.4.0...v2.5.0)

1. New linters
   - Add `godoclint` linter <https://github.com/godoc-lint/godoc-lint>
   - Add `unqueryvet` linter <https://github.com/MirrexOne/unqueryvet>
   - Add `iotamixing` linter <https://github.com/AdminBenni/iota-mixing>
2. Linters new features or changes
   - `embeddedstructfieldcheck`: from 0.3.0 to 0.4.0 (new option: `empty-line`)
   - `err113`: from [`aea10b5`](aea10b59be) to 0.1.1 (skip internals of `Is` methods for `error` type)
   - `ginkgolinter`: from 0.20.0 to 0.21.0 (new option: `force-tonot`)
   - `gofumpt`: from 0.8.0 to 0.9.1 (new rule is to "clothe" naked returns for the sake of clarity)
   - `ineffassign`: from 0.1.0 to 0.2.0 (new option: `check-escaping-errors`)
   - `musttag`: from 0.13.1 to 0.14.0 (support interface methods)
   - `revive`: from 1.11.0 to 1.12.0 (new options: `identical-ifelseif-branches`, `identical-ifelseif-conditions`, `identical-switch-branches`, `identical-switch-conditions`, `package-directory-mismatch`, `unsecure-url-scheme`, `use-waitgroup-go`, `useless-fallthrough`)
   - `thelper`: from 0.6.3 to 0.7.1 (skip `t.Helper` in functions passed to `synctest.Test`)
   - `wsl`: from 5.1.1 to 5.2.0 (improvements related to subexpressions)
3. Linters bug fixes
   - `asciicheck`: from 0.4.1 to 0.5.0
   - `errname`: from 1.1.0 to 1.1.1
   - `fatcontext`: from 0.8.0 to 0.8.1
   - `go-printf-func-name`: from 0.1.0 to 0.1.1
   - `godot`: from 1.5.1 to 1.5.4
   - `gosec`: from 2.22.7 to 2.22.8
   - `nilerr`: from 0.1.1 to a temporary fork
   - `nilnil`: from 1.1.0 to 1.1.1
   - `protogetter`: from 0.3.15 to 0.3.16
   - `tagliatelle`: from 0.7.1 to 0.7.2
   - `testifylint`: from 1.6.1 to 1.6.4
4. Misc.
   - fix: "no export data" errors are now handled as a standard typecheck error
5. Documentation
   - Improve nolint section about syntax

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMTMuMyIsInVwZGF0ZWRJblZlciI6IjQxLjExMy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1023
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-22 10:10:07 +00:00
Renovate Bot
225a05e1a5
Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.6 (#1022)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [code.forgejo.org/forgejo/forgejo](https://forgejo.org) ([source](https://codeberg.org/forgejo/forgejo)) | patch | `11.0.5` -> `11.0.6` |

---

### Release Notes

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

### [`v11.0.6`](https://codeberg.org/forgejo/forgejo/releases/tag/v11.0.6)

[Compare Source](https://codeberg.org/forgejo/forgejo/compare/v11.0.5...v11.0.6)

See <https://codeberg.org/forgejo/forgejo/src/branch/forgejo/release-notes-published/11.0.6.md>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMTMuMyIsInVwZGF0ZWRJblZlciI6IjQxLjExMy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1022
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-21 06:51:38 +00:00
Earl Warren
8512d76ce7
chore: upgrade LXC example to Debian GNU/Linux trixie (#1020)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1020): <!--number 1020 --><!--line 0 --><!--description Y2hvcmU6IHVwZ3JhZGUgTFhDIGV4YW1wbGUgdG8gRGViaWFuIEdOVS9MaW51eCB0cml4aWU=-->chore: upgrade LXC example to Debian GNU/Linux trixie<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1020
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-20 20:57:17 +00:00
Earl Warren
ed7dcb0081
fix: a composite action must not change the result of the calling step before it completes (#1019)
Resolves forgejo/runner#1014

---

Manual testing can also be done using the [reproducer from the issue](https://code.forgejo.org/forgejo/runner/issues/1014#issuecomment-60694).

## Before

The first step of the local composite action sets the step result of the job to success which confuses Forgejo display.

![image](/attachments/4f5c9477-47b8-4450-a858-c86312ced946)

## After

Forgejo displays the progress of the composite action in the step calling it.

![image](/attachments/eed08b5d-b590-472f-9140-eced739dd47b)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1019): <!--number 1019 --><!--line 0 --><!--description Zml4OiBhIGNvbXBvc2l0ZSBhY3Rpb24gbXVzdCBub3QgY2hhbmdlIHRoZSByZXN1bHQgb2YgdGhlIGNhbGxpbmcgc3RlcCBiZWZvcmUgaXQgY29tcGxldGVz-->fix: a composite action must not change the result of the calling step before it completes<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1019
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-20 16:30:19 +00:00
Renovate Bot
71bd44f9a0
Update https://data.forgejo.org/actions/setup-forgejo action to v3.0.4 (#1021)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [https://data.forgejo.org/actions/setup-forgejo](https://code.forgejo.org/actions/setup-forgejo) | action | patch | `v3.0.3` -> `v3.0.4` |

---

### Release Notes

<details>
<summary>actions/setup-forgejo (https://data.forgejo.org/actions/setup-forgejo)</summary>

### [`v3.0.4`](https://code.forgejo.org/actions/setup-forgejo/compare/v3.0.3...v3.0.4)

[Compare Source](https://code.forgejo.org/actions/setup-forgejo/compare/v3.0.3...v3.0.4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMTMuMyIsInVwZGF0ZWRJblZlciI6IjQxLjExMy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1021
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-20 16:26:21 +00:00
Renovate Bot
aed4dd8766
Update forgejo-runner to v11.1.1 (#1018)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [code.forgejo.org/forgejo/runner](https://forgejo.org) ([source](https://code.forgejo.org/forgejo/runner)) | minor | `11.0.0` -> `11.1.1` |
| [forgejo/runner](https://code.forgejo.org/forgejo/runner) | minor | `11.0.0` -> `11.1.1` |

---

### Release Notes

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

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v11.1.0...v11.1.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-->

- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1017): <!--number 1017 --><!--line 0 --><!--description Zml4OiBvdXRwdXRzIGFyZSBvbmx5IHNldCB3aGVuIHRoZSBqb2IgaXMgc3VjY2Vzc2Z1bA==-->fix: outputs are only set when the job is successful<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1015): <!--number 1015 --><!--line 0 --><!--description Zml4KHByZS1jb21taXQpOiBkb27igJl0IGRlZmF1bHQgYHZlcmJvc2VgIHRvIG9u-->fix(pre-commit): don’t default `verbose` to on<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1013): <!--number 1013 --><!--line 0 --><!--description Y2hvcmU6IGRvY3VtZW50IHRoYXQgRE9DS0VSX0hPU1Qgc2hvdWxkIGJlIHVzZWQgaW5zdGVhZCBvZiAtLWNvbnRhaW5lci1kYWVtb24tc29ja2V0-->chore: document that DOCKER\_HOST should be used instead of --container-daemon-socket<!--description-->

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

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v11.0.0...v11.1.0)

> **Warning** Upgrade to v11.1.1 instead. A [regression was found](https://code.forgejo.org/forgejo/runner/issues/1016) that crashed the runner on skipped or failed jobs.

- [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/1002): <!--number 1002 --><!--line 0 --><!--description ZmVhdDogYWRkIHByZS1jb21taXQgaG9vayBmb3IgdmFsaWRhdG9y-->feat: add pre-commit hook for validator<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1008): <!--number 1008 --><!--line 0 --><!--description ZmVhdDogdmFsaWRhdGUgLS1kaXJlY3RvcnkgYWx0ZXJuYXRpdmUgdG8gLS1yZXBvc2l0b3J5IHRvIG5vdCBjbG9uZQ==-->feat: validate --directory alternative to --repository to not clone<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/999): <!--number 999 --><!--line 0 --><!--description ZmVhdDogdGhlIGZvcmdlam8gY29udGV4dCBpcyBlcXVpdmFsZW50IHRvIHRoZSBnaXRodWIgY29udGV4dA==-->feat: the forgejo context is equivalent to the github context<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/997): <!--number 997 --><!--line 0 --><!--description ZmVhdDogYWRkIHN1cHBvcnQgZm9yIGEgRGViaWFuIEdOVS9MaW51eCBMWEMgYmFja2VuZCBiYXNlZCBvbiB0cml4aWUgKGUuZy4gdHJpeGllLWx4YzpseGM6Ly9kZWJpYW46dHJpeGllKQ==-->feat: add support for a Debian GNU/Linux LXC backend based on trixie (e.g. trixie-lxc:lxc://debian:trixie)<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1012): <!--number 1012 --><!--line 0 --><!--description Zml4OiBzY2hlbWEgdmFsaWRhdGlvbiBtdXN0IGFjY2VwdCBhbGlhc2VzIGFuZCBtZXJnZXM=-->fix: schema validation must accept aliases and merges<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1009): <!--number 1009 --><!--line 0 --><!--description Zml4OiBmb3JnZWpvLXJ1bm5lciB2YWxpZGF0ZSBleGl0IHdpdGggZXJyb3Igd2hlbiB2YWxpZGF0aW9uIGZhaWxz-->fix: forgejo-runner validate exit with error when validation fails<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1006): <!--number 1006 --><!--line 0 --><!--description Zml4OiBkbyBub3Qgc2F2ZSAucnVubmVyIHVubGVzcyBpdCBpcyBtb2RpZmllZA==-->fix: do not save .runner unless it is modified<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1003): <!--number 1003 --><!--line 0 --><!--description Zml4OiByZW1vdmUgTFhDIHdvcmtpbmcgZGlyZWN0b3J5IHdoZW4gaXQgY29tcGxldGVz-->fix: remove LXC working directory when it completes<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/995): <!--number 995 --><!--line 0 --><!--description Zml4OiBzZW5kIGpvYiBvdXRwdXRzICYgam9iIHJlc3VsdCB0byBGb3JnZWpvIGluIHN5bmMgd2l0aCBlYWNoIG90aGVy-->fix: send job outputs & job result to Forgejo in sync with each other<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/986): <!--number 986 --><!--line 0 --><!--description Zml4OiBpZiB0aGUgRm9yZ2VqbyBpbnN0YW5jZSBmYWlsZWQgYSBqb2IsIGNhbmNlbCBpdA==-->fix: if the Forgejo instance failed a job, cancel it<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/982): <!--number 982 --><!--line 0 --><!--description Zml4OiBlbmZvcmNlIGpvYi48am9iLWlkPi50aW1lb3V0LW1pbnV0ZXM=-->fix: enforce job.<job-id>.timeout-minutes<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/972): <!--number 972 --><!--line 0 --><!--description Zml4OiB1c2UgYSBmaXhlZCBydW5uZXIgbmFtZSBmb3Igb2xkICg8PSB2MS4yMCkgRm9yZ2VqbyBpbnN0YW5jZXM=-->fix: use a fixed runner name for old (<= v1.20) Forgejo instances<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/965): <!--number 965 --><!--line 0 --><!--description Zml4OiBkb2NrZXItY29tcG9zZSBleGFtcGxlOiBhbGxvdyB0aGUgcnVubmVyIHRvIGtlZXAgaXRzIGxhYmVscw==-->fix: docker-compose example: allow the runner to keep its labels<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1001): <!--number 1001 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9seGMtaGVscGVycyB0byB2MS4xLjA=-->Update dependency forgejo/lxc-helpers to v1.1.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1000): <!--number 1000 --><!--line 0 --><!--description Y2hvcmU6IG1pbmltYWwgaW50ZWdyYXRpb24gdGVzdCBmb3IgdGhlIExYQyBiYWNrZW5k-->chore: minimal integration test for the LXC backend<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/993): <!--number 993 --><!--line 0 --><!--description Y2hvcmU6IHVuaWZ5IGFjdGlvbnMgVVJMcyBpbiAuZm9yZ2Vqby93b3JrZmxvd3M=-->chore: unify actions URLs in .forgejo/workflows<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/992): <!--number 992 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL2Nhc2NhZGluZy1wciBhY3Rpb24gdG8gdjIuMy4w-->Update <https://data.forgejo.org/actions/cascading-pr> action to v2.3.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/990): <!--number 990 --><!--line 0 --><!--description Y2hvcmU6IGRhdGEuZm9yZ2Vqby5vcmcvYWN0aW9ucy9jYXNjYWRpbmctcHIgaXMgdGhlIGNhbm9uaWNhbCBsb2NhdGlvbg==-->chore: data.forgejo.org/actions/cascading-pr is the canonical location<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/989): <!--number 989 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9yZWxlYXNlLW5vdGVzLWFzc2lzdGFudCB0byB2MS40LjE=-->Update dependency forgejo/release-notes-assistant to v1.4.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/988): <!--number 988 --><!--line 0 --><!--description Y2hvcmU6IHdhaXQgNCB0aW1lcyBsb25nZXIgZm9yIHRoZSBmb3JnZWpvIGNhc2NhZGUgcHVsbCByZXF1ZXN0IHRvIGNvbXBsZXRl-->chore: wait 4 times longer for the forgejo cascade pull request to complete<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/985): <!--number 985 --><!--line 0 --><!--description UmVtb3ZlIHdpbmRvd3MgYnVpbGQvdGVzdCBwaXBlbGluZSBmb3IgR2l0SHVi-->Remove windows build/test pipeline for GitHub<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/981): <!--number 981 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBjb2RlLmZvcmdlam8ub3JnL2Zvcmdlam8vYWN0aW9ucy1wcm90byB0byB2MC41LjI=-->Update module code.forgejo.org/forgejo/actions-proto to v0.5.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/969): <!--number 969 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL3NldHVwLWZvcmdlam8gYWN0aW9uIHRvIHYzLjAuMw==-->Update <https://data.forgejo.org/actions/setup-forgejo> action to v3.0.3<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/975): <!--number 975 --><!--line 0 --><!--description VXBkYXRlIGZvcmdlam8tcnVubmVyIHRvIHYxMSAobWFqb3Ip-->Update forgejo-runner to v11 (major)<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/973): <!--number 973 --><!--line 0 --><!--description Y2k6IHVwZGF0ZSBmb3JnZWpvIHZlcnNpb24gZm9yIHJlbGVhc2UgaW50ZWdyYXRpb24=-->ci: update forgejo version for release integration<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/970): <!--number 970 --><!--line 0 --><!--description Y2hvcmU6IGx4Yy1zeXN0ZW1kIG1heSBuZWVkIG1vcmUgdGltZSB0byBzdGFydCBvbiBzbG93IG1hY2hpbmVz-->chore: lxc-systemd may need more time to start on slow machines<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/966): <!--number 966 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvdGVybSB0byB2MC4zNS4w-->Update module golang.org/x/term to v0.35.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/964): <!--number 964 --><!--line 0 --><!--description Y2hvcmU6IGNhbGwgdGhlIHJlbGVhc2Ugbm90ZXMgYXNzaXN0YW50IHdoZW4gb3BlbmluZyBhIG5ldyBwdWxsIHJlcXVlc3Q=-->chore: call the release notes assistant when opening a new pull request<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/954): <!--number 954 --><!--line 0 --><!--description Y2hvcmU6IHNraXAgcmVsZWFzZS1ub3Rlcy1hc3Npc3RhbnQgZm9yIGRlcGVuZGVuY3kgdXBkYXRlcw==-->chore: skip release-notes-assistant for dependency updates<!--description-->

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

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (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 these updates 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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMTMuMyIsInVwZGF0ZWRJblZlciI6IjQxLjExMy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1018
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-19 04:31:14 +00:00
Earl Warren
331979b887
fix: outputs are only set when the job is successful (#1017)
Resolves forgejo/runner#1016

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1017): <!--number 1017 --><!--line 0 --><!--description Zml4OiBvdXRwdXRzIGFyZSBvbmx5IHNldCB3aGVuIHRoZSBqb2IgaXMgc3VjY2Vzc2Z1bA==-->fix: outputs are only set when the job is successful<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1017
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-18 16:17:56 +00:00
Freso
c25bd51857
fix(pre-commit): don’t default verbose to on (#1015)
`verbose` was only set here as a work-around to make sure users saw the output of `validate` since there was no fail signal from the executable.

As of https://code.forgejo.org/forgejo/runner/pulls/1009 there now is a signal that the validation failed which pre-commit can pick up on, so we no longer need to default `verbose` to be on.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1015): <!--number 1015 --><!--line 0 --><!--description Zml4KHByZS1jb21taXQpOiBkb27igJl0IGRlZmF1bHQgYHZlcmJvc2VgIHRvIG9u-->fix(pre-commit): don’t default `verbose` to on<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Frederik “Freso” S. Olesen <freso.dk@gmail.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1015
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Freso <freso@noreply.code.forgejo.org>
Co-committed-by: Freso <freso@noreply.code.forgejo.org>
2025-09-18 12:02:07 +00:00
Earl Warren
ae283ef0f5
chore: document that DOCKER_HOST should be used instead of --container-daemon-socket (#1013)
Resolves forgejo/runner#577

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1013): <!--number 1013 --><!--line 0 --><!--description Y2hvcmU6IGRvY3VtZW50IHRoYXQgRE9DS0VSX0hPU1Qgc2hvdWxkIGJlIHVzZWQgaW5zdGVhZCBvZiAtLWNvbnRhaW5lci1kYWVtb24tc29ja2V0-->chore: document that DOCKER_HOST should be used instead of --container-daemon-socket<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1013
Reviewed-by: sclu1034 <sclu1034@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-18 11:51:33 +00:00
53 changed files with 1601 additions and 430 deletions

View file

@ -0,0 +1,27 @@
name: ci
on:
push:
tags:
- v*
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: ">=1.25.1"
- name: Test code
run: make test
- name: Run GoReleaser
uses: https://github.com/goreleaser/goreleaser-action@v6
env:
GITEA_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
with:
args: release --clean

View file

@ -19,7 +19,7 @@ on:
enable-email-notifications: true
env:
FORGEJO_VERSION: 11.0.5 # renovate: datasource=docker depName=code.forgejo.org/forgejo/forgejo
FORGEJO_VERSION: 11.0.7 # renovate: datasource=docker depName=code.forgejo.org/forgejo/forgejo
jobs:
release-simulation:
@ -29,7 +29,7 @@ jobs:
- uses: https://data.forgejo.org/actions/checkout@v4
- id: forgejo
uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.3
uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.4
with:
user: root
password: admin1234

View file

@ -21,7 +21,7 @@ on:
enable-email-notifications: true
env:
FORGEJO_VERSION: 11.0.5 # renovate: datasource=docker depName=code.forgejo.org/forgejo/forgejo
FORGEJO_VERSION: 11.0.7 # renovate: datasource=docker depName=code.forgejo.org/forgejo/forgejo
FORGEJO_USER: root
FORGEJO_PASSWORD: admin1234
@ -34,7 +34,7 @@ jobs:
- name: install Forgejo so it can be used as a container registry
id: registry
uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.3
uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.4
with:
user: ${{ env.FORGEJO_USER }}
password: ${{ env.FORGEJO_PASSWORD }}

View file

@ -14,11 +14,12 @@ env:
SERIAL: "30"
LIFETIME: "60"
SYSTEMD_OPTIONS: "--no-pager --full"
USE_VERSION: 11.0.7 # renovate: datasource=docker depName=code.forgejo.org/forgejo/forgejo
jobs:
example-lxc-systemd:
if: vars.ROLE == 'forgejo-coding'
runs-on: lxc-bookworm
runs-on: lxc-trixie
steps:
- uses: https://data.forgejo.org/actions/checkout@v4
@ -53,11 +54,11 @@ jobs:
done
- id: forgejo
uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.3
uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.4
with:
user: root
password: admin1234
binary: https://code.forgejo.org/forgejo/forgejo/releases/download/v7.0.12/forgejo-7.0.12-linux-amd64
binary: https://code.forgejo.org/forgejo/forgejo/releases/download/v${{ env.USE_VERSION }}/forgejo-${{ env.USE_VERSION }}-linux-amd64
# must be the same as LXC_IPV4_PREFIX in examples/lxc-systemd/forgejo-runner-service.sh
lxc-ip-prefix: 10.105.7

60
.goreleaser.yaml Normal file
View file

@ -0,0 +1,60 @@
version: 2
before:
hooks:
- go mod download
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- darwin
- windows
goarch:
- amd64
- arm64
archives:
- formats: [binary]
# this name template makes the OS and Arch compatible with the results of `uname`.
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end }}
changelog:
abbrev: 10
filters:
exclude:
- "^docs:"
- "^test:"
format: "{{.SHA}}: {{.Message}}"
groups:
- title: Features
regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
order: 0
- title: "Bug fixes"
regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$'
order: 1
- title: "Chores"
regexp: '^.*?chore(\([[:word:]]+\))??!?:.+$'
order: 2
- title: Others
order: 999
sort: asc
release:
gitea:
owner: DevFW-CICD
name: runner
force_token: gitea
gitea_urls:
api: https://edp.buildth.ing/api/v1
download: https://edp.buildth.ing
# set to true if you use a self-signed certificate
skip_tls_verify: false

View file

@ -11,6 +11,3 @@
# Old names (without the pre- prefix) are deprecated since 4.0.0.
minimum_pre_commit_version: '3.2.0'
stages: [pre-commit, pre-merge-commit, pre-push, manual]
# validate doesnt currently provide non-success exit codes,
# so falling back to always printing verbose output for now.
verbose: true

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.24-alpine3.22 AS build-env
FROM --platform=$BUILDPLATFORM data.forgejo.org/oci/golang:1.25-alpine3.22 AS build-env
#
# Transparently cross compile for the target platform

View file

@ -14,7 +14,7 @@ GO_FMT_FILES := $(shell find . -type f -name "*.go" ! -name "generated.*")
GOFILES := $(shell find . -type f -name "*.go" -o -name "go.mod" ! -name "generated.*")
MOCKERY_PACKAGE ?= github.com/vektra/mockery/v2@v2.53.5 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.4.0 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.5.0 # renovate: datasource=go
DOCKER_IMAGE ?= gitea/act_runner
DOCKER_TAG ?= nightly

View file

@ -19,12 +19,13 @@ import (
//go:generate mockery --inpackage --name caches
type caches interface {
openDB() (*bolthold.Store, error)
getDB() *bolthold.Store
validateMac(rundata RunData) (string, error)
readCache(id uint64, repo string) (*Cache, error)
useCache(id uint64) error
setgcAt(at time.Time)
gcCache()
close()
serve(w http.ResponseWriter, r *http.Request, id uint64)
commit(id uint64, size int64) (int64, error)
@ -38,6 +39,8 @@ type cachesImpl struct {
logger logrus.FieldLogger
secret string
db *bolthold.Store
gcing atomic.Bool
gcAt time.Time
}
@ -68,12 +71,6 @@ func newCaches(dir, secret string, logger logrus.FieldLogger) (caches, error) {
}
c.storage = storage
c.gcCache()
return c, nil
}
func (c *cachesImpl) openDB() (*bolthold.Store, error) {
file := filepath.Join(c.dir, "bolt.db")
db, err := bolthold.Open(file, 0o644, &bolthold.Options{
Encoder: json.Marshal,
@ -87,7 +84,22 @@ func (c *cachesImpl) openDB() (*bolthold.Store, error) {
if err != nil {
return nil, fmt.Errorf("Open(%s): %w", file, err)
}
return db, nil
c.db = db
c.gcCache()
return c, nil
}
func (c *cachesImpl) close() {
if c.db != nil {
c.db.Close()
c.db = nil
}
}
func (c *cachesImpl) getDB() *bolthold.Store {
return c.db
}
var findCacheWithIsolationKeyFallback = func(db *bolthold.Store, repo string, keys []string, version, writeIsolationKey string) (*Cache, error) {
@ -156,11 +168,7 @@ func insertCache(db *bolthold.Store, cache *Cache) error {
}
func (c *cachesImpl) readCache(id uint64, repo string) (*Cache, error) {
db, err := c.openDB()
if err != nil {
return nil, err
}
defer db.Close()
db := c.getDB()
cache := &Cache{}
if err := db.Get(id, cache); err != nil {
return nil, fmt.Errorf("readCache: Get(%v): %w", id, err)
@ -173,11 +181,7 @@ func (c *cachesImpl) readCache(id uint64, repo string) (*Cache, error) {
}
func (c *cachesImpl) useCache(id uint64) error {
db, err := c.openDB()
if err != nil {
return err
}
defer db.Close()
db := c.getDB()
cache := &Cache{}
if err := db.Get(id, cache); err != nil {
return fmt.Errorf("useCache: Get(%v): %w", id, err)
@ -232,12 +236,7 @@ func (c *cachesImpl) gcCache() {
c.gcAt = time.Now()
c.logger.Debugf("gc: %v", c.gcAt.String())
db, err := c.openDB()
if err != nil {
fatal(c.logger, err)
return
}
defer db.Close()
db := c.getDB()
// Remove the caches which are not completed for a while, they are most likely to be broken.
var caches []*Cache

View file

@ -14,6 +14,7 @@ import (
func TestCacheReadWrite(t *testing.T) {
caches, err := newCaches(t.TempDir(), "secret", logrus.New())
require.NoError(t, err)
defer caches.close()
t.Run("NotFound", func(t *testing.T) {
found, err := caches.readCache(456, "repo")
assert.Nil(t, found)
@ -33,9 +34,7 @@ func TestCacheReadWrite(t *testing.T) {
cache.Repo = repo
t.Run("Insert", func(t *testing.T) {
db, err := caches.openDB()
require.NoError(t, err)
defer db.Close()
db := caches.getDB()
assert.NoError(t, insertCache(db, cache))
})

View file

@ -9,7 +9,6 @@ import (
"net/http"
"strconv"
"strings"
"syscall"
"time"
"github.com/julienschmidt/httprouter"
@ -25,7 +24,7 @@ const (
var fatal = func(logger logrus.FieldLogger, err error) {
logger.Errorf("unrecoverable error in the cache: %v", err)
if err := syscall.Kill(syscall.Getpid(), syscall.SIGTERM); err != nil {
if err := suicide(); err != nil {
logger.Errorf("unrecoverable error in the cache: failed to send the TERM signal to shutdown the daemon %v", err)
}
}
@ -122,6 +121,10 @@ func (h *handler) Close() error {
return nil
}
var retErr error
if h.caches != nil {
h.caches.close()
h.caches = nil
}
if h.server != nil {
err := h.server.Close()
if err != nil {
@ -151,6 +154,9 @@ func (h *handler) getCaches() caches {
}
func (h *handler) setCaches(caches caches) {
if h.caches != nil {
h.caches.close()
}
h.caches = caches
}
@ -170,12 +176,7 @@ func (h *handler) find(w http.ResponseWriter, r *http.Request, params httprouter
}
version := r.URL.Query().Get("version")
db, err := h.caches.openDB()
if err != nil {
h.responseFatalJSON(w, r, err)
return
}
defer db.Close()
db := h.caches.getDB()
cache, err := findCacheWithIsolationKeyFallback(db, repo, keys, version, rundata.WriteIsolationKey)
if err != nil {
@ -221,12 +222,7 @@ func (h *handler) reserve(w http.ResponseWriter, r *http.Request, params httprou
api.Key = strings.ToLower(api.Key)
cache := api.ToCache()
db, err := h.caches.openDB()
if err != nil {
h.responseFatalJSON(w, r, err)
return
}
defer db.Close()
db := h.caches.getDB()
now := time.Now().Unix()
cache.CreatedAt = now
@ -335,12 +331,7 @@ func (h *handler) commit(w http.ResponseWriter, r *http.Request, params httprout
// write real size back to cache, it may be different from the current value when the request doesn't specify it.
cache.Size = size
db, err := h.caches.openDB()
if err != nil {
h.responseFatalJSON(w, r, err)
return
}
defer db.Close()
db := h.caches.getDB()
cache.Complete = true
if err := db.Update(cache.ID, cache); err != nil {

View file

@ -78,9 +78,7 @@ func TestHandler(t *testing.T) {
defer func() {
t.Run("inspect db", func(t *testing.T) {
db, err := handler.getCaches().openDB()
require.NoError(t, err)
defer db.Close()
db := handler.getCaches().getDB()
require.NoError(t, db.Bolt().View(func(tx *bbolt.Tx) error {
return tx.Bucket([]byte("Cache")).ForEach(func(k, v []byte) error {
t.Logf("%s: %s", k, v)
@ -937,40 +935,11 @@ func TestHandlerAPIFatalErrors(t *testing.T) {
handler.find(w, req, nil)
},
},
{
name: "find open",
caches: func(t *testing.T, message string) caches {
caches := newMockCaches(t)
caches.On("validateMac", RunData{}).Return(cacheRepo, nil)
caches.On("openDB", mock.Anything, mock.Anything).Return(nil, errors.New(message))
return caches
},
call: func(t *testing.T, handler Handler, w http.ResponseWriter) {
req, err := http.NewRequest("GET", "example.com/cache", nil)
require.NoError(t, err)
handler.find(w, req, nil)
},
},
{
name: "reserve",
caches: func(t *testing.T, message string) caches {
caches := newMockCaches(t)
caches.On("validateMac", RunData{}).Return(cacheRepo, nil)
caches.On("openDB", mock.Anything, mock.Anything).Return(nil, errors.New(message))
return caches
},
call: func(t *testing.T, handler Handler, w http.ResponseWriter) {
body, err := json.Marshal(&Request{})
require.NoError(t, err)
req, err := http.NewRequest("POST", "example.com/caches", bytes.NewReader(body))
require.NoError(t, err)
handler.reserve(w, req, nil)
},
},
{
name: "upload",
caches: func(t *testing.T, message string) caches {
caches := newMockCaches(t)
caches.On("close").Return()
caches.On("validateMac", RunData{}).Return(cacheRepo, nil)
caches.On("readCache", mock.Anything, mock.Anything).Return(nil, errors.New(message))
return caches
@ -988,6 +957,7 @@ func TestHandlerAPIFatalErrors(t *testing.T) {
name: "commit",
caches: func(t *testing.T, message string) caches {
caches := newMockCaches(t)
caches.On("close").Return()
caches.On("validateMac", RunData{}).Return(cacheRepo, nil)
caches.On("readCache", mock.Anything, mock.Anything).Return(nil, errors.New(message))
return caches
@ -1005,6 +975,7 @@ func TestHandlerAPIFatalErrors(t *testing.T) {
name: "get",
caches: func(t *testing.T, message string) caches {
caches := newMockCaches(t)
caches.On("close").Return()
caches.On("validateMac", RunData{}).Return(cacheRepo, nil)
caches.On("readCache", mock.Anything, mock.Anything).Return(nil, errors.New(message))
return caches
@ -1042,10 +1013,12 @@ func TestHandlerAPIFatalErrors(t *testing.T) {
dir := filepath.Join(t.TempDir(), "artifactcache")
handler, err := StartHandler(dir, "", 0, "secret", nil)
require.NoError(t, err)
defer handler.Close()
fatalMessage = "<unset>"
handler.setCaches(testCase.caches(t, message))
caches := testCase.caches(t, message) // doesn't need to be closed because it will be given to handler
handler.setCaches(caches)
w := httptest.NewRecorder()
testCase.call(t, handler, w)
@ -1138,18 +1111,15 @@ func TestHandler_gcCache(t *testing.T) {
},
}
db, err := handler.getCaches().openDB()
require.NoError(t, err)
db := handler.getCaches().getDB()
for _, c := range cases {
require.NoError(t, insertCache(db, c.Cache))
}
require.NoError(t, db.Close())
handler.getCaches().setgcAt(time.Time{}) // ensure gcCache will not skip
handler.getCaches().gcCache()
db, err = handler.getCaches().openDB()
require.NoError(t, err)
db = handler.getCaches().getDB()
for i, v := range cases {
t.Run(fmt.Sprintf("%d_%s", i, v.Cache.Key), func(t *testing.T) {
cache := &Cache{}
@ -1161,7 +1131,6 @@ func TestHandler_gcCache(t *testing.T) {
}
})
}
require.NoError(t, db.Close())
}
func TestHandler_ExternalURL(t *testing.T) {

View file

@ -19,6 +19,11 @@ type mockCaches struct {
mock.Mock
}
// close provides a mock function with no fields
func (_m *mockCaches) close() {
_m.Called()
}
// commit provides a mock function with given fields: id, size
func (_m *mockCaches) commit(id uint64, size int64) (int64, error) {
ret := _m.Called(id, size)
@ -80,19 +85,15 @@ func (_m *mockCaches) gcCache() {
_m.Called()
}
// openDB provides a mock function with no fields
func (_m *mockCaches) openDB() (*bolthold.Store, error) {
// getDB provides a mock function with no fields
func (_m *mockCaches) getDB() *bolthold.Store {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for openDB")
panic("no return value specified for getDB")
}
var r0 *bolthold.Store
var r1 error
if rf, ok := ret.Get(0).(func() (*bolthold.Store, error)); ok {
return rf()
}
if rf, ok := ret.Get(0).(func() *bolthold.Store); ok {
r0 = rf()
} else {
@ -101,13 +102,7 @@ func (_m *mockCaches) openDB() (*bolthold.Store, error) {
}
}
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
return r0
}
// readCache provides a mock function with given fields: id, repo

View file

@ -0,0 +1,9 @@
//go:build !windows
package artifactcache
import "syscall"
func suicide() error {
return syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
}

View file

@ -0,0 +1,14 @@
//go:build windows
package artifactcache
import "syscall"
func suicide() error {
handle, err := syscall.GetCurrentProcess()
if err != nil {
return err
}
return syscall.TerminateProcess(handle, uint32(syscall.SIGTERM))
}

View file

@ -38,6 +38,7 @@ type Handler struct {
outboundIP string
cacheServerHost string
cacheProxyHostOverride string
cacheSecret string
@ -55,7 +56,7 @@ func (h *Handler) CreateRunData(fullName, runNumber, timestamp, writeIsolationKe
}
}
func StartHandler(targetHost, outboundIP string, port uint16, cacheSecret string, logger logrus.FieldLogger) (*Handler, error) {
func StartHandler(targetHost, outboundIP string, port uint16, cacheProxyHostOverride, cacheSecret string, logger logrus.FieldLogger) (*Handler, error) {
h := &Handler{}
if logger == nil {
@ -63,7 +64,7 @@ func StartHandler(targetHost, outboundIP string, port uint16, cacheSecret string
discard.Out = io.Discard
logger = discard
}
logger = logger.WithField("module", "artifactcache")
logger = logger.WithField("module", "cacheproxy")
h.logger = logger
h.cacheSecret = cacheSecret
@ -77,10 +78,11 @@ func StartHandler(targetHost, outboundIP string, port uint16, cacheSecret string
}
h.cacheServerHost = targetHost
h.cacheProxyHostOverride = cacheProxyHostOverride
proxy, err := h.newReverseProxy(targetHost)
if err != nil {
return nil, fmt.Errorf("unable to set up proxy to target host")
return nil, fmt.Errorf("unable to set up proxy to target host: %v", err)
}
router := httprouter.New()
@ -137,6 +139,7 @@ func (h *Handler) newReverseProxy(targetHost string) (*httputil.ReverseProxy, er
r.SetURL(targetURL)
r.Out.URL.Path = uri
h.logger.Debugf("proxy req %s %q to %q", r.In.Method, r.In.URL, r.Out.URL)
r.Out.Header.Set("Forgejo-Cache-Repo", runData.RepositoryFullName)
r.Out.Header.Set("Forgejo-Cache-RunNumber", runData.RunNumber)
@ -148,12 +151,18 @@ func (h *Handler) newReverseProxy(targetHost string) (*httputil.ReverseProxy, er
r.Out.Header.Set("Forgejo-Cache-WriteIsolationKey", runData.WriteIsolationKey)
}
},
ModifyResponse: func(r *http.Response) error {
h.logger.Debugf("proxy resp %s w/ %d bytes", r.Status, r.ContentLength)
return nil
},
}
return proxy, nil
}
func (h *Handler) ExternalURL() string {
// TODO: make the external url configurable if necessary
if h.cacheProxyHostOverride != "" {
return h.cacheProxyHostOverride
}
return fmt.Sprintf("http://%s", net.JoinHostPort(h.outboundIP, strconv.Itoa(h.listener.Addr().(*net.TCPAddr).Port)))
}

View file

@ -305,7 +305,7 @@ func gitOptions(token string) (fetchOptions git.FetchOptions, pullOptions git.Pu
func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor {
return func(ctx context.Context) error {
logger := common.Logger(ctx)
logger.Infof(" \u2601 git clone '%s' # ref=%s", input.URL, input.Ref)
logger.Infof(" \u2601\ufe0f git clone '%s' # ref=%s", input.URL, input.Ref)
logger.Debugf(" cloning %s to %s", input.URL, input.Dir)
cloneLock.Lock()

View file

@ -483,6 +483,14 @@ func (cr *containerReference) mergeJobOptions(ctx context.Context, config *conta
}
}
if jobConfig.HostConfig.Memory > 0 {
logger.Debugf("--memory %v", jobConfig.HostConfig.Memory)
if hostConfig.Memory > 0 && jobConfig.HostConfig.Memory > hostConfig.Memory {
return nil, nil, fmt.Errorf("the --memory %v option found in the workflow cannot be greater than the --memory %v option from the runner configuration file", jobConfig.HostConfig.Memory, hostConfig.Memory)
}
hostConfig.Memory = jobConfig.HostConfig.Memory
}
if len(jobConfig.Config.Hostname) > 0 {
logger.Debugf("--hostname %v", jobConfig.Config.Hostname)
config.Hostname = jobConfig.Config.Hostname

View file

@ -34,7 +34,6 @@ type HostEnvironment struct {
Workdir string
ActPath string
Root string
CleanUp func()
StdOut io.Writer
LXC bool
}
@ -389,7 +388,7 @@ func (e *HostEnvironment) ExecWithCmdLine(command []string, cmdline string, env
if err := e.exec(ctx, command, cmdline, env, user, workdir); err != nil {
select {
case <-ctx.Done():
return fmt.Errorf("this step has been cancelled: %w", err)
return fmt.Errorf("this step has been cancelled: ctx: %w, exec: %w", ctx.Err(), err)
default:
return err
}
@ -404,11 +403,12 @@ func (e *HostEnvironment) UpdateFromEnv(srcPath string, env *map[string]string)
func (e *HostEnvironment) Remove() common.Executor {
return func(ctx context.Context) error {
if e.CleanUp != nil {
e.CleanUp()
if e.GetLXC() {
// there may be files owned by root: removal
// is the responsibility of the LXC backend
return nil
}
common.Logger(ctx).Debugf("HostEnvironment.Remove %s", e.Path)
return os.RemoveAll(e.Path)
return os.RemoveAll(e.Root)
}
}

View file

@ -76,6 +76,36 @@ func NewInterpeter(
return exprparser.NewInterpeter(ee, config)
}
// Returns an interpeter used in the server in the context of workflow-level templates. Needs github, inputs, and vars
// context only.
func NewWorkflowInterpeter(
gitCtx *model.GithubContext,
vars map[string]string,
inputs map[string]any,
) exprparser.Interpreter {
ee := &exprparser.EvaluationEnvironment{
Github: gitCtx,
Env: nil, // no need
Job: nil, // no need
Steps: nil, // no need
Runner: nil, // no need
Secrets: nil, // no need
Strategy: nil, // no need
Matrix: nil, // no need
Needs: nil, // no need
Inputs: inputs,
Vars: vars,
}
config := exprparser.Config{
Run: nil,
WorkingDir: "", // WorkingDir is used for the function hashFiles, but it's not needed in the server
Context: "workflow",
}
return exprparser.NewInterpeter(ee, config)
}
// JobResult is the minimum requirement of job results for Interpeter
type JobResult struct {
Needs []string

View file

@ -1,8 +1,8 @@
package jobparser
import (
"bytes"
"fmt"
"strings"
"code.forgejo.org/forgejo/runner/v11/act/model"
"go.yaml.in/yaml/v3"
@ -193,83 +193,32 @@ func (evt *Event) Schedules() []map[string]string {
return evt.schedules
}
func ReadWorkflowRawConcurrency(content []byte) (*model.RawConcurrency, error) {
w := new(model.Workflow)
err := yaml.NewDecoder(bytes.NewReader(content)).Decode(w)
return w.RawConcurrency, err
}
func EvaluateConcurrency(rc *model.RawConcurrency, jobID string, job *Job, gitCtx map[string]any, results map[string]*JobResult, vars map[string]string, inputs map[string]any) (string, bool, error) {
actJob := &model.Job{}
if job != nil {
actJob.Strategy = &model.Strategy{
FailFastString: job.Strategy.FailFastString,
MaxParallelString: job.Strategy.MaxParallelString,
RawMatrix: job.Strategy.RawMatrix,
}
actJob.Strategy.FailFast = actJob.Strategy.GetFailFast()
actJob.Strategy.MaxParallel = actJob.Strategy.GetMaxParallel()
}
matrix := make(map[string]any)
matrixes, err := actJob.GetMatrixes()
if err != nil {
return "", false, err
}
if len(matrixes) > 0 {
matrix = matrixes[0]
}
evaluator := NewExpressionEvaluator(NewInterpeter(jobID, actJob, matrix, toGitContext(gitCtx), results, vars, inputs))
// Convert the raw YAML from the `concurrency` block on a workflow into the evaluated concurrency group and
// cancel-in-progress value. This implementation only supports workflow-level concurrency definition, where we expect
// expressions to be able to access only the github, inputs and vars contexts. If RawConcurrency is empty, then the
// returned concurrency group will be "" and cancel-in-progress will be nil -- this can be used to distinguish from an
// explicit cancel-in-progress choice even if a group isn't specified.
func EvaluateWorkflowConcurrency(rc *model.RawConcurrency, gitCtx *model.GithubContext, vars map[string]string, inputs map[string]any) (string, *bool, error) {
evaluator := NewExpressionEvaluator(NewWorkflowInterpeter(gitCtx, vars, inputs))
var node yaml.Node
if err := node.Encode(rc); err != nil {
return "", false, fmt.Errorf("failed to encode concurrency: %w", err)
return "", nil, fmt.Errorf("failed to encode concurrency: %w", err)
}
if err := evaluator.EvaluateYamlNode(&node); err != nil {
return "", false, fmt.Errorf("failed to evaluate concurrency: %w", err)
return "", nil, fmt.Errorf("failed to evaluate concurrency: %w", err)
}
var evaluated model.RawConcurrency
if err := node.Decode(&evaluated); err != nil {
return "", false, fmt.Errorf("failed to unmarshal evaluated concurrency: %w", err)
return "", nil, fmt.Errorf("failed to unmarshal evaluated concurrency: %w", err)
}
if evaluated.RawExpression != "" {
return evaluated.RawExpression, false, nil
return evaluated.RawExpression, nil, nil
}
return evaluated.Group, evaluated.CancelInProgress == "true", nil
}
func toGitContext(input map[string]any) *model.GithubContext {
gitContext := &model.GithubContext{
EventPath: asString(input["event_path"]),
Workflow: asString(input["workflow"]),
RunID: asString(input["run_id"]),
RunNumber: asString(input["run_number"]),
Actor: asString(input["actor"]),
Repository: asString(input["repository"]),
EventName: asString(input["event_name"]),
Sha: asString(input["sha"]),
Ref: asString(input["ref"]),
RefName: asString(input["ref_name"]),
RefType: asString(input["ref_type"]),
HeadRef: asString(input["head_ref"]),
BaseRef: asString(input["base_ref"]),
Token: asString(input["token"]),
Workspace: asString(input["workspace"]),
Action: asString(input["action"]),
ActionPath: asString(input["action_path"]),
ActionRef: asString(input["action_ref"]),
ActionRepository: asString(input["action_repository"]),
Job: asString(input["job"]),
RepositoryOwner: asString(input["repository_owner"]),
RetentionDays: asString(input["retention_days"]),
if evaluated.CancelInProgress == "" {
return evaluated.Group, nil, nil
}
event, ok := input["event"].(map[string]any)
if ok {
gitContext.Event = event
}
return gitContext
cancelInProgress := evaluated.CancelInProgress == "true"
return evaluated.Group, &cancelInProgress, nil
}
func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
@ -278,7 +227,7 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
var val string
err := rawOn.Decode(&val)
if err != nil {
return nil, err
return nil, fmt.Errorf("unable to interpret scalar value into a string: %w", err)
}
return []*Event{
{Name: val},
@ -290,12 +239,12 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
return nil, err
}
res := make([]*Event, 0, len(val))
for _, v := range val {
for i, v := range val {
switch t := v.(type) {
case string:
res = append(res, &Event{Name: t})
default:
return nil, fmt.Errorf("invalid type %T", t)
return nil, fmt.Errorf("value at index %d was unexpected type %[2]T; must be a string but was %#[2]v", i, v)
}
}
return res, nil
@ -315,16 +264,6 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
continue
}
switch t := v.(type) {
case string:
res = append(res, &Event{
Name: k,
acts: map[string][]string{},
})
case []string:
res = append(res, &Event{
Name: k,
acts: map[string][]string{},
})
case map[string]any:
acts := make(map[string][]string, len(t))
for act, branches := range t {
@ -338,15 +277,15 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
for i, v := range b {
var ok bool
if acts[act][i], ok = v.(string); !ok {
return nil, fmt.Errorf("unknown on type: %#v", branches)
return nil, fmt.Errorf("key %q.%q index %d had unexpected type %[4]T; a string was expected but was %#[4]v", k, act, i, v)
}
}
case map[string]any:
if isInvalidOnType(k, act) {
return nil, fmt.Errorf("unknown on type: %#v", v)
if err := isInvalidOnType(k, act); err != nil {
return nil, fmt.Errorf("invalid value on key %q: %w", k, err)
}
default:
return nil, fmt.Errorf("unknown on type: %#v", branches)
return nil, fmt.Errorf("key %q.%q had unexpected type %T; was %#v", k, act, branches, branches)
}
}
if k == "workflow_dispatch" || k == "workflow_call" {
@ -358,19 +297,22 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
})
case []any:
if k != "schedule" {
return nil, fmt.Errorf("unknown on type: %#v", v)
return nil, fmt.Errorf("key %q had an type %T; only the 'schedule' key is expected with this type", k, v)
}
schedules := make([]map[string]string, len(t))
for i, tt := range t {
vv, ok := tt.(map[string]any)
if !ok {
return nil, fmt.Errorf("unknown on type: %#v", v)
return nil, fmt.Errorf("key %q[%d] had unexpected type %[3]T; a map with a key \"cron\" was expected, but value was %#[3]v", k, i, tt)
}
schedules[i] = make(map[string]string, len(vv))
for k, vvv := range vv {
for kk, vvv := range vv {
if strings.ToLower(kk) != "cron" {
return nil, fmt.Errorf("key %q[%d] had unexpected key %q; \"cron\" was expected", k, i, kk)
}
var ok bool
if schedules[i][k], ok = vvv.(string); !ok {
return nil, fmt.Errorf("unknown on type: %#v", v)
if schedules[i][kk], ok = vvv.(string); !ok {
return nil, fmt.Errorf("key %q[%d].%q had unexpected type %[4]T; a string was expected by was %#[4]v", k, i, kk, vvv)
}
}
}
@ -379,23 +321,29 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
schedules: schedules,
})
default:
return nil, fmt.Errorf("unknown on type: %#v", v)
return nil, fmt.Errorf("key %q had unexpected type %[2]T; expected a map or array but was %#[2]v", k, v)
}
}
return res, nil
default:
return nil, fmt.Errorf("unknown on type: %v", rawOn.Kind)
return nil, fmt.Errorf("unexpected yaml node in `on`: %v", rawOn.Kind)
}
}
func isInvalidOnType(onType, subKey string) bool {
if onType == "workflow_dispatch" && subKey == "inputs" {
return false
func isInvalidOnType(onType, subKey string) error {
if onType == "workflow_dispatch" {
if subKey == "inputs" {
return nil
}
if onType == "workflow_call" && (subKey == "inputs" || subKey == "outputs") {
return false
return fmt.Errorf("workflow_dispatch only supports key \"inputs\", but key %q was found", subKey)
}
return true
if onType == "workflow_call" {
if subKey == "inputs" || subKey == "outputs" {
return nil
}
return fmt.Errorf("workflow_call only supports keys \"inputs\" and \"outputs\", but key %q was found", subKey)
}
return fmt.Errorf("unexpected key %q.%q", onType, subKey)
}
// parseMappingNode parse a mapping node and preserve order.
@ -430,12 +378,3 @@ func parseMappingNode[T any](node *yaml.Node) ([]string, []T, error) {
return scalars, datas, nil
}
func asString(v any) string {
if v == nil {
return ""
} else if s, ok := v.(string); ok {
return s
}
return ""
}

View file

@ -16,6 +16,7 @@ func TestParseRawOn(t *testing.T) {
kases := []struct {
input string
result []*Event
err string
}{
{
input: "on: issue_comment",
@ -33,7 +34,10 @@ func TestParseRawOn(t *testing.T) {
},
},
},
{
input: "on: [123]",
err: "value at index 0 was unexpected type int; must be a string but was 123",
},
{
input: "on:\n - push\n - pull_request",
result: []*Event{
@ -45,6 +49,19 @@ func TestParseRawOn(t *testing.T) {
},
},
},
{
input: "on: { push: null }",
result: []*Event{
{
Name: "push",
acts: map[string][]string{},
},
},
},
{
input: "on: { push: 'abc' }",
err: "key \"push\" had unexpected type string; expected a map or array but was \"abc\"",
},
{
input: "on:\n push:\n branches:\n - master",
result: []*Event{
@ -72,6 +89,10 @@ func TestParseRawOn(t *testing.T) {
},
},
},
{
input: "on:\n branch_protection_rule:\n types: [123, deleted]",
err: "key \"branch_protection_rule\".\"types\" index 0 had unexpected type int; a string was expected but was 123",
},
{
input: "on:\n project:\n types: [created, deleted]\n milestone:\n types: [opened, deleted]",
result: []*Event{
@ -189,6 +210,22 @@ func TestParseRawOn(t *testing.T) {
},
},
},
{
input: "on:\n schedule2:\n - cron: '20 6 * * *'",
err: "key \"schedule2\" had an type []interface {}; only the 'schedule' key is expected with this type",
},
{
input: "on:\n schedule:\n - 123",
err: "key \"schedule\"[0] had unexpected type int; a map with a key \"cron\" was expected, but value was 123",
},
{
input: "on:\n schedule:\n - corn: '20 6 * * *'",
err: "key \"schedule\"[0] had unexpected key \"corn\"; \"cron\" was expected",
},
{
input: "on:\n schedule:\n - cron: 123",
err: "key \"schedule\"[0].\"cron\" had unexpected type int; a string was expected by was 123",
},
{
input: `
on:
@ -222,15 +259,37 @@ on:
},
},
},
{
input: `
on:
workflow_call:
mistake:
access-token:
description: 'A token passed from the caller workflow'
required: false
`,
err: "invalid value on key \"workflow_call\": workflow_call only supports keys \"inputs\" and \"outputs\", but key \"mistake\" was found",
},
{
input: `
on:
workflow_call: { map: 123 }
`,
err: "key \"workflow_call\".\"map\" had unexpected type int; was 123",
},
}
for _, kase := range kases {
t.Run(kase.input, func(t *testing.T) {
origin, err := model.ReadWorkflow(strings.NewReader(kase.input), false)
assert.NoError(t, err)
require.NoError(t, err)
events, err := ParseRawOn(&origin.RawOn)
if kase.err != "" {
assert.ErrorContains(t, err, kase.err)
} else {
assert.NoError(t, err)
assert.EqualValues(t, kase.result, events, fmt.Sprintf("%#v", events))
}
})
}
}
@ -345,6 +404,7 @@ func TestEvaluateConcurrency(t *testing.T) {
name string
input model.RawConcurrency
group string
cancelInProgressNil bool
cancelInProgress bool
}{
{
@ -360,7 +420,7 @@ func TestEvaluateConcurrency(t *testing.T) {
name: "undefined",
input: model.RawConcurrency{},
group: "",
cancelInProgress: false,
cancelInProgressNil: true,
},
{
name: "group-evaluation",
@ -368,7 +428,7 @@ func TestEvaluateConcurrency(t *testing.T) {
Group: "${{ github.workflow }}-${{ github.ref }}",
},
group: "test_workflow-main",
cancelInProgress: false,
cancelInProgressNil: true,
},
{
name: "cancel-evaluation-true",
@ -394,7 +454,7 @@ func TestEvaluateConcurrency(t *testing.T) {
Group: "user-${{ github.event.commits[0].author.username }}",
},
group: "user-someone",
cancelInProgress: false,
cancelInProgressNil: true,
},
{
name: "arbitrary-var",
@ -402,7 +462,7 @@ func TestEvaluateConcurrency(t *testing.T) {
Group: "${{ vars.eval_arbitrary_var }}",
},
group: "123",
cancelInProgress: false,
cancelInProgressNil: true,
},
{
name: "arbitrary-input",
@ -410,20 +470,27 @@ func TestEvaluateConcurrency(t *testing.T) {
Group: "${{ inputs.eval_arbitrary_input }}",
},
group: "456",
cancelInProgress: false,
cancelInProgressNil: true,
},
{
name: "cancel-in-progress-only",
input: model.RawConcurrency{
CancelInProgress: "true",
},
group: "",
cancelInProgress: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
group, cancelInProgress, err := EvaluateConcurrency(
group, cancelInProgress, err := EvaluateWorkflowConcurrency(
&test.input,
"job-id",
nil, // job
map[string]any{
"workflow": "test_workflow",
"ref": "main",
"event": map[string]any{
// gitCtx
&model.GithubContext{
Workflow: "test_workflow",
Ref: "main",
Event: map[string]any{
"commits": []any{
map[string]any{
"author": map[string]any{
@ -437,20 +504,24 @@ func TestEvaluateConcurrency(t *testing.T) {
},
},
},
}, // gitCtx
map[string]*JobResult{
"job-id": {},
}, // results
},
// vars
map[string]string{
"eval_arbitrary_var": "123",
}, // vars
},
// inputs
map[string]any{
"eval_arbitrary_input": "456",
}, // inputs
},
)
assert.NoError(t, err)
assert.EqualValues(t, test.group, group)
assert.EqualValues(t, test.cancelInProgress, cancelInProgress)
if test.cancelInProgressNil {
assert.Nil(t, cancelInProgress)
} else {
require.NotNil(t, cancelInProgress)
assert.EqualValues(t, test.cancelInProgress, *cancelInProgress)
}
})
}
}

View file

@ -479,8 +479,6 @@ func rewriteSubExpression(ctx context.Context, in string, forceFormat bool) (str
func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]any {
inputs := map[string]any{}
setupWorkflowInputs(ctx, &inputs, rc)
var env map[string]string
if step != nil {
env = *step.getEnv()
@ -494,6 +492,8 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod
}
}
setupWorkflowInputs(ctx, &inputs, rc)
if rc.caller == nil && ghc.EventName == "workflow_dispatch" {
config := rc.Run.Workflow.WorkflowDispatchConfig()
if config != nil && config.Inputs != nil {

View file

@ -180,31 +180,35 @@ func setJobResult(ctx context.Context, info jobInfo, rc *RunContext, success boo
jobResult = "failure"
}
// Set local result on current job (child or parent)
info.result(jobResult)
if rc.caller != nil {
// set reusable workflow job result
// Child reusable workflow:
// 1) propagate result to parent job state
rc.caller.runContext.result(jobResult)
// 2) copy workflow_call outputs from child to parent (as in upstream)
jobOutputs := make(map[string]string)
ee := rc.NewExpressionEvaluator(ctx)
if wfcc := rc.Run.Workflow.WorkflowCallConfig(); wfcc != nil {
for k, v := range wfcc.Outputs {
jobOutputs[k] = ee.Interpolate(ctx, ee.Interpolate(ctx, v.Value))
}
}
rc.caller.runContext.Run.Job().Outputs = jobOutputs
// 3) DO NOT print banner in child job (prevents premature token revocation)
logger.Debugf("Reusable job result=%s (parent will finalize, no banner)", jobResult)
return
}
// Parent job: print the final banner ONCE (job-level)
jobResultMessage := "succeeded"
if jobResult != "success" {
jobResultMessage = "failed"
}
jobOutputs := rc.Run.Job().Outputs
if rc.caller != nil {
// Rewrite the job's outputs into the workflow_call outputs...
jobOutputs = make(map[string]string)
ee := rc.NewExpressionEvaluator(ctx)
for k, v := range rc.Run.Workflow.WorkflowCallConfig().Outputs {
jobOutputs[k] = ee.Interpolate(ctx, ee.Interpolate(ctx, v.Value))
}
// When running as a daemon and receiving jobs from Forgejo, the next job (and any of it's `needs` outputs) will
// be provided by Forgejo based upon the data sent to the logger below. However, when running `forgejo-runner
// exec` with a reusable workflow, the next job will only be able to read outputs if those outputs are stored on
// the workflow -- that's what is accomplished here:
rc.caller.runContext.Run.Job().Outputs = jobOutputs
}
logger.
WithFields(logrus.Fields{

View file

@ -444,3 +444,76 @@ func TestSetJobResultConcurrency(t *testing.T) {
assert.Equal(t, "failure", lastResult)
}
func TestSetJobResult_SkipsBannerInChildReusableWorkflow(t *testing.T) {
// Test that child reusable workflow does not print final banner
// to prevent premature token revocation
mockLogger := mocks.NewFieldLogger(t)
// Allow all variants of Debugf (git operations can call with 1-3 args)
mockLogger.On("Debugf", mock.Anything).Return(0).Maybe()
mockLogger.On("Debugf", mock.Anything, mock.Anything).Return(0).Maybe()
mockLogger.On("Debugf", mock.Anything, mock.Anything, mock.Anything).Return(0).Maybe()
// CRITICAL: In CI, git ref detection may fail and call Warningf
mockLogger.On("Warningf", mock.Anything, mock.Anything).Return(0).Maybe()
mockLogger.On("WithField", mock.Anything, mock.Anything).Return(&logrus.Entry{Logger: &logrus.Logger{}}).Maybe()
mockLogger.On("WithFields", mock.Anything).Return(&logrus.Entry{Logger: &logrus.Logger{}}).Maybe()
ctx := common.WithLogger(common.WithJobErrorContainer(t.Context()), mockLogger)
// Setup parent job
parentJob := &model.Job{
Result: "success",
}
parentRC := &RunContext{
Config: &Config{Env: map[string]string{}}, // Must have Config
Run: &model.Run{
JobID: "parent",
Workflow: &model.Workflow{
Jobs: map[string]*model.Job{
"parent": parentJob,
},
},
},
}
// Setup child job with caller reference
childJob := &model.Job{
Result: "success",
}
childRC := &RunContext{
Config: &Config{Env: map[string]string{}}, // Must have Config
Run: &model.Run{
JobID: "child",
Workflow: &model.Workflow{
Jobs: map[string]*model.Job{
"child": childJob,
},
},
},
caller: &caller{
runContext: parentRC,
},
}
jim := &jobInfoMock{}
jim.On("matrix").Return(map[string]any{}) // REQUIRED: setJobResult always calls matrix()
jim.On("result", "success")
// Call setJobResult for child workflow
setJobResult(ctx, jim, childRC, true)
// Verify:
// 1. Child result is set
jim.AssertCalled(t, "result", "success")
// 2. Parent result is propagated
assert.Equal(t, "success", parentJob.Result)
// 3. Final banner was NOT printed by child (critical for token security)
mockLogger.AssertNotCalled(t, "WithFields", mock.MatchedBy(func(fields logrus.Fields) bool {
_, okJobResult := fields["jobResult"]
_, okJobOutput := fields["jobOutputs"]
return okJobOutput && okJobResult
}))
}

View file

@ -146,6 +146,26 @@ func WithCompositeStepLogger(ctx context.Context, stepID string) context.Context
}).WithContext(ctx))
}
func GetOuterStepResult(entry *logrus.Entry) any {
r, ok := entry.Data["stepResult"]
if !ok {
return nil
}
// composite actions steps log with a list of stepID
if s, ok := entry.Data["stepID"]; ok {
if stepIDs, ok := s.([]string); ok {
if len(stepIDs) > 1 {
return nil
}
}
} else {
return nil
}
return r
}
func withStepLogger(ctx context.Context, stepNumber int, stepID, stepName, stageName string) context.Context {
rtn := common.Logger(ctx).WithFields(logrus.Fields{
"stepNumber": stepNumber,

63
act/runner/logger_test.go Normal file
View file

@ -0,0 +1,63 @@
package runner
import (
"testing"
"code.forgejo.org/forgejo/runner/v11/act/common"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRunner_GetOuterStepResult(t *testing.T) {
nullLogger, hook := test.NewNullLogger()
ctx := common.WithLogger(t.Context(), nullLogger)
t.Run("no stepResult", func(t *testing.T) {
hook.Reset()
common.Logger(ctx).Info("✅ Success")
entry := hook.LastEntry()
require.NotNil(t, entry)
assert.Nil(t, GetOuterStepResult(entry))
})
t.Run("stepResult and no stepID", func(t *testing.T) {
hook.Reset()
common.Logger(ctx).WithField("stepResult", "success").Info("✅ Success")
entry := hook.LastEntry()
require.NotNil(t, entry)
assert.Nil(t, GetOuterStepResult(entry))
})
stepNumber := 123
stepID := "step id"
stepName := "readable name"
stageName := "Main"
ctx = withStepLogger(ctx, stepNumber, stepID, stepName, stageName)
t.Run("stepResult and stepID", func(t *testing.T) {
hook.Reset()
common.Logger(ctx).WithField("stepResult", "success").Info("✅ Success")
entry := hook.LastEntry()
actualStepIDs, ok := entry.Data["stepID"]
require.True(t, ok)
require.Equal(t, []string{stepID}, actualStepIDs)
require.NotNil(t, entry)
assert.Equal(t, "success", GetOuterStepResult(entry))
})
compositeStepID := "composite step id"
ctx = WithCompositeStepLogger(ctx, compositeStepID)
t.Run("stepResult and composite stepID", func(t *testing.T) {
hook.Reset()
common.Logger(ctx).WithField("stepResult", "success").Info("✅ Success")
entry := hook.LastEntry()
actualStepIDs, ok := entry.Data["stepID"]
require.True(t, ok)
require.Equal(t, []string{stepID, compositeStepID}, actualStepIDs)
require.NotNil(t, entry)
assert.Nil(t, GetOuterStepResult(entry))
})
}

View file

@ -11,6 +11,8 @@ LXC_IPV6_PREFIX_DEFAULT="fd15"
LXC_DOCKER_PREFIX_DEFAULT="172.17"
LXC_IPV6_DOCKER_PREFIX_DEFAULT="fd00:d0ca"
LXC_APT_TOO_OLD='1 week ago'
: ${LXC_TRANSACTION_TIMEOUT:=600}
LXC_TRANSACTION_LOCK_FILE=/tmp/lxc-helper.lock
: ${LXC_SUDO:=}
: ${LXC_CONTAINER_RELEASE:=bookworm}
@ -28,16 +30,22 @@ function lxc_template_release() {
echo lxc-helpers-$LXC_CONTAINER_RELEASE
}
function lxc_directory() {
local name="$1"
echo /var/lib/lxc/$name
}
function lxc_root() {
local name="$1"
echo /var/lib/lxc/$name/rootfs
echo $(lxc_directory $name)/rootfs
}
function lxc_config() {
local name="$1"
echo /var/lib/lxc/$name/config
echo $(lxc_directory $name)/config
}
function lxc_container_run() {
@ -47,6 +55,42 @@ function lxc_container_run() {
$LXC_SUDO lxc-attach --clear-env --name $name -- "$@"
}
function lxc_transaction_lock() {
exec 7>$LXC_TRANSACTION_LOCK_FILE
flock --timeout $LXC_TRANSACTION_TIMEOUT 7
}
function lxc_transaction_unlock() {
exec 7>&-
}
function lxc_transaction_draft_name() {
echo "lxc-helper-draft"
}
function lxc_transaction_begin() {
local name=$1 # not actually used but it helps when reading in the caller
local draft=$(lxc_transaction_draft_name)
lxc_transaction_lock
lxc_container_destroy $draft
}
function lxc_transaction_commit() {
local name=$1
local draft=$(lxc_transaction_draft_name)
# do not use lxc-copy because it is not atomic if lxc-copy is
# interrupted it may leave the $name container half populated
$LXC_SUDO sed -i -e "s/$draft/$name/g" \
$(lxc_config $draft) \
$(lxc_root $draft)/etc/hosts \
$(lxc_root $draft)/etc/hostname
$LXC_SUDO rm -f $(lxc_root $draft)/var/lib/dhcp/dhclient.*
$LXC_SUDO mv $(lxc_directory $draft) $(lxc_directory $name)
lxc_transaction_unlock
}
function lxc_container_run_script_as() {
local name="$1"
local user="$2"
@ -242,7 +286,7 @@ function lxc_container_configure() {
function lxc_container_install_lxc_helpers() {
local name="$1"
$LXC_SUDO cp -a $LXC_SELF_DIR/lxc-helpers*.sh $root/$LXC_BIN
$LXC_SUDO cp -a $LXC_SELF_DIR/lxc-helpers*.sh $(lxc_root $name)/$LXC_BIN
#
# Wait for the network to come up
#
@ -304,10 +348,9 @@ function lxc_container_stop() {
function lxc_container_destroy() {
local name="$1"
local root="$2"
if lxc_exists "$name"; then
lxc_container_stop $name $root
lxc_container_stop $name
$LXC_SUDO lxc-destroy --force --name="$name"
fi
}
@ -342,36 +385,44 @@ function lxc_running() {
function lxc_build_template_release() {
local name="$(lxc_template_release)"
lxc_transaction_begin $name
if lxc_exists_and_apt_not_old $name; then
lxc_transaction_unlock
return
fi
local root=$(lxc_root $name)
$LXC_SUDO lxc-create --name $name --template debian -- --release=$LXC_CONTAINER_RELEASE
echo 'lxc.apparmor.profile = unconfined' | $LXC_SUDO tee -a $(lxc_config $name)
lxc_container_install_lxc_helpers $name
lxc_container_start $name
lxc_container_run $name apt-get update -qq
lxc_apt_install $name sudo git python3
lxc_container_stop $name
local draft=$(lxc_transaction_draft_name)
$LXC_SUDO lxc-create --name $draft --template debian -- --release=$LXC_CONTAINER_RELEASE
echo 'lxc.apparmor.profile = unconfined' | $LXC_SUDO tee -a $(lxc_config $draft)
lxc_container_install_lxc_helpers $draft
lxc_container_start $draft
lxc_container_run $draft apt-get update -qq
lxc_apt_install $draft sudo git python3
lxc_container_stop $draft
lxc_transaction_commit $name
}
function lxc_build_template() {
local name="$1"
local newname="$2"
if lxc_exists_and_apt_not_old $newname; then
return
fi
if test "$name" = "$(lxc_template_release)"; then
lxc_build_template_release
fi
if ! $LXC_SUDO lxc-copy --name=$name --newname=$newname; then
echo lxc-copy --name=$name --newname=$newname failed
lxc_transaction_begin $name
if lxc_exists_and_apt_not_old $newname; then
lxc_transaction_unlock
return
fi
local draft=$(lxc_transaction_draft_name)
if ! $LXC_SUDO lxc-copy --name=$name --newname=$draft; then
echo lxc-copy --name=$name --newname=$draft failed
return 1
fi
lxc_transaction_commit $newname
lxc_container_configure $newname
}

View file

@ -16,6 +16,7 @@ import (
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common/git"
"code.forgejo.org/forgejo/runner/v11/act/model"
"github.com/sirupsen/logrus"
)
func newLocalReusableWorkflowExecutor(rc *RunContext) common.Executor {
@ -115,7 +116,10 @@ func newActionCacheReusableWorkflowExecutor(rc *RunContext, filename string, rem
return err
}
return runner.NewPlanExecutor(plan)(ctx)
planErr := runner.NewPlanExecutor(plan)(ctx)
// Finalize from parent context: one job-level banner
return finalizeReusableWorkflow(ctx, rc, planErr)
}
}
@ -171,7 +175,10 @@ func newReusableWorkflowExecutor(rc *RunContext, directory, workflow string) com
return err
}
return runner.NewPlanExecutor(plan)(ctx)
planErr := runner.NewPlanExecutor(plan)(ctx)
// Finalize from parent context: one job-level banner
return finalizeReusableWorkflow(ctx, rc, planErr)
}
}
@ -229,3 +236,29 @@ func newRemoteReusableWorkflowWithPlat(url, uses string) *remoteReusableWorkflow
URL: url,
}
}
// finalizeReusableWorkflow prints the final job banner from the parent job context.
//
// The Forgejo reporter waits for this banner (log entry with "jobResult"
// field and without stage="Main") before marking the job as complete and revoking
// tokens. Printing this banner from the child reusable workflow would cause
// premature token revocation, breaking subsequent steps in the parent workflow.
func finalizeReusableWorkflow(ctx context.Context, rc *RunContext, planErr error) error {
jobResult := "success"
jobResultMessage := "succeeded"
if planErr != nil {
jobResult = "failure"
jobResultMessage = "failed"
}
// Outputs should already be present in the parent context:
// - copied by child's setJobResult branch (rc.caller != nil)
jobOutputs := rc.Run.Job().Outputs
common.Logger(ctx).WithFields(logrus.Fields{
"jobResult": jobResult,
"jobOutputs": jobOutputs,
}).Infof("\U0001F3C1 Job %s", jobResultMessage)
return planErr
}

View file

@ -0,0 +1,247 @@
package runner
import (
"errors"
"testing"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/model"
"code.forgejo.org/forgejo/runner/v11/act/runner/mocks"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestConfig_GetToken(t *testing.T) {
t.Run("returns GITEA_TOKEN when both GITEA_TOKEN and GITHUB_TOKEN present", func(t *testing.T) {
c := &Config{
Secrets: map[string]string{
"GITHUB_TOKEN": "github-token",
"GITEA_TOKEN": "gitea-token",
},
}
assert.Equal(t, "gitea-token", c.GetToken())
})
t.Run("returns GITHUB_TOKEN when only GITHUB_TOKEN present", func(t *testing.T) {
c := &Config{
Secrets: map[string]string{
"GITHUB_TOKEN": "github-token",
},
}
assert.Equal(t, "github-token", c.GetToken())
})
t.Run("returns empty string when no tokens present", func(t *testing.T) {
c := &Config{
Secrets: map[string]string{},
}
assert.Equal(t, "", c.GetToken())
})
t.Run("returns empty string when Secrets is nil", func(t *testing.T) {
c := &Config{}
assert.Equal(t, "", c.GetToken())
})
}
func TestRemoteReusableWorkflow_CloneURL(t *testing.T) {
t.Run("adds https prefix when missing", func(t *testing.T) {
rw := &remoteReusableWorkflow{
URL: "code.forgejo.org",
Org: "owner",
Repo: "repo",
}
assert.Equal(t, "https://code.forgejo.org/owner/repo", rw.CloneURL())
})
t.Run("preserves https prefix", func(t *testing.T) {
rw := &remoteReusableWorkflow{
URL: "https://code.forgejo.org",
Org: "owner",
Repo: "repo",
}
assert.Equal(t, "https://code.forgejo.org/owner/repo", rw.CloneURL())
})
t.Run("preserves http prefix", func(t *testing.T) {
rw := &remoteReusableWorkflow{
URL: "http://localhost:3000",
Org: "owner",
Repo: "repo",
}
assert.Equal(t, "http://localhost:3000/owner/repo", rw.CloneURL())
})
}
func TestRemoteReusableWorkflow_FilePath(t *testing.T) {
tests := []struct {
name string
gitPlatform string
filename string
expectedPath string
}{
{
name: "github platform",
gitPlatform: "github",
filename: "test.yml",
expectedPath: "./.github/workflows/test.yml",
},
{
name: "gitea platform",
gitPlatform: "gitea",
filename: "build.yaml",
expectedPath: "./.gitea/workflows/build.yaml",
},
{
name: "forgejo platform",
gitPlatform: "forgejo",
filename: "deploy.yml",
expectedPath: "./.forgejo/workflows/deploy.yml",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rw := &remoteReusableWorkflow{
GitPlatform: tt.gitPlatform,
Filename: tt.filename,
}
assert.Equal(t, tt.expectedPath, rw.FilePath())
})
}
}
func TestNewRemoteReusableWorkflowWithPlat(t *testing.T) {
tests := []struct {
name string
url string
uses string
expectedOrg string
expectedRepo string
expectedPlatform string
expectedFilename string
expectedRef string
shouldFail bool
}{
{
name: "valid github workflow",
url: "github.com",
uses: "owner/repo/.github/workflows/test.yml@main",
expectedOrg: "owner",
expectedRepo: "repo",
expectedPlatform: "github",
expectedFilename: "test.yml",
expectedRef: "main",
shouldFail: false,
},
{
name: "valid gitea workflow",
url: "code.forgejo.org",
uses: "forgejo/runner/.gitea/workflows/build.yaml@v1.0.0",
expectedOrg: "forgejo",
expectedRepo: "runner",
expectedPlatform: "gitea",
expectedFilename: "build.yaml",
expectedRef: "v1.0.0",
shouldFail: false,
},
{
name: "invalid format - missing platform",
url: "github.com",
uses: "owner/repo/workflows/test.yml@main",
shouldFail: true,
},
{
name: "invalid format - no ref",
url: "github.com",
uses: "owner/repo/.github/workflows/test.yml",
shouldFail: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := newRemoteReusableWorkflowWithPlat(tt.url, tt.uses)
if tt.shouldFail {
assert.Nil(t, result)
} else {
assert.NotNil(t, result)
assert.Equal(t, tt.expectedOrg, result.Org)
assert.Equal(t, tt.expectedRepo, result.Repo)
assert.Equal(t, tt.expectedPlatform, result.GitPlatform)
assert.Equal(t, tt.expectedFilename, result.Filename)
assert.Equal(t, tt.expectedRef, result.Ref)
assert.Equal(t, tt.url, result.URL)
}
})
}
}
func TestFinalizeReusableWorkflow_PrintsBannerSuccess(t *testing.T) {
mockLogger := mocks.NewFieldLogger(t)
bannerCalled := false
mockLogger.On("WithFields",
mock.MatchedBy(func(fields logrus.Fields) bool {
result, ok := fields["jobResult"].(string)
if !ok || result != "success" {
return false
}
outs, ok := fields["jobOutputs"].(map[string]string)
return ok && outs["foo"] == "bar"
}),
).Run(func(args mock.Arguments) {
bannerCalled = true
}).Return(&logrus.Entry{Logger: &logrus.Logger{}}).Once()
ctx := common.WithLogger(t.Context(), mockLogger)
rc := &RunContext{
Run: &model.Run{
JobID: "parent",
Workflow: &model.Workflow{
Jobs: map[string]*model.Job{
"parent": {
Outputs: map[string]string{"foo": "bar"},
},
},
},
},
}
err := finalizeReusableWorkflow(ctx, rc, nil)
assert.NoError(t, err)
assert.True(t, bannerCalled, "final banner should be printed from parent")
}
func TestFinalizeReusableWorkflow_PrintsBannerFailure(t *testing.T) {
mockLogger := mocks.NewFieldLogger(t)
bannerCalled := false
mockLogger.On("WithFields",
mock.MatchedBy(func(fields logrus.Fields) bool {
result, ok := fields["jobResult"].(string)
return ok && result == "failure"
}),
).Run(func(args mock.Arguments) {
bannerCalled = true
}).Return(&logrus.Entry{Logger: &logrus.Logger{}}).Once()
ctx := common.WithLogger(t.Context(), mockLogger)
rc := &RunContext{
Run: &model.Run{
JobID: "parent",
Workflow: &model.Workflow{
Jobs: map[string]*model.Job{
"parent": {},
},
},
},
}
planErr := errors.New("workflow failed")
err := finalizeReusableWorkflow(ctx, rc, planErr)
assert.EqualError(t, err, "workflow failed")
assert.True(t, bannerCalled, "banner should be printed even on failure")
}

View file

@ -248,12 +248,18 @@ var stopTemplate = template.Must(template.New("stop").Parse(`#!/bin/bash
source $(dirname $0)/lxc-helpers-lib.sh
lxc_container_destroy "{{.Name}}"
lxc_maybe_sudo
$LXC_SUDO rm -fr "{{ .Root }}"
`))
func (rc *RunContext) stopHostEnvironment(ctx context.Context) error {
logger := common.Logger(ctx)
logger.Debugf("stopHostEnvironment")
if !rc.IsLXCHostEnv(ctx) {
return nil
}
var stopScript bytes.Buffer
if err := stopTemplate.Execute(&stopScript, struct {
Name string
@ -310,9 +316,6 @@ func (rc *RunContext) startHostEnvironment() common.Executor {
ToolCache: rc.getToolCache(ctx),
Workdir: rc.Config.Workdir,
ActPath: actPath,
CleanUp: func() {
os.RemoveAll(miscpath)
},
StdOut: logWriter,
LXC: rc.IsLXCHostEnv(ctx),
}
@ -945,7 +948,7 @@ func (rc *RunContext) Executor() (common.Executor, error) {
return err
}
if res {
timeoutctx, cancelTimeOut := evaluateTimeout(ctx, rc.ExprEval, rc.Run.Job().TimeoutMinutes)
timeoutctx, cancelTimeOut := evaluateTimeout(ctx, "job", rc.ExprEval, rc.Run.Job().TimeoutMinutes)
defer cancelTimeOut()
return executor(timeoutctx)
@ -1207,7 +1210,7 @@ func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext
ghc.RetentionDays = preset.RetentionDays
instance := rc.Config.GitHubInstance
if !strings.HasPrefix(instance, "http://") &&
if instance != "" && !strings.HasPrefix(instance, "http://") &&
!strings.HasPrefix(instance, "https://") {
instance = "https://" + instance
}
@ -1250,7 +1253,7 @@ func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext
{ // Adapt to Gitea
instance := rc.Config.GitHubInstance
if !strings.HasPrefix(instance, "http://") &&
if instance != "" && !strings.HasPrefix(instance, "http://") &&
!strings.HasPrefix(instance, "https://") {
instance = "https://" + instance
}
@ -1352,16 +1355,6 @@ func (rc *RunContext) withGithubEnv(ctx context.Context, github *model.GithubCon
set("SERVER_URL", github.ServerURL)
set("API_URL", github.APIURL)
{ // Adapt to Forgejo
instance := rc.Config.GitHubInstance
if !strings.HasPrefix(instance, "http://") &&
!strings.HasPrefix(instance, "https://") {
instance = "https://" + instance
}
set("SERVER_URL", instance)
set("API_URL", instance+"/api/v1")
}
if rc.Config.ArtifactServerPath != "" {
setActionRuntimeVars(rc, env)
}

View file

@ -280,6 +280,39 @@ func TestRunContext_GetBindsAndMounts(t *testing.T) {
})
}
func TestRunContext_GetGithubContextURL(t *testing.T) {
table := []struct {
instance string
serverURL string
APIURL string
}{
{instance: "", serverURL: "", APIURL: "/api/v1"},
{instance: "example.com", serverURL: "https://example.com", APIURL: "https://example.com/api/v1"},
{instance: "http://example.com", serverURL: "http://example.com", APIURL: "http://example.com/api/v1"},
{instance: "https://example.com", serverURL: "https://example.com", APIURL: "https://example.com/api/v1"},
}
for _, data := range table {
t.Run(data.instance, func(t *testing.T) {
rc := &RunContext{
EventJSON: "{}",
Config: &Config{
GitHubInstance: data.instance,
},
Run: &model.Run{
Workflow: &model.Workflow{
Name: "GitHubContextTest",
},
},
}
ghc := rc.getGithubContext(t.Context())
assert.Equal(t, data.serverURL, ghc.ServerURL)
assert.Equal(t, data.APIURL, ghc.APIURL)
})
}
}
func TestRunContext_GetGithubContextRef(t *testing.T) {
table := []struct {
event string

View file

@ -263,6 +263,7 @@ func TestRunner_RunEvent(t *testing.T) {
{workdir, "uses-workflow", "pull_request", "", platforms, map[string]string{"secret": "keep_it_private"}},
{workdir, "uses-docker-url", "push", "", platforms, secrets},
{workdir, "act-composite-env-test", "push", "", platforms, secrets},
{workdir, "uses-workflow-env-input", "push", "", platforms, secrets},
// Eval
{workdir, "evalmatrix", "push", "", platforms, secrets},

View file

@ -177,7 +177,7 @@ func runStepExecutor(step step, stage stepStage, executor common.Executor) commo
Mode: 0o666,
})(ctx)
timeoutctx, cancelTimeOut := evaluateTimeout(ctx, rc.ExprEval, stepModel.TimeoutMinutes)
timeoutctx, cancelTimeOut := evaluateTimeout(ctx, "step", rc.ExprEval, stepModel.TimeoutMinutes)
defer cancelTimeOut()
err = executor(timeoutctx)
@ -213,12 +213,12 @@ func runStepExecutor(step step, stage stepStage, executor common.Executor) commo
}
}
func evaluateTimeout(ctx context.Context, exprEval ExpressionEvaluator, timeoutMinutes string) (context.Context, context.CancelFunc) {
func evaluateTimeout(ctx context.Context, contextType string, exprEval ExpressionEvaluator, timeoutMinutes string) (context.Context, context.CancelFunc) {
timeout := exprEval.Interpolate(ctx, timeoutMinutes)
if timeout != "" {
timeOutMinutes, err := strconv.ParseInt(timeout, 10, 64)
if err == nil {
common.Logger(ctx).Debugf("the step will stop in timeout-minutes %s", timeout)
common.Logger(ctx).Debugf("the %s will stop in timeout-minutes %s", contextType, timeout)
return context.WithTimeout(ctx, time.Duration(timeOutMinutes)*time.Minute)
}
common.Logger(ctx).Errorf("timeout-minutes %s cannot be parsed and will be ignored: %w", timeout, err)

View file

@ -0,0 +1,21 @@
name: "use-inputs-impl"
on:
workflow_call:
inputs:
greet_target:
type: string
required: false
default: "Some Default Value"
jobs:
works:
runs-on: ubuntu-latest
env:
MY_INPUT_TEST: ${{ inputs.greet_target }}
INPUT_TEST: ${{ inputs.greet_target }}
INPUT_GREET_TARGET: ${{ inputs.greet_target }}
steps:
- run: '[ "$MY_INPUT_TEST" = "Mona the Octocat" ] || exit 1'
- run: '[ "$INPUT_TEST" = "Mona the Octocat" ] || exit 1'
- run: '[ "$INPUT_GREET_TARGET" = "Mona the Octocat" ] || exit 1'

View file

@ -1,4 +1,4 @@
FROM alpine:3
FROM code.forgejo.org/oci/alpine:latest
COPY entrypoint.sh /entrypoint.sh

View file

@ -0,0 +1,8 @@
name: local-action-env-input
on: push
jobs:
test:
runs-on: docker
uses: ./testdata/.github/workflows/local-reusable-env-input.yml
with:
greet_target: 'Mona the Octocat'

View file

@ -30,6 +30,84 @@ jobs:
assert.NoError(t, err)
}
func TestContextsInWorkflowMatrix(t *testing.T) {
t.Run("KnownContexts", func(t *testing.T) {
// Parse raw YAML snippet.
var node yaml.Node
err := yaml.Unmarshal([]byte(`
on: push
jobs:
job:
uses: ./.forgejo/workflow/test.yaml
strategy:
matrix:
input1:
- ${{ forge.KEY }}
- ${{ forgejo.KEY }}
- ${{ github.KEY }}
- ${{ inputs.KEY }}
- ${{ vars.KEY }}
- ${{ needs.KEY }}
include:
- forge: ${{ forge.KEY }}
- forgejo: ${{ forgejo.KEY }}
- github: ${{ github.KEY }}
- inputs: ${{ inputs.KEY }}
- vars: ${{ vars.KEY }}
- needs: ${{ needs.KEY }}
exclude:
- forge: ${{ forge.KEY }}
- forgejo: ${{ forgejo.KEY }}
- github: ${{ github.KEY }}
- inputs: ${{ inputs.KEY }}
- vars: ${{ vars.KEY }}
- needs: ${{ needs.KEY }}
`), &node)
if !assert.NoError(t, err) {
return
}
// Parse YAML node as a validated workflow.
err = (&Node{
Definition: "workflow-root",
Schema: GetWorkflowSchema(),
}).UnmarshalYAML(&node)
assert.NoError(t, err)
})
t.Run("UnknownContext", func(t *testing.T) {
for _, property := range []string{"include", "exclude", "input1"} {
t.Run(property, func(t *testing.T) {
for _, context := range []string{"secrets", "job", "steps", "runner", "matrix", "strategy"} {
t.Run(context, func(t *testing.T) {
var node yaml.Node
err := yaml.Unmarshal([]byte(fmt.Sprintf(`
on: push
jobs:
job:
uses: ./.forgejo/workflow/test.yaml
strategy:
matrix:
%[1]s:
- input1: ${{ %[2]s.KEY }}
`, property, context)), &node)
if !assert.NoError(t, err) {
return
}
err = (&Node{
Definition: "workflow-root",
Schema: GetWorkflowSchema(),
}).UnmarshalYAML(&node)
assert.ErrorContains(t, err, "Unknown Variable Access "+context)
})
}
})
}
})
}
func TestReusableWorkflow(t *testing.T) {
t.Run("KnownContexts", func(t *testing.T) {
var node yaml.Node
@ -164,7 +242,7 @@ jobs:
name: Build Silo Frontend DEV
runs-on: ubuntu-latest
container:
image: code.forgejo.org/oci/node:22-bookworm
image: code.forgejo.org/oci/${{ env.IMAGE }}
uses: ./.forgejo/workflows/${{ vars.PATHNAME }}
with:
STAGE: dev

View file

@ -2008,7 +2008,7 @@
},
"container": {
"description": "A container to run any steps in a job that don't already specify a container. If you have steps that use both script and container actions, the container actions will run as sibling containers on the same network with the same volume mounts.\n\nIf you do not set a container, all steps will run directly on the host specified by runs-on unless a step refers to an action configured to run in a container.",
"context": ["forge", "forgejo", "github", "inputs", "vars", "needs", "strategy", "matrix"],
"context": ["forge", "forgejo", "github", "inputs", "vars", "needs", "strategy", "matrix", "env"],
"one-of": ["string", "container-mapping"]
},
"container-mapping": {

View file

@ -51,7 +51,7 @@ services:
- 8080:3000
runner-register:
image: code.forgejo.org/forgejo/runner:11.0.0
image: code.forgejo.org/forgejo/runner:11.1.2
links:
- docker-in-docker
- forgejo
@ -77,7 +77,7 @@ services:
'
runner-daemon:
image: code.forgejo.org/forgejo/runner:11.0.0
image: code.forgejo.org/forgejo/runner:11.1.2
links:
- docker-in-docker
- forgejo

View file

@ -20,14 +20,14 @@ trap "rm -fr $TMPDIR" EXIT
: ${INPUTS_TOKEN:=}
: ${INPUTS_FORGEJO:=https://code.forgejo.org}
: ${INPUTS_LIFETIME:=7d}
DEFAULT_LXC_HELPERS_VERSION=1.1.0 # renovate: datasource=forgejo-tags depName=forgejo/lxc-helpers
DEFAULT_LXC_HELPERS_VERSION=1.1.3 # renovate: datasource=forgejo-tags depName=forgejo/lxc-helpers
: ${INPUTS_LXC_HELPERS_VERSION:=$DEFAULT_LXC_HELPERS_VERSION}
DEFAULT_RUNNER_VERSION=11.0.0 # renovate: datasource=forgejo-releases depName=forgejo/runner
DEFAULT_RUNNER_VERSION=11.1.2 # renovate: datasource=forgejo-releases depName=forgejo/runner
: ${INPUTS_RUNNER_VERSION:=$DEFAULT_RUNNER_VERSION}
: ${KILL_AFTER:=21600} # 6h == 21600
NODEJS_VERSION=20
DEBIAN_RELEASE=bookworm
DEBIAN_RELEASE=trixie
YQ_VERSION=v4.45.1
SELF=${BASH_SOURCE[0]}
SELF_FILENAME=$(basename "$SELF")

31
go.mod
View file

@ -2,22 +2,22 @@ module code.forgejo.org/forgejo/runner/v11
go 1.24.0
toolchain go1.24.7
toolchain go1.24.9
require (
code.forgejo.org/forgejo/actions-proto v0.5.2
connectrpc.com/connect v1.18.1
code.forgejo.org/forgejo/actions-proto v0.5.3
connectrpc.com/connect v1.19.1
dario.cat/mergo v1.0.2
github.com/Masterminds/semver v1.5.0
github.com/avast/retry-go/v4 v4.6.1
github.com/avast/retry-go/v4 v4.7.0
github.com/containerd/errdefs v1.0.0
github.com/creack/pty v1.1.24
github.com/distribution/reference v0.6.0
github.com/docker/cli v28.4.0+incompatible
github.com/docker/docker v28.4.0+incompatible
github.com/docker/cli v28.5.1+incompatible
github.com/docker/docker v28.5.1+incompatible
github.com/docker/go-connections v0.6.0
github.com/go-git/go-billy/v5 v5.6.2
github.com/go-git/go-git/v5 v5.16.2
github.com/go-git/go-git/v5 v5.16.3
github.com/gobwas/glob v0.2.3
github.com/google/go-cmp v0.7.0
github.com/google/uuid v1.6.0
@ -29,7 +29,7 @@ require (
github.com/moby/patternmatcher v0.6.0
github.com/opencontainers/image-spec v1.1.1
github.com/opencontainers/selinux v1.12.0
github.com/rhysd/actionlint v1.7.7
github.com/rhysd/actionlint v1.7.8
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.10.1
github.com/spf13/pflag v1.0.10
@ -37,9 +37,9 @@ require (
github.com/timshannon/bolthold v0.0.0-20240314194003-30aac6950928
go.etcd.io/bbolt v1.4.3
go.yaml.in/yaml/v3 v3.0.4
golang.org/x/term v0.35.0
golang.org/x/time v0.13.0
google.golang.org/protobuf v1.36.9
golang.org/x/term v0.36.0
golang.org/x/time v0.14.0
google.golang.org/protobuf v1.36.10
gotest.tools/v3 v3.5.2
)
@ -47,7 +47,7 @@ require (
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.1.6 // indirect
github.com/bmatcuk/doublestar/v4 v4.8.0 // indirect
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
@ -69,7 +69,7 @@ require (
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.17 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/atomicwriter v0.1.0 // indirect
@ -98,10 +98,11 @@ require (
go.opentelemetry.io/otel/metric v1.36.0 // indirect
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect
go.yaml.in/yaml/v4 v4.0.0-rc.2 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.37.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

58
go.sum
View file

@ -1,7 +1,7 @@
code.forgejo.org/forgejo/actions-proto v0.5.2 h1:2+j3pXKk7l4cqATb7de75ZPPsNqc6e7RWX7xJ8DmySY=
code.forgejo.org/forgejo/actions-proto v0.5.2/go.mod h1:6CtsEiLzyODMO/3sqsdoTij4Y3gyQ29Nn8QnWunOw98=
connectrpc.com/connect v1.18.1 h1:PAg7CjSAGvscaf6YZKUefjoih5Z/qYkyaTrBW8xvYPw=
connectrpc.com/connect v1.18.1/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
code.forgejo.org/forgejo/actions-proto v0.5.3 h1:dDProRNB4CDvEl9gfo8jkiVfGdiW7fXAt5TM9Irka28=
code.forgejo.org/forgejo/actions-proto v0.5.3/go.mod h1:33iTdur/jVa/wAQP+BuciRTK9WZcVaxy0BNEnSWWFDM=
connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
@ -19,10 +19,10 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/avast/retry-go/v4 v4.6.1 h1:VkOLRubHdisGrHnTu89g08aQEWEgRU7LVEop3GbIcMk=
github.com/avast/retry-go/v4 v4.6.1/go.mod h1:V6oF8njAwxJ5gRo1Q7Cxab24xs5NCWZBeaHHBklR8mA=
github.com/bmatcuk/doublestar/v4 v4.8.0 h1:DSXtrypQddoug1459viM9X9D3dp1Z7993fw36I2kNcQ=
github.com/bmatcuk/doublestar/v4 v4.8.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/avast/retry-go/v4 v4.7.0 h1:yjDs35SlGvKwRNSykujfjdMxMhMQQM0TnIjJaHB+Zio=
github.com/avast/retry-go/v4 v4.7.0/go.mod h1:ZMPDa3sY2bKgpLtap9JRUgk2yTAba7cgiFhqxY2Sg6Q=
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/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
@ -43,10 +43,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v28.4.0+incompatible h1:RBcf3Kjw2pMtwui5V0DIMdyeab8glEw5QY0UUU4C9kY=
github.com/docker/cli v28.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v28.4.0+incompatible h1:KVC7bz5zJY/4AZe/78BIvCnPsLaC9T/zh72xnlrTTOk=
github.com/docker/docker v28.4.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/cli v28.5.1+incompatible h1:ESutzBALAD6qyCLqbQSEf1a/U8Ybms5agw59yGVc+yY=
github.com/docker/cli v28.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM=
github.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
@ -69,8 +69,8 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM=
github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
github.com/go-git/go-git/v5 v5.16.3 h1:Z8BtvxZ09bYm/yYNgPKCzgWtaRqDTgIKRgIRHBfU6Z8=
github.com/go-git/go-git/v5 v5.16.3/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@ -115,8 +115,8 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
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.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
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/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
@ -151,8 +151,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rhysd/actionlint v1.7.7 h1:0KgkoNTrYY7vmOCs9BW2AHxLvvpoY9nEUzgBHiPUr0k=
github.com/rhysd/actionlint v1.7.7/go.mod h1:AE6I6vJEkNaIfWqC2GNE5spIJNhxf8NCtLEKU4NnUXg=
github.com/rhysd/actionlint v1.7.8 h1:3d+N9ourgAxVYG4z2IFxFIk/YiT6V+VnKASfXGwT60E=
github.com/rhysd/actionlint v1.7.8/go.mod h1:3kiS6egcbXG+vQsJIhFxTz+UKaF1JprsE0SKrpCZKvU=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
@ -222,6 +222,8 @@ go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lI
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s=
go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
@ -230,8 +232,8 @@ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbR
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -242,16 +244,16 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
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=
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f h1:2yNACc1O40tTnrsbk9Cv6oxiW8pxI/pXj0wRtdlYmgY=
@ -260,8 +262,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=

View file

@ -371,6 +371,10 @@ func runExec(ctx context.Context, execArgs *executeArgs) func(cmd *cobra.Command
log.Infof("cache handler listens on: %v", handler.ExternalURL())
execArgs.cacheHandler = handler
if execArgs.containerDaemonSocket != "/var/run/docker.sock" {
log.Warnf("--container-daemon-socket %s: please use the DOCKER_HOST environment variable as documented at https://forgejo.org/docs/next/admin/actions/runner-installation/#setting-up-the-container-environment instead. See https://code.forgejo.org/forgejo/runner/issues/577 for more information.", execArgs.containerDaemonSocket)
}
// run the plan
config := &runner.Config{
Workdir: execArgs.Workdir(),
@ -462,7 +466,7 @@ func loadExecCmd(ctx context.Context) *cobra.Command {
execCmd.Flags().BoolVar(&execArg.privileged, "privileged", false, "use privileged mode")
execCmd.Flags().StringVar(&execArg.usernsMode, "userns", "", "user namespace to use")
execCmd.PersistentFlags().StringVarP(&execArg.containerArchitecture, "container-architecture", "", "", "Architecture which should be used to run containers, e.g.: linux/amd64. If not specified, will use host default architecture. Requires Docker server API Version 1.41+. Ignored on earlier Docker server platforms.")
execCmd.PersistentFlags().StringVarP(&execArg.containerDaemonSocket, "container-daemon-socket", "", "/var/run/docker.sock", "Path to Docker daemon socket which will be mounted to containers")
execCmd.PersistentFlags().StringVarP(&execArg.containerDaemonSocket, "container-daemon-socket", "", "/var/run/docker.sock", "Please use the DOCKER_HOST environment variable as documented at https://forgejo.org/docs/next/admin/actions/runner-installation/#setting-up-the-container-environment instead.")
execCmd.Flags().BoolVar(&execArg.useGitIgnore, "use-gitignore", true, "Controls whether paths specified in .gitignore should be copied into container")
execCmd.Flags().StringArrayVarP(&execArg.containerCapAdd, "container-cap-add", "", []string{}, "kernel capabilities to add to the workflow containers (e.g. --container-cap-add SYS_PTRACE)")
execCmd.Flags().StringArrayVarP(&execArg.containerCapDrop, "container-cap-drop", "", []string{}, "kernel capabilities to remove from the workflow containers (e.g. --container-cap-drop SYS_PTRACE)")

View file

@ -36,11 +36,20 @@ func NewJob(cfg *config.Config, client client.Client, runner run.RunnerInterface
}
func (j *Job) Run(ctx context.Context) error {
log.Info("Polling for a job...")
for {
task, ok := j.fetchTask(ctx)
if !ok {
return fmt.Errorf("could not fetch task")
}
if ok {
return j.runTaskWithRecover(ctx, task)
}
// No task available, continue polling
select {
case <-ctx.Done():
return ctx.Err()
default:
// Continue to next iteration
}
}
}
func (j *Job) runTaskWithRecover(ctx context.Context, task *runnerv1.Task) error {

View file

@ -90,10 +90,10 @@ func (p *poller) Shutdown(ctx context.Context) error {
return nil
case <-ctx.Done():
log.Trace("forcing the jobs to shutdown")
log.Info("forcing the jobs to shutdown")
p.shutdownJobs()
<-p.done
log.Trace("all jobs have been shutdown")
log.Info("all jobs have been shutdown")
return ctx.Err()
}
}

View file

@ -117,13 +117,13 @@ func setupCache(cfg *config.Config, envs map[string]string) *cacheproxy.Handler
cacheServer, err := artifactcache.StartHandler(
cfg.Cache.Dir,
cfg.Cache.Host,
"", // automatically detect
cfg.Cache.Port,
cacheSecret,
log.StandardLogger().WithField("module", "cache_request"),
)
if err != nil {
log.Error("Could not start the cache server, cache will be disabled")
log.Errorf("Could not start the cache server, cache will be disabled: %v", err)
return nil
}
@ -144,16 +144,14 @@ func setupCache(cfg *config.Config, envs map[string]string) *cacheproxy.Handler
cacheURL,
cfg.Cache.Host,
cfg.Cache.ProxyPort,
cfg.Cache.ActionsCacheURLOverride,
cacheSecret,
log.StandardLogger().WithField("module", "cache_proxy"),
)
if err != nil {
log.Errorf("cannot init cache proxy, cache will be disabled: %v", err)
}
} else {
envs["ACTIONS_CACHE_URL"] = cacheProxy.ExternalURL()
if cfg.Cache.ActionsCacheURLOverride != "" {
envs["ACTIONS_CACHE_URL"] = cfg.Cache.ActionsCacheURLOverride
}
return cacheProxy
@ -195,6 +193,44 @@ func explainFailedGenerateWorkflow(task *runnerv1.Task, log func(message string,
return fmt.Errorf("the workflow file is not usable")
}
func getWriteIsolationKey(ctx context.Context, eventName, ref string, event map[string]any) (string, error) {
if eventName == "pull_request" {
// The "closed" action of a pull request event runs in the context of the base repository
// and was merged by a user with write access to the base repository. It is authorized to
// write the repository cache.
if event["action"] == "closed" {
pullRequest, ok := event["pull_request"].(map[string]any)
if !ok {
return "", fmt.Errorf("getWriteIsolationKey: event.pull_request is not a map[string]any but %T", event["pull_request"])
}
merged, ok := pullRequest["merged"].(bool)
if !ok {
return "", fmt.Errorf("getWriteIsolationKey: event.pull_request.merged is not a bool but %T", pullRequest["merged"])
}
if merged {
return "", nil
}
// a pull request that is closed but not merged falls thru and is expected to obey the same
// constraints as an opened pull request, it may be closed by a user with no write permissions to the
// base repository
}
// When performing an action on an event from an opened PR, provide a "write isolation key" to the cache. The generated
// ACTIONS_CACHE_URL will be able to read the cache, and write to a cache, but its writes will be isolated to
// future runs of the PR's workflows and won't be shared with other pull requests or actions. This is a security
// measure to prevent a malicious pull request from poisoning the cache with secret-stealing code which would
// later be executed on another action.
// Ensure that `ref` has the expected format so that we don't end up with a useless write isolation key
if !strings.HasPrefix(ref, "refs/pull/") {
return "", fmt.Errorf("getWriteIsolationKey: expected ref to be refs/pull/..., but was %q", ref)
}
return ref, nil
}
// Other events do not allow the trigger user to modify the content of the repository and
// are allowed to write the cache without an isolation key
return "", nil
}
func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.Reporter) (err error) {
defer func() {
if r := recover(); r != nil {
@ -228,15 +264,18 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
defaultActionURL,
r.client.Address())
eventName := taskContext["event_name"].GetStringValue()
ref := taskContext["ref"].GetStringValue()
event := taskContext["event"].GetStructValue().AsMap()
preset := &model.GithubContext{
Event: taskContext["event"].GetStructValue().AsMap(),
Event: event,
RunID: taskContext["run_id"].GetStringValue(),
RunNumber: taskContext["run_number"].GetStringValue(),
Actor: taskContext["actor"].GetStringValue(),
Repository: taskContext["repository"].GetStringValue(),
EventName: taskContext["event_name"].GetStringValue(),
EventName: eventName,
Sha: taskContext["sha"].GetStringValue(),
Ref: taskContext["ref"].GetStringValue(),
Ref: ref,
RefName: taskContext["ref_name"].GetStringValue(),
RefType: taskContext["ref_type"].GetStringValue(),
HeadRef: taskContext["head_ref"].GetStringValue(),
@ -266,19 +305,9 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
// Register the run with the cacheproxy and modify the CACHE_URL
if r.cacheProxy != nil {
writeIsolationKey := ""
// When performing an action on an event from a PR, provide a "write isolation key" to the cache. The generated
// ACTIONS_CACHE_URL will be able to read the cache, and write to a cache, but its writes will be isolated to
// future runs of the PR's workflows and won't be shared with other pull requests or actions. This is a security
// measure to prevent a malicious pull request from poisoning the cache with secret-stealing code which would
// later be executed on another action.
if taskContext["event_name"].GetStringValue() == "pull_request" {
// Ensure that `Ref` has the expected format so that we don't end up with a useless write isolation key
if !strings.HasPrefix(preset.Ref, "refs/pull/") {
return fmt.Errorf("write isolation key: expected preset.Ref to be refs/pull/..., but was %q", preset.Ref)
}
writeIsolationKey = preset.Ref
writeIsolationKey, err := getWriteIsolationKey(ctx, eventName, ref, event)
if err != nil {
return err
}
timestamp := strconv.FormatInt(time.Now().Unix(), 10)

View file

@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"net"
"os"
"testing"
"time"
@ -70,6 +71,7 @@ func TestLabelUpdate(t *testing.T) {
type forgejoClientMock struct {
mock.Mock
sent string
}
func (m *forgejoClientMock) Address() string {
@ -122,11 +124,20 @@ func (m *forgejoClientMock) UpdateTask(ctx context.Context, request *connect.Req
return args.Get(0).(*connect.Response[runnerv1.UpdateTaskResponse]), args.Error(1)
}
func rowsToString(rows []*runnerv1.LogRow) string {
s := ""
for _, row := range rows {
s += row.Content + "\n"
}
return s
}
func (m *forgejoClientMock) UpdateLog(ctx context.Context, request *connect.Request[runnerv1.UpdateLogRequest]) (*connect.Response[runnerv1.UpdateLogResponse], error) {
// Enable for log output from runs if needed.
// for _, row := range request.Msg.Rows {
// println(fmt.Sprintf("UpdateLog: %q", row.Content))
// }
m.sent += rowsToString(request.Msg.Rows)
args := m.Called(ctx, request)
mockRetval := args.Get(0)
mockError := args.Error(1)
@ -141,6 +152,83 @@ func (m *forgejoClientMock) UpdateLog(ctx context.Context, request *connect.Requ
}), nil
}
func TestRunner_getWriteIsolationKey(t *testing.T) {
t.Run("push", func(t *testing.T) {
key, err := getWriteIsolationKey(t.Context(), "push", "whatever", nil)
require.NoError(t, err)
assert.Empty(t, key)
})
t.Run("pull_request synchronized key is ref", func(t *testing.T) {
expectedKey := "refs/pull/1/head"
actualKey, err := getWriteIsolationKey(t.Context(), "pull_request", expectedKey, map[string]any{
"action": "synchronized",
})
require.NoError(t, err)
assert.Equal(t, expectedKey, actualKey)
})
t.Run("pull_request synchronized ref is invalid", func(t *testing.T) {
invalidKey := "refs/is/invalid"
key, err := getWriteIsolationKey(t.Context(), "pull_request", invalidKey, map[string]any{
"action": "synchronized",
})
require.Empty(t, key)
assert.ErrorContains(t, err, invalidKey)
})
t.Run("pull_request closed and not merged key is ref", func(t *testing.T) {
expectedKey := "refs/pull/1/head"
actualKey, err := getWriteIsolationKey(t.Context(), "pull_request", expectedKey, map[string]any{
"action": "closed",
"pull_request": map[string]any{
"merged": false,
},
})
require.NoError(t, err)
assert.Equal(t, expectedKey, actualKey)
})
t.Run("pull_request closed and merged key is empty", func(t *testing.T) {
key, err := getWriteIsolationKey(t.Context(), "pull_request", "whatever", map[string]any{
"action": "closed",
"pull_request": map[string]any{
"merged": true,
},
})
require.NoError(t, err)
assert.Empty(t, key)
})
t.Run("pull_request missing event.pull_request", func(t *testing.T) {
key, err := getWriteIsolationKey(t.Context(), "pull_request", "whatever", map[string]any{
"action": "closed",
})
require.Empty(t, key)
assert.ErrorContains(t, err, "event.pull_request is not a map")
})
t.Run("pull_request missing event.pull_request.merge", func(t *testing.T) {
key, err := getWriteIsolationKey(t.Context(), "pull_request", "whatever", map[string]any{
"action": "closed",
"pull_request": map[string]any{},
})
require.Empty(t, key)
assert.ErrorContains(t, err, "event.pull_request.merged is not a bool")
})
t.Run("pull_request with event.pull_request.merge of an unexpected type", func(t *testing.T) {
key, err := getWriteIsolationKey(t.Context(), "pull_request", "whatever", map[string]any{
"action": "closed",
"pull_request": map[string]any{
"merged": "string instead of bool",
},
})
require.Empty(t, key)
assert.ErrorContains(t, err, "not a bool but string")
})
}
func TestRunnerCacheConfiguration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
@ -344,6 +432,98 @@ jobs:
})
}
func TestRunnerCacheStartupFailure(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
testCases := []struct {
desc string
listen string
}{
{
desc: "disable cache server",
listen: "127.0.0.1:40715",
},
{
desc: "disable cache proxy server",
listen: "127.0.0.1:40716",
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
forgejoClient := &forgejoClientMock{}
forgejoClient.On("Address").Return("https://127.0.0.1:8080") // not expected to be used in this test
forgejoClient.On("UpdateLog", mock.Anything, mock.Anything).Return(nil, nil)
forgejoClient.On("UpdateTask", mock.Anything, mock.Anything).
Return(connect.NewResponse(&runnerv1.UpdateTaskResponse{}), nil)
// We'll be listening on some network port in this test that will conflict with the cache configuration...
l, err := net.Listen("tcp4", tc.listen)
require.NoError(t, err)
defer l.Close()
runner := NewRunner(
&config.Config{
Cache: config.Cache{
Port: 40715,
ProxyPort: 40716,
Dir: t.TempDir(),
},
Host: config.Host{
WorkdirParent: t.TempDir(),
},
},
&config.Registration{
Labels: []string{"ubuntu-latest:docker://code.forgejo.org/oci/node:20-bookworm"},
},
forgejoClient)
require.NotNil(t, runner)
// Ensure that cacheProxy failed to start
assert.Nil(t, runner.cacheProxy)
runWorkflow := func(ctx context.Context, cancel context.CancelFunc, yamlContent string) {
task := &runnerv1.Task{
WorkflowPayload: []byte(yamlContent),
Context: &structpb.Struct{
Fields: map[string]*structpb.Value{
"token": structpb.NewStringValue("some token here"),
"forgejo_default_actions_url": structpb.NewStringValue("https://data.forgejo.org"),
"repository": structpb.NewStringValue("runner"),
"event_name": structpb.NewStringValue("push"),
"ref": structpb.NewStringValue("refs/heads/main"),
},
},
}
reporter := report.NewReporter(ctx, cancel, forgejoClient, task, time.Second)
err := runner.run(ctx, task, reporter)
reporter.Close(nil)
require.NoError(t, err)
}
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
checkCacheYaml := `
name: Verify No ACTIONS_CACHE_URL
on:
push:
jobs:
job-cache-check-1:
runs-on: ubuntu-latest
steps:
- run: echo $ACTIONS_CACHE_URL
- run: '[[ "$ACTIONS_CACHE_URL" = "" ]] || exit 1'
`
runWorkflow(ctx, cancel, checkCacheYaml)
})
}
}
func TestRunnerLXC(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
@ -414,8 +594,164 @@ jobs:
job:
runs-on: lxc
steps:
- run: echo OK
- run: mkdir -p some/directory/owned/by/root
`
runWorkflow(ctx, cancel, workflow, "push", "refs/heads/main", "OK")
})
}
func TestRunnerResources(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
forgejoClient := &forgejoClientMock{}
forgejoClient.On("Address").Return("https://127.0.0.1:8080") // not expected to be used in this test
forgejoClient.On("UpdateLog", mock.Anything, mock.Anything).Return(nil, nil)
forgejoClient.On("UpdateTask", mock.Anything, mock.Anything).
Return(connect.NewResponse(&runnerv1.UpdateTaskResponse{}), nil)
workdirParent := t.TempDir()
runWorkflow := func(ctx context.Context, cancel context.CancelFunc, yamlContent, options, errorMessage, logMessage string) {
task := &runnerv1.Task{
WorkflowPayload: []byte(yamlContent),
Context: &structpb.Struct{
Fields: map[string]*structpb.Value{
"token": structpb.NewStringValue("some token here"),
"forgejo_default_actions_url": structpb.NewStringValue("https://data.forgejo.org"),
"repository": structpb.NewStringValue("runner"),
"event_name": structpb.NewStringValue("push"),
"ref": structpb.NewStringValue("refs/heads/main"),
},
},
}
runner := NewRunner(
&config.Config{
Log: config.Log{
JobLevel: "trace",
},
Host: config.Host{
WorkdirParent: workdirParent,
},
Container: config.Container{
Options: options,
},
},
&config.Registration{
Labels: []string{"docker:docker://code.forgejo.org/oci/node:20-bookworm"},
},
forgejoClient)
require.NotNil(t, runner)
reporter := report.NewReporter(ctx, cancel, forgejoClient, task, time.Second)
err := runner.run(ctx, task, reporter)
reporter.Close(nil)
if len(errorMessage) > 0 {
require.Error(t, err)
assert.ErrorContains(t, err, errorMessage)
} else {
require.NoError(t, err)
}
if len(logMessage) > 0 {
assert.Contains(t, forgejoClient.sent, logMessage)
}
}
t.Run("config.yaml --memory set and enforced", func(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
workflow := `
on:
push:
jobs:
job:
runs-on: docker
steps:
- run: |
# more than 300MB
perl -e '$a = "a" x (300 * 1024 * 1024)'
`
runWorkflow(ctx, cancel, workflow, "--memory 200M", "Job 'job' failed", "Killed")
})
t.Run("config.yaml --memory set and within limits", func(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
workflow := `
on:
push:
jobs:
job:
runs-on: docker
steps:
- run: echo OK
`
runWorkflow(ctx, cancel, workflow, "--memory 200M", "", "")
})
t.Run("config.yaml --memory set and container fails to increase it", func(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
workflow := `
on:
push:
jobs:
job:
runs-on: docker
container:
image: code.forgejo.org/oci/node:20-bookworm
options: --memory 4G
steps:
- run: |
# more than 300MB
perl -e '$a = "a" x (300 * 1024 * 1024)'
`
runWorkflow(ctx, cancel, workflow, "--memory 200M", "option found in the workflow cannot be greater than", "")
})
t.Run("container --memory set and enforced", func(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
workflow := `
on:
push:
jobs:
job:
runs-on: docker
container:
image: code.forgejo.org/oci/node:20-bookworm
options: --memory 200M
steps:
- run: |
# more than 300MB
perl -e '$a = "a" x (300 * 1024 * 1024)'
`
runWorkflow(ctx, cancel, workflow, "", "Job 'job' failed", "Killed")
})
t.Run("container --memory set and within limits", func(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
workflow := `
on:
push:
jobs:
job:
runs-on: docker
container:
image: code.forgejo.org/oci/node:20-bookworm
options: --memory 200M
steps:
- run: echo OK
`
runWorkflow(ctx, cancel, workflow, "", "", "")
})
}

View file

@ -110,25 +110,20 @@ cache:
#
external_server: ""
#
#######################################################################
#
# Common to the internal and external cache server
#
#######################################################################
#
# The shared cache secret used to secure the communications between
# the cache proxy and the cache server.
#
# If empty, it will be generated to a new secret automatically when
# the server starts and it will stay the same until it restarts.
#
# Every time the secret is modified, all cache entries that were
# created with it are invalidated. In order to ensure that the cache
# content is reused when the runner restarts, this secret must be
# set, for instance with the output of openssl rand -hex 40.
#
secret: ""
#
#######################################################################
#
# Common to the internal and external cache server
#
#######################################################################
#
# The IP or hostname (195.84.20.30 or example.com) to use when constructing
# ACTIONS_CACHE_URL which is the URL of the cache proxy.
#
@ -138,7 +133,7 @@ cache:
# different network than the Forgejo runner (for instance when the
# docker server used to create containers is not running on the same
# host as the Forgejo runner), it may be impossible to figure that
# out automatically. In that case you can specifify which IP or
# out automatically. In that case you can specify which IP or
# hostname to use to reach the internal cache server created by the
# Forgejo runner.
#
@ -181,10 +176,12 @@ container:
# valid_volumes:
# - '**'
valid_volumes: []
# overrides the docker client host with the specified one.
# If "-" or "", an available docker host will automatically be found.
# Overrides the docker host set by the DOCKER_HOST environment variable, and mounts on the job container.
# If "-" or "", no docker host will be mounted in the job container
# If "automount", an available docker host will automatically be found and mounted in the job container (e.g. /var/run/docker.sock).
# Otherwise the specified docker host will be used and an error will be returned if it doesn't work.
# If it's a url, the specified docker host will be mounted in the job container
# Example urls: unix:///run/docker.socket or ssh://user@host
# The specified socket is mounted within the job container at /var/run/docker.sock
docker_host: "-"
# Pull docker image(s) even if already present
force_pull: false

View file

@ -38,7 +38,7 @@ func (o *masker) add(secret string) {
})
// a multiline secret transformed into a single line by replacing
// newlines with \ followed by n must also be redacted
secret = strings.Join(lines, "\\n")
o.lines = append(o.lines, strings.Join(lines, "\\n"))
}
o.lines = append(o.lines, secret)

View file

@ -7,6 +7,8 @@ import (
"fmt"
"testing"
runnerv1 "code.forgejo.org/forgejo/actions-proto/runner/v1"
"github.com/stretchr/testify/assert"
)
@ -267,4 +269,17 @@ SIX`
assert.Equal(t, testCase.out, rowsToString(rows))
})
}
t.Run("MultilineSecretInSingleRow", func(t *testing.T) {
secret := "ABC\nDEF\nGHI"
m := newMasker()
m.add(secret)
rows := []*runnerv1.LogRow{
{Content: fmt.Sprintf("BEFORE%sAFTER", secret)},
}
noMore := false
needMore := m.replace(rows, noMore)
assert.False(t, needMore)
assert.Equal(t, "BEFORE***AFTER\n", rowsToString(rows))
})
}

View file

@ -13,6 +13,7 @@ import (
"time"
runnerv1 "code.forgejo.org/forgejo/actions-proto/runner/v1"
"code.forgejo.org/forgejo/runner/v11/act/runner"
"connectrpc.com/connect"
retry "github.com/avast/retry-go/v4"
log "github.com/sirupsen/logrus"
@ -47,6 +48,7 @@ type Reporter struct {
debugOutputEnabled bool
stopCommandEndToken string
issuedLocalCancel bool
}
func NewReporter(ctx context.Context, cancel context.CancelFunc, c client.Client, task *runnerv1.Task, reportInterval time.Duration) *Reporter {
@ -130,10 +132,12 @@ func (r *Reporter) Fire(entry *log.Entry) error {
}
}
}
if r.state.Result == runnerv1.Result_RESULT_SUCCESS {
if v, ok := entry.Data["jobOutputs"]; ok {
_ = r.setOutputs(v.(map[string]string))
} else {
log.Panicf("received log entry with jobResult, but without jobOutputs -- outputs will be corrupted for this job")
log.Panicf("received log entry with successful jobResult, but without jobOutputs -- outputs will be corrupted for this job")
}
}
}
if !r.duringSteps() {
@ -171,7 +175,7 @@ func (r *Reporter) Fire(entry *log.Entry) error {
} else if !r.duringSteps() {
r.logRows = appendIfNotNil(r.logRows, r.parseLogRow(entry))
}
if v, ok := entry.Data["stepResult"]; ok {
if v := runner.GetOuterStepResult(entry); v != nil {
if stepResult, ok := r.parseResult(v); ok {
if step.LogLength == 0 {
step.LogIndex = int64(r.logOffset + len(r.logRows))
@ -189,11 +193,19 @@ func (r *Reporter) RunDaemon() {
return
}
if r.ctx.Err() != nil {
// This shouldn't happen because DaemonContext is used for `r.ctx` which should outlive any running job.
log.Warnf("Terminating RunDaemon on an active job due to error: %v", r.ctx.Err())
return
}
_ = r.ReportLog(false)
_ = r.ReportState()
err := r.ReportLog(false)
if err != nil {
log.Warnf("ReportLog error: %v", err)
}
err = r.ReportState()
if err != nil {
log.Warnf("ReportState error: %v", err)
}
time.AfterFunc(r.reportInterval, r.RunDaemon)
}
@ -388,8 +400,17 @@ func (r *Reporter) ReportState() error {
r.outputs.Store(k, struct{}{})
}
switch resp.Msg.GetState().GetResult() {
localResultState := state.GetResult()
remoteResultState := resp.Msg.GetState().GetResult()
switch remoteResultState {
case runnerv1.Result_RESULT_CANCELLED, runnerv1.Result_RESULT_FAILURE:
// issuedLocalCancel is just used to deduplicate this log message if our local state doesn't catch up with our
// remote state as quickly as the report-interval, which would cause this message to repeat in the logs.
if !r.issuedLocalCancel && remoteResultState != localResultState {
log.Infof("UpdateTask returned task result %v for a task that was in local state %v - beginning local task termination",
remoteResultState, localResultState)
r.issuedLocalCancel = true
}
r.cancel()
}

View file

@ -301,6 +301,20 @@ func TestReporter_Fire(t *testing.T) {
value, _ := reporter.outputs.Load("key1")
assert.EqualValues(t, "value1", value)
})
t.Run("jobResult jobOutputs is absent if not success", func(t *testing.T) {
reporter, _, _ := mockReporter(t)
dataStep0 := map[string]any{
"stage": "Post",
"stepNumber": 0,
"raw_output": true,
"jobResult": "skipped",
}
assert.NoError(t, reporter.Fire(&log.Entry{Message: "skipped!", Data: dataStep0}))
assert.EqualValues(t, runnerv1.Result_RESULT_SKIPPED, reporter.state.Result)
})
}
func TestReporterReportState(t *testing.T) {