Compare commits

...

291 commits
v9.0.0 ... main

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
Freso
f4eb8e57fb
feat: add pre-commit hook for validator (#1002)
This will allow users to validate their Forgejo Actions files (both actions and workflows) prior to committing them to their repositories, using a `pre-commit` configuration similar to
```yaml
  - repo: https://code.forgejo.org/forgejo/runner
    rev: v11.1.0
    hooks:
      - id: forgejo-runner-validate
```

<!--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-->
<!--end release-notes-assistant-->

Co-authored-by: Frederik “Freso” S. Olesen <freso.dk@gmail.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1002
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 08:08:57 +00:00
Earl Warren
b8ab05e367
fix: schema validation must accept aliases and merges (#1012)
- aliases are an indirection to follow
  https://yaml.org/spec/1.2.1/#id2785586
- merges cannot be conveniently validated and are skipped
  https://yaml.org/type/merge.html

Resolves forgejo/runner#1011

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- 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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1012
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-18 07:19:44 +00:00
earl-warren
797e0cd250
fix: forgejo-runner validate exit with error when validation fails (#1009)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1009
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2025-09-18 06:52:19 +00:00
Earl Warren
8c6c089a65
fix: forgejo-runner validate exit with error when validation fails
Refs forgejo/runner#1002
2025-09-18 08:40:41 +02:00
Earl Warren
bcf2bfbf20
fix: find action.y*ml at the root of the directory
The lookup of action.y*ml files failed at the root of the directory
when specified with . because it does not start with a / when walking
the directory.
2025-09-18 08:36:33 +02:00
Earl Warren
89f37985bd
feat: validate --directory alternative to --repository to not clone (#1008)
Resolves forgejo/forgejo-actions-feature-requests#51

---

Note to reviewers: while working on fixing the exit status of the validate command, a border case was discovered when using `--clonedir . --repository .` by which it will not find an `action.yml` file at the root of the directory. It will be easier to fix and test using a `--directory` option designed to use a pre-existing directory instead because it is not a border case but the most common case really.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1008
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-17 16:40:31 +00:00
Earl Warren
aaf9dea44a
fix: do not save .runner unless it is modified (#1006)
Resolves forgejo/runner#548

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1006
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-17 12:48:52 +00:00
Earl Warren
e1e7d0e85a
fix: remove LXC working directory when it completes (#1003)
The working directory was not cleaned up upon completion of a LXC job because rc.stopJobContainer() -> rc.cleanUpJobContainer() -> rc.JobContainer.Remove() was never called for LXC containers.

- stopContainer() and closeContainer() must not call
  rc.stopHostEnvironment(ctx) for LXC containers because
  - it will needlessly be called twice
  - it intercepts the call to
    - rc.stopJobContainer()
    - rc.JobContainer.Close()
- rc.stopHostEnvironment(ctx) must be called in rc.cleanUpJobContainer which is indirectly called by rc.stopJobContainer()
- since rc.JobContainer.Close() is a noop, not calling it for LXC containers had no consequence

Resolves forgejo/runner#442

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/1003): <!--number 1003 --><!--line 0 --><!--description Zml4OiByZW1vdmUgTFhDIHdvcmtpbmcgZGlyZWN0b3J5IHdoZW4gaXQgY29tcGxldGVz-->fix: remove LXC working directory when it completes<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1003
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-16 19:42:04 +00:00
Renovate Bot
d98522a2b6
Update dependency forgejo/lxc-helpers to v1.1.0 (#1001)
This PR contains the following updates:

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

---

### Release Notes

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

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

[Compare Source](https://code.forgejo.org/forgejo/lxc-helpers/compare/v1.0.3...v1.1.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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMTMuMyIsInVwZGF0ZWRJblZlciI6IjQxLjExMy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0RlcGVuZGVuY3lVcGRhdGUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1001
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-16 13:20:43 +00:00
earl-warren
6576754256
chore: minimal integration test for the LXC backend (#1000)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/1000
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
2025-09-15 15:46:46 +00:00
Earl Warren
69df253e41
fix: ptyWriter.AutoStop is used by multiple goroutines
```
WARNING: DATA RACE
Write at 0x00c0008541d8 by goroutine 9324:
  code.forgejo.org/forgejo/runner/v11/act/container.(*HostEnvironment).exec()
      /home/debian/.cache/act/37b13738279f9342/hostexecutor/act/container/host_environment.go:368 +0x12dd
  code.forgejo.org/forgejo/runner/v11/act/runner.(*stepRun).main.func1.(*HostEnvironment).ExecWithCmdLine.1()
      /home/debian/.cache/act/37b13738279f9342/hostexecutor/act/container/host_environment.go:388
      +0x354

Previous read at 0x00c0008541d8 by goroutine 9328:
  code.forgejo.org/forgejo/runner/v11/act/container.(*ptyWriter).Write()
      /home/debian/.cache/act/37b13738279f9342/hostexecutor/act/container/host_environment.go:199 +0x57
  io.copyBuffer()
      /home/debian/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.7.linux-amd64/src/io/io.go:431
      +0x2ce

Goroutine 9324 (running) created at:
  code.forgejo.org/forgejo/runner/v11/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2()
      /home/debian/.cache/act/37b13738279f9342/hostexecutor/act/common/executor.go:105 +0x144
  code.forgejo.org/forgejo/runner/v11/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.1()
      /home/debian/.cache/act/37b13738279f9342/hostexecutor/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v11/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.gowrap1()
      /home/debian/.cache/act/37b13738279f9342/hostexecutor/act/common/executor.go:109 +0x4f
Goroutine 9328 (running) created at:
  code.forgejo.org/forgejo/runner/v11/act/container.(*HostEnvironment).exec()
      /home/debian/.cache/act/37b13738279f9342/hostexecutor/act/container/host_environment.go:356 +0x112a
  code.forgejo.org/forgejo/runner/v11/act/runner.(*stepRun).main.func1.(*HostEnvironment).ExecWithCmdLine.1()
      /home/debian/.cache/act/37b13738279f9342/hostexecutor/act/container/host_environment.go:388 +0x354
  code.forgejo.org/forgejo/runner/v11/act/runner.(*stepRun).main.func1()
```
2025-09-15 17:17:44 +02:00
Earl Warren
6877142ba4
chore: minimal integration test for the LXC backend 2025-09-15 16:14:11 +02:00
Earl Warren
b3c603644a
chore: set log level to trace for runner tests 2025-09-15 15:53:21 +02:00
Earl Warren
5c93da6fc7
feat: the forgejo context is equivalent to the github context (#999)
Resolves forgejo/runner#729

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/999
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-15 09:14:11 +00:00
cascading-pr
543f3fd495
feat: add support for a trixie based Debian GNU/Linux backend (e.g. trixie-lxc:lxc://debian:trixie) (#997)
cascading-pr from https://code.forgejo.org/forgejo/lxc-helpers/pulls/35

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/997): <!--number 997 --><!--line 0 --><!--description ZmVhdDogYWRkIHN1cHBvcnQgZm9yIGEgdHJpeGllIGJhc2VkIERlYmlhbiBHTlUvTGludXggYmFja2VuZCAoZS5nLiB0cml4aWUtbHhjOmx4YzovL2RlYmlhbjp0cml4aWUp-->feat: add support for a trixie based Debian GNU/Linux backend (e.g. trixie-lxc:lxc://debian:trixie)<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: cascading-pr <cascading-pr@example.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/997
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-09-15 07:26:56 +00:00
Mathieu Fenniak
2573ccaf19
fix: send job outputs & job result to Forgejo in sync with each other (#995)
Fixes #994.

First commit ensures that the interpolateResults method is invoked before data is sent to the reporter.  Second commit changes how data is sent to the reporter to include both the result and the job outputs.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/995
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-14 20:02:43 +00:00
Earl Warren
3585d67743
chore: unify actions URLs in .forgejo/workflows (#993)
- make them all absolute
- use data.forgejo.org instead of code.forgejo.org

This allows renovate to propose more consistent updates.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/993): <!--number 993 --><!--line 0 --><!--description Y2hvcmU6IHVuaWZ5IGFjdGlvbnMgVVJMcyBpbiAuZm9yZ2Vqby93b3JrZmxvd3M=-->chore: unify actions URLs in .forgejo/workflows<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/993
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-13 17:35:56 +00:00
Renovate Bot
458dae9827
Update https://data.forgejo.org/actions/cascading-pr action to v2.3.0 (#992)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [https://data.forgejo.org/actions/cascading-pr](https://code.forgejo.org/actions/cascading-pr) | action | minor | `v2.2.1` -> `v2.3.0` |

---

### Release Notes

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

### [`v2.3.0`](https://code.forgejo.org/actions/cascading-pr/compare/v2.2.1...v2.3.0)

[Compare Source](https://code.forgejo.org/actions/cascading-pr/compare/v2.2.1...v2.3.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:eyJjcmVhdGVkSW5WZXIiOiI0MS45OS44IiwidXBkYXRlZEluVmVyIjoiNDEuOTkuOCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9EZXBlbmRlbmN5VXBkYXRlIiwicnVuLWVuZC10by1lbmQtdGVzdHMiXX0=-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/992
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-12 11:04:10 +00:00
Earl Warren
19f4dbeb4b
chore: data.forgejo.org/actions/cascading-pr is the canonical location (#990)
![image](/attachments/28a98026-29ec-41c2-b3c6-c539098e8df6)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/990
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-12 06:49:16 +00:00
Renovate Bot
b6c9da470e
Update dependency forgejo/release-notes-assistant to v1.4.1 (#989)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [forgejo/release-notes-assistant](https://code.forgejo.org/forgejo/release-notes-assistant) | patch | `v1.4.0` -> `v1.4.1` |

---

### Release Notes

<details>
<summary>forgejo/release-notes-assistant (forgejo/release-notes-assistant)</summary>

### [`v1.4.1`](https://code.forgejo.org/forgejo/release-notes-assistant/releases/tag/v1.4.1)

[Compare Source](https://code.forgejo.org/forgejo/release-notes-assistant/compare/v1.4.0...v1.4.1)

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

<!--URL:https://code.forgejo.org/forgejo/release-notes-assistant-->

- other
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/115): <!--number 115 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL2Zvcmdlam8tcmVsZWFzZSBhY3Rpb24gdG8gdjIuNy4z-->Update <https://data.forgejo.org/actions/forgejo-release> action to v2.7.3<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/114): <!--number 114 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBtdmRhbi5jYy9nb2Z1bXB0IHRvIHYwLjkuMQ==-->Update module mvdan.cc/gofumpt to v0.9.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/113): <!--number 113 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjQuNw==-->Update dependency go to v1.24.7<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/112): <!--number 112 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBtdmRhbi5jYy9nb2Z1bXB0IHRvIHYwLjkuMA==-->Update module mvdan.cc/gofumpt to v0.9.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/110): <!--number 110 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3N0cmV0Y2hyL3Rlc3RpZnkgdG8gdjEuMTEuMA==-->Update module github.com/stretchr/testify to v1.11.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/109): <!--number 109 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuNC4w-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.4.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/108): <!--number 108 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvdG9vbHMvY21kL2RlYWRjb2RlIHRvIHYwLjM2LjA=-->Update module golang.org/x/tools/cmd/deadcode to v0.36.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/107): <!--number 107 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjQuNg==-->Update dependency go to v1.24.6<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/106): <!--number 106 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL2Zvcmdlam8tcmVsZWFzZSBhY3Rpb24gdG8gdjIuNy4y-->Update <https://data.forgejo.org/actions/forgejo-release> action to v2.7.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/105): <!--number 105 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuMy4x-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.3.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 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:eyJjcmVhdGVkSW5WZXIiOiI0MS45OS44IiwidXBkYXRlZEluVmVyIjoiNDEuOTkuOCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9EZXBlbmRlbmN5VXBkYXRlIiwicnVuLWVuZC10by1lbmQtdGVzdHMiXX0=-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/989
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-12 05:31:59 +00:00
Earl Warren
f728f8a923
fix: if the Forgejo instance failed a job, cancel it (#986)
- when the Forgejo instance stops a job because it runs for too long, it will be reported back as failed and it must be stopped, exactly as if it was canceled from the web UI by the user.
- add test coverage for Reporter.ReportState
- extract Reporter.Outputs output of Reporter.ReportState

Resolves https://code.forgejo.org/forgejo/runner/issues/980

---

Manual testing with a locally built Forgejo instance built to check every minute instead of every 30 minutes, with

```ini
[actions]
ENABLED = true
ENDLESS_TASK_TIMEOUT = 1m
```

and the following workflow:

```yaml
on: [push]
jobs:
  test:
    runs-on: docker
    steps:
      - run: sleep 60
      - run: sleep 61
      - run: sleep 62
```

waiting in front of the screen and watching the logs of the runner, I see it stops before `sleep 62` is complete.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/986
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-11 20:03:17 +00:00
Earl Warren
6f212fbb5a
chore: wait 4 times longer for the forgejo cascade pull request to complete (#988)
If the CI is busy, it may take more than one hour, for instance because the workflow is waiting while others are running.

---

Note to reviewers: this input is not yet implemented, the next version of the cascading-pr action will have it (see [the pr](https://code.forgejo.org/actions/cascading-pr/pulls/40)). In the meantime it will be ignored.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/988
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-11 17:11:06 +00:00
Earl Warren
02a51c0a21
fix: enforce job.<job-id>.timeout-minutes (#982)
- enforce timeout-minutes timeout for jobs in a way similar  to how it is done for steps
- minimal refactor of evaluateStepTimeout evaluateTimeout so it  can be used by jobs as well, with additional debug information  and error logging if parsing fails
- add integration tests for both step and job timeout-minutes,  verifying expressions are allowed and evaluated

Resolves forgejo/runner#979

---

Manually verified to work as expected https://v13.next.forgejo.org/earl-warren/testtimeout-minutes/actions/runs/3/jobs/0/attempt/1

```yaml
on: [push]
jobs:
  test:
    runs-on: docker
    timeout-minutes: 1
    steps:
      - run: |
          set -x
          while : ; do
            sleep 30
          done
```

![image](/attachments/047ddd15-7109-4931-a6ed-43073e4d31f9)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/982): <!--number 982 --><!--line 0 --><!--description Zml4OiBlbmZvcmNlIGpvYi48am9iLWlkPi50aW1lb3V0LW1pbnV0ZXM=-->fix: enforce job.<job-id>.timeout-minutes<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/982
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-11 14:43:26 +00:00
Crown0815
933667bdf1
Remove windows build/test pipeline for GitHub (#985)
Windows builds have move to an [independent repository](https://github.com/Crown0815/Forgejo-runner-windows-builder).

Same changes as in #983

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/985): <!--number 985 --><!--line 0 --><!--description UmVtb3ZlIHdpbmRvd3MgYnVpbGQvdGVzdCBwaXBlbGluZSBmb3IgR2l0SHVi-->Remove windows build/test pipeline for GitHub<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Felix Kröner <felix.kroener@bruker.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/985
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Crown0815 <crown0815@noreply.code.forgejo.org>
Co-committed-by: Crown0815 <crown0815@noreply.code.forgejo.org>
2025-09-11 11:25:52 +00:00
Renovate Bot
3dd167d770
Update module code.forgejo.org/forgejo/actions-proto to v0.5.2 (#981)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| code.forgejo.org/forgejo/actions-proto | `v0.5.1` -> `v0.5.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/code.forgejo.org%2fforgejo%2factions-proto/v0.5.2?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.1/v0.5.2?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:eyJjcmVhdGVkSW5WZXIiOiI0MS45Ny45IiwidXBkYXRlZEluVmVyIjoiNDEuOTcuOSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9EZXBlbmRlbmN5VXBkYXRlIiwicnVuLWVuZC10by1lbmQtdGVzdHMiXX0=-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/981
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-11 04:50:00 +00:00
Earl Warren
16276cc0d6
fix: use a fixed runner name for old (<= v1.20) Forgejo instances (#972)
The bug was already there before the recent refactor. Only it
manifested itself when shutting down the runner because
`resp.Msg.GetRunner().GetName()` was only called then. It was
correctly refactored in the createRunner function and therefore
surfaced because `resp.Msg.GetRunner().GetName()` was called
during initialization instead of during shutdown.

```
time="2025-09-10T05:41:10Z" level=info msg="log level changed to debug" func="[func2]" file="[daemon.go:130]"
time="2025-09-10T05:41:10Z" level=info msg="Starting runner daemon" func="[runDaemon]" file="[daemon.go:51]"
time="2025-09-10T05:41:10Z" level=warning msg="Because the Forgejo instance is an old version, skipping declaring the labels and version." func="[func6]" file="[daemon.go:208]"
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xcc1a23]
goroutine 1 [running]:
code.forgejo.org/forgejo/runner/v11/internal/app/cmd.init.func6({0x111f428, 0xc0000e8ab0}, 0xc0003b4000, 0xc0003b8230, {0x1125eb8?, 0xc000424040?}, {0xc000032840, 0x6, 0x8})
	/srv/internal/app/cmd/daemon.go:222 +0x4a3
code.forgejo.org/forgejo/runner/v11/internal/app/cmd.runDaemon({0x111f578, 0xc00025fa00}, 0xc0000380b0)
	/srv/internal/app/cmd/daemon.go:68 +0x23f
code.forgejo.org/forgejo/runner/v11/internal/app/cmd.Execute.getRunDaemonCommandProcessor.func6(0xc000044d00?, {0xc0000c4360?, 0x4?, 0xf63e10?})
	/srv/internal/app/cmd/daemon.go:33 +0x1f
github.com/spf13/cobra.(*Command).execute(0xc0000fe908, {0xc0000c4340, 0x2, 0x2})
	/go/pkg/mod/github.com/spf13/cobra@v1.10.1/command.go:1015 +0xaaa
github.com/spf13/cobra.(*Command).ExecuteC(0xc0000fe008)
	/go/pkg/mod/github.com/spf13/cobra@v1.10.1/command.go:1148 +0x46f
github.com/spf13/cobra.(*Command).Execute(...)
	/go/pkg/mod/github.com/spf13/cobra@v1.10.1/command.go:1071
code.forgejo.org/forgejo/runner/v11/internal/app/cmd.Execute({0x111f578, 0xc00025fa00})
	/srv/internal/app/cmd/cmd.go:89 +0xa05
main.main()
	/srv/main.go:18 +0x7b
20250910 05:41:10 daemon: client (pid 4264) exited with 2 status, exiting
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/972
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-10 16:06:48 +00:00
Renovate Bot
4d98bda282
Update https://data.forgejo.org/actions/setup-forgejo action to v3.0.3 (#969)
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.2` -> `v3.0.3` |

---

### Release Notes

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

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

[Compare Source](https://code.forgejo.org/actions/setup-forgejo/compare/v3.0.2...v3.0.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:eyJjcmVhdGVkSW5WZXIiOiI0MS45Ny45IiwidXBkYXRlZEluVmVyIjoiNDEuOTcuOSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9EZXBlbmRlbmN5VXBkYXRlIiwicnVuLWVuZC10by1lbmQtdGVzdHMiXX0=-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/969
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-10 09:18:53 +00:00
Renovate Bot
7f75f52aaf
Update forgejo-runner to v11 (major) (#975)
This PR contains the following updates:

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

---

### Release Notes

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

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

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

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

Release Notes

The breaking change in this release is not technical, it is the change of the license which is now GPLv3-or-later.

- [PR](https://code.forgejo.org/forgejo/runner/pulls/773): <!--number 773 --><!--line 0 --><!--description Y2hvcmU6IGNoYW5nZSB0aGUgbGljZW5zZSB0byBHUEx2My1vci1sYXRlcg==-->chore: change the license to GPLv3-or-later<!--description-->

***

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

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

- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/935): <!--number 935 --><!--line 0 --><!--description Zml4OiBzaHV0ZG93biB0aGUgcnVubmVyIHdoZW4gIHRoZSBjYWNoZSBmYWlscyB3aXRoIGEgbm9uIHJlY292ZXJhYmxlIGVycm9y-->fix: shutdown the runner when  the cache fails with a non recoverable error<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/948): <!--number 948 --><!--line 0 --><!--description Zml4OiBhbHNvIGNhc2NhZGUgaWYgcnVuLSotdGVzdCBpcyBzZXQgd2hlbiB0aGUgUFIgaXMgb3Blbg==-->fix: also cascade if run-\*-test is set when the PR is open<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/946): <!--number 946 --><!--line 0 --><!--description Zml4OiBncmFjZWZ1bCBzaHV0ZG93biBvZiB0YXNrcyBiZWluZyBpbnRlcnJ1cHRlZCBieSBzaWduYWw=-->fix: graceful shutdown of tasks being interrupted by signal<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/943): <!--number 943 --><!--line 0 --><!--description Zml4OiBseGMtc3lzdGVtZCBleGFtcGxlOiBleHBvcnQgSU5QVVRTX1NFUklBTA==-->fix: lxc-systemd example: export INPUTS\_SERIAL<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/941): <!--number 941 --><!--line 0 --><!--description Zml4OiBhbGxvdyBpbnB1dHMgY29udGV4dCBpbiBhY3Rpb24gZGVmYXVsdHM=-->fix: allow inputs context in action defaults<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/931): <!--number 931 --><!--line 0 --><!--description Zml4OiBhbiBleHByZXNzaW9uIGluIHdpdGg6IGZvciBhIHJldXNhYmxlIHdvcmtmbG93IGNhbGwgY2FuIHVzZSBlbnY=-->fix: an expression in with: for a reusable workflow call can use env<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/951): <!--number 951 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvdGltZSB0byB2MC4xMy4w-->Update module golang.org/x/time to v0.13.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/950): <!--number 950 --><!--line 0 --><!--description UmV2ZXJ0ICJmaXg6IGFsc28gY2FzY2FkZSBpZiBydW4tKi10ZXN0IGlzIHNldCB3aGVuIHRoZSBQUiBpcyBvcGVuICgjOTQ4KSI=-->Revert "fix: also cascade if run-\*-test is set when the PR is open ([#&#8203;948](https://github.com/forgejo/runner/issues/948))"<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/945): <!--number 945 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9mb3JnZWpvIERvY2tlciB0YWcgdG8gdjExLjAuNQ==-->Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.5<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/942): <!--number 942 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2RvY2tlci9kb2NrZXIgdG8gdjI4LjQuMCtpbmNvbXBhdGlibGU=-->Update module github.com/docker/docker to v28.4.0+incompatible<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/773): <!--number 773 --><!--line 0 --><!--description Y2hvcmU6IGNoYW5nZSB0aGUgbGljZW5zZSB0byBHUEx2My1vci1sYXRlcg==-->chore: change the license to GPLv3-or-later<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/940): <!--number 940 --><!--line 0 --><!--description Y2hvcmU6IGJ1bXAgdmVyc2lvbiB0byB2MTE=-->chore: bump version to v11<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/936): <!--number 936 --><!--line 0 --><!--description cmVmYWN0b3I6IHJlbW92ZSBkdXBsaWNhdGUgY29tcHV0ZU1hYyBmdW5jdGlvbg==-->refactor: remove duplicate computeMac function<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/938): <!--number 938 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2RvY2tlci9jbGkgdG8gdjI4LjQuMCtpbmNvbXBhdGlibGU=-->Update module github.com/docker/cli to v28.4.0+incompatible<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/934): <!--number 934 --><!--line 0 --><!--description Y2hvcmU6IHJlZmFjdG9yIGFjdC9hcnRpZmFjdGNhY2hlIEhhbmRsZXIgdG8gYW4gaW50ZXJmYWNl-->chore: refactor act/artifactcache Handler to an interface<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/933): <!--number 933 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjQuNw==-->Update dependency go to v1.24.7<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/932): <!--number 932 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NwZjEzL3BmbGFnIHRvIHYxLjAuMTA=-->Update module github.com/spf13/pflag to v1.0.10<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/930): <!--number 930 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NwZjEzL2NvYnJhIHRvIHYxLjEwLjE=-->Update module github.com/spf13/cobra to v1.10.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/928): <!--number 928 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9ydW5uZXIgdG8gdjEw-->Update dependency forgejo/runner to v10<!--description-->

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

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v10.0.0...v10.0.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/927): <!--number 927 --><!--line 0 --><!--description Zml4OiBwdWxsX3JlcXVlc3RfdGFyZ2V0IGV2ZW50cyBjYW4gc2hhcmUgdGhlIGNhY2hlIG9mIHRoZSByZXBvc2l0b3J5-->fix: pull\_request\_target events can share the cache of the repository<!--description-->

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

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v9.1.1...v10.0.0)

> **Warning** Upgrade to v10.0.1 instead. A regression was found on `pull_request_target` events and is fixed in the [v10.0.1 release](https://code.forgejo.org/forgejo/runner/releases/tag/v10.0.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

- [PR](https://code.forgejo.org/forgejo/runner/pulls/925): <!--number 925 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogcHJldmVudCBvbjogcHVsbF9yZXF1ZXN0IGFjdGlvbnMgZnJvbSBtdXRhdGluZyBjYWNoZXMgb2Ygb3RoZXIgd29ya2Zsb3cgZXZlbnRz-->fix(security): prevent on: pull\_request actions from mutating caches of other workflow events<!--description-->
  forgej-runner currently creates a safer execution environment for workflows triggered by pull requests by denying those workflows access to the repository's secrets, preventing pull requests from compromising the confidentiality of the secrets.

  Workflows do have access to write to the action cache, which is shared with future workflow executions, including executions that may have access to repository secrets.  This was assumed safe as the cache is a "write-once" operation based upon the cache key; if an execution writes to that cache, it will be read by other workflows only if a matching key parameter is provided, and it can not be modified again.  These assumptions were identified as weak security practices with known workarounds.

  It is possible for a malicious pull request to mutate the shared cache and embed untrusted artifacts, which may later be executed in workflow executions with access to secrets, risking the confidentiality of those secrets.

  In order to eliminate this risk, workflows executing with the `pull_request` and `pull_request_target` events have their write operations to the cache isolated to future workflow executions from the same pull request.  They can continue to read from the shared cache if applicable.

  If using an external cache server configuration, both the cache server and other instances of the runner must be running the same software version.  The recommended upgrade procedure in this configuration is to bring all runners offline, upgrade the cache server to the latest release and bring it online, and then bring all other runners online.
- [PR](https://code.forgejo.org/forgejo/runner/pulls/924): <!--number 924 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogZW5zdXJlIHVuaXF1ZSBuYW1lcyBmb3IgY29udGFpbmVyIGltYWdlcyBjcmVhdGVkIGJ5IGFjdGlvbnM=-->fix(security): ensure unique names for container images created by actions<!--description-->
  Without this fix, when a workflow ran a local [docker action](https://forgejo.org/docs/next/user/actions/actions/#docker-actions) (e.g. the [example in the end-to-end tests](8f920b4b7a/actions/example-force-rebuild/.forgejo/workflows/test.yml)), it used an image tag that could collide with other workflows that happen to use the same name. The workaround for older runner versions is to set [`[container].force_rebuild: true`](https://forgejo.org/docs/next/admin/actions/runner-installation/#configuration) in the runner configuration file.

***

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

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

- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/925): <!--number 925 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogcHJldmVudCBvbjogcHVsbF9yZXF1ZXN0IGFjdGlvbnMgZnJvbSBtdXRhdGluZyBjYWNoZXMgb2Ygb3RoZXIgd29ya2Zsb3cgZXZlbnRz-->fix(security): prevent on: pull\_request actions from mutating caches of other workflow events<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/924): <!--number 924 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogZW5zdXJlIHVuaXF1ZSBuYW1lcyBmb3IgY29udGFpbmVyIGltYWdlcyBjcmVhdGVkIGJ5IGFjdGlvbnM=-->fix(security): ensure unique names for container images created by actions<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/921): <!--number 921 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9mb3JnZWpvIERvY2tlciB0YWcgdG8gdjExLjAuNA==-->Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.4<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/922): <!--number 922 --><!--line 0 --><!--description Y2hvcmU6IGV4cGxhaW4gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBgam9iX2xldmVsYCBhbmQgYGxldmVsYA==-->chore: explain the difference between `job_level` and `level`<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/917): <!--number 917 --><!--line 0 --><!--description Y2hvcmU6IGFkZCByZW1pbmRlciBvZiBob3cgdG8gcnVuIGEgbG9jYWwgdGVzdA==-->chore: add reminder of how to run a local test<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/919): <!--number 919 --><!--line 0 --><!--description Y2hvcmU6IHVuaWZ5IGNhc2NhZGUtc2V0dXAtZm9yZ2VqbyB3aXRoIGNhc2NhZGUtZm9yZ2Vqbw==-->chore: unify cascade-setup-forgejo with cascade-forgejo<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/873): <!--number 873 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSBgZ2l0aHViLmNvbS9wa2cvZXJyb3JzYA==-->chore: remove `github.com/pkg/errors`<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/915): <!--number 915 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3N0cmV0Y2hyL3Rlc3RpZnkgdG8gdjEuMTEuMQ==-->Update module github.com/stretchr/testify to v1.11.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/914): <!--number 914 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1ZiB0byB2MS4zNi44-->Update module google.golang.org/protobuf to v1.36.8<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/907): <!--number 907 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnby5ldGNkLmlvL2Jib2x0IHRvIHYxLjQuMw==-->Update module go.etcd.io/bbolt to v1.4.3<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/906): <!--number 906 --><!--line 0 --><!--description dGVzdDogcmVtb3ZlIGludGVybmFsIHRpbWVvdXQgaW4gVGVzdFJ1bm5lckNhY2hlQ29uZmlndXJhdGlvbg==-->test: remove internal timeout in TestRunnerCacheConfiguration<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/902): <!--number 902 --><!--line 0 --><!--description Y2hvcmU6IHNraXAgdGVzdHMgdGhhdCByZXF1aXJlIEZvcmdlam8gaWYgaXQgaXMgbm90IGF2YWlsYWJsZQ==-->chore: skip tests that require Forgejo if it is not available<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/903): <!--number 903 --><!--line 0 --><!--description Y2hvcmU6IHJld29yayB0aGUgUkVBRE1F-->chore: rework the README<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/904): <!--number 904 --><!--line 0 --><!--description VXBkYXRlIGdpdGh1Yi5jb20vZ28tdmlwZXIvbWFwc3RydWN0dXJlL3YyIChpbmRpcmVjdCkgdG8gdjIuNC4wIFtTRUNVUklUWV0=-->Update github.com/go-viper/mapstructure/v2 (indirect) to v2.4.0 \[SECURITY]<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/900): <!--number 900 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSBUZXN0UnVuQ29udGV4dF9HZXRHaXRIdWJDb250ZXh0-->chore: remove TestRunContext\_GetGitHubContext<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/899): <!--number 899 --><!--line 0 --><!--description Y2hvcmU6IGRvIG5vdCBmb3JjZSBHT1BST1hZ-->chore: do not force GOPROXY<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/890): <!--number 890 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3Zla3RyYS9tb2NrZXJ5L3YyIHRvIHYyLjUzLjU=-->Update module github.com/vektra/mockery/v2 to v2.53.5<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/893): <!--number 893 --><!--line 0 --><!--description Y2hvcmU6IGZpeCAuUEhPTlkgbGludCB0YXJnZXRz-->chore: fix .PHONY lint targets<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/898): <!--number 898 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9ydW5uZXIgdG8gdjkuMS4x-->Update dependency forgejo/runner to v9.1.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/897): <!--number 897 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9ydW5uZXIgRG9ja2VyIHRhZyB0byB2OS4xLjE=-->Update code.forgejo.org/forgejo/runner Docker tag to v9.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:eyJjcmVhdGVkSW5WZXIiOiI0MS45Ny45IiwidXBkYXRlZEluVmVyIjoiNDEuOTcuOSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9EZXBlbmRlbmN5VXBkYXRlIiwicnVuLWVuZC10by1lbmQtdGVzdHMiXX0=-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/975
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-10 09:18:50 +00:00
Michael Kriese
106c50a51d
chore(renovate): group runner updates 2025-09-10 09:51:22 +02:00
Michael Kriese
86653c237d
ci: update forgejo version for release integration (#973)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/973): <!--number 973 --><!--line 0 --><!--description Y2k6IHVwZGF0ZSBmb3JnZWpvIHZlcnNpb24gZm9yIHJlbGVhc2UgaW50ZWdyYXRpb24=-->ci: update forgejo version for release integration<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/973
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-committed-by: Michael Kriese <michael.kriese@visualon.de>
2025-09-10 07:22:16 +00:00
Earl Warren
9a62046607
chore: lxc-systemd may need more time to start on slow machines (#970)
This false negative happened in the past 24h at

https://code.forgejo.org/forgejo/runner/actions/runs/9581/jobs/0

and was resolved by just running it again.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/970
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-10 07:18:40 +00:00
Renovate Bot
6a6a41bf05
Update module golang.org/x/term to v0.35.0 (#966)
This PR contains the following updates:

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

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/966
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-09 08:52:15 +00:00
Earl Warren
151c90b2a9
chore: call the release notes assistant when opening a new pull request (#964)
When a new pull request is opened and has no labels, the release notes
assistant will not be called and it will look like the event was
missed.

Most of the time the label will be set when the pull request is open
and that will fire two runs. However, the release notes assistant is
idempotent and that will just make one extra run in the CI that is a
noop.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [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-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/964
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-09 05:23:55 +00:00
jankatins
02df78a9ec
fix: Allow the runner to keep it's labels (#965)
I had the case that an already registered runner was losing it's labels due to a race condition (I think): the compose file was restarted, the runner came up but 10 seconds later, the labels were reset:

>If the command is run without --labels, they will be reset, and the runner won’t set them back until it is restarted. The --keep-labels option can be used to preserve the existing labels.

I always started all services in the compose file at once, so I never got the idea to restart the runner alone and the runner logs actually always said that the labels where there:

> ... with labels: [docker-cli node-bookworm], declared successfully

Signed-off-by: jankatins <jankatins@noreply.code.forgejo.org>

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/965): <!--number 965 --><!--line 0 --><!--description Zml4OiBBbGxvdyB0aGUgcnVubmVyIHRvIGtlZXAgaXQncyBsYWJlbHM=-->fix: Allow the runner to keep it's labels<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/965
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: jankatins <jankatins@noreply.code.forgejo.org>
Co-committed-by: jankatins <jankatins@noreply.code.forgejo.org>
2025-09-08 21:27:43 +00:00
Earl Warren
864fce89d2
chore: debug release-notes-assistant workflow 2025-09-08 11:14:42 +02:00
Earl Warren
149a9e3cf5
chore: skip release-notes-assistant for dependency updates (#954)
Resolves forgejo/runner#953

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [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-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/954
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-08 08:41:21 +00:00
Renovate Bot
a2622dbe3d
Update module golang.org/x/time to v0.13.0 (#951)
This PR contains the following updates:

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

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/951): <!--number 951 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvdGltZSB0byB2MC4xMy4w-->Update module golang.org/x/time to v0.13.0<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/951
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-08 05:00:28 +00:00
Earl Warren
ad90bb4b68
Revert "fix: also cascade if run-*-test is set when the PR is open (#948)" (#950)
This reverts commit 1178cf6d24.

This was an incorrect fix to a different problem. The `labeled` event is run when a pull request is opened. Adding an `opened` event will just needlessly duplicate the runs.

The actual problem was me assuming too quickly that a short runtime (15s) indicated that the cascade was not run.

This is what happened at https://code.forgejo.org/forgejo/runner/pulls/935

- the cascade is run https://code.forgejo.org/forgejo/runner/pulls/935#issuecomment-57986
- the duration is very short because the commit status is set [by the last event (closed)](https://code.forgejo.org/forgejo/runner/actions/runs/9344/jobs/0#jobstep-1-12)
  ![image](/attachments/2aecc2f6-8fc0-4778-91c3-de689808a30e)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/950): <!--number 950 --><!--line 0 --><!--description UmV2ZXJ0ICJmaXg6IGFsc28gY2FzY2FkZSBpZiBydW4tKi10ZXN0IGlzIHNldCB3aGVuIHRoZSBQUiBpcyBvcGVuICgjOTQ4KSI=-->Revert "fix: also cascade if run-*-test is set when the PR is open (#948)"<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/950
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-08 00:14:44 +00:00
earl-warren
16cb2d5b75
fix: graceful shutdown of tasks being interrupted by signal (#946)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/946
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
2025-09-07 22:45:15 +00:00
Earl Warren
1178cf6d24
fix: also cascade if run-*-test is set when the PR is open (#948)
Testing

- after merge
- open a pull request with the tags run-end-to-end-test and run-forgejo-test set
- verify both workflow run instead of being skipped

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/948): <!--number 948 --><!--line 0 --><!--description Zml4OiBhbHNvIGNhc2NhZGUgaWYgcnVuLSotdGVzdCBpcyBzZXQgd2hlbiB0aGUgUFIgaXMgb3Blbg==-->fix: also cascade if run-*-test is set when the PR is open<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/948
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-07 21:25:13 +00:00
Mathieu Fenniak
458ca52101 test: add TestRunDaemonGracefulShutdown 2025-09-07 14:00:55 -06:00
Mathieu Fenniak
bfa86327ce test: add mocks for RunnerInterface & Poller 2025-09-07 13:52:47 -06:00
Mathieu Fenniak
82cbe791dc refactor: split runDaemon into testable lambdas 2025-09-07 13:51:58 -06:00
earl-warren
09adcc47d2
fix: shutdown the runner when the cache fails with a non recoverable error (#935)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/935
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2025-09-07 16:03:31 +00:00
Renovate Bot
441f142089
Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.5 (#945)
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.4` -> `11.0.5` |

---

### Release Notes

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

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

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

See <https://codeberg.org/forgejo/forgejo/src/branch/forgejo/release-notes-published/11.0.5.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:eyJjcmVhdGVkSW5WZXIiOiI0MS45MS4yIiwidXBkYXRlZEluVmVyIjoiNDEuOTEuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSIsInJ1bi1lbmQtdG8tZW5kLXRlc3RzIl19-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/945): <!--number 945 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9mb3JnZWpvIERvY2tlciB0YWcgdG8gdjExLjAuNQ==-->Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.5<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/945
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-07 07:48:49 +00:00
Mathieu Fenniak
b2865e5a2d fix: graceful shutdown of tasks being interrupted by signal 2025-09-06 19:09:25 -06:00
Earl Warren
e6a61d940d
fix: lxc-systemd example: export INPUTS_SERIAL (#943)
otherwise it will not be set when copy/pasting the following commands

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/943): <!--number 943 --><!--line 0 --><!--description Zml4OiBseGMtc3lzdGVtZCBleGFtcGxlOiBleHBvcnQgSU5QVVRTX1NFUklBTA==-->fix: lxc-systemd example: export INPUTS_SERIAL<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/943
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-06 17:19:13 +00:00
Renovate Bot
26fda6e084
Update module github.com/docker/docker to v28.4.0+incompatible (#942)
This PR contains the following updates:

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

---

### Release Notes

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

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

[Compare Source](https://github.com/docker/docker/compare/v28.3.3...v28.4.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:eyJjcmVhdGVkSW5WZXIiOiI0MS45MS4yIiwidXBkYXRlZEluVmVyIjoiNDEuOTEuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSIsInJ1bi1lbmQtdG8tZW5kLXRlc3RzIl19-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/942): <!--number 942 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2RvY2tlci9kb2NrZXIgdG8gdjI4LjQuMCtpbmNvbXBhdGlibGU=-->Update module github.com/docker/docker to v28.4.0+incompatible<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/942
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-06 05:52:41 +00:00
Earl Warren
4beb514232
fix: allow inputs context in action defaults (#941)
Resolves forgejo/runner#939

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/941): <!--number 941 --><!--line 0 --><!--description Zml4OiBhbGxvdyBpbnB1dHMgY29udGV4dCBpbiBhY3Rpb24gZGVmYXVsdHM=-->fix: allow inputs context in action defaults<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/941
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-05 22:14:52 +00:00
Earl Warren
c7e2db2559
chore: cache: handler: test coverage for fatal errors 2025-09-05 17:30:08 +02:00
Earl Warren
5f0b036e34
chore: cache: move findCacheWithIsolationKeyFallback out of handler.find 2025-09-05 17:30:08 +02:00
Earl Warren
c48accfb51
chore: cache: generate mocks for act/artifactcache/caches.go 2025-09-05 17:30:08 +02:00
Earl Warren
c28a98082b
chore: cache: move repo != cache.Repo in readCache
- it only is used after calling readCache
- add unit test

it reduces the number of testcase to be considered in handler
2025-09-05 17:30:08 +02:00
Earl Warren
6c4e705f97
chore: cache: split caches implementation out of handler
- create the caches interface and matching cachesImpl
- move the cache logic out of handler
  - openDB
  - readCache
  - useCache
  - gcCache
  - access to the storage struct
    - serve
    - commit
    - exist
    - write
- add getCaches / setCaches to the handler interface so it can be
  used by tests. The caches test should be implemented independently
  in the future but this is a different kind of cleanup.
- no functional change, minimal refactor
2025-09-05 17:30:08 +02:00
Earl Warren
37f634fd31
fix: cache: call fatal() on errors that are not recoverable
- responseFatalJSON(w, r, err) replaces responseJSON(w, r, 500, err)
  and calls fatal() when the following fail because they are
  not recoverable. There may be other non-recoverable errors but
  it is difficult to be 100% sure they cannot be engineered by the
  caller of the API for DoS purposes.
  - openDB
  - findCache
  - cache.Repo != repo
- wrap errors in
  - openDB() - it was missing
  - readCache() - it was missing
  - useCache() - it was missing
  - findCache() - some had identical messages
- in gc
  - replace logger.Warnf with h.fatal
  - differentiate errors that have identical messages
  - call fatal if openDB fails instead of returning
2025-09-05 17:29:04 +02:00
Earl Warren
36ca627f2e
feat: cache: fatal() helper to gracefully terminate the runner
in case of an error that is not recoverable (e.g. failing to open the
bolthold database), the cache can call fatal() to log the error and
send a TERM signal that will gracefully shutdown the daemon.
2025-09-05 17:26:12 +02:00
Earl Warren
98552f9b99
feat: cache-server: shutdown on TERM
in the same way the daemon can be shutdown by either INT or TERM
the cache server could only be shutdown with INT
2025-09-05 17:25:51 +02:00
Earl Warren
39dd708768
chore: cosmetic fixes 2025-09-05 13:22:59 +02:00
Earl Warren
8a7f760d3c
chore: bump version to v11 (#940)
the license change from MIT to GPLv3+ is a breaking change

Refs forgejo/runner#773

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/940): <!--number 940 --><!--line 0 --><!--description Y2hvcmU6IGJ1bXAgdmVyc2lvbiB0byB2MTE=-->chore: bump version to v11<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/940
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-05 07:29:38 +00:00
Mathieu Fenniak
a3aedba3f1
refactor: remove duplicate computeMac function (#936)
It was raised during embargo review of #925 that there are two implementations of `computeMac`; this PR fixes that.

As all the tests for `computeMac` were in the `artifactcache` package, it made more sense to keep the method there.  That required reversing the dependency `artifactcache->cacheproxy` package dependency -- it makes more sense to me for the proxy to depend on the cache, rather than vice-versa.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/936): <!--number 936 --><!--line 0 --><!--description cmVmYWN0b3I6IHJlbW92ZSBkdXBsaWNhdGUgY29tcHV0ZU1hYyBmdW5jdGlvbg==-->refactor: remove duplicate computeMac function<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/936
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-09-05 06:01:49 +00:00
Renovate Bot
35f93b6b11
Update module github.com/docker/cli to v28.4.0+incompatible (#938)
This PR contains the following updates:

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

---

### Release Notes

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

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

[Compare Source](https://github.com/docker/cli/compare/v28.3.3...v28.4.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:eyJjcmVhdGVkSW5WZXIiOiI0MS45MS4yIiwidXBkYXRlZEluVmVyIjoiNDEuOTEuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSIsInJ1bi1lbmQtdG8tZW5kLXRlc3RzIl19-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/938): <!--number 938 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2RvY2tlci9jbGkgdG8gdjI4LjQuMCtpbmNvbXBhdGlibGU=-->Update module github.com/docker/cli to v28.4.0+incompatible<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/938
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-05 05:09:07 +00:00
Earl Warren
69c6c70845
chore: refactor act/artifactcache Handler to an interface (#934)
- the Handler struct becomes handler (lowercase)
- the Handler interface is defined to be the existing methods
- isClosed() is added and used only in tests
- setgcAt() is added and used only in tests

---

This is to allow mocking the Handler interface for testing.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/934): <!--number 934 --><!--line 0 --><!--description Y2hvcmU6IHJlZmFjdG9yIGFjdC9hcnRpZmFjdGNhY2hlIEhhbmRsZXIgdG8gYW4gaW50ZXJmYWNl-->chore: refactor act/artifactcache Handler to an interface<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/934
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-04 14:38:50 +00:00
Earl Warren
bfc5516467
chore: change the license to GPLv3-or-later (#773)
The Forgejo runner is part of the Forgejo project. The licensing
agreement in the governance repository reads like this:

> Forgejo accepts contributions compatible with the GPLv3-or-later license.
> The license under which Forgejo is distributed will be changed upon the acceptance of such contributions.

The first step is to update the LICENSE file to reflect that
decision. The individual copyright notice of each source file will be
updated when and if relevant. If a change is made that is eligible for
copyright, the author may decide change the copyright notice from MIT
or Apache 2 to GPLv3-or-later.

Refs licensing agreement 6eb522282f/AGREEMENTS.md (licensing)
Refs blog post about the licensing agreement https://forgejo.org/2024-08-gpl/

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/773): <!--number 773 --><!--line 0 --><!--description Y2hvcmU6IGNoYW5nZSB0aGUgbGljZW5zZSB0byBHUEx2My1vci1sYXRlcg==-->chore: change the license to GPLv3-or-later<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/773
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Reviewed-by: Beowulf <beowulf@noreply.code.forgejo.org>
Reviewed-by: pat-s <pat-s@noreply.code.forgejo.org>
Reviewed-by: fnetX <fnetx@noreply.code.forgejo.org>
Reviewed-by: 0ko <0ko@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-04 09:26:12 +00:00
Renovate Bot
54591f946a
Update dependency go to v1.24.7 (#933)
This PR contains the following updates:

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

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS45MS4yIiwidXBkYXRlZEluVmVyIjoiNDEuOTEuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSIsInJ1bi1lbmQtdG8tZW5kLXRlc3RzIl19-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/933): <!--number 933 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjQuNw==-->Update dependency go to v1.24.7<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/933
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-04 06:16:31 +00:00
Renovate Bot
d09e688738
Update module github.com/spf13/pflag to v1.0.10 (#932)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/spf13/pflag](https://github.com/spf13/pflag) | `v1.0.9` -> `v1.0.10` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fspf13%2fpflag/v1.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fspf13%2fpflag/v1.0.9/v1.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>spf13/pflag (github.com/spf13/pflag)</summary>

### [`v1.0.10`](https://github.com/spf13/pflag/releases/tag/v1.0.10)

[Compare Source](https://github.com/spf13/pflag/compare/v1.0.9...v1.0.10)

#### What's Changed

- fix deprecation comment for (FlagSet.)ParseErrorsWhitelist by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;447](https://github.com/spf13/pflag/pull/447)
- remove uses of errors.Is, which requires go1.13, move go1.16/go1.21 tests to separate file by [@&#8203;thaJeztah](https://github.com/thaJeztah) in [#&#8203;448](https://github.com/spf13/pflag/pull/448)

#### New Contributors

- [@&#8203;thaJeztah](https://github.com/thaJeztah) made their first contribution in [#&#8203;447](https://github.com/spf13/pflag/pull/447)

**Full Changelog**: <https://github.com/spf13/pflag/compare/v1.0.9...v1.0.10>

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

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/932): <!--number 932 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NwZjEzL3BmbGFnIHRvIHYxLjAuMTA=-->Update module github.com/spf13/pflag to v1.0.10<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/932
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-03 05:52:27 +00:00
Earl Warren
aa428e375c
fix: an expression in with: for a reusable workflow call can use env (#931)
Resolves forgejo/runner#929

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/931): <!--number 931 --><!--line 0 --><!--description Zml4OiBhbiBleHByZXNzaW9uIGluIHdpdGg6IGZvciBhIHJldXNhYmxlIHdvcmtmbG93IGNhbGwgY2FuIHVzZSBlbnY=-->fix: an expression in with: for a reusable workflow call can use env<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/931
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-01 22:09:43 +00:00
Renovate Bot
323554256c
Update module github.com/spf13/cobra to v1.10.1 (#930)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/spf13/cobra](https://github.com/spf13/cobra) | `v1.9.1` -> `v1.10.1` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fspf13%2fcobra/v1.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fspf13%2fcobra/v1.9.1/v1.10.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>spf13/cobra (github.com/spf13/cobra)</summary>

### [`v1.10.1`](https://github.com/spf13/cobra/releases/tag/v1.10.1)

[Compare Source](https://github.com/spf13/cobra/compare/v1.10.0...v1.10.1)

##### 🐛 Fix

- chore: upgrade pflags v1.0.9 by [@&#8203;jpmcb](https://github.com/jpmcb) in [#&#8203;2305](https://github.com/spf13/cobra/pull/2305)

v1.0.9 of pflags brought back `ParseErrorsWhitelist` and marked it as deprecated

**Full Changelog**: <https://github.com/spf13/cobra/compare/v1.10.0...v1.10.1>

### [`v1.10.0`](https://github.com/spf13/cobra/releases/tag/v1.10.0)

[Compare Source](https://github.com/spf13/cobra/compare/v1.9.1...v1.10.0)

#### What's Changed

##### 🚨 Attention!

- Bump pflag to 1.0.8 by [@&#8203;tomasaschan](https://github.com/tomasaschan) in [#&#8203;2303](https://github.com/spf13/cobra/pull/2303)

This version of `pflag` carried a breaking change: it renamed `ParseErrorsWhitelist` to `ParseErrorsAllowlist` which can break builds if both `pflag` and `cobra` are dependencies in your project.

- If you use both `pflag and `cobra`, upgrade `pflag`to 1.0.8 and`cobra`to`1.10.0\`
- ***or*** use the newer, fixed version of `pflag` v1.0.9 which keeps the deprecated `ParseErrorsWhitelist`

More details can be found here: [#&#8203;2303 (comment)](https://github.com/spf13/cobra/pull/2303#issuecomment-3242333515)

#####  Features

- Flow context to command in SetHelpFunc by [@&#8203;Frassle](https://github.com/Frassle) in [#&#8203;2241](https://github.com/spf13/cobra/pull/2241)
- The default ShellCompDirective can be customized for a command and its subcommands by [@&#8203;albers](https://github.com/albers) in [#&#8203;2238](https://github.com/spf13/cobra/pull/2238)

##### 🐛 Fix

- Upgrade golangci-lint to v2, address findings by [@&#8203;scop](https://github.com/scop) in [#&#8203;2279](https://github.com/spf13/cobra/pull/2279)

##### 🪠 Testing

- Test with Go 1.24 by [@&#8203;harryzcy](https://github.com/harryzcy) in [#&#8203;2236](https://github.com/spf13/cobra/pull/2236)
- chore: Rm GitHub Action PR size labeler by [@&#8203;jpmcb](https://github.com/jpmcb) in [#&#8203;2256](https://github.com/spf13/cobra/pull/2256)

##### 📝 Docs

- Remove traling curlybrace by [@&#8203;yedayak](https://github.com/yedayak) in [#&#8203;2237](https://github.com/spf13/cobra/pull/2237)
- Update command.go by [@&#8203;styee](https://github.com/styee) in [#&#8203;2248](https://github.com/spf13/cobra/pull/2248)
- feat: Add security policy by [@&#8203;jpmcb](https://github.com/jpmcb) in [#&#8203;2253](https://github.com/spf13/cobra/pull/2253)
- Update Readme (Warp) by [@&#8203;ericdachen](https://github.com/ericdachen) in [#&#8203;2267](https://github.com/spf13/cobra/pull/2267)
- Add Periscope to the list of projects using Cobra by [@&#8203;anishathalye](https://github.com/anishathalye) in [#&#8203;2299](https://github.com/spf13/cobra/pull/2299)

#### New Contributors

- [@&#8203;harryzcy](https://github.com/harryzcy) made their first contribution in [#&#8203;2236](https://github.com/spf13/cobra/pull/2236)
- [@&#8203;yedayak](https://github.com/yedayak) made their first contribution in [#&#8203;2237](https://github.com/spf13/cobra/pull/2237)
- [@&#8203;Frassle](https://github.com/Frassle) made their first contribution in [#&#8203;2241](https://github.com/spf13/cobra/pull/2241)
- [@&#8203;styee](https://github.com/styee) made their first contribution in [#&#8203;2248](https://github.com/spf13/cobra/pull/2248)
- [@&#8203;ericdachen](https://github.com/ericdachen) made their first contribution in [#&#8203;2267](https://github.com/spf13/cobra/pull/2267)
- [@&#8203;albers](https://github.com/albers) made their first contribution in [#&#8203;2238](https://github.com/spf13/cobra/pull/2238)
- [@&#8203;anishathalye](https://github.com/anishathalye) made their first contribution in [#&#8203;2299](https://github.com/spf13/cobra/pull/2299)
- [@&#8203;tomasaschan](https://github.com/tomasaschan) made their first contribution in [#&#8203;2303](https://github.com/spf13/cobra/pull/2303)

**Full Changelog**: <https://github.com/spf13/cobra/compare/v1.9.1...v1.9.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:eyJjcmVhdGVkSW5WZXIiOiI0MS45MS4yIiwidXBkYXRlZEluVmVyIjoiNDEuOTEuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSIsInJ1bi1lbmQtdG8tZW5kLXRlc3RzIl19-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/930): <!--number 930 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NwZjEzL2NvYnJhIHRvIHYxLjEwLjE=-->Update module github.com/spf13/cobra to v1.10.1<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/930
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-01 19:42:17 +00:00
Renovate Bot
877749a730
Update dependency forgejo/runner to v10 (#928)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [forgejo/runner](https://code.forgejo.org/forgejo/runner) | major | `9.1.1` -> `10.0.1` |

---

### Release Notes

<details>
<summary>forgejo/runner (forgejo/runner)</summary>

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v10.0.0...v10.0.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

***

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v9.1.1...v10.0.0)

> **Warning** Upgrade to v10.0.1 instead. A regression was found on `pull_request_target` events and is fixed in the [v10.0.1 release](https://code.forgejo.org/forgejo/runner/releases/tag/v10.0.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

- [PR](https://code.forgejo.org/forgejo/runner/pulls/925): <!--number 925 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogcHJldmVudCBvbjogcHVsbF9yZXF1ZXN0IGFjdGlvbnMgZnJvbSBtdXRhdGluZyBjYWNoZXMgb2Ygb3RoZXIgd29ya2Zsb3cgZXZlbnRz-->fix(security): prevent on: pull\_request actions from mutating caches of other workflow events<!--description-->
  forgej-runner currently creates a safer execution environment for workflows triggered by pull requests by denying those workflows access to the repository's secrets, preventing pull requests from compromising the confidentiality of the secrets.

  Workflows do have access to write to the action cache, which is shared with future workflow executions, including executions that may have access to repository secrets.  This was assumed safe as the cache is a "write-once" operation based upon the cache key; if an execution writes to that cache, it will be read by other workflows only if a matching key parameter is provided, and it can not be modified again.  These assumptions were identified as weak security practices with known workarounds.

  It is possible for a malicious pull request to mutate the shared cache and embed untrusted artifacts, which may later be executed in workflow executions with access to secrets, risking the confidentiality of those secrets.

  In order to eliminate this risk, workflows executing with the `pull_request` and `pull_request_target` events have their write operations to the cache isolated to future workflow executions from the same pull request.  They can continue to read from the shared cache if applicable.

  If using an external cache server configuration, both the cache server and other instances of the runner must be running the same software version.  The recommended upgrade procedure in this configuration is to bring all runners offline, upgrade the cache server to the latest release and bring it online, and then bring all other runners online.
- [PR](https://code.forgejo.org/forgejo/runner/pulls/924): <!--number 924 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogZW5zdXJlIHVuaXF1ZSBuYW1lcyBmb3IgY29udGFpbmVyIGltYWdlcyBjcmVhdGVkIGJ5IGFjdGlvbnM=-->fix(security): ensure unique names for container images created by actions<!--description-->
  Without this fix, when a workflow ran a local [docker action](https://forgejo.org/docs/next/user/actions/actions/#docker-actions) (e.g. the [example in the end-to-end tests](8f920b4b7a/actions/example-force-rebuild/.forgejo/workflows/test.yml)), it used an image tag that could collide with other workflows that happen to use the same name. The workaround for older runner versions is to set [`[container].force_rebuild: true`](https://forgejo.org/docs/next/admin/actions/runner-installation/#configuration) in the runner configuration file.

***

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

- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/925): <!--number 925 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogcHJldmVudCBvbjogcHVsbF9yZXF1ZXN0IGFjdGlvbnMgZnJvbSBtdXRhdGluZyBjYWNoZXMgb2Ygb3RoZXIgd29ya2Zsb3cgZXZlbnRz-->fix(security): prevent on: pull\_request actions from mutating caches of other workflow events<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/924): <!--number 924 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogZW5zdXJlIHVuaXF1ZSBuYW1lcyBmb3IgY29udGFpbmVyIGltYWdlcyBjcmVhdGVkIGJ5IGFjdGlvbnM=-->fix(security): ensure unique names for container images created by actions<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/921): <!--number 921 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9mb3JnZWpvIERvY2tlciB0YWcgdG8gdjExLjAuNA==-->Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.4<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/922): <!--number 922 --><!--line 0 --><!--description Y2hvcmU6IGV4cGxhaW4gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBgam9iX2xldmVsYCBhbmQgYGxldmVsYA==-->chore: explain the difference between `job_level` and `level`<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/917): <!--number 917 --><!--line 0 --><!--description Y2hvcmU6IGFkZCByZW1pbmRlciBvZiBob3cgdG8gcnVuIGEgbG9jYWwgdGVzdA==-->chore: add reminder of how to run a local test<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/919): <!--number 919 --><!--line 0 --><!--description Y2hvcmU6IHVuaWZ5IGNhc2NhZGUtc2V0dXAtZm9yZ2VqbyB3aXRoIGNhc2NhZGUtZm9yZ2Vqbw==-->chore: unify cascade-setup-forgejo with cascade-forgejo<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/873): <!--number 873 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSBgZ2l0aHViLmNvbS9wa2cvZXJyb3JzYA==-->chore: remove `github.com/pkg/errors`<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/915): <!--number 915 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3N0cmV0Y2hyL3Rlc3RpZnkgdG8gdjEuMTEuMQ==-->Update module github.com/stretchr/testify to v1.11.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/914): <!--number 914 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1ZiB0byB2MS4zNi44-->Update module google.golang.org/protobuf to v1.36.8<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/907): <!--number 907 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnby5ldGNkLmlvL2Jib2x0IHRvIHYxLjQuMw==-->Update module go.etcd.io/bbolt to v1.4.3<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/906): <!--number 906 --><!--line 0 --><!--description dGVzdDogcmVtb3ZlIGludGVybmFsIHRpbWVvdXQgaW4gVGVzdFJ1bm5lckNhY2hlQ29uZmlndXJhdGlvbg==-->test: remove internal timeout in TestRunnerCacheConfiguration<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/902): <!--number 902 --><!--line 0 --><!--description Y2hvcmU6IHNraXAgdGVzdHMgdGhhdCByZXF1aXJlIEZvcmdlam8gaWYgaXQgaXMgbm90IGF2YWlsYWJsZQ==-->chore: skip tests that require Forgejo if it is not available<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/903): <!--number 903 --><!--line 0 --><!--description Y2hvcmU6IHJld29yayB0aGUgUkVBRE1F-->chore: rework the README<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/904): <!--number 904 --><!--line 0 --><!--description VXBkYXRlIGdpdGh1Yi5jb20vZ28tdmlwZXIvbWFwc3RydWN0dXJlL3YyIChpbmRpcmVjdCkgdG8gdjIuNC4wIFtTRUNVUklUWV0=-->Update github.com/go-viper/mapstructure/v2 (indirect) to v2.4.0 \[SECURITY]<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/900): <!--number 900 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSBUZXN0UnVuQ29udGV4dF9HZXRHaXRIdWJDb250ZXh0-->chore: remove TestRunContext\_GetGitHubContext<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/899): <!--number 899 --><!--line 0 --><!--description Y2hvcmU6IGRvIG5vdCBmb3JjZSBHT1BST1hZ-->chore: do not force GOPROXY<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/890): <!--number 890 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3Zla3RyYS9tb2NrZXJ5L3YyIHRvIHYyLjUzLjU=-->Update module github.com/vektra/mockery/v2 to v2.53.5<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/893): <!--number 893 --><!--line 0 --><!--description Y2hvcmU6IGZpeCAuUEhPTlkgbGludCB0YXJnZXRz-->chore: fix .PHONY lint targets<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/898): <!--number 898 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9ydW5uZXIgdG8gdjkuMS4x-->Update dependency forgejo/runner to v9.1.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/897): <!--number 897 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9ydW5uZXIgRG9ja2VyIHRhZyB0byB2OS4xLjE=-->Update code.forgejo.org/forgejo/runner Docker tag to v9.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 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:eyJjcmVhdGVkSW5WZXIiOiI0MS45MS4yIiwidXBkYXRlZEluVmVyIjoiNDEuOTEuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSIsInJ1bi1lbmQtdG8tZW5kLXRlc3RzIl19-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/928): <!--number 928 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9ydW5uZXIgdG8gdjEw-->Update dependency forgejo/runner to v10<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/928
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-01 14:24:38 +00:00
Earl Warren
dce6af9d24
fix: pull_request_target events can share the cache of the repository (#927)
This is a regression introduced in v10.0.0 by which a pull_request_target event would fail because it attemps to set an isolation key, as if it was a pull request originating from a fork.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/927): <!--number 927 --><!--line 0 --><!--description Zml4OiBwdWxsX3JlcXVlc3RfdGFyZ2V0IGV2ZW50cyBjYW4gc2hhcmUgdGhlIGNhY2hlIG9mIHRoZSByZXBvc2l0b3J5-->fix: pull_request_target events can share the cache of the repository<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/927
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-09-01 13:39:30 +00:00
earl-warren
57efbac055
fix(security): prevent on: pull_request actions from mutating caches of other workflow events (#925)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/925
2025-09-01 12:24:30 +00:00
earl-warren
77ea273a14
fix(security): ensure unique names for container images created by actions (#924)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/924
2025-09-01 12:23:26 +00:00
Renovate Bot
a334431107
Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.4 (#921)
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.3` -> `11.0.4` |

---

### Release Notes

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

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

[Compare Source](https://codeberg.org/forgejo/forgejo/compare/v11.0.3...v11.0.4)

See <https://codeberg.org/forgejo/forgejo/src/branch/forgejo/release-notes-published/11.0.4.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:eyJjcmVhdGVkSW5WZXIiOiI0MS44Mi4xMCIsInVwZGF0ZWRJblZlciI6IjQxLjkxLjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbIktpbmQvQ2hvcmUiLCJydW4tZW5kLXRvLWVuZC10ZXN0cyJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/921): <!--number 921 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9mb3JnZWpvIERvY2tlciB0YWcgdG8gdjExLjAuNA==-->Update code.forgejo.org/forgejo/forgejo Docker tag to v11.0.4<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/921
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-09-01 11:51:24 +00:00
Mathieu Fenniak
5a569d4ed1
adopt t.Context() now that we're on go1.24; remove per-test explicit timeout 2025-09-01 13:45:43 +02:00
Mathieu Fenniak
dded18c94d
add an integration test for PR cache pollution 2025-09-01 13:45:43 +02:00
Mathieu Fenniak
4bd93294d4
add WriteIsolationKey to MAC 2025-09-01 13:45:43 +02:00
Mathieu Fenniak
6c35ea4fd9
add unit tests for all changes in artifactcache 2025-09-01 13:45:43 +02:00
Mathieu Fenniak
da7ef7c2a1
fix: PRs cache artifacts separate from other runs 2025-09-01 13:45:43 +02:00
Earl Warren
11a96bb462
fix(security): ensure unique names for container images created by actions
Container images built by the runner are tagged with a unique name:

- based on the specified `uses` URL for remote actions.
- random for local actions.

In the case of local actions, this will create new tags for each run
but the images (and their layers) will be shared and not be
duplicated. The least recently used tags can be garbage collected by
tools such as https://github.com/stepchowfun/docuum.

Using a different method for creating the tag name for the remote
actions is to help with maintenance by establishing a direct relation
with the `uses` field. It was instead relying on a name transformed
multiple times which makes it more difficult to verify name collision
are not accidentally made possible by one of those transformations.

Without this fix, when a workflow ran a local [docker action](https://forgejo.org/docs/next/user/actions/actions/#docker-actions)
(e.g. the [example in the end-to-end
tests](8f920b4b7a/actions/example-force-rebuild/.forgejo/workflows/test.yml)),
it used an image tag that could collide with other workflows that
happen to use the same name.

The workaround for older runner versions is to set
[`[container].force_rebuild: true`](https://forgejo.org/docs/next/admin/actions/runner-installation/#configuration)
in the runner configuration file.
2025-09-01 13:41:06 +02:00
Earl Warren
7efe25f13d
chore: local action name collision regression tests
If the tag name collide (e.g. v9.1.1), it will fail with:

```
[push.yml/test] [DEBUG] Working directory '/home/earl-warren/software/runner/act/runner/testdata/local-action-dockerfile-tag/example2'
[push.yml/test]     Failure - Main [[ "example1 SOMEONE" == "example2 SOMEONE" ]]
```
2025-09-01 13:41:06 +02:00
Earl Warren
d29cba2946
chore: explain the difference between job_level and level (#922)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/922): <!--number 922 --><!--line 0 --><!--description Y2hvcmU6IGV4cGxhaW4gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBgam9iX2xldmVsYCBhbmQgYGxldmVsYA==-->chore: explain the difference between `job_level` and `level`<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/922
Reviewed-by: msrd0 <msrd0@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-09-01 11:32:19 +00:00
Earl Warren
583adee780
chore: add reminder of how to run a local test (#917)
So that it can be copy/pasted.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/917): <!--number 917 --><!--line 0 --><!--description Y2hvcmU6IGFkZCByZW1pbmRlciBvZiBob3cgdG8gcnVuIGEgbG9jYWwgdGVzdA==-->chore: add reminder of how to run a local test<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/917
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-08-29 12:38:25 +00:00
Earl Warren
4bb2daca9d
chore: unify cascade-setup-forgejo with cascade-forgejo (take 2) 2025-08-29 11:17:40 +02:00
Earl Warren
04801dedd5
chore: unify cascade-setup-forgejo with cascade-forgejo (#919)
Tested out of the wip-cascade branch:

- https://code.forgejo.org/forgejo/runner/actions/runs/8746
- https://code.forgejo.org/actions/setup-forgejo/pulls/646
- https://code.forgejo.org/forgejo/end-to-end/pulls/984

----

Instead of always running end-to-end tests, only run them when the
run-end-to-end-tests label is set. They are heavy duty and should not
be run when a new contributor sends their first pull request.

- fix bug: close-merge is close
- add instructions for debug
- identify the origin of the tokens
- do not needlessly run setup-forgejo integration tests
- copy/paste from cascade-forgejo.yml with the following exceptions:
  - do not trigger on main
  - use run-end-to-end-test instead of run-forgejo-test

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/919): <!--number 919 --><!--line 0 --><!--description Y2hvcmU6IHVuaWZ5IGNhc2NhZGUtc2V0dXAtZm9yZ2VqbyB3aXRoIGNhc2NhZGUtZm9yZ2Vqbw==-->chore: unify cascade-setup-forgejo with cascade-forgejo<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/919
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-08-29 08:45:53 +00:00
Gusted
bbb2cdd9f7
chore: remove github.com/pkg/errors (#873)
The functionality provided by this package is also provided by the
standard library.

`fmt.Errorf` for dynamically generated errors.
`errors.new` for static errors.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/873): <!--number 873 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSBgZ2l0aHViLmNvbS9wa2cvZXJyb3JzYA==-->chore: remove `github.com/pkg/errors`<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/873
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
2025-08-28 09:33:52 +00:00
Renovate Bot
0e780482eb
Update module github.com/stretchr/testify to v1.11.1 (#915)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/stretchr/testify](https://github.com/stretchr/testify) | `v1.10.0` -> `v1.11.1` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fstretchr%2ftestify/v1.11.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fstretchr%2ftestify/v1.10.0/v1.11.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>stretchr/testify (github.com/stretchr/testify)</summary>

### [`v1.11.1`](https://github.com/stretchr/testify/releases/tag/v1.11.1)

[Compare Source](https://github.com/stretchr/testify/compare/v1.11.0...v1.11.1)

This release fixes [#&#8203;1785](https://github.com/stretchr/testify/issues/1785) introduced in v1.11.0 where expected argument values implementing the stringer interface (`String() string`) with a method which mutates their value, when passed to mock.Mock.On (`m.On("Method", <expected>).Return()`) or actual argument values passed to mock.Mock.Called may no longer match one another where they previously did match. The behaviour prior to v1.11.0 where the stringer is always called is restored. Future testify releases may not call the stringer method at all in this case.

#### What's Changed

- Backport [#&#8203;1786](https://github.com/stretchr/testify/issues/1786) to release/1.11: mock: revert to pre-v1.11.0 argument matching behavior for mutating stringers by [@&#8203;brackendawson](https://github.com/brackendawson) in [#&#8203;1788](https://github.com/stretchr/testify/pull/1788)

**Full Changelog**: <https://github.com/stretchr/testify/compare/v1.11.0...v1.11.1>

### [`v1.11.0`](https://github.com/stretchr/testify/releases/tag/v1.11.0)

[Compare Source](https://github.com/stretchr/testify/compare/v1.10.0...v1.11.0)

#### What's Changed

##### Functional Changes

v1.11.0 Includes a number of performance improvements.

- Call stack perf change for CallerInfo by [@&#8203;mikeauclair](https://github.com/mikeauclair) in [#&#8203;1614](https://github.com/stretchr/testify/pull/1614)
- Lazily render mock diff output on successful match by [@&#8203;mikeauclair](https://github.com/mikeauclair) in [#&#8203;1615](https://github.com/stretchr/testify/pull/1615)
- assert: check early in Eventually, EventuallyWithT, and Never by [@&#8203;cszczepaniak](https://github.com/cszczepaniak) in [#&#8203;1427](https://github.com/stretchr/testify/pull/1427)
- assert: add IsNotType by [@&#8203;bartventer](https://github.com/bartventer) in [#&#8203;1730](https://github.com/stretchr/testify/pull/1730)
- assert.JSONEq: shortcut if same strings by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1754](https://github.com/stretchr/testify/pull/1754)
- assert.YAMLEq: shortcut if same strings by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1755](https://github.com/stretchr/testify/pull/1755)
- assert: faster and simpler isEmpty using reflect.Value.IsZero by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1761](https://github.com/stretchr/testify/pull/1761)
- suite: faster methods filtering (internal refactor) by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1758](https://github.com/stretchr/testify/pull/1758)

##### Fixes

- assert.ErrorAs: log target type by [@&#8203;craig65535](https://github.com/craig65535) in [#&#8203;1345](https://github.com/stretchr/testify/pull/1345)
- Fix failure message formatting for Positive and Negative asserts in [#&#8203;1062](https://github.com/stretchr/testify/pull/1062)
- Improve ErrorIs message when error is nil but an error was expected by [@&#8203;tsioftas](https://github.com/tsioftas) in [#&#8203;1681](https://github.com/stretchr/testify/pull/1681)
- fix Subset/NotSubset when calling with mixed input types by [@&#8203;siliconbrain](https://github.com/siliconbrain) in [#&#8203;1729](https://github.com/stretchr/testify/pull/1729)
- Improve ErrorAs failure message when error is nil by [@&#8203;ccoVeille](https://github.com/ccoVeille) in [#&#8203;1734](https://github.com/stretchr/testify/pull/1734)
- mock.AssertNumberOfCalls: improve error msg by [@&#8203;3scalation](https://github.com/3scalation) in [#&#8203;1743](https://github.com/stretchr/testify/pull/1743)

##### Documentation, Build & CI

- docs: Fix typo in README by [@&#8203;alexandear](https://github.com/alexandear) in [#&#8203;1688](https://github.com/stretchr/testify/pull/1688)
- Replace deprecated io/ioutil with io and os by [@&#8203;alexandear](https://github.com/alexandear) in [#&#8203;1684](https://github.com/stretchr/testify/pull/1684)
- Document consequences of calling t.FailNow() by [@&#8203;greg0ire](https://github.com/greg0ire) in [#&#8203;1710](https://github.com/stretchr/testify/pull/1710)
- chore: update docs for Unset [#&#8203;1621](https://github.com/stretchr/testify/issues/1621) by [@&#8203;techfg](https://github.com/techfg) in [#&#8203;1709](https://github.com/stretchr/testify/pull/1709)
- README: apply gofmt to examples by [@&#8203;alexandear](https://github.com/alexandear) in [#&#8203;1687](https://github.com/stretchr/testify/pull/1687)
- refactor: use %q and %T to simplify fmt.Sprintf by [@&#8203;alexandear](https://github.com/alexandear) in [#&#8203;1674](https://github.com/stretchr/testify/pull/1674)
- Propose Christophe Colombier (ccoVeille) as approver by [@&#8203;brackendawson](https://github.com/brackendawson) in [#&#8203;1716](https://github.com/stretchr/testify/pull/1716)
- Update documentation for the Error function in assert or require package by [@&#8203;architagr](https://github.com/architagr) in [#&#8203;1675](https://github.com/stretchr/testify/pull/1675)
- assert: remove deprecated build constraints by [@&#8203;alexandear](https://github.com/alexandear) in [#&#8203;1671](https://github.com/stretchr/testify/pull/1671)
- assert: apply gofumpt to internal test suite by [@&#8203;ccoVeille](https://github.com/ccoVeille) in [#&#8203;1739](https://github.com/stretchr/testify/pull/1739)
- CI: fix shebang in .ci.\*.sh scripts by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1746](https://github.com/stretchr/testify/pull/1746)
- assert,require: enable parallel testing on (almost) all top tests by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1747](https://github.com/stretchr/testify/pull/1747)
- suite.Passed: add one more status test report by [@&#8203;Ararsa-Derese](https://github.com/Ararsa-Derese) in [#&#8203;1706](https://github.com/stretchr/testify/pull/1706)
- Add Helper() method in internal mocks and assert.CollectT by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1423](https://github.com/stretchr/testify/pull/1423)
- assert.Same/NotSame: improve usage of Sprintf by [@&#8203;ccoVeille](https://github.com/ccoVeille) in [#&#8203;1742](https://github.com/stretchr/testify/pull/1742)
- mock: enable parallel testing on internal testsuite by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1756](https://github.com/stretchr/testify/pull/1756)
- suite: cleanup use of 'testing' internals at runtime by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1751](https://github.com/stretchr/testify/pull/1751)
- assert: check test failure message for Empty and NotEmpty  by [@&#8203;ccoVeille](https://github.com/ccoVeille) in [#&#8203;1745](https://github.com/stretchr/testify/pull/1745)
- deps: fix dependency cycle with objx (again) by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1567](https://github.com/stretchr/testify/pull/1567)
- assert.Empty: comprehensive doc of "Empty"-ness rules by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1753](https://github.com/stretchr/testify/pull/1753)
- doc: improve godoc of top level 'testify' package by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1760](https://github.com/stretchr/testify/pull/1760)
- assert.ErrorAs: simplify retrieving the type name by [@&#8203;ccoVeille](https://github.com/ccoVeille) in [#&#8203;1740](https://github.com/stretchr/testify/pull/1740)
- assert.EqualValues: improve test coverage to 100% by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1763](https://github.com/stretchr/testify/pull/1763)
- suite.Run: simplify running of Setup/TeardownSuite by [@&#8203;renzoarreaza](https://github.com/renzoarreaza) in [#&#8203;1769](https://github.com/stretchr/testify/pull/1769)
- assert.CallerInfo: micro optimization by using LastIndexByte by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1767](https://github.com/stretchr/testify/pull/1767)
- assert.CallerInfo: micro cleanup by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1768](https://github.com/stretchr/testify/pull/1768)
- assert: refactor Test*FileExists and Test*DirExists tests to enable parallel testing by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1766](https://github.com/stretchr/testify/pull/1766)
- suite.Run: refactor handling of stats for improved readability by [@&#8203;dolmen](https://github.com/dolmen) in [#&#8203;1764](https://github.com/stretchr/testify/pull/1764)
- tests: improve captureTestingT helper by [@&#8203;ccoVeille](https://github.com/ccoVeille) in [#&#8203;1741](https://github.com/stretchr/testify/pull/1741)
- build(deps): bump actions/checkout from 4 to 5 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in [#&#8203;1778](https://github.com/stretchr/testify/pull/1778)

#### New Contributors

- [@&#8203;greg0ire](https://github.com/greg0ire) made their first contribution in [#&#8203;1710](https://github.com/stretchr/testify/pull/1710)
- [@&#8203;techfg](https://github.com/techfg) made their first contribution in [#&#8203;1709](https://github.com/stretchr/testify/pull/1709)
- [@&#8203;mikeauclair](https://github.com/mikeauclair) made their first contribution in [#&#8203;1614](https://github.com/stretchr/testify/pull/1614)
- [@&#8203;cszczepaniak](https://github.com/cszczepaniak) made their first contribution in [#&#8203;1427](https://github.com/stretchr/testify/pull/1427)
- [@&#8203;architagr](https://github.com/architagr) made their first contribution in [#&#8203;1675](https://github.com/stretchr/testify/pull/1675)
- [@&#8203;tsioftas](https://github.com/tsioftas) made their first contribution in [#&#8203;1681](https://github.com/stretchr/testify/pull/1681)
- [@&#8203;siliconbrain](https://github.com/siliconbrain) made their first contribution in [#&#8203;1729](https://github.com/stretchr/testify/pull/1729)
- [@&#8203;bartventer](https://github.com/bartventer) made their first contribution in [#&#8203;1730](https://github.com/stretchr/testify/pull/1730)
- [@&#8203;Ararsa-Derese](https://github.com/Ararsa-Derese) made their first contribution in [#&#8203;1706](https://github.com/stretchr/testify/pull/1706)
- [@&#8203;renzoarreaza](https://github.com/renzoarreaza) made their first contribution in [#&#8203;1769](https://github.com/stretchr/testify/pull/1769)
- [@&#8203;3scalation](https://github.com/3scalation) made their first contribution in [#&#8203;1743](https://github.com/stretchr/testify/pull/1743)

**Full Changelog**: <https://github.com/stretchr/testify/compare/v1.10.0...v1.11.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:eyJjcmVhdGVkSW5WZXIiOiI0MS44Mi4xMCIsInVwZGF0ZWRJblZlciI6IjQxLjgyLjEwIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJLaW5kL0Nob3JlIl19-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/915): <!--number 915 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3N0cmV0Y2hyL3Rlc3RpZnkgdG8gdjEuMTEuMQ==-->Update module github.com/stretchr/testify to v1.11.1<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/915
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-08-28 09:31:53 +00:00
Renovate Bot
fa365952f6
Update module google.golang.org/protobuf to v1.36.8 (#914)
This PR contains the following updates:

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

---

### Release Notes

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

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

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

Maintenance:

[CL/696316](https://go-review.googlesource.com/c/protobuf/+/696316): all: set Go language version to Go 1.23
[CL/696315](https://go-review.googlesource.com/c/protobuf/+/696315): types: regenerate using latest protobuf v32 release

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

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/914): <!--number 914 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1ZiB0byB2MS4zNi44-->Update module google.golang.org/protobuf to v1.36.8<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/914
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-08-26 06:51:01 +00:00
Renovate Bot
612bd1e0ce
Update module go.etcd.io/bbolt to v1.4.3 (#907)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) | `v1.4.2` -> `v1.4.3` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.etcd.io%2fbbolt/v1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.etcd.io%2fbbolt/v1.4.2/v1.4.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>etcd-io/bbolt (go.etcd.io/bbolt)</summary>

### [`v1.4.3`](https://github.com/etcd-io/bbolt/releases/tag/v1.4.3)

[Compare Source](https://github.com/etcd-io/bbolt/compare/v1.4.2...v1.4.3)

See the [CHANGELOG/v1.4.3](https://github.com/etcd-io/bbolt/blob/main/CHANGELOG/CHANGELOG-1.4.md#v1432025-08-19) for more details.

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS43Ni4wIiwidXBkYXRlZEluVmVyIjoiNDEuNzYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/907): <!--number 907 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnby5ldGNkLmlvL2Jib2x0IHRvIHYxLjQuMw==-->Update module go.etcd.io/bbolt to v1.4.3<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/907
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-08-25 06:05:53 +00:00
Mathieu Fenniak
086a8f9847
test: remove internal timeout in TestRunnerCacheConfiguration (#906)
Performance has been in the range of 2.5 - 3 minutes for the "runner integration tests" step, causing this arbitrary timeout to be hit.  The timeout was useful for early test development when nothing was running successfully, but meaningful now.

Fixes #905.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/906): <!--number 906 --><!--line 0 --><!--description dGVzdDogcmVtb3ZlIGludGVybmFsIHRpbWVvdXQgaW4gVGVzdFJ1bm5lckNhY2hlQ29uZmlndXJhdGlvbg==-->test: remove internal timeout in TestRunnerCacheConfiguration<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/906
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-08-22 05:09:36 +00:00
Earl Warren
fac8be3c56
chore: skip tests that require Forgejo if it is not available (#902)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/902): <!--number 902 --><!--line 0 --><!--description Y2hvcmU6IHNraXAgdGVzdHMgdGhhdCByZXF1aXJlIEZvcmdlam8gaWYgaXQgaXMgbm90IGF2YWlsYWJsZQ==-->chore: skip tests that require Forgejo if it is not available<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/902
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
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-08-21 19:50:05 +00:00
Earl Warren
8eda2e40a4
chore: rework the README (#903)
- Explain how to run tests locally instead of pointing to the
  workflow.
- Explain how to run lint checks & fix locally
- Replace the `forgejo-setup` based instructions with shorter and more
  actionable instructions based out of the end-to-end tests.
- Remove the reporting bug section, the issue template has all the
  information it needs. It is unlikely that someone reporting a bug
  will read that section in the README before filing the bug. It
  removes the suggestion to file a bug in the end-to-end repository
  but I don't think it was actually beneficial to anyone in the past
  two years.
- Remove the mock generation part as it is now self documented in the
  job that takes care of it.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/903): <!--number 903 --><!--line 0 --><!--description Y2hvcmU6IHJld29yayB0aGUgUkVBRE1FIFtza2lwIGNhc2NhZGVd-->chore: rework the README [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/903
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
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-08-21 19:48:28 +00:00
Renovate Bot
d2b39167a8
Update github.com/go-viper/mapstructure/v2 (indirect) to v2.4.0 [SECURITY] (#904)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) | `v2.3.0` -> `v2.4.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgo-viper%2fmapstructure%2fv2/v2.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fgo-viper%2fmapstructure%2fv2/v2.3.0/v2.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### go-viper's mapstructure May Leak Sensitive Information in Logs When Processing Malformed Data
[GHSA-2464-8j7c-4cjm](https://github.com/advisories/GHSA-2464-8j7c-4cjm)

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

#### Details
##### Summary

Use of this library in a security-critical context may result in leaking sensitive information, if used to process sensitive fields.

##### Details

OpenBao (and presumably HashiCorp Vault) have surfaced error messages from `mapstructure` as follows:

98c3a59c04/sdk/framework/field_data.go (L43-L50)

```go
			_, _, err := d.getPrimitive(field, schema)
			if err != nil {
				return fmt.Errorf("error converting input for field %q: %w", field, err)
			}
```

where this calls `mapstructure.WeakDecode(...)`: 98c3a59c04/sdk/framework/field_data.go (L181-L193)

```go

func (d *FieldData) getPrimitive(k string, schema *FieldSchema) (interface{}, bool, error) {
	raw, ok := d.Raw[k]
	if !ok {
		return nil, false, nil
	}

	switch t := schema.Type; t {
	case TypeBool:
		var result bool
		if err := mapstructure.WeakDecode(raw, &result); err != nil {
			return nil, false, err
		}
		return result, true, nil
```

Notably, `WeakDecode(...)` eventually calls one of the decode helpers, which surfaces the original value via `strconv` helpers:

8c61ec1924/mapstructure.go (L720-L727)

8c61ec1924/mapstructure.go (L791-L798)

8c61ec1924/decode_hooks.go (L180)

& more. These are different code paths than are fixed in the previous iteration at https://github.com/go-viper/mapstructure/security/advisories/GHSA-fv92-fjc5-jj9h.

##### PoC

To reproduce with OpenBao:

```
$ podman run --pull=always -p 8300:8300 openbao/openbao:latest server -dev -dev-root-token-id=root -dev-listen-address=0.0.0.0:8300
```

and in a new tab:

```
$ BAO_TOKEN=root BAO_ADDR=http://localhost:8300 bao auth enable userpass
Success! Enabled userpass auth method at: userpass/
$ curl -X PUT -H "X-Vault-Request: true" -H "X-Vault-Token: root" -d '{"ttl":"asdf"}' "http://localhost:8200/v1/auth/userpass/users/asdf"

--> server logs:

2025-06-25T21:32:25.101-0500 [ERROR] core: failed to run existence check: error="error converting input for field \"ttl\": time: invalid duration \"asdf\""
```

##### Impact

This is an information disclosure bug with little mitigation. See https://discuss.hashicorp.com/t/hcsec-2025-09-vault-may-expose-sensitive-information-in-error-logs-when-processing-malformed-data-with-the-kv-v2-plugin/74717 for a previous version. That version was fixed, but this is in the second part of that error message (starting at `'' expected a map, got 'string'` -- when the field type is `string` and a `map` is provided, we see the above information leak -- the previous example had a `map` type field with a `string` value provided).

This was rated 4.5 Medium by HashiCorp in the past iteration.

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

#### References
- [https://github.com/go-viper/mapstructure/security/advisories/GHSA-2464-8j7c-4cjm](https://github.com/go-viper/mapstructure/security/advisories/GHSA-2464-8j7c-4cjm)
- [742921c9ba)
- [https://github.com/go-viper/mapstructure](https://github.com/go-viper/mapstructure)

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

---

### Release Notes

<details>
<summary>go-viper/mapstructure (github.com/go-viper/mapstructure/v2)</summary>

### [`v2.4.0`](https://github.com/go-viper/mapstructure/releases/tag/v2.4.0)

[Compare Source](https://github.com/go-viper/mapstructure/compare/v2.3.0...v2.4.0)

#### What's Changed

- refactor: replace interface{} with any by [@&#8203;sagikazarmark](https://github.com/sagikazarmark) in https://github.com/go-viper/mapstructure/pull/115
- build(deps): bump github/codeql-action from 3.29.0 to 3.29.2 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in https://github.com/go-viper/mapstructure/pull/114
- Generic tests by [@&#8203;sagikazarmark](https://github.com/sagikazarmark) in https://github.com/go-viper/mapstructure/pull/118
- Fix godoc reference link in README.md by [@&#8203;peczenyj](https://github.com/peczenyj) in https://github.com/go-viper/mapstructure/pull/107
- feat: add StringToTimeLocationHookFunc to convert strings to \*time.Location by [@&#8203;ErfanMomeniii](https://github.com/ErfanMomeniii) in https://github.com/go-viper/mapstructure/pull/117
- feat: add back previous StringToSlice as a weak function by [@&#8203;sagikazarmark](https://github.com/sagikazarmark) in https://github.com/go-viper/mapstructure/pull/119

#### New Contributors

- [@&#8203;ErfanMomeniii](https://github.com/ErfanMomeniii) made their first contribution in https://github.com/go-viper/mapstructure/pull/117

**Full Changelog**: https://github.com/go-viper/mapstructure/compare/v2.3.0...v2.4.0

</details>

---

### Configuration

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

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS43Ni4wIiwidXBkYXRlZEluVmVyIjoiNDEuNzYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/904): <!--number 904 --><!--line 0 --><!--description VXBkYXRlIGdpdGh1Yi5jb20vZ28tdmlwZXIvbWFwc3RydWN0dXJlL3YyIChpbmRpcmVjdCkgdG8gdjIuNC4wIFtTRUNVUklUWV0=-->Update github.com/go-viper/mapstructure/v2 (indirect) to v2.4.0 [SECURITY]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/904
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-08-21 19:44:03 +00:00
Earl Warren
579c5e24fc
chore: remove TestRunContext_GetGitHubContext (#900)
It does not assert anything useful and te associated function is otherwise heavily used in many tests. It may benefit from unit testing but this test would need to be done very differently to achieve that.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/900): <!--number 900 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSBUZXN0UnVuQ29udGV4dF9HZXRHaXRIdWJDb250ZXh0-->chore: remove TestRunContext_GetGitHubContext<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/900
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-08-21 11:54:04 +00:00
Earl Warren
8a44eb421f
chore: do not force GOPROXY (#899)
let `setup-go` figure it out

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/899): <!--number 899 --><!--line 0 --><!--description Y2hvcmU6IGRvIG5vdCBmb3JjZSBHT1BST1hZ-->chore: do not force GOPROXY<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/899
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-08-21 11:53:48 +00:00
Earl Warren
ea0a3f1f12
chore: fix .PHONY lint targets (#893)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/893): <!--number 893 --><!--line 0 --><!--description Y2hvcmU6IGZpeCAuUEhPTlkgbGludCB0YXJnZXRz-->chore: fix .PHONY lint targets<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/893
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-08-21 11:24:11 +00:00
Renovate Bot
e0dd374a3b
Update dependency forgejo/runner to v9.1.1 (#898)
This PR contains the following updates:

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

---

### Release Notes

<details>
<summary>forgejo/runner (forgejo/runner)</summary>

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

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

***

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS43Ni4wIiwidXBkYXRlZEluVmVyIjoiNDEuNzYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/898): <!--number 898 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9ydW5uZXIgdG8gdjkuMS4x-->Update dependency forgejo/runner to v9.1.1<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/898
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-08-21 07:16:34 +00:00
Renovate Bot
914808bea0
Update code.forgejo.org/forgejo/runner Docker tag to v9.1.1 (#897)
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 | `9.1.0` -> `9.1.1` |

---

### Release Notes

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

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

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

***

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS43Ni4wIiwidXBkYXRlZEluVmVyIjoiNDEuNzYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/897): <!--number 897 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9ydW5uZXIgRG9ja2VyIHRhZyB0byB2OS4xLjE=-->Update code.forgejo.org/forgejo/runner Docker tag to v9.1.1<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/897
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-08-21 06:59:15 +00:00
Renovate Bot
7512133cb7
Update module github.com/vektra/mockery/v2 to v2.53.5 (#890)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/vektra/mockery/v2](https://github.com/vektra/mockery) | `v2.53.4` -> `v2.53.5` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fvektra%2fmockery%2fv2/v2.53.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fvektra%2fmockery%2fv2/v2.53.4/v2.53.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>vektra/mockery (github.com/vektra/mockery/v2)</summary>

### [`v2.53.5`](https://github.com/vektra/mockery/compare/v2.53.4...v2.53.5)

[Compare Source](https://github.com/vektra/mockery/compare/v2.53.4...v2.53.5)

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS43Ni4wIiwidXBkYXRlZEluVmVyIjoiNDEuNzYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/890): <!--number 890 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3Zla3RyYS9tb2NrZXJ5L3YyIHRvIHYyLjUzLjU=-->Update module github.com/vektra/mockery/v2 to v2.53.5<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/890
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-08-21 06:30:27 +00:00
earl-warren
33e0ab7b68
test: run all tests with the data race detector (#861)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/861
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
2025-08-21 04:50:48 +00:00
Earl Warren
b8f8b0f674
fix: an error from a SKIPPED job does not transform it into a FAILURE (#896)
The result of a job can only be changed to FAILURE by the Close() function of the reporter under two conditions:

- If it is UNSPECIFIED
- If the context timeout

In all other cases it must be preserved. It is possible, for instance, for a job to be SKIPPED and be associated with an error message, e.g.

```
time="2025-08-20T21:02:07+02:00" level=trace msg="evaluating expression 'success()'" dryrun=false job="Test Action/job-1" jobID=job-1 matrix="map[]"
[Test Action/job-1] [DEBUG] evaluating expression 'success()'
time="2025-08-20T21:02:07+02:00" level=trace msg="expression 'success()' evaluated to 'true'" dryrun=false job="Test Action/job-1" jobID=job-1 matrix="map[]"
[Test Action/job-1] [DEBUG] expression 'success()' evaluated to 'true'
time="2025-08-20T21:02:07+02:00" level=trace msg="'runs-on' key not defined in Test Action/job-1" dryrun=false job="Test Action/job-1" jobID=job-1 matrix="map[]"
[Test Action/job-1] 'runs-on' key not defined in Test Action/job-1
[Test Action/job-1] [DEBUG] No steps found
```

Those errors show in the logs when a job is skipped, because the worflow is empty. But they are expected and to be ignored.

Refs forgejo/runner#895

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/896): <!--number 896 --><!--line 0 --><!--description Zml4OiBhbiBlcnJvciBmcm9tIGEgU0tJUFBFRCBqb2IgZG9lcyBub3QgdHJhbnNmb3JtIGl0IGludG8gYSBGQUlMVVJF-->fix: an error from a SKIPPED job does not transform it into a FAILURE<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/896
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-08-20 22:02:43 +00:00
Mathieu Fenniak
55c873f360 add gcc package for cgo/-race 2025-08-20 15:06:59 -06:00
Mathieu Fenniak
528bb594af test: enable data race detector in CI-executed tests 2025-08-20 14:56:42 -06:00
Earl Warren
8f5470ad37
chore: replace gopkg.in/yaml.v3 with go.yaml.in/yaml/v3 (#888)
- gopkg.in/yaml.v3 is archived and unmaintained
- go.yaml.in/yaml/v3 is a compatible fork under the umbrella
  of https://yaml.org/

Refs https://code.forgejo.org/forgejo/runner/issues/887

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/888): <!--number 888 --><!--line 0 --><!--description V0lQOiBjaG9yZTogcmVwbGFjZSBnb3BrZy5pbi95YW1sLnYzIHdpdGggZ28ueWFtbC5pbi95YW1sL3Yz-->WIP: chore: replace gopkg.in/yaml.v3 with go.yaml.in/yaml/v3<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/888
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-08-20 20:49:49 +00:00
Mathieu Fenniak
ce6502e7b6
chore: fix 'false positive' data race detection in Id/Number default init (#867)
A step's `Id` & `Number` are potentially initialized in different goroutines on matrix evaluations; this change ensures they're initialized before execution fans out to multiple goroutines.  There doesn't seem to be any functional impact of this data race for end-users.

Where `Number` was previously initialized, a runtime error was added to ensure that the behavior is the same.

`ID` data race:
```
==================
WARNING: DATA RACE
Read at 0x00c0001ff348 by goroutine 77:
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor()
      /.../forgejo-runner/act/runner/job_executor.go:64 +0x424
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).Executor()
      /.../forgejo-runner/act/runner/run_context.go:931 +0x2c6
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.1()
      /.../forgejo-runner/act/runner/runner.go:218 +0x150
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Previous write at 0x00c0001ff348 by goroutine 76:
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor()
      /.../forgejo-runner/act/runner/job_executor.go:65 +0x4cc
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).Executor()
      /.../forgejo-runner/act/runner/run_context.go:931 +0x2c6
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.1()
      /.../forgejo-runner/act/runner/runner.go:218 +0x150
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Goroutine 77 (running) created at:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2()
      /.../forgejo-runner/act/common/executor.go:105 +0x144
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Goroutine 76 (running) created at:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2()
      /.../forgejo-runner/act/common/executor.go:105 +0x144
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f
==================
```

`Number` data race:
```
==================
WARNING: DATA RACE
Write at 0x00c0001ff340 by goroutine 77:
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor()
      /.../forgejo-runner/act/runner/job_executor.go:67 +0x536
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).Executor()
      /.../forgejo-runner/act/runner/run_context.go:931 +0x2c6
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.1()
      /.../forgejo-runner/act/runner/runner.go:218 +0x150
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Previous write at 0x00c0001ff340 by goroutine 76:
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor()
      /.../forgejo-runner/act/runner/job_executor.go:67 +0x536
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).Executor()
      /.../forgejo-runner/act/runner/run_context.go:931 +0x2c6
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.1()
      /.../forgejo-runner/act/runner/runner.go:218 +0x150
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Goroutine 77 (running) created at:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2()
      /.../forgejo-runner/act/common/executor.go:105 +0x144
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Goroutine 76 (running) created at:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2()
      /.../forgejo-runner/act/common/executor.go:105 +0x144
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f
==================
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/867): <!--number 867 --><!--line 0 --><!--description Y2hvcmU6IGZpeCAnZmFsc2UgcG9zaXRpdmUnIGRhdGEgcmFjZSBkZXRlY3Rpb24gaW4gSWQvTnVtYmVyIGRlZmF1bHQgaW5pdA==-->chore: fix 'false positive' data race detection in Id/Number default init<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/867
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-08-20 19:56:03 +00:00
Mathieu Fenniak
91e7940947
test: add an integration test for embedded runner cache (#889)
Adds a limited integration test in the runner which verifies that the embedded cache server starts up, can be written to by an action, and can be read by a subsequent action.  This is a solid base foundation for future nearly-end-to-end tests.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/889): <!--number 889 --><!--line 0 --><!--description dGVzdDogYWRkIGFuIGludGVncmF0aW9uIHRlc3QgZm9yIGVtYmVkZGVkIHJ1bm5lciBjYWNoZQ==-->test: add an integration test for embedded runner cache<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/889
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-08-20 19:46:03 +00:00
Earl Warren
22762480d8
chore: merge ACT and runner unit & integration tests together (#894)
When run in parallel they will race to populate the Go cache in a different way (GOPROXY is not configured the same) and that will lead to transient errors when one job tries to use the cache that is populated differently by the other job.

The chain of `needs` is adjusted accordingly and the required checks too.

![image](/attachments/4b83fc9d-d5f8-497e-9e94-976fcf52f088)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/894): <!--number 894 --><!--line 0 --><!--description Y2hvcmU6IG1lcmdlIEFDVCBhbmQgcnVubmVyIHVuaXQgJiBpbnRlZ3JhdGlvbiB0ZXN0cyB0b2dldGhlcg==-->chore: merge ACT and runner unit & integration tests together<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/894
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-08-20 17:09:04 +00:00
Earl Warren
8ce7965030
chore: when comparing mockery generated files, ignore the version (#891)
Refs https://code.forgejo.org/forgejo/runner/actions/runs/7645/jobs/2#jobstep-4-8

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/891): <!--number 891 --><!--line 0 --><!--description Y2hvcmU6IHdoZW4gY29tcGFyaW5nIG1vY2tlcnkgZ2VuZXJhdGVkIGZpbGVzLCBpZ25vcmUgdGhlIHZlcnNpb24=-->chore: when comparing mockery generated files, ignore the version<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/891
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-08-20 14:36:44 +00:00
Mathieu Fenniak
fa42b8394e
chore: fix data race in reusable workflows with inherited secrets (#875)
Data race detection identified that `getWorkflowSecrets` is mutating `rc.caller.runContext.Config.Secrets` while interpolating values, in the case where secrets are inherited by a reusable workflow. This map is also mutated earlier in evaluation by `(*RunContext).handleCredentials`.  It's possible that multiple goroutines performing mutation to this shared map could cause runtime panics (not observed).

The issue is addressed creating a separate map to store interpolated secrets in `getWorkflowSecrets`, which was already the behavior in the non-inherited secret case.

Automated testing for this issue will be provided by #861 when all data races are resolved.

```
==================
WARNING: DATA RACE
Read at 0x00c0003a9620 by goroutine 2546:
  runtime.mapaccess1_faststr()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/internal/runtime/maps/runtime_faststr_swiss.go:103 +0x0
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).handleCredentials()
      /.../forgejo-runner/act/runner/run_context.go:1395 +0xab
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).prepareJobContainer()
      /.../forgejo-runner/act/runner/run_context.go:460 +0x2de
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).startContainer.func1.(*RunContext).startJobContainer.2()
      /.../forgejo-runner/act/runner/run_context.go:610 +0x5e
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).startContainer.func1()
      /.../forgejo-runner/act/runner/run_context.go:853 +0xf3
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.NewPipelineExecutor.Executor.Then.func22()
      /.../forgejo-runner/act/common/executor.go:136 +0x57
...snip...

Previous write at 0x00c0003a9620 by goroutine 2440:
  runtime.mapassign_faststr()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/internal/runtime/maps/runtime_faststr_swiss.go:263 +0x0
  code.forgejo.org/forgejo/runner/v9/act/runner.getWorkflowSecrets()
      /.../forgejo-runner/act/runner/expression.go:578 +0x547
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).NewExpressionEvaluatorWithEnv()
      /.../forgejo-runner/act/runner/expression.go:85 +0x3fc
  code.forgejo.org/forgejo/runner/v9/act/common/git.FindGitRevision()
      /.../forgejo-runner/act/common/git/git.go:70 +0xe4
  github.com/go-git/go-git/v5.PlainOpenWithOptions()
      /home/mfenniak/go/pkg/mod/github.com/go-git/go-git/v5@v5.16.2/repository.go:332 +0x7a6
  code.forgejo.org/forgejo/runner/v9/act/common/git.FindGitRevision()
      /.../forgejo-runner/act/common/git/git.go:58 +0xc4
...snip...
==================
```

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/875
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-08-20 13:34:57 +00:00
Mathieu Fenniak
022d5ad3e7
fix: artifact cache DB not using indexes for searching (#878)
Uses the `Repo` field as an index during searches of the cache database.  Removes unused indexes.

To measure the performance of this change, I created a synthetic test which wrote 10,000 records into the artifact cache DB.  Of course, all benchmarks are lies that can't be generalized to real-world usage, but it seems clear from the magnitude of improvement that this fixes a flawed implementation, even if it's not perfect.
- Unmodified performance:
    - Write: 196 records/second
    - Read: 1 record/second
- With `Repo` index being used for reads, and other indexes being removed:
    - Write: 347 records/second
    - Read: 22,398 records/second

`Repo` is, I think, the only index that made sense to remain, with an eye on workflow run performance:
- `Key` -- can't be used for index because `findCache` searches for key *prefixes*, not equal values.
- `Version` -- isn't very distinct for different workflow runs (https://code.forgejo.org/actions/cache#cache-version)
- `Complete` - significant portion of the cache DB will be complete, making it the least selective possible index
- `UsedAt` & `CreatedAt` - only used in GC operation, so could remain, but this isn't a performance-sensitive codepath

Closes #874.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/878): <!--number 878 --><!--line 0 --><!--description Zml4OiBhcnRpZmFjdCBjYWNoZSBEQiBub3QgdXNpbmcgaW5kZXhlcyBmb3Igc2VhcmNoaW5n-->fix: artifact cache DB not using indexes for searching<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/878
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-08-19 20:19:23 +00:00
Michael Kriese
6d2cc80aa1
chore: revert mockery v3 update and validate mockery updates (#886)
- reverts #841 and #868
- add ci to validate mock changes
- https://code.forgejo.org/forgejo/runner/pulls/841#issuecomment-53111

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/886): <!--number 886 --><!--line 0 --><!--description Y2hvcmU6IHJldmVydCBtb2NrZXJ5IHYzIHVwZGF0ZSBhbmQgdmFsaWRhdGUgbW9ja2VyeSB1cGRhdGVz-->chore: revert mockery v3 update and validate mockery updates<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/886
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-committed-by: Michael Kriese <michael.kriese@visualon.de>
2025-08-18 14:22:48 +00:00
Earl Warren
24360de912
chore: cascade forgejo pull request out of the runner branch or PR (followup)
close-merge is not an input, close is
2025-08-18 14:23:53 +02:00
Earl Warren
b91e041a13
fix: RunsOn in jobparser is not used by the runner but it is used by Forgejo [skip cascade] (#884)
Refs forgejo/runner#881

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/884): <!--number 884 --><!--line 0 --><!--description Zml4OiBSdW5zT24gaW4gam9icGFyc2VyIGlzIG5vdCB1c2VkIGJ5IHRoZSBydW5uZXIgYnV0IGl0IGlzIHVzZWQgYnkgRm9yZ2VqbyBbc2tpcCBjYXNjYWRlXQ==-->fix: RunsOn in jobparser is not used by the runner but it is used by Forgejo [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/884
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-08-18 12:16:44 +00:00
Earl Warren
f793c00981
chore: cascade forgejo pull request out of the runner branch or PR (followup)
Also run the workflow when the pull request is closed so that it
closes the forgejo pull request. It would otherwise clutter the pull
request list and require manual intervention.
2025-08-18 14:07:20 +02:00
Earl Warren
d78c75f7c0
chore: cascade forgejo pull request out of the runner branch or PR (followup)
Add missing .name
2025-08-18 13:39:31 +02:00
Earl Warren
ebbe6ad2b1
chore: cascade forgejo pull request out of the runner branch or PR (followup)
debug information to figure out why it does not work
2025-08-18 13:36:18 +02:00
Earl Warren
54130f2380
chore: cascade forgejo pull request out of the runner branch or PR (followup)
Also run when the `run-forgejo-tests` is set so that it is not
necessary to push a commit to the pull request in addition.
2025-08-18 13:22:15 +02:00
Earl Warren
2286f71dd5
chore: cascade forgejo pull request out of the runner branch or PR (followup)
The SHA must be reachable from a branch or tags to be discovered by go
mod tidy.
2025-08-18 12:49:23 +02:00
Earl Warren
096d57953c
chore: cascade forgejo pull request out of the runner branch or PR (followup)
Because it is a pull_request_target, the ref_name will always be
main. Differentiate based on the event name.
2025-08-18 11:56:54 +02:00
Earl Warren
059a528adf
chore: cascade forgejo pull request out of the runner branch or PR (followup) 2025-08-18 11:48:54 +02:00
Earl Warren
07fadb3461
chore: cascade forgejo pull request out of the runner branch or PR (#883)
Refs forgejo/runner#881

---

This was tested manually to work but cannot be tested automatically. It is archived in this pull request for the record rather than for review. Testing will continue after it is merged, to verify it does what it should for pull requests and not just for branches.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/883): <!--number 883 --><!--line 0 --><!--description Y2hvcmU6IGNhc2NhZGUgZm9yZ2VqbyBwdWxsIHJlcXVlc3Qgb3V0IG9mIHRoZSBydW5uZXIgYnJhbmNoIG9yIFBS-->chore: cascade forgejo pull request out of the runner branch or PR<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/883
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-18 09:26:58 +00:00
Daniel Morante
34731a41be
fix: fixes the build on FreeBSD (#882)
Just fixes the build, not sure if this actually enables any functionality (yet) on FreeBSD.  However, it does seem to at least start:

```
time="2025-08-18T01:02:58-04:00" level=info msg="Starting runner daemon"
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/882): <!--number 882 --><!--line 0 --><!--description Zml4OiBmaXhlcyB0aGUgYnVpbGQgb24gRnJlZUJTRCBbc2tpcCBjYXNjYWRlXQ==-->fix: fixes the build on FreeBSD [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/882
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Daniel Morante <daniel@morante.net>
Co-committed-by: Daniel Morante <daniel@morante.net>
2025-08-18 06:01:33 +00:00
Renovate Bot
b73cf0d017
Update dependency forgejo/runner to v9.1.0 (#879)
This PR contains the following updates:

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

---

### Release Notes

<details>
<summary>forgejo/runner (forgejo/runner)</summary>

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

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

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

Release Notes

***

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS43Ni4wIiwidXBkYXRlZEluVmVyIjoiNDEuNzYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/879): <!--number 879 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9ydW5uZXIgdG8gdjkuMS4w-->Update dependency forgejo/runner to v9.1.0<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/879
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-08-18 05:45:50 +00:00
Earl Warren
86c8e646fa
chore: go.mod should use the minor version only (#880)
Refs https://codeberg.org/forgejo/forgejo/pulls/8926

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/880): <!--number 880 --><!--line 0 --><!--description Y2hvcmU6IGdvLm1vZCBzaG91bGQgdXNlIHRoZSBtaW5vciB2ZXJzaW9uIG9ubHkgW3NraXAgY2FzY2FkZV0=-->chore: go.mod should use the minor version only [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/880
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-18 05:31:36 +00:00
Renovate Bot
ac726862f2
Update code.forgejo.org/forgejo/runner Docker tag to v9.1.0 (#877)
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 | `9.0.3` -> `9.1.0` |

---

### Release Notes

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

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

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

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

Release Notes

***

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS42MS4wIiwidXBkYXRlZEluVmVyIjoiNDEuNzYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/877): <!--number 877 --><!--line 0 --><!--description VXBkYXRlIGNvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9ydW5uZXIgRG9ja2VyIHRhZyB0byB2OS4xLjA=-->Update code.forgejo.org/forgejo/runner Docker tag to v9.1.0<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/877
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-08-18 04:55:39 +00:00
earl-warren
1f7fa31b1a
fix: report the job as failed when the [runner].timeout expires (#870)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/870
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
2025-08-16 20:45:24 +00:00
Mathieu Fenniak
165b44deec
fix: data race in 'runs-on' expressions causes incorrect job labels during execution (#871)
A job with a `runs-on` that references matrix variables will not run with the expected labels.  eg.

```
jobs:
  matrix-runs-on:
    strategy:
      matrix:
        os: [ubuntu-latest, ubuntu-20.04]
    runs-on: ${{ matrix.os }}
    steps:
      ...
```
Due to shared mutated state, both jobs that this generates will (w/ a race condition) either run with the `ubuntu-latest` or `ubuntu-20.04`, but rarely (never observed) with the expected outcome of running on both labels.

`EvaluateYamlNode` is used to evaluate expressions in the `runs-on` field in the context of the current running job, but mutating an object shared between multiple concurrent jobs (in matrix evaluation).  This results in the evaluation results from one job spilling into another and corrupting their `runs-on` labels.

```
==================
WARNING: DATA RACE
Write at 0x00c00047e0b0 by goroutine 1739:
  reflect.typedmemmove()
      /.../go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/runtime/mbarrier.go:213 +0x0
  reflect.Value.Set()
      /.../go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/reflect/value.go:2062 +0x184
  gopkg.in/yaml%2ev3.(*decoder).unmarshal()
      /.../go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/decode.go:493 +0x7b4
  gopkg.in/yaml%2ev3.(*Node).Decode()
      /.../go/pkg/mod/gopkg.in/yaml.v3@v3.0.1/yaml.go:149 +0x355
  code.forgejo.org/forgejo/runner/v9/act/runner.expressionEvaluator.EvaluateYamlNode()
      /.../forgejo-runner/act/runner/expression.go:372 +0x7a
  code.forgejo.org/forgejo/runner/v9/act/runner.(*expressionEvaluator).EvaluateYamlNode()
      <autogenerated>:1 +0x6b
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).runsOnPlatformNames()
      /.../forgejo-runner/act/runner/run_context.go:1019 +0x2af
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).runsOnImage()
      /.../forgejo-runner/act/runner/run_context.go:1002 +0x772
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).platformImage()
      /.../forgejo-runner/act/runner/run_context.go:1032 +0x77
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).isEnabled()
      /.../forgejo-runner/act/runner/run_context.go:1069 +0x3c7
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).Executor.func1()
      /.../forgejo-runner/act/runner/run_context.go:964 +0x4b
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.1()
      /.../forgejo-runner/act/runner/runner.go:223 +0x271
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Previous read at 0x00c00047e0b0 by goroutine 1742:
  code.forgejo.org/forgejo/runner/v9/act/model.(*Job).RunsOn()
      /.../forgejo-runner/act/model/workflow.go:361 +0x3c4
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).runsOnImage()
      /.../forgejo-runner/act/runner/run_context.go:991 +0x57a
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).platformImage()
      /.../forgejo-runner/act/runner/run_context.go:1032 +0x77
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).isEnabled()
      /.../forgejo-runner/act/runner/run_context.go:1069 +0x3c7
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).Executor.func1()
      /.../forgejo-runner/act/runner/run_context.go:964 +0x4b
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.1()
      /.../forgejo-runner/act/runner/runner.go:223 +0x271
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f
...
==================
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/871): <!--number 871 --><!--line 0 --><!--description Zml4OiBkYXRhIHJhY2UgaW4gJ3J1bnMtb24nIGV4cHJlc3Npb25zIGNhdXNlcyBpbmNvcnJlY3Qgam9iIGxhYmVscyBkdXJpbmcgZXhlY3V0aW9u-->fix: data race in 'runs-on' expressions causes incorrect job labels during execution<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/871
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-08-16 20:44:40 +00:00
Earl Warren
25879b92f4
feat: log a descriptive message when a job exceeds the config timeout
- change the argument from string to error to differentiate
  a timeout error
- when there is a timeout, display a message more descriptive than
  "context deadline"
- always set the StoppedAt state value instead of only if the
  result was unspecified: it is the last state update.
2025-08-16 20:22:33 +02:00
earl-warren
776f0641fd
feat: fail when using an invalid label during non interactive registration (#647)
* add test
* return validation error not nil from function

Reviewed-on: https://gitea.com/gitea/act_runner/pulls/683
Reviewed-by: techknowlogick <techknowlogick@noreply.gitea.com>
Co-authored-by: Christopher Homberger <christopher.homberger@web.de>
Co-committed-by: Christopher Homberger <christopher.homberger@web.de>
(cherry picked from commit f0b5aff3bbeda469a682fe21144c16485ea2189a)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/647): <!--number 647 --><!--line 0 --><!--description ZmVhdDogZmFpbCB3aGVuIHVzaW5nIGFuIGludmFsaWQgbGFiZWwgZHVyaW5nIG5vbiBpbnRlcmFjdGl2ZSByZWdpc3RyYXRpb24=-->feat: fail when using an invalid label during non interactive registration<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Christopher Homberger <christopher.homberger@web.de>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/647
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
2025-08-16 17:59:20 +00:00
Earl Warren
bd2b7d2b32
fix: after canceling the context, the reporter cannot communicate
ctx & cancel are related and when cancel is called, the context is no
longer usable. Use the daemon context context to allow the reporter to
continue to operate and conclude the converation with the Forgejo
instance.
2025-08-16 19:35:54 +02:00
Earl Warren
d114f3646d
feat: insert the daemon context in the poller context
The daemon context is needed when the context of a job or the poller
is done. Otherwise it is no longer possible to send a conclusion
report to Forgejo, short of creating a context.Background() which
poses its own set of problems.

- WithDaemonContext is used to store the daemon context
- The poller uses the daemon context instead of context.Background
2025-08-16 19:13:32 +02:00
Mathieu Fenniak
fccf857bce
test: fix data race triggered by testing mocks in TestSetJobResultConcurrency (#869)
#862 caused a **new** data race in its mock testing while fixing `setJobResult`'s data race. 🤣  I'm going backwards!

```
==================
WARNING: DATA RACE
Read at 0x00c000168d88 by goroutine 943:
  code.forgejo.org/forgejo/runner/v9/act/model.(*Workflow).GetJob()
      /home/debian/.cache/act/8afb5309fced9ef8/hostexecutor/act/model/workflow.go:742
+0x244
  code.forgejo.org/forgejo/runner/v9/act/model.(*Run).Job()
      /home/debian/.cache/act/8afb5309fced9ef8/hostexecutor/act/model/planner.go:50
+0xab
  code.forgejo.org/forgejo/runner/v9/act/runner.setJobResult()
      /home/debian/.cache/act/8afb5309fced9ef8/hostexecutor/act/runner/job_executor.go:166
+0x7c
  code.forgejo.org/forgejo/runner/v9/act/runner.TestSetJobResultConcurrency.func2()
      /home/debian/.cache/act/8afb5309fced9ef8/hostexecutor/act/runner/job_executor_test.go:404
+0xfb
Previous write at 0x00c000168d88 by goroutine 944:
  code.forgejo.org/forgejo/runner/v9/act/model.(*Workflow).GetJob()
      /home/debian/.cache/act/8afb5309fced9ef8/hostexecutor/act/model/workflow.go:743
+0x258
  code.forgejo.org/forgejo/runner/v9/act/model.(*Run).Job()
      /home/debian/.cache/act/8afb5309fced9ef8/hostexecutor/act/model/planner.go:50
+0xab
  code.forgejo.org/forgejo/runner/v9/act/runner.setJobResult()
      /home/debian/.cache/act/8afb5309fced9ef8/hostexecutor/act/runner/job_executor.go:166
+0x7c
  code.forgejo.org/forgejo/runner/v9/act/runner.TestSetJobResultConcurrency.func3()
      /home/debian/.cache/act/8afb5309fced9ef8/hostexecutor/act/runner/job_executor_test.go:409
+0xf8
...
==================
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/869): <!--number 869 --><!--line 0 --><!--description dGVzdDogZml4IGRhdGEgcmFjZSB0cmlnZ2VyZWQgYnkgdGVzdGluZyBtb2NrcyBpbiBUZXN0U2V0Sm9iUmVzdWx0Q29uY3VycmVuY3k=-->test: fix data race triggered by testing mocks in TestSetJobResultConcurrency<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/869
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-08-16 05:15:38 +00:00
Renovate Bot
cf1a723a88
Update module github.com/vektra/mockery/v2 to v3.5.3 (#868)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/vektra/mockery/v2](https://github.com/vektra/mockery) | `v3.5.2` -> `v3.5.3` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fvektra%2fmockery%2fv2/v3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fvektra%2fmockery%2fv2/v3.5.2/v3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>vektra/mockery (github.com/vektra/mockery/v2)</summary>

### [`v3.5.3`](https://github.com/vektra/mockery/releases/tag/v3.5.3)

[Compare Source](https://github.com/vektra/mockery/compare/v3.5.2...v3.5.3)

#### What's Changed

- Support Go 1.25 by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1104

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.5.2...v3.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:eyJjcmVhdGVkSW5WZXIiOiI0MS42MS4wIiwidXBkYXRlZEluVmVyIjoiNDEuNjEuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/868): <!--number 868 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3Zla3RyYS9tb2NrZXJ5L3YyIHRvIHYzLjUuMw==-->Update module github.com/vektra/mockery/v2 to v3.5.3<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/868
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
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-08-16 05:02:49 +00:00
earl-warren
6d9a2f6fca
fix: ensure unique container names for reusable workflows (#808)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/808
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
2025-08-16 04:45:55 +00:00
Mathieu Fenniak
76bf87f472
fix: data race condition causing incorrect shell on a task step if it referenced a matrix variable (#865)
The `setupShell` function would update the shell stored on the `Step` object, setting it to either a default value from the job, an expression evaluated in the context of the job, a default from the workflow, or finally falling back to bash or powershell defaults.  Typically this would be fine -- although it would trigger the data race detector because the `Step` is a shared object between multiple concurrent matrix evaluations for the job.

In the *really quite unlikely* case that the `shell` field on a step or job referenced a matrix variable, this data race would actually trigger the shared step's `Shell` value to end up as "whichever one was evaluated last", causing the wrong shell to be used.  The new `matrix-shell` test triggers this behavior, and fails without the associated code fix.

As a fix, the `Shell` field in `Step` is never mutated; instead only the value on non-shared `stepRun` instance is updated from `setupShellCommand`.  `Shell` was renamed to `RawShell` as part of verifying all references were updated and it seemed to make sense to keep that name since it is a pre-evaluator value.

```
==================
WARNING: DATA RACE
Write at 0x00c00013e9b0 by goroutine 1470:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*stepRun).setupShell()
      /.../forgejo-runner/act/runner/step_run.go:210 +0x8f2
  code.forgejo.org/forgejo/runner/v9/act/common/git.FindGitRevision()
      /.../forgejo-runner/act/common/git/git.go:58 +0xc4
  code.forgejo.org/forgejo/runner/v9/act/model.(*GithubContext).SetSha()
      /.../forgejo-runner/act/model/github_context.go:161 +0x6b5
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).getGithubContext()
      /.../forgejo-runner/act/runner/run_context.go:1228 +0x26ca
  ...

Previous write at 0x00c00013e9b0 by goroutine 1469:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*stepRun).setupShell()
      /.../forgejo-runner/act/runner/step_run.go:210 +0x8f2
  code.forgejo.org/forgejo/runner/v9/act/common/git.FindGitRevision()
      /.../forgejo-runner/act/common/git/git.go:58 +0xc4
  code.forgejo.org/forgejo/runner/v9/act/model.(*GithubContext).SetSha()
      /.../forgejo-runner/act/model/github_context.go:161 +0x6b5
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).getGithubContext()
      /.../forgejo-runner/act/runner/run_context.go:1228 +0x26ca

...
==================
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/865): <!--number 865 --><!--line 0 --><!--description Zml4OiBkYXRhIHJhY2UgY29uZGl0aW9uIGNhdXNpbmcgaW5jb3JyZWN0IGBzaGVsbGAgb24gYSB0YXNrIHN0ZXAgaWYgaXQgcmVmZXJlbmNlZCBhIG1hdHJpeCB2YXJpYWJsZQ==-->fix: data race condition causing incorrect `shell` on a task step if it referenced a matrix variable<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/865
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-08-15 21:10:53 +00:00
Shuroii
d976b1c65a
docs: clarify actions_cache_url_option (#866)
The other setting that asks you for a URL as input
does so while specifically stating it should have a
trailing slash. This commit adds similar
clarification to the other setting.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/866): <!--number 866 --><!--line 0 --><!--description ZG9jczogQ2xhcmlmeSBhY3Rpb25zX2NhY2hlX3VybF9vcHRpb24gW3NraXAgY2FzY2FkZV0=-->docs: Clarify actions_cache_url_option [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Shuroii <shuroii@local.local>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/866
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Co-authored-by: Shuroii <shuroii@noreply.code.forgejo.org>
Co-committed-by: Shuroii <shuroii@noreply.code.forgejo.org>
2025-08-15 19:32:45 +00:00
Mathieu Fenniak
d63d70c080
chore: prevent 'false positive' data race detection with Job.If [skip cascade] (#864)
Initialization of the default value of the `If` field is functionally safe, but triggers the data race detector.

```
==================
WARNING: DATA RACE
Read at 0x00c00037cf78 by goroutine 10:
  code.forgejo.org/forgejo/runner/v9/act/model.(*Workflow).GetJob()
      /.../forgejo-runner/act/model/workflow.go:766 +0x2ae
  code.forgejo.org/forgejo/runner/v9/act/model.(*Run).Job()
      /.../forgejo-runner/act/model/planner.go:50 +0xab
  code.forgejo.org/forgejo/runner/v9/act/runner.setJobResult()
      /.../forgejo-runner/act/runner/job_executor.go:168
+0x7c
  code.forgejo.org/forgejo/runner/v9/act/runner.TestSetJobResultConcurrency.func3()
      /.../forgejo-runner/act/runner/job_executor_test.go:410
+0xf8

Previous write at 0x00c00037cf78 by goroutine 9:
  code.forgejo.org/forgejo/runner/v9/act/model.(*Workflow).GetJob()
      /.../forgejo-runner/act/model/workflow.go:767 +0x2ce
  code.forgejo.org/forgejo/runner/v9/act/model.(*Run).Job()
      /.../forgejo-runner/act/model/planner.go:50 +0xab
  code.forgejo.org/forgejo/runner/v9/act/runner.setJobResult()
      /.../forgejo-runner/act/runner/job_executor.go:168
+0x7c
  code.forgejo.org/forgejo/runner/v9/act/runner.TestSetJobResultConcurrency.func2()
      /.../forgejo-runner/act/runner/job_executor_test.go:405
+0xfb

Goroutine 10 (running) created at:
  code.forgejo.org/forgejo/runner/v9/act/runner.TestSetJobResultConcurrency()
      /.../forgejo-runner/act/runner/job_executor_test.go:408
+0xbac
  testing.tRunner()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/testing/testing.go:1792
+0x225
  testing.(*T).Run.gowrap1()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/testing/testing.go:1851
+0x44

Goroutine 9 (running) created at:
  code.forgejo.org/forgejo/runner/v9/act/runner.TestSetJobResultConcurrency()
      /.../forgejo-runner/act/runner/job_executor_test.go:403
+0xa84
  testing.tRunner()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/testing/testing.go:1792
+0x225
  testing.(*T).Run.gowrap1()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/testing/testing.go:1851
+0x44
==================
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/864): <!--number 864 --><!--line 0 --><!--description Y2hvcmU6IHByZXZlbnQgJ2ZhbHNlIHBvc2l0aXZlJyBkYXRhIHJhY2UgZGV0ZWN0aW9uIHdpdGggSm9iLklmIFtza2lwIGNhc2NhZGVd-->chore: prevent 'false positive' data race detection with Job.If [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/864
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-08-15 19:19:54 +00:00
Mathieu Fenniak
69a3adad21
fix: race condition in matrix job result state may result in failed jobs being marked as successful (#862)
In `setJobResult` there is no coordination between multiple jobs that are completing, leading to a possible condition where `jobResult` can be read from the matrix job as `"success"` by a job, marked as `"failed"` by another job, and then marked as `"success"` by other jobs.

To my knowledge, the race condition has not been observed in a real-world case, but has been reproduced in a unit test.

```
==================
WARNING: DATA RACE
Read at 0x00c0006d08a0 by goroutine 29232:
  code.forgejo.org/forgejo/runner/v9/act/runner.setJobResult()
      /.../forgejo-runner/act/runner/job_executor.go:173
+0x359
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.func6()
      /.../forgejo-runner/act/runner/job_executor.go:118
+0x15d
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.Executor.Finally.func14()
      /.../forgejo-runner/act/common/executor.go:183 +0x86
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.func7()
      /.../forgejo-runner/act/runner/job_executor.go:161
+0x191
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.Executor.Finally.func16()
      /.../forgejo-runner/act/common/executor.go:183 +0x86
  ...

Previous write at 0x00c0006d08a0 by goroutine 29234:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).result()
      /.../forgejo-runner/act/runner/run_context.go:897
+0x271
  code.forgejo.org/forgejo/runner/v9/act/runner.setJobResult()
      /.../forgejo-runner/act/runner/job_executor.go:181
+0x66e
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.func6()
      /.../forgejo-runner/act/runner/job_executor.go:118
+0x15d
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.Executor.Finally.func14()
      /.../forgejo-runner/act/common/executor.go:183 +0x86
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.func7()
      /.../forgejo-runner/act/runner/job_executor.go:161
+0x191
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.Executor.Finally.func16()
      /.../forgejo-runner/act/common/executor.go:183 +0x86
  ...
==================
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/862): <!--number 862 --><!--line 0 --><!--description Zml4OiByYWNlIGNvbmRpdGlvbiBpbiBtYXRyaXggam9iIHJlc3VsdCBzdGF0ZSBtYXkgcmVzdWx0IGluIGZhaWxlZCBqb2JzIGJlaW5nIG1hcmtlZCBhcyBzdWNjZXNzZnVs-->fix: race condition in matrix job result state may result in failed jobs being marked as successful<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/862
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-08-15 19:11:57 +00:00
Renovate Bot
03fbeab01b
Update https://data.forgejo.org/actions/setup-forgejo action to v3.0.2 (#863)
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.1` -> `v3.0.2` |

---

### Release Notes

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

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

[Compare Source](https://code.forgejo.org/actions/setup-forgejo/compare/v3.0.1...v3.0.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:eyJjcmVhdGVkSW5WZXIiOiI0MS42MS4wIiwidXBkYXRlZEluVmVyIjoiNDEuNjEuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/863): <!--number 863 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL3NldHVwLWZvcmdlam8gYWN0aW9uIHRvIHYzLjAuMg==-->Update https://data.forgejo.org/actions/setup-forgejo action to v3.0.2<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/863
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-08-15 09:49:04 +00:00
Mathieu Fenniak
13247246fc
test: fix data race in TestNewParallelExecutor... tests (#860)
Tests were using `count` and similar variables without any concurrency safety and have been updated to use atomic operations.  This may have caused rare miscounts in tests as operations like `count++` are not thread-safe, but to my knowledge these have never been observed.

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/860
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-08-15 09:12:32 +00:00
Mathieu Fenniak
815e7aed04
chore: prevent "false positive" data race detection w/ ContainerDaemonSocket (#859)
`ContainerDaemonSocket` is stored on a shared struct and was mutated to a default value when empty, which trips the data race detector as a mutation of shared state without any synchronization.  However as all codepaths would be setting it to the same value in the mutation, here's no functional bug.  This commit prevents the "false positive", but it also centralizes the default value for a slightly better programming practice.

```
==================
WARNING: DATA RACE
Read at 0x00c00027f9e0 by goroutine 1104:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).GetBindsAndMounts()
      /.../forgejo-runner/act/runner/run_context.go:130 +0x87
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).prepareJobContainer()
      /.../forgejo-runner/act/runner/run_context.go:449 +0xad1
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).startContainer.func1.(*RunContext).startJobContainer.2()
      /.../forgejo-runner/act/runner/run_context.go:587 +0x5e
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).startContainer.func1()
      /.../forgejo-runner/act/runner/run_context.go:836 +0xf3
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.NewPipelineExecutor.Executor.Then.func21()
      /.../forgejo-runner/act/common/executor.go:136 +0x57
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).Executor.func1()
      /.../forgejo-runner/act/runner/run_context.go:929 +0x68
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.1()
      /.../forgejo-runner/act/runner/runner.go:218 +0x271
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Previous write at 0x00c00027f9e0 by goroutine 1103:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).GetBindsAndMounts()
      /.../forgejo-runner/act/runner/run_context.go:131 +0xc7
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).prepareJobContainer()
      /.../forgejo-runner/act/runner/run_context.go:449 +0xad1
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).startContainer.func1.(*RunContext).startJobContainer.2()
      /.../forgejo-runner/act/runner/run_context.go:587 +0x5e
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).startContainer.func1()
      /.../forgejo-runner/act/runner/run_context.go:836 +0xf3
  code.forgejo.org/forgejo/runner/v9/act/runner.newJobExecutor.NewPipelineExecutor.Executor.Then.func21()
      /.../forgejo-runner/act/common/executor.go:136 +0x57
  code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).Executor.func1()
      /.../forgejo-runner/act/runner/run_context.go:929 +0x68
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.1()
      /.../forgejo-runner/act/runner/runner.go:218 +0x271
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Goroutine 1104 (running) created at:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2()
      /.../forgejo-runner/act/common/executor.go:105 +0x144
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f

Goroutine 1103 (running) created at:
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.2()
      /.../forgejo-runner/act/common/executor.go:105 +0x144
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.1()
      /.../forgejo-runner/act/common/executor.go:107 +0x61
  code.forgejo.org/forgejo/runner/v9/act/runner.(*runnerImpl).NewPlanExecutor.func1.NewParallelExecutor.3.gowrap1()
      /.../forgejo-runner/act/common/executor.go:109 +0x4f
==================
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/859): <!--number 859 --><!--line 0 --><!--description Y2hvcmU6IHByZXZlbnQgImZhbHNlIHBvc2l0aXZlIiBkYXRhIHJhY2UgZGV0ZWN0aW9uIHcvIENvbnRhaW5lckRhZW1vblNvY2tldA==-->chore: prevent "false positive" data race detection w/ ContainerDaemonSocket<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/859
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-08-15 09:11:15 +00:00
Mathieu Fenniak
af0ebf6d51
test: prevent data race detection in TestActionCache (#858)
Data race is being flagged because a goroutine is currently writing tar data into `atar`, and `assert.NotEmpty(atar)` performs internal structure reflection into the returned `io.PipeWriter` and violates its internal synchronization primitives.  This assertion doesn't seem to add any value to the test compared to just reading the pipe, so it has been removed.

Data race details (abbreviated):
```
==================
WARNING: DATA RACE
Write at 0x00c00041fbc0 by goroutine 55:
  sync/atomic.CompareAndSwapInt32()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/runtime/race_amd64.s:361
+0xb
  sync/atomic.CompareAndSwapInt32()
      <autogenerated>:1 +0x18
  sync.(*Mutex).Lock()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/sync/mutex.go:46
+0x28
  io.(*pipe).write()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/io/pipe.go:81
+0x9e
  io.(*PipeWriter).Write()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/io/pipe.go:161
+0x46
  archive/tar.(*Writer).Flush()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/archive/tar/writer.go:59
+0xcc
  archive/tar.(*Writer).WriteHeader()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/archive/tar/writer.go:71
+0x46
  code.forgejo.org/forgejo/runner/v9/act/runner.actionCacheCopyFileOrDir()
      /home/mfenniak/Dev/forgejo-runner/act/runner/action_cache.go:203
+0xabd
  code.forgejo.org/forgejo/runner/v9/act/runner.GoGitActionCache.GetTarArchive.func2.1()
      /home/mfenniak/Dev/forgejo-runner/act/runner/action_cache.go:154
+0xa5
...

Previous read at 0x00c00041fbc0 by goroutine 9:
  reflect.typedmemmove()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/runtime/mbarrier.go:213
+0x0
  reflect.packEface()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/reflect/value.go:136
+0xc5
  reflect.valueInterface()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/reflect/value.go:1513
+0x179
  reflect.Value.Interface()
      /home/mfenniak/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.6.linux-amd64/src/reflect/value.go:1484
+0x106
  github.com/stretchr/testify/assert.isEmpty()
      /home/mfenniak/go/pkg/mod/github.com/stretchr/testify@v1.10.0/assert/assertions.go:735
+0x7f
  github.com/stretchr/testify/assert.NotEmpty()
      /home/mfenniak/go/pkg/mod/github.com/stretchr/testify@v1.10.0/assert/assertions.go:769
+0x56
  github.com/stretchr/testify/assert.(*Assertions).NotEmpty()
      /home/mfenniak/go/pkg/mod/github.com/stretchr/testify@v1.10.0/assert/assertion_forward.go:1175
+0xb1
  code.forgejo.org/forgejo/runner/v9/act/runner.TestActionCache.func1()
      /home/mfenniak/Dev/forgejo-runner/act/runner/action_cache_test.go:60
+0x21e
==================
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/858): <!--number 858 --><!--line 0 --><!--description dGVzdDogcHJldmVudCBkYXRhIHJhY2UgZGV0ZWN0aW9uIGluIFRlc3RBY3Rpb25DYWNoZSBbc2tpcCBjYXNjYWRlXQ==-->test: prevent data race detection in TestActionCache [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/858
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-08-15 09:00:50 +00:00
Earl Warren
2207ff4518
fix: a remote reusable workflow may be from any host 2025-08-15 09:20:19 +02:00
Earl Warren
43c5b23c83
chore: enable test cases for reusable workflows 2025-08-15 09:20:19 +02:00
Earl Warren
026f1ed16c
fix: ensure unique container names for reusable workflows 2025-08-15 09:20:19 +02:00
Michael Kriese
27f425987c
chore: modernize code (#857)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/857
Reviewed-by: earl-warren <earl-warren@noreply.code.forgejo.org>
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-committed-by: Michael Kriese <michael.kriese@visualon.de>
2025-08-15 04:54:13 +00:00
earl-warren
886bf2a4f3
fix: use a unique random name to derive network and volumes for a job (#850)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/850
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.code.forgejo.org>
2025-08-14 16:22:14 +00:00
Earl Warren
c85eb0e647
fix: use a unique random name to derive network and volumes for a job
When a reusable workflow is called twice in the same workflow in
parallel, it may require a dedicated network to run (for instance if
it spawns services) and will always require unique volumes to mount
the workdir and the env.

There really is no way to guarantee a unique name derived from the
job name etc. Instead, a random name is set and used as a base for
both the internal volumes and the dedicated network (if any).
2025-08-14 17:48:34 +02:00
Earl Warren
10c26c53a3
chore: do not hardcode names in TestRunContext_PrepareJobContainer
Replace asserting hard coded names with assertions on how the services
and the job container relate. It slightly improves logic coverage and
makes the test insensitive to how network and volume names are created.

- compare the network names of the services and the job container to be
  equal, demonstrating they can communicate
- verify the mounts and valid volumes of services to be empty
- verify the internal mounts of the job container to be valid volumes
2025-08-14 17:48:34 +02:00
Earl Warren
a197fea4ba
feat: assign a unique random name to each run context
If the run context has a parent, both share the same unique random
name. A composite action does not have a run context of its own, it
re-uses the run context of the job that calls it: this is when a
parent is used and needed.

There may be any level of parent / child relationship and ensureRandom
name recursively look for the first parent with a non empty random.
2025-08-14 17:48:34 +02:00
Earl Warren
023427115f
chore: refactor internal volume names accessors
- getInternalVolumeWorkdir is used instead of rc.jobContainerName()
- getInternalVolumeEnv is used insted of rc.jobContainerName() + "-env"
- getInternalVolumeNames is used when all internal volumes are needed
2025-08-14 17:48:34 +02:00
Earl Warren
8a8e01522d
chore: refactor network name creation
- networkName becomes ensureNetworkName and stores the results
  in the run context instead of returning it
- the getNetworkName and getNetworkCreated accessors are used
  instead of local variables
2025-08-14 17:48:34 +02:00
Earl Warren
f392ec4caa
chore: refactor GetBindsAndMounts to have a context.Context arg 2025-08-14 17:48:34 +02:00
Earl Warren
159c6af0dd
chore: refactor NewDockerVolumeRemoveExecutor (#854)
- remove the force argument as it is always false
- accept more than one volume to be removed

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/854): <!--number 854 --><!--line 0 --><!--description Y2hvcmU6IHJlZmFjdG9yIE5ld0RvY2tlclZvbHVtZVJlbW92ZUV4ZWN1dG9y-->chore: refactor NewDockerVolumeRemoveExecutor<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/854
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-08-14 15:46:52 +00:00
Earl Warren
0ff1ec4c04
chore: panic if a random name cannot be created (#853)
If that happens so much will go wrong that there is no point in continuing to do anything. It simplifies the requirements of the caller: it may be a function that is assumed to never error.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/853): <!--number 853 --><!--line 0 --><!--description Y2hvcmU6IHBhbmljIGlmIGEgcmFuZG9tIG5hbWUgY2Fubm90IGJlIGNyZWF0ZWQ=-->chore: panic if a random name cannot be created<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/853
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-08-14 15:46:01 +00:00
Renovate Bot
987efff021
Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.4.0 (#852)
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.3.1` -> `v2.4.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgolangci%2fgolangci-lint%2fv2%2fcmd%2fgolangci-lint/v2.4.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.3.1/v2.4.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.4.0`](https://github.com/golangci/golangci-lint/blob/HEAD/CHANGELOG.md#v240)

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

1. Enhancements
   - 🎉 go1.25 support
2. Linters new features or changes
   - `exhaustruct`: from v3.3.1 to 4.0.0 (new options: `allow-empty`, `allow-empty-rx`, `allow-empty-returns`, `allow-empty-declarations`)
3. Linters bug fixes
   - `godox`: trim filepath from report messages
   - `staticcheck`: allow empty options
   - `tagalign`: from 1.4.2 to 1.4.3
4. Documentation
   - 🌟 New website (with a search engine)

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS42MS4wIiwidXBkYXRlZEluVmVyIjoiNDEuNjEuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiS2luZC9DaG9yZSJdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/852): <!--number 852 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuNC4w-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.4.0<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/852
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-08-14 11:16:01 +00:00
Earl Warren
773bb92aa3
fix: container removal is the runner responsibility (#851)
If a container is configured for implicit removal in the docker/podman server, it will race against the explicit removal performed by the runner.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/851): <!--number 851 --><!--line 0 --><!--description Zml4OiBjb250YWluZXIgcmVtb3ZhbCBpcyB0aGUgcnVubmVyIHJlc3BvbnNpYmlsaXR5-->fix: container removal is the runner responsibility<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/851
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-08-14 07:47:50 +00:00
Earl Warren
41f8b03b79
fix: the configuration must not be used as temporary storage (#849)
rc.Config should be treated as read-only and not as a temporary storage for the variable list of valid volumes for containers sharing this configuration.

Refs forgejo/runner#848

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/849): <!--number 849 --><!--line 0 --><!--description Zml4OiB0aGUgY29uZmlndXJhdGlvbiBtdXN0IG5vdCBiZSB1c2VkIGFzIHRlbXBvcmFyeSBzdG9yYWdl-->fix: the configuration must not be used as temporary storage<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/849
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-08-12 10:09:42 +00:00
Earl Warren
555b322ce5
fix: update reusable workflow input handling (#834)
Refs https://github.com/nektos/act/pull/2349

---

* update reusable workflow input handling

* make test stricter

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 44d7ad54b07530793bbf965598636c8378beb3f9)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/834): <!--number 834 --><!--line 0 --><!--description Zml4OiB1cGRhdGUgcmV1c2FibGUgd29ya2Zsb3cgaW5wdXQgaGFuZGxpbmc=-->fix: update reusable workflow input handling<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/834
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-08-11 21:10:44 +00:00
Earl Warren
432ea9fdad
fix(security): multline secrets trivially transformed are redacted (#845)
A multiline secret transformed into a single line by replacing with \ followed by n is also redacted.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/845): <!--number 845 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogbXVsdGxpbmUgc2VjcmV0cyB0cml2aWFsbHkgdHJhbnNmb3JtZWQgYXJlIHJlZGFjdGVk-->fix(security): multline secrets trivially transformed are redacted<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/845
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-08-11 18:56:35 +00:00
Earl Warren
0f27403e36
chore(tests): differentiate 'failed to copy content' errors (#846)
```
2025-08-11T13:02:51.0737198Z --- FAIL: TestRunner_RunEvent (431.14s)
2025-08-11T13:02:51.0737236Z     --- FAIL: TestRunner_RunEvent/evalmatrix (2.69s)
2025-08-11T13:02:51.0737270Z         runner_test.go:211:
2025-08-11T13:02:51.0737303Z             	Error Trace:	/home/debian/.cache/act/1682da88a8a84081/hostexecutor/act/runner/runner_test.go:211
2025-08-11T13:02:51.0737398Z             	            				/home/debian/.cache/act/1682da88a8a84081/hostexecutor/act/runner/runner_test.go:362
2025-08-11T13:02:51.0737436Z             	Error:      	Received unexpected error:
2025-08-11T13:02:51.0737470Z             	            	failed to copy content to container: Error response from daemon: Could not find the file /var/run/act/ in container ab61dffc6010bc922c0ab2d2c7edb7a7fe066258ce0145d4146771ce6afbc8f9
2025-08-11T13:02:51.0737507Z             	Test:       	TestRunner_RunEvent/evalmatrix
2025-08-11T13:02:51.0737551Z             	Messages:   	/home/debian/.cache/act/1682da88a8a84081/hostexecutor/act/runner/testdata/evalmatrix
```

```
2025-08-11T13:12:06.9179188Z --- FAIL: TestRunner_RunEvent (343.90s)
2025-08-11T13:12:06.9179215Z     --- FAIL: TestRunner_RunEvent/strategy (7.71s)
2025-08-11T13:12:06.9179241Z         runner_test.go:211:
2025-08-11T13:12:06.9179269Z             	Error Trace:	/home/debian/.cache/act/5a78e5e8c5cb3275/hostexecutor/act/runner/runner_test.go:211
2025-08-11T13:12:06.9179296Z             	            				/home/debian/.cache/act/5a78e5e8c5cb3275/hostexecutor/act/runner/runner_test.go:362
2025-08-11T13:12:06.9179325Z             	Error:      	Received unexpected error:
2025-08-11T13:12:06.9179352Z             	            	failed to copy content to container: Error response from daemon: Could not find the file /var/run/act/ in container 0bee24fbd0b16843147b45915d25aa7bb32c09d68bfdff81cc73bf7278d1c72d
2025-08-11T13:12:06.9179381Z             	Test:       	TestRunner_RunEvent/strategy
2025-08-11T13:12:06.9179407Z             	Messages:   	/home/debian/.cache/act/5a78e5e8c5cb3275/hostexecutor/act/model/testdata/strategy
```

```
2025-08-11T13:34:24.7442134Z --- FAIL: TestRunner_RunEvent (369.80s)
2025-08-11T13:34:24.7442158Z     --- FAIL: TestRunner_RunEvent/no-panic-on-invalid-composite-action (3.04s)
2025-08-11T13:34:24.7442185Z         runner_test.go:214:
2025-08-11T13:34:24.7442209Z             	Error Trace:	/home/debian/.cache/act/690f62172f9b2595/hostexecutor/act/runner/runner_test.go:214
2025-08-11T13:34:24.7442235Z             	            				/home/debian/.cache/act/690f62172f9b2595/hostexecutor/act/runner/runner_test.go:362
2025-08-11T13:34:24.7442262Z             	Error:      	Error "failed to copy content to container: Error response from daemon: Could not find the file /var/run/act/ in container 6441c18fec5b0e3a172672a243e599b628f7729ecaeb543fa3bd2cd02af146e1" does not contain "missing steps in composite action"
2025-08-11T13:34:24.7442295Z             	Test:       	TestRunner_RunEvent/no-panic-on-invalid-composite-action
```

In the absence of a stack trace, having three different places in the
sources where the same error message shows does not help to figure out
how it can happen.

This is a daily false negative.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/846): <!--number 846 --><!--line 0 --><!--description Y2hvcmUodGVzdHMpOiBkaWZmZXJlbnRpYXRlICdmYWlsZWQgdG8gY29weSBjb250ZW50JyBlcnJvcnM=-->chore(tests): differentiate 'failed to copy content' errors<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/846
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-08-11 18:54:09 +00:00
Mathieu Fenniak
e760d04aa6
feat: support actions with 'using: node24' (#847)
It's worth noting for users: the runner does not actually invoke different versions of node depending on the `using` tag -- it just defers to the `node` command in the path regardless of the tagged value.  This change allows `node24` to be provided without error, the same level of support as node12...node20.

FYI: This allows the use of `github.com/actions/checkout@v5`, which was released today and is marked `using: node24`.

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/847
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
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-08-11 18:53:48 +00:00
Earl Warren
e5603fe6d9
chore: integration tests can run for more than 10 minutes (#843)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/843): <!--number 843 --><!--line 0 --><!--description Y2hvcmU6IGludGVncmF0aW9uIHRlc3RzIGNhbiBydW4gZm9yIG1vcmUgdGhhbiAxMCBtaW51dGVz-->chore: integration tests can run for more than 10 minutes<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/843
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-11 13:25:06 +00:00
Earl Warren
0520ff4e05
chore: use t.Context for tests, activate usetesting for lint + add t.TempDir and t.Chdir (#844)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/844): <!--number 844 --><!--line 0 --><!--description Y2hvcmU6IHVzZSB0LkNvbnRleHQgZm9yIHRlc3RzLCBhY3RpdmF0ZSB1c2V0ZXN0aW5nIGZvciBsaW50ICsgYWRkIHQuVGVtcERpciBhbmQgdC5DaGRpciBbc2tpcCBjYXNjYWRlXQ==-->chore: use t.Context for tests, activate usetesting for lint + add t.TempDir and t.Chdir [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/844
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-11 13:21:42 +00:00
Earl Warren
66bb63ea18
chore: require Go v1.24 (#839)
It is not a breaking change for Forgejo because Forgejo v13 already depends on Go v1.24 and Forgejo runner v9 is not compatible with Forgejo versions before v13 from an API point of view. It is however compatible from a protocol point of view and this does not depend on the Go version being used.

It would be a breaking change for third party software using the runner as a package but it is not designed or supported for that.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/839): <!--number 839 --><!--line 0 --><!--description Y2hvcmU6IHJlcXVpcmUgR28gdjEuMjQ=-->chore: require Go v1.24<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/839
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-11 12:49:51 +00:00
Earl Warren
592226943f
chore: set the Kind/Chore label on dependencies upgrades (#842)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/842): <!--number 842 --><!--line 0 --><!--description Y2hvcmU6IHNldCB0aGUgS2luZC9DaG9yZSBsYWJlbCBvbiBkZXBlbmRlbmNpZXMgdXBncmFkZXM=-->chore: set the Kind/Chore label on dependencies upgrades<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/842
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-08-11 08:30:33 +00:00
Renovate Bot
7953ef9a4f
Update module github.com/imdario/mergo to v1 (#840)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/imdario/mergo](https://github.com/imdario/mergo) | `v0.3.16` -> `v1.0.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fimdario%2fmergo/v1.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fimdario%2fmergo/v0.3.16/v1.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>imdario/mergo (github.com/imdario/mergo)</summary>

### [`v1.0.2`](https://github.com/darccio/mergo/releases/tag/v1.0.2)

[Compare Source](https://github.com/imdario/mergo/compare/v1.0.1...v1.0.2)

#### What's Changed

- Drops `gopkg.in/yaml.v3`, only used for loading fixtures. Thanks [@&#8203;trim21](https://github.com/trim21) for bringing to my attention ([#&#8203;262](https://github.com/imdario/mergo/issues/262)) that this library is no longer maintained.

**Full Changelog**: https://github.com/darccio/mergo/compare/v1.0.1...v1.0.2

### [`v1.0.1`](https://github.com/darccio/mergo/releases/tag/v1.0.1)

[Compare Source](https://github.com/imdario/mergo/compare/v1.0.0...v1.0.1)

#### What's Changed

- fixes issue [#&#8203;187](https://github.com/imdario/mergo/issues/187) by [@&#8203;vsemichev](https://github.com/vsemichev) in https://github.com/darccio/mergo/pull/253
- fix: `WithoutDereference` should respect non-nil struct pointers by [@&#8203;joshkaplinsky](https://github.com/joshkaplinsky) in https://github.com/darccio/mergo/pull/251

#### New Contributors

- [@&#8203;vsemichev](https://github.com/vsemichev) made their first contribution in https://github.com/darccio/mergo/pull/253
- [@&#8203;joshkaplinsky](https://github.com/joshkaplinsky) made their first contribution in https://github.com/darccio/mergo/pull/251

**Full Changelog**: https://github.com/darccio/mergo/compare/v1.0.0...v1.0.1

### [`v1.0.0`](https://github.com/darccio/mergo/releases/tag/v1.0.0): 1.0.0 released with new module URL: dario.cat/mergo

[Compare Source](https://github.com/imdario/mergo/compare/v0.3.16...v1.0.0)

This PR is a release containing [0.3.15](https://github.com/imdario/mergo/releases/tag/v0.3.15) features but changing the module URL to `dario.cat/mergo`.

#### What's Changed

- feat: v1.0.0 released by [@&#8203;imdario](https://github.com/imdario) in https://github.com/imdario/mergo/pull/238

**Full Changelog**: https://github.com/imdario/mergo/compare/v0.3.16...v1.0.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:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/840): <!--number 840 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2ltZGFyaW8vbWVyZ28gdG8gdjE=-->Update module github.com/imdario/mergo to v1<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Earl Warren <contact@earl-warren.org>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/840
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-08-11 07:53:51 +00:00
Renovate Bot
92518a9a74
Update module github.com/vektra/mockery/v2 to v3 (#841)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/vektra/mockery/v2](https://github.com/vektra/mockery) | `v2.53.4` -> `v3.5.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fvektra%2fmockery%2fv2/v3.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fvektra%2fmockery%2fv2/v2.53.4/v3.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>vektra/mockery (github.com/vektra/mockery/v2)</summary>

### [`v3.5.2`](https://github.com/vektra/mockery/releases/tag/v3.5.2)

[Compare Source](https://github.com/vektra/mockery/compare/v3.5.1...v3.5.2)

#### What's Changed

- Fix bug with replace-type not working with pointers by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1099

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.5.1...v3.5.2

### [`v3.5.1`](https://github.com/vektra/mockery/releases/tag/v3.5.1)

[Compare Source](https://github.com/vektra/mockery/compare/v3.5.0...v3.5.1)

#### What's Changed

- Bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0 by [@&#8203;dependabot](https://github.com/dependabot)\[bot] in https://github.com/vektra/mockery/pull/1081

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.5.0...v3.5.1

### [`v3.5.0`](https://github.com/vektra/mockery/releases/tag/v3.5.0)

[Compare Source](https://github.com/vektra/mockery/compare/v3.4.0...v3.5.0)

#### What's Changed

- Add `inpackage` flag to override in-package detection logic by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1077
- Add `include-auto-generated` config option by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1079
- Fix issue with rendering multiple templates from same interface by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1080

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.4.0...v3.5.0

### [`v3.4.0`](https://github.com/vektra/mockery/releases/tag/v3.4.0)

[Compare Source](https://github.com/vektra/mockery/compare/v3.3.6...v3.4.0)

#### What's Changed

- Fix issue with type alias to interface not being generated by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1074

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.3.6...v3.4.0

### [`v3.3.6`](https://github.com/vektra/mockery/releases/tag/v3.3.6)

[Compare Source](https://github.com/vektra/mockery/compare/v3.3.5...v3.3.6)

#### What's Changed

- Separate release into reusable github action by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1071
- Fix matryer template imports when outputting mock to different package than source by [@&#8203;chadwpetersen](https://github.com/chadwpetersen) in https://github.com/vektra/mockery/pull/1061
- Fix issue in koanf v2.2.1 by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1068

#### New Contributors

- [@&#8203;chadwpetersen](https://github.com/chadwpetersen) made their first contribution in https://github.com/vektra/mockery/pull/1061

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.3.5...v3.3.6

### [`v3.3.5`](https://github.com/vektra/mockery/compare/v3.3.4...v3.3.5)

[Compare Source](https://github.com/vektra/mockery/compare/v3.3.4...v3.3.5)

### [`v3.3.4`](https://github.com/vektra/mockery/releases/tag/v3.3.4)

[Compare Source](https://github.com/vektra/mockery/compare/v3.3.3...v3.3.4)

#### What's Changed

- Ditch pathlib and fix Windows bugs by [@&#8203;kgadams](https://github.com/kgadams) in https://github.com/vektra/mockery/pull/1062

#### New Contributors

- [@&#8203;kgadams](https://github.com/kgadams) made their first contribution in https://github.com/vektra/mockery/pull/1062

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.3.2...v3.3.4

### [`v3.3.3`](https://github.com/vektra/mockery/compare/v3.3.2...v3.3.3)

[Compare Source](https://github.com/vektra/mockery/compare/v3.3.2...v3.3.3)

### [`v3.3.2`](https://github.com/vektra/mockery/releases/tag/v3.3.2)

[Compare Source](https://github.com/vektra/mockery/compare/v3.3.1...v3.3.2)

#### What's Changed

- Fix anchors causing panics by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1058
- Fix issue with relative `dir` values causing invalid in-package calculation by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1059

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.3.1...v3.3.2

### [`v3.3.1`](https://github.com/vektra/mockery/releases/tag/v3.3.1)

[Compare Source](https://github.com/vektra/mockery/compare/v3.3.0...v3.3.1)

#### What's Changed

- Fix issue when no value specified for variadic arg by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1055
- Bump github.com/spf13/viper from 1.15.0 to 1.20.1 in /tools by [@&#8203;peczenyj](https://github.com/peczenyj) in https://github.com/vektra/mockery/pull/1036

#### New Contributors

- [@&#8203;peczenyj](https://github.com/peczenyj) made their first contribution in https://github.com/vektra/mockery/pull/1036

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.3.0...v3.3.1

### [`v3.3.0`](https://github.com/vektra/mockery/releases/tag/v3.3.0)

[Compare Source](https://github.com/vektra/mockery/compare/v3.2.5...v3.3.0)

#### What's Changed

- Fix uppercase generic type parameters by [@&#8203;fen4o](https://github.com/fen4o) in https://github.com/vektra/mockery/pull/1022
- Add parameter type to EXPECT method doc comments. by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1034
- Fix missing dependency by running go mod tidy by [@&#8203;miner46er](https://github.com/miner46er) in https://github.com/vektra/mockery/pull/1045
- Fix issue with nil in `.Run()` causing panic by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1043
- Fix unroll-variadic default in v3 migration by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1054

#### New Contributors

- [@&#8203;fen4o](https://github.com/fen4o) made their first contribution in https://github.com/vektra/mockery/pull/1022
- [@&#8203;miner46er](https://github.com/miner46er) made their first contribution in https://github.com/vektra/mockery/pull/1045

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.2.5...v3.3.0

### [`v3.2.5`](https://github.com/vektra/mockery/releases/tag/v3.2.5)

[Compare Source](https://github.com/vektra/mockery/compare/v3.2.4...v3.2.5)

#### What's Changed

- Disable `goimports` from messing with imports by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1032
- Fix mockery reading auto-generated files by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1029

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.2.4...v3.2.5

### [`v3.2.4`](https://github.com/vektra/mockery/releases/tag/v3.2.4)

[Compare Source](https://github.com/vektra/mockery/compare/v3.2.3...v3.2.4)

#### What's Changed

- Recursive package generation regex fix by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1026
- Fix variadic parameter handling in `.EXPECT().Run()` by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1027
- Fix unknown `MOCKERY_` env vars causing panics by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1028

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.2.3...v3.2.4

### [`v3.2.3`](https://github.com/vektra/mockery/releases/tag/v3.2.3)

[Compare Source](https://github.com/vektra/mockery/compare/v3.2.2...v3.2.3)

#### What's Changed

- Mention PackageName template variable deprecation by [@&#8203;thejan2009](https://github.com/thejan2009) in https://github.com/vektra/mockery/pull/1018

#### New Contributors

- [@&#8203;thejan2009](https://github.com/thejan2009) made their first contribution in https://github.com/vektra/mockery/pull/1018

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.2.2...v3.2.3

### [`v3.2.2`](https://github.com/vektra/mockery/releases/tag/v3.2.2)

[Compare Source](https://github.com/vektra/mockery/compare/v3.2.1...v3.2.2)

#### What's Changed

- Fix issue with scope lookup returning nil by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1010
- Fix variadic mock generation when `unroll-variadic: false`. by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1011

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.2.1...v3.2.2

### [`v3.2.1`](https://github.com/vektra/mockery/releases/tag/v3.2.1)

[Compare Source](https://github.com/vektra/mockery/compare/v3.2.0...v3.2.1)

#### What's Changed

- Fix invalid generation when variadic has no return values by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1007

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.2.0...v3.2.1

### [`v3.2.0`](https://github.com/vektra/mockery/releases/tag/v3.2.0)

[Compare Source](https://github.com/vektra/mockery/compare/v3.1.0...v3.2.0)

#### What's Changed

- Fix `with-expecter` in migrate command by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1002
- Change `force-file-write` default to be `true`. by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1003
- Fix issue with variadic arguments from return function provider by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/1004
- Bump github.com/go-git/go-git/v5 from 5.12.0 to 5.13.0 in /tools by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/vektra/mockery/pull/1005
- Bump golang.org/x/net from 0.33.0 to 0.36.0 in /tools by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/vektra/mockery/pull/1006

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.1.0...v3.2.0

### [`v3.1.0`](https://github.com/vektra/mockery/releases/tag/v3.1.0)

[Compare Source](https://github.com/vektra/mockery/compare/v3.0.2...v3.1.0)

#### What's Changed

- v3: Build release with latest stable Go version by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/998
- v3: Add `*ast.GenDecl` and `*ast.TypeSpec` comments to `template.Interface` by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/999

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.0.2...v3.1.0

### [`v3.0.2`](https://github.com/vektra/mockery/releases/tag/v3.0.2)

[Compare Source](https://github.com/vektra/mockery/compare/v3.0.1...v3.0.2)

#### What's Changed

- v3: Fix constructor name not respecting exported-ness by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/995

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.0.1...v3.0.2

### [`v3.0.1`](https://github.com/vektra/mockery/releases/tag/v3.0.1)

[Compare Source](https://github.com/vektra/mockery/compare/v3.0.0...v3.0.1)

#### What's Changed

- Fixing the v3 docs configuration by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/986
- v3: Fix `mockery init` failing by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/994

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.0.0...v3.0.1

### [`v3.0.0`](https://github.com/vektra/mockery/releases/tag/v3.0.0)

[Compare Source](https://github.com/vektra/mockery/compare/v2.53.4...v3.0.0)

#### What's Changed

- v3: Update docs and release for v3 GA. by [@&#8203;LandonTClipp](https://github.com/LandonTClipp) in https://github.com/vektra/mockery/pull/985

**Full Changelog**: https://github.com/vektra/mockery/compare/v3.0.0-beta.11...v3.0.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:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/841): <!--number 841 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3Zla3RyYS9tb2NrZXJ5L3YyIHRvIHYz-->Update module github.com/vektra/mockery/v2 to v3<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/841
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-08-11 05:33:56 +00:00
Renovate Bot
f142385313
Update code.forgejo.org/forgejo/runner Docker tag to v9 (#838)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [code.forgejo.org/forgejo/runner](https://forgejo.org) ([source](https://code.forgejo.org/forgejo/runner)) | major | `7.0.0` -> `9.0.3` |

---

### Release Notes

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

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v9.0.2...v9.0.3)

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

Release Notes

***

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

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

- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/804): <!--number 804 --><!--line 0 --><!--description ZmVhdDogbHhjLXN5c3RlbWQgZGVmYXVsdHMgdG8gdXNpbmcgRm9yZ2VqbyBydW5uZXIgOS4wLjI=-->feat: lxc-systemd defaults to using Forgejo runner 9.0.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/784): <!--number 784 --><!--line 0 --><!--description ZmVhdDogLS1oZWFsdGgtKiBvcHRpb25zIGFyZSBhbGxvd2VkIGluIGpvYi48aWQ+LnNlcnZpY2VzLjxpZD4ub3B0aW9ucw==-->feat: --health-\* options are allowed in `job.<id>.services.<id>.options`<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/810): <!--number 810 --><!--line 0 --><!--description Zml4OiBsb2cgdGhlIFVSTCBvZiB0aGUgYWN0aW9uIHdoZW4gaXQgZmFpbHMgc2NoZW1hIHZhbGlkYXRpb24=-->fix: log the URL of the action when it fails schema validation<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/798): <!--number 798 --><!--line 0 --><!--description Zml4OiBsaW5nZXJpbmcgc2VydmljZXMvdm9sdW1lcy9uZXR3b3JrcyBhZnRlciBqb2JzIGlmIGNsZWFudXAgdGFrZXMgPjFtaW4=-->fix: lingering services/volumes/networks after jobs if cleanup takes >1min<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/806): <!--number 806 --><!--line 0 --><!--description Y2hvcmU6IHVwZ3JhZGUgbHhjLWhlbHBlcnM=-->chore: upgrade lxc-helpers<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/627): <!--number 627 --><!--line 0 --><!--description Y2hvcmU6IHRlYWNoIHJlbm92YXRlIGFib3V0IGV4YW1wbGVzL2x4Yy1zeXN0ZW1kL2Zvcmdlam8tcnVubmVyLXNlcnZpY2Uuc2g=-->chore: teach renovate about examples/lxc-systemd/forgejo-runner-service.sh<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/807): <!--number 807 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2NvbnRhaW5lcmQvZXJyZGVmcyB0byB2MQ==-->Update module github.com/containerd/errdefs to v1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/803): <!--number 803 --><!--line 0 --><!--description Y2hvcmU6IGV4cGxhaW4gdGhhdCBwYXJ0IG9mIHRoZSBzb3VyY2UgaXMgQXBhY2hlIDI=-->chore: explain that part of the source is Apache 2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/790): <!--number 790 --><!--line 0 --><!--description Y2hvcmUoY2xlYW51cCk6IGRpc3BhdGNoIHdvcmtmbG93cyBhY2NvcmRpbmcgdG8gdGhlIHJvbGUgb2YgdGhlIHJlcG9zaXRvcnk=-->chore(cleanup): dispatch workflows according to the role of the repository<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/797): <!--number 797 --><!--line 0 --><!--description Y2hvcmU6IHVuaWZ5IGZvcmdlam8gaW1hZ2UgbmFtZXMgbG9jYXRpb24=-->chore: unify forgejo image names location<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/799): <!--number 799 --><!--line 0 --><!--description Y2hvcmU6IHJlcGxhY2UgZG9ja2VyIGh1YiB3aXRoIGNvZGUuZm9yZ2Vqby5vcmc=-->chore: replace docker hub with code.forgejo.org<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/802): <!--number 802 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuMy4x-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.3.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/801): <!--number 801 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL29wZW5jb250YWluZXJzL3NlbGludXggdG8gdjEuMTIuMA==-->Update module github.com/opencontainers/selinux to v1.12.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/800): <!--number 800 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLWdpdC9nby1naXQvdjUgdG8gdjUuMTYuMg==-->Update module github.com/go-git/go-git/v5 to v5.16.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/796): <!--number 796 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2RvY2tlci9jbGkgdG8gdjI4LjMuMytpbmNvbXBhdGlibGU=-->Update module github.com/docker/cli to v28.3.3+incompatible<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/795): <!--number 795 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9yZWxlYXNlLW5vdGVzLWFzc2lzdGFudCB0byB2MS40LjA=-->Update dependency forgejo/release-notes-assistant to v1.4.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/794): <!--number 794 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NwZjEzL3BmbGFnIHRvIHYxLjAuNw==-->Update module github.com/spf13/pflag to v1.0.7<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/793): <!--number 793 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL29wZW5jb250YWluZXJzL2ltYWdlLXNwZWMgdG8gdjEuMS4x-->Update module github.com/opencontainers/image-spec to v1.1.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/792): <!--number 792 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnby5ldGNkLmlvL2Jib2x0IHRvIHYxLjQuMg==-->Update module go.etcd.io/bbolt to v1.4.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/791): <!--number 791 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3JoeXNkL2FjdGlvbmxpbnQgdG8gdjEuNy43-->Update module github.com/rhysd/actionlint to v1.7.7<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/787): <!--number 787 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLWdpdC9nby1iaWxseS92NSB0byB2NS42LjI=-->Update module github.com/go-git/go-billy/v5 to v5.6.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/789): <!--number 789 --><!--line 0 --><!--description Y2hvcmU6IHRoZSByZWxlYXNlIGxpbmsgdG8gUkVMRUFTRS1OT1RFUy5tZCBpcyBubyBsb25nZXIgbmVlZGVkICh0YWtlIDIp-->chore: the release link to RELEASE-NOTES.md is no longer needed (take 2)<!--description-->

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

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v9.0.1...v9.0.2)

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

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

- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/783): <!--number 783 --><!--line 0 --><!--description ZmVhdDogdXNlIGNhY2hlLXtmcm9tLHRvfTogdHlwZT1naGEgaW4gdGhlIGRvY2tlci9idWlsZC1wdXNoLWFjdGlvbiBleGFtcGxl-->feat: use cache-{from,to}: type=gha in the docker/build-push-action example<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/781): <!--number 781 --><!--line 0 --><!--description ZmVhdDogYWRkIGFuIExYQyBiYXNlZCBleGFtcGxlIG9mIGRvY2tlci9idWlsZC1wdXNoLWFjdGlvbiB1c2FnZQ==-->feat: add an LXC based example of docker/build-push-action usage<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/786): <!--number 786 --><!--line 0 --><!--description Zml4OiB2YXJzIGNvbnRleHQgaXMgYWxsb3dlZCBpbiBkZWZhdWx0IHZhbHVlcyBvZiBhY3Rpb24gaW5wdXRz-->fix: vars context is allowed in default values of action inputs<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/788): <!--number 788 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9mb3JnZWpvL2Zvcmdlam8tYnVpbGQtcHVibGlzaCBhY3Rpb24gdG8gdjUuNC4x-->Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.4.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/782): <!--number 782 --><!--line 0 --><!--description Y2hvcmU6IHRoZSByZWxlYXNlIGxpbmsgdG8gUkVMRUFTRS1OT1RFUy5tZCBpcyBubyBsb25nZXIgbmVlZGVk-->chore: the release link to RELEASE-NOTES.md is no longer needed<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/780): <!--number 780 --><!--line 0 --><!--description Y2hvcmUoY2kpOiBhdXRvcmVtb3ZlIHdoZW4gcnVubmluZyBhIHdvcmtmbG93IGluIGEgdGVzdA==-->chore(ci): autoremove when running a workflow in a test<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/778): <!--number 778 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9yZWxlYXNlLW5vdGVzLWFzc2lzdGFudCB0byB2MS4zLjY=-->Update dependency forgejo/release-notes-assistant to v1.3.6<!--description-->

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

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

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

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

<!--URL:https://placeholder:cf42304136a3685c49de800f5b056f97d6471d33@&#8203;code.forgejo.org/forgejo/runner-->

- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/777): <!--number 777 --><!--line 0 --><!--description Y2hvcmU6IHRvIGFsbG93IHRoZSBydW5uZXIgdG8gYmUgaW1wb3J0ZWQsIHY5IG5lZWRzIHRvIGJlIGluIHRoZSBnbyBtb2R1bGU=-->chore: to allow the runner to be imported, v9 needs to be in the go module<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/776): <!--number 776 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2RvY2tlci9kb2NrZXIgdG8gdjI4LjMuMytpbmNvbXBhdGlibGUgW1NFQ1VSSVRZXQ==-->Update module github.com/docker/docker to v28.3.3+incompatible \[SECURITY]<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/775): <!--number 775 --><!--line 0 --><!--description Y2hvcmU6IHJlbGVhc2Ugbm90ZXMgYXJlIG5vdyBwdWJsaXNoZWQgdG9nZXRoZXIgd2l0aCB0aGUgcmVsZWFzZQ==-->chore: release notes are now published together with the release<!--description-->

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

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v8.0.1...v9.0.0)

Workflows and actions go through a schema validation and the runner will not start a job if they do not pass. Some existing workflows or actions may have syntax errors that did not prevent them from running with versions 7.0.0 and below but they will no longer work with versions 8.0.0 and above.

Existing workflows can be verified and fixed before upgrading by using the new `forgejo-runner validate` command. For instance, the following will try to validate workflows and/or actions found in the Git repository at `https://example.com/my/repo` (a local directory at the root of a Git repository can also be used):

```sh
$ forgejo-runner validate --repository https://example.com/my/repo
.forgejo/workflows/release.yml workflow schema validation OK
.forgejo/workflows/test.yml workflow schema validation OK
```

If the error is not immediately obvious, please file an issue with a copy of the failed workflow and revert to using version 7.0.0 until it is resolved.

***

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

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

- features including breaking changes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/740): <!--number 740 --><!--line 0 --><!--description ZmVhdCE6IHJlbW92ZSBzdXBwb3J0IGZvciB1c2luZyBhbiBhcnRpZmFjdCBzZXJ2ZXIgdmlhIENMSQ==-->feat!: remove support for using an artifact server via CLI<!--description-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/757): <!--number 757 --><!--line 0 --><!--description ZmVhdDogdGhlIG5ldyBgZm9yZ2Vqby1ydW5uZXIgdmFsaWRhdGVgIGNvbW1hbmQgY2FuIGJlIHVzZWQgdG8gdmVyaWZ5IGlmIGFuIGFjdGlvbiBvciBhIHdvcmtmbG93IGlzIGNvbmZvcm1hbnQgd2l0aCB0aGUgZXhwZWN0ZWQgc2NoZW1hLiBgZm9yZ2Vqby1ydW5uZXIgdmFsaWRhdGUgLS1yZXBvc2l0b3J5IGh0dHBzOi8vZXhhbXBsZS5jb20vbXkvcmVwb3NpdG9yeWAgd2lsbCB2YWxpZGF0ZSBhbGwgdGhlIHdvcmtmbG93cyBhbmQgYWN0aW9ucyBhIEdpdCByZXBvc2l0b3J5IGNvbnRhaW5zLiBBbHRlcm5hdGl2ZWx5ICBgZm9yZ2Vqby1ydW5uZXIgdmFsaWRhdGUgLS1wYXRoIG15YWN0aW9uL2FjdGlvbi55bWwgLS1hY3Rpb25gIG9yIGBmb3JnZWpvLXJ1bm5lciB2YWxpZGF0ZSAtLXBhdGggLmZvcmdlam8vd29ya2Zsb3dzL3Rlc3QueW1sIC0td29ya2Zsb3dgIGNhbiBiZSB1c2VkIHRvIHZhbGlkYXRlIGEgc2luZ2xlIGZpbGUuIEl0IGlzIHJlY29tbWVuZGVkIHRvIHVzZSB0aGVzZSBjb21tYW5kcyB0byB2ZXJpZnkgZXhpc3RpbmcgYWN0aW9ucyBhbmQgd29ya2Zsb3dzIHBhc3MgYmVmb3JlIHVwZ3JhZGluZyB0byBbRm9yZ2VqbyBydW5uZXIgdjguMC4wXShodHRwczovL2NvZGUuZm9yZ2Vqby5vcmcvZm9yZ2Vqby9ydW5uZXIvc3JjL2JyYW5jaC9tYWluL1JFTEVBU0UtTk9URVMubWQjOC0wLTApIG9yIGFib3ZlIHRvIG5vdCBkaXNydXB0IGV4aXN0aW5nIHdvcmtmbG93cy4=-->feat: the new `forgejo-runner validate` command can be used to verify if an action or a workflow is conformant with the expected schema. `forgejo-runner validate --repository https://example.com/my/repository` will validate all the workflows and actions a Git repository contains. Alternatively  `forgejo-runner validate --path myaction/action.yml --action` or `forgejo-runner validate --path .forgejo/workflows/test.yml --workflow` can be used to validate a single file. It is recommended to use these commands to verify existing actions and workflows pass before upgrading to [Forgejo runner v8.0.0](https://code.forgejo.org/forgejo/runner/src/branch/main/RELEASE-NOTES.md#8-0-0) or above to not disrupt existing workflows.<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/768): <!--number 768 --><!--line 0 --><!--description ZmVhdChzZWN1cml0eSk6IHJlY29tbWVuZCBzZWN1cml0eSBpc3N1ZXMgYXJlIHJlcG9ydGVkIHRvIHNlY3VyaXR5QGZvcmdlam8ub3Jn-->feat(security): recommend security issues are reported to security@forgejo.org<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/769): <!--number 769 --><!--line 0 --><!--description ZmVhdCh0ZXN0cyk6IGNtZCBleGVjdXRlQ29tbWFuZCBjYXB0dXJlcyBzdGRlcnIgJiBzdGRvdXQ=-->feat(tests): cmd executeCommand captures stderr & stdout<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/753): <!--number 753 --><!--line 0 --><!--description ZmVhdDogbWVyZ2UgZm9yZ2Vqby9hY3QvcGtnIGluIHRoZSBhY3QgZGlyZWN0b3J5-->feat: merge forgejo/act/pkg in the act directory<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/770): <!--number 770 --><!--line 0 --><!--description Zml4OiBhbGxvdyBleHByZXNzaW9ucyBpbiBhY3Rpb24gZGVzY3JpcHRpb25zIGFuZCBpbmNvbXBsZXRlIGFjdGlvbiBpbnB1dHM=-->fix: allow expressions in action descriptions and incomplete action inputs<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/761): <!--number 761 --><!--line 0 --><!--description Zml4OiB0aGUgdmFycyBjb250ZXh0IGlzIGFsbG93ZWQgaW4gYW4gYWN0aW9uIHN0ZXAgZW52-->fix: the vars context is allowed in an action step env<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/766): <!--number 766 --><!--line 0 --><!--description Zml4OiBhbGxvdyBleHByZXNzaW9ucyBpbiBzdGVwIGFuZCBqb2IgdXNlczo=-->fix: allow expressions in step and job uses:<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/762): <!--number 762 --><!--line 0 --><!--description Zml4KGNpKTogdXNlIGNvZGUuZm9yZ2Vqby5vcmcgaW5zdGVhZCBvZiB0aGUgZG9ja2VyIGh1Yg==-->fix(ci): use code.forgejo.org instead of the docker hub<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/772): <!--number 772 --><!--line 0 --><!--description UmVzdG9yZSBgY29udHJpYi9mb3JnZWpvLXJ1bm5lci5zZXJ2aWNlYA==-->Restore `contrib/forgejo-runner.service`<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/767): <!--number 767 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSB1bnVzZWQvdW5tYWludGFpbmVkIGZpbGVz-->chore: remove unused/unmaintained files<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/759): <!--number 759 --><!--line 0 --><!--description Y2hvcmU6IGEgc2luZ2xlIHRlc3R1dGlscyBmb3IgYm90aCBhY3QgYW5kIHRoZSBydW5uZXI=-->chore: a single testutils for both act and the runner<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/758): <!--number 758 --><!--line 0 --><!--description Y2hvcmU6IHJlbm92YXRlIG11c3Qgbm90IGxvb2sgYXQgYW55IHRlc3RkYXRhIHN1YmRpcmVjdG9yeQ==-->chore: renovate must not look at any testdata subdirectory<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/756): <!--number 756 --><!--line 0 --><!--description Y2hvcmUocmVsZWFzZS1ub3Rlcyk6IGZpbmFsaXplIDkuMC4w-->chore(release-notes): finalize 9.0.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/754): <!--number 754 --><!--line 0 --><!--description Y2hvcmU6IHVzZSB0aGUgYWN0IGRpcmVjdG9yeSBpbnN0ZWFkIG9mIGh0dHBzOi8vY29kZS5mb3JnZWpvLm9yZy9mb3JnZWpvL2FjdA==-->chore: use the act directory instead of https://code.forgejo.org/forgejo/act<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/752): <!--number 752 --><!--line 0 --><!--description Y2hvcmUoZG9jcyk6IG5ha2VkIGBob3N0YCBzY2hlbWEgaW4gOC4wLjAgaXMgYSBicmVha2luZyBjaGFuZ2U=-->chore(docs): naked `host` schema in 8.0.0 is a breaking change<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/750): <!--number 750 --><!--line 0 --><!--description Y2hvcmU6IGRpc2FibGUgcGFja2FnZSBuYW1lIGNoZWNrcyBmb3IgcmV2aXZlIFtza2lwIGNhc2NhZGVd-->chore: disable package name checks for revive \[skip cascade]<!--description-->

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

### [`v8.0.1`](https://code.forgejo.org/forgejo/runner/blob/HEAD/RELEASE-NOTES.md#801)

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

- [tolerate strings for fail-fast, max-parallel, timeout-minutes, cancel-timeout-minutes](https://code.forgejo.org/forgejo/act/pulls/203).

### [`v8.0.0`](https://code.forgejo.org/forgejo/runner/blob/HEAD/RELEASE-NOTES.md#800)

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

- Breaking change: workflows files go through a [schema validation](https://code.forgejo.org/forgejo/act/pulls/170) and will not run if they do not pass. Some existing workflows may have syntax errors that did not prevent them from running with versions 7.0.0 and below but they will no longer work with versions 8.0.0 and above.
  Existing workflows can be verified and fixed before upgrading by using `forgejo-runner exec --workflows path-to-the-workflow`. For instance in a workflow where `ruins-on` was typed by mistake instead of `runs-on`:
  ```sh
  $ forgejo-runner exec --event unknown --workflows ../forgejo/.forgejo/workflows/build-release.yml
  Error: workflow is not valid. 'build-release.yml': Line: 32 Column 5: Failed to match job-factory: Line: 32 Column 5: Unknown Property ruins-on
  Line: 32 Column 5: Failed to match workflow-job: Line: 32 Column 5: Unknown Property ruins-on
  Line: 35 Column 5: Unknown Property steps
  Forgejo Actions YAML Schema validation error
  ```
  If the error is not immediately obvious, please file an issue with a copy of the failed workflow and revert to using version 7.0.0 until it is resolved.
- Breaking change: the logic assigning labels was updated and refactored:
  - in the absence of a label or a label, [default to `docker://node:22-bookworm` instead of `docker://node:20-bullseye` or `host`](https://code.forgejo.org/forgejo/runner/issues/134).
  - if the `lxc` scheme is set with no argument, it defaults to `lxc://debian:bookworm` instead of `lxc://debian:bullseye`.
  - the `host` schema cannot have any argument, it can no longer be `host://-self-hosted`
- Breaking change: [bash fallback to sh if it is not available](https://code.forgejo.org/forgejo/runner/issues/150). It will use `bash` instead of `sh` when a container image is explicitly specified in the step. If a workflow depens on that behavior, it will need to be modified to explictly set the shell to `sh`.
- Breaking change: [sanitize network aliases to be valid DNS names](https://code.forgejo.org/forgejo/act/pulls/190). It is breaking for workflows with services that rely on host names (derived from the service name or the job name) that do not match `[^A-Z0-9-]+`. They will be sanitized and a message displayed in the logs showing the sanitized name. The service can either be renamed to match the constraint so it can be used as is. Or the sanitized name can be used. For instance of a PostgreSQL service runs as `data.base` it will be sanitized as `data_base`.
- [secrets that contain multiple lines are masked from the output](https://code.forgejo.org/forgejo/runner/pulls/661).
- [sum256 the container name so derivations do not overflow](https://code.forgejo.org/forgejo/act/pulls/191).

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/838
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-08-10 21:10:03 +00:00
Earl Warren
366e88069e
chore: remove the alpha quality warning, it is secure enough to be used in production (#774)
> **Note** change the repository description once it is merged.

- Security issues are to be filed responsibly and will be taken care of by the security team.

Refs https://codeberg.org/forgejo/discussions/issues/377

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/774): <!--number 774 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSB0aGUgYWxwaGEgcXVhbGl0eSB3YXJuaW5nLCBpdCBpcyBzZWN1cmUgZW5vdWdoIHRvIGJlIHVzZWQgaW4gcHJvZHVjdGlvbg==-->chore: remove the alpha quality warning, it is secure enough to be used in production<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/774
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-10 20:21:05 +00:00
Renovate Bot
059ef13b99
Update module golang.org/x/term to v0.34.0 (#837)
This PR contains the following updates:

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

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/837
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-08-10 20:16:40 +00:00
Earl Warren
be5c615201
fix: prevent unintended input replacement in reusable workflows with workflow_dispatch when using workflow_call (#833)
Refs https://github.com/nektos/act/pull/2349

---

See: https://github.com/nektos/act/issues/2464#issuecomment-2430903650

* Add condition to prevent replacing inputs in reusable workflows with workflow_dispatch inputs

---------

Co-authored-by: ChristopherHX <christopher.homberger@web.de>
(cherry picked from commit f4f4265e977a760e0637a65b1554af2cada034cc)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/833): <!--number 833 --><!--line 0 --><!--description Zml4OiBwcmV2ZW50IHVuaW50ZW5kZWQgaW5wdXQgcmVwbGFjZW1lbnQgaW4gcmV1c2FibGUgd29ya2Zsb3dzIHdpdGggd29ya2Zsb3dfZGlzcGF0Y2ggd2hlbiB1c2luZyB3b3JrZmxvd19jYWxs-->fix: prevent unintended input replacement in reusable workflows with workflow_dispatch when using workflow_call<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: S. M. Mahmudul Haque (Yamin) <haque@campus.tu-berlin.de>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/833
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-08-10 19:37:14 +00:00
Renovate Bot
2cbe205186
Update module github.com/docker/go-connections to v0.6.0 (#836)
This PR contains the following updates:

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

---

### Release Notes

<details>
<summary>docker/go-connections (github.com/docker/go-connections)</summary>

### [`v0.6.0`](https://github.com/docker/go-connections/compare/v0.5.0...v0.6.0)

[Compare Source](https://github.com/docker/go-connections/compare/v0.5.0...v0.6.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:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/836
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-08-10 18:25:59 +00:00
Earl Warren
4e5a3025d7
chore: "unable to get git repo" is a debug message, not a warning (#822)
Refs https://github.com/nektos/act/pull/2495

---

* Disable "unable to get git repo" when none exists.

* Restore error back so it's included in bug reports

Change from Warningf to Debugf.

---------

Co-authored-by: Casey Lee <cplee@nektos.com>
(cherry picked from commit e42a534b2e65d28b41532f9a44d18c0354aecfc2)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/822): <!--number 822 --><!--line 0 --><!--description Y2hvcmU6ICJ1bmFibGUgdG8gZ2V0IGdpdCByZXBvIiBpcyBhIGRlYnVnIG1lc3NhZ2UsIG5vdCBhIHdhcm5pbmcgW3NraXAgY2FzY2FkZV0=-->chore: "unable to get git repo" is a debug message, not a warning [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Steven Edwards <cureadvocate@gmail.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/822
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-10 16:24:49 +00:00
Earl Warren
b236cb64f9
fix: composite action input pollution (#818)
refuses to use the default for an nodejs input when an composite action has an input with the same name.

clean cherry-pick (except for trivial context conflict) of two related pull requests

- https://github.com/nektos/act/pull/2348
- https://github.com/nektos/act/pull/2473

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/818): <!--number 818 --><!--line 0 --><!--description Zml4OiBjb21wb3NpdGUgYWN0aW9uIGlucHV0IHBvbGx1dGlvbg==-->fix: composite action input pollution<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/818
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-10 16:24:19 +00:00
Earl Warren
931c2c0ac3
feat: added support for dereferenced map properties (#821)
Refs https://github.com/nektos/act/pull/2635

---

* Added support for dereferenced properties

* Added negative test

* Update pkg/exprparser/functions_test.go

Co-authored-by: ChristopherHX <christopher.homberger@web.de>

* Update pkg/exprparser/functions_test.go

Co-authored-by: ChristopherHX <christopher.homberger@web.de>

* fix lint

---------

Co-authored-by: m1r4c <lars-github@domesjo.com>
Co-authored-by: ChristopherHX <christopher.homberger@web.de>
(cherry picked from commit 20bb25432dd8db44c689a3bc2d440a648e71b3bb)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/821): <!--number 821 --><!--line 0 --><!--description ZmVhdDogYWRkZWQgc3VwcG9ydCBmb3IgZGVyZWZlcmVuY2VkIG1hcCBwcm9wZXJ0aWVz-->feat: added support for dereferenced map properties<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: m1r4c <lars-github.com@domesjo.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/821
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-10 16:24:02 +00:00
Renovate Bot
3ef94e3b41
Update dependency go to v1.24 (#832)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [go](https://go.dev/) ([source](https://github.com/golang/go)) | toolchain | minor | `1.23.12` -> `1.24.6` |

---

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

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/832
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-08-10 16:14:38 +00:00
Mathieu Fenniak
c7dc688858
fix: prevent space prefix/suffix in runner labels (#829)
[Raised on Forgejo](https://codeberg.org/forgejo/forgejo/issues/8803): when a runner is registered with spaces in the comma-separated label list, eg. ` "docker:docker://node:22-bookworm, self-hosted:host, lxc:lxc://debian:bookworm"`, the runner will currently get the labels `"docker"`, `" self-hosted"`, and `" lxc"` which causes unexpected confusion.  Forgejo doesn't display the labels usefully, and targeting the runner with `runs-on` in an action would require an unexpected quoting (eg. `runs-on: " lxc"`).

As an alternative to fixing this in Forgejo's label display, two changes are present here:
- When registering labels via the CLI `--labels` option, or the interactive registering, automatically strip spaces around the commas in the comma-separated list.
- **Breaking**: During startup of the runner, label names that start/end with a space will be considered invalid, resulting in a logged error and the label being ignored:
    ```
    WARN[2025-08-08T21:00:13-06:00] ignored invalid label " debian-latest:docker://node:current-bookworm"  error="invalid label \" debian-latest\": starting or ending with a space is invalid"
    ```
    This is a breaking change in behavior in the case that someone has registered a runner with spaces and modified their activities to use them after recognizing the problem.  But I tend to think it's more likely that this change will *highlight* a misconfiguration and help someone fix it.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/829): <!--number 829 --><!--line 0 --><!--description Zml4OiBwcmV2ZW50IHNwYWNlIHByZWZpeC9zdWZmaXggaW4gcnVubmVyIGxhYmVscw==-->fix: prevent space prefix/suffix in runner labels<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/829
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
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-08-10 15:43:34 +00:00
Earl Warren
e049c82d9c
chore: cancel context used in CI when running workflows (#831)
the context obtained from context.Background() may otherwise survive the test instead. It is equivalent to t.Context() which is only available in go >= v1.24

---

It is suspected to be the cause of

```
2025-08-10T13:01:08.5866723Z [services/Reproduction of failing Services interpolation] [DEBUG] Writing entry to tarball workflow/event.json len:2
2025-08-10T13:01:08.5866772Z [services/Reproduction of failing Services interpolation] [DEBUG] Writing entry to tarball workflow/envs.txt len:0
2025-08-10T13:01:08.5866818Z [services/Reproduction of failing Services interpolation] [DEBUG] Extracting content to '/var/run/act/'
2025-08-10T13:01:08.5866868Z [services/Reproduction of failing Services interpolation] service [postgres]: container health check a6b5d1443dd78f3d3aa244aeccabe72542f1c1ee33200f74a9ea33ae736f01f0 (code.forgejo.org/oci/postgres:16) is starting, waiting 10s
2025-08-10T13:01:08.5866919Z panic: test timed out after 10m0s
2025-08-10T13:01:08.5866984Z 	running tests:
2025-08-10T13:01:08.5867024Z 		TestRunner_RunWithService (2s)
2025-08-10T13:01:08.5867081Z
2025-08-10T13:01:08.5867142Z goroutine 55693 [running]:
2025-08-10T13:01:08.5867206Z testing.(*M).startAlarm.func1()
2025-08-10T13:01:08.5867250Z 	/go_path/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.12.linux-amd64/src/testing/testing.go:2373 +0x385
2025-08-10T13:01:08.5867300Z created by time.goFunc
2025-08-10T13:01:08.5867368Z 	/go_path/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.12.linux-amd64/src/time/sleep.go:215 +0x2d
...
2025-08-10T13:01:08.5878289Z goroutine 55692 [select]:
2025-08-10T13:01:08.5878350Z code.forgejo.org/forgejo/runner/v9/act/runner.waitForServiceContainer({0xf12e50, 0xc0006bbe30}, {0xf1e120, 0xc0003643c0})
2025-08-10T13:01:08.5878402Z 	/home/debian/.cache/act/7ffa26f4231b52fa/hostexecutor/act/runner/run_context.go:757 +0xd7
2025-08-10T13:01:08.5878460Z code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).waitForServiceContainers.func1.1({0xf12e50?, 0xc0006bbe30?})
2025-08-10T13:01:08.5878524Z 	/home/debian/.cache/act/7ffa26f4231b52fa/hostexecutor/act/runner/run_context.go:770 +0x25
2025-08-10T13:01:08.5878592Z code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).waitForServiceContainers.func1.NewParallelExecutor.2.1(0xc00015a5b0, 0xc00015a700)
2025-08-10T13:01:08.5878684Z 	/home/debian/.cache/act/7ffa26f4231b52fa/hostexecutor/act/common/executor.go:107 +0x52
2025-08-10T13:01:08.5878729Z created by code.forgejo.org/forgejo/runner/v9/act/runner.(*RunContext).waitForServiceContainers.func1.NewParallelExecutor.2 in goroutine 55682
2025-08-10T13:01:08.5878777Z 	/home/debian/.cache/act/7ffa26f4231b52fa/hostexecutor/act/common/executor.go:105 +0xf4
2025-08-10T13:01:08.5878821Z

...
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/831): <!--number 831 --><!--line 0 --><!--description Y2hvcmU6IGNhbmNlbCBjb250ZXh0IHVzZWQgaW4gQ0kgd2hlbiBydW5uaW5nIHdvcmtmbG93cyBbc2tpcCBjYXNjYWRlXQ==-->chore: cancel context used in CI when running workflows [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/831
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-08-10 15:10:30 +00:00
Renovate Bot
e331b4380f
Update module google.golang.org/protobuf to v1.36.7 (#828)
This PR contains the following updates:

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

---

### Release Notes

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

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

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

Maintenance / optimizations:

[CL/683955](https://go-review.googlesource.com/c/protobuf/+/683955): encoding/protowire: micro-optimize SizeVarint (-20% on Intel)
[CL/674055](https://go-review.googlesource.com/c/protobuf/+/674055): internal/impl: remove unnecessary atomic access for non-lazy lists
[CL/674015](https://go-review.googlesource.com/c/protobuf/+/674015): impl: remove unnecessary nil check from presence.Present
[CL/673495](https://go-review.googlesource.com/c/protobuf/+/673495): types/descriptorpb: regenerate using latest protobuf v31 release
[CL/670516](https://go-review.googlesource.com/c/protobuf/+/670516): cmd/protoc-gen-go: centralize presence and lazy logic into filedesc
[CL/670515](https://go-review.googlesource.com/c/protobuf/+/670515): internal: move usePresenceForField to internal/filedesc
[CL/670275](https://go-review.googlesource.com/c/protobuf/+/670275): internal/impl: clean up usePresenceForField() (no-op)

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/828): <!--number 828 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1ZiB0byB2MS4zNi43-->Update module google.golang.org/protobuf to v1.36.7<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/828
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-08-10 13:43:45 +00:00
Mathieu Fenniak
a737f197c7
test: fix failures caused by node24 usage in hello-world-javascript-action [skip cascade] (#830)
node24 support has been added to GitHub Actions runner (https://github.com/actions/runner/releases/tag/v2.327.1), after which hello-world-javascript-action was updated to node24 (d5e3943272) causing test failures since forgejo-runner doesn't support `node24`.  To unblock test execution, this pins to the `v1` tag which was already done in two other tests anyway.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/830): <!--number 830 --><!--line 0 --><!--description dGVzdDogZml4IGZhaWx1cmVzIGNhdXNlZCBieSBub2RlMjQgdXNhZ2UgaW4gaGVsbG8td29ybGQtamF2YXNjcmlwdC1hY3Rpb24gW3NraXAgY2FzY2FkZV0=-->test: fix failures caused by node24 usage in hello-world-javascript-action [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/830
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net>
Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
2025-08-10 12:03:50 +00:00
Mathieu Fenniak
7a31b6a55e
feat: support evaluation of concurrency clauses in runner (#827)
Pre-req for support `concurrency` clauses for Gitea Actions, later added to Gitea in PR: https://github.com/go-gitea/gitea/pull/32751. Unit tests added in this PR relative to upstream.

Squashes PRs https://gitea.com/gitea/act/pulls/124 & https://gitea.com/gitea/act/pulls/139, as noted in https://code.forgejo.org/forgejo/runner/issues/678

Reviewed-on: https://gitea.com/gitea/act/pulls/124
Reviewed-by: Lunny Xiao <lunny@noreply.gitea.com>
Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-committed-by: Zettat123 <zettat123@gmail.com>
Reviewed-on: https://gitea.com/gitea/act/pulls/139
Reviewed-by: Zettat123 <zettat123@noreply.gitea.com>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Co-committed-by: ChristopherHX <christopher.homberger@web.de>

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/827): <!--number 827 --><!--line 0 --><!--description ZmVhdDogc3VwcG9ydCBldmFsdWF0aW9uIG9mIGNvbmN1cnJlbmN5IGNsYXVzZXMgaW4gcnVubmVy-->feat: support evaluation of concurrency clauses in runner<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/827
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-08-07 21:47:01 +00:00
Earl Warren
3f468733cb
fix: valueMasker concurrent map write (#825)
* valueMasker create secrets copy

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 7ed767c23a554eefb0a7563c674e7a406393b60f)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/825): <!--number 825 --><!--line 0 --><!--description Zml4OiB2YWx1ZU1hc2tlciBjb25jdXJyZW50IG1hcCB3cml0ZQ==-->fix: valueMasker concurrent map write<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/825
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-07 21:36:28 +00:00
earl-warren
4f883e9707
fix: short sha has at least four digits (#820)
Refs https://github.com/nektos/act/pull/2540

---

Currently it is not very unlikly to have a false match for tag `0` with sha `0XXXXXXXXXXXXXXXXXXXXXXX`, 1 to 16

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 4dc67f6ba28f888328a2568bbcacf49e552650da)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/820): <!--number 820 --><!--line 0 --><!--description Zml4OiBzaG9ydCBzaGEgaGFzIGF0IGxlYXN0IGZvdXIgZGlnaXRz-->fix: short sha has at least four digits<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/820
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
2025-08-07 21:04:09 +00:00
earl-warren
e100e3084c
feat: log parsed commands and step summary (#824)
Refs https://github.com/nektos/act/pull/2761

---

* feat: log parsed command data in json logger

* Could be used to upload the GITHUB_STEP_SUMMARY by downstream Projects
* You can see the summary and other commands
* Access the raw line of most commands

* Update step.go

* Update step.go

* Update push.yml

* .

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit bb7db7b1c8a456d46907f3e65a6c4c2c1dcb6286)

```
Conflicts:
	act/runner/command.go
	act/runner/runner_test.go

  trivial context conflicts for both
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/824): <!--number 824 --><!--line 0 --><!--description ZmVhdDogbG9nIHBhcnNlZCBjb21tYW5kcyBhbmQgc3RlcCBzdW1tYXJ5-->feat: log parsed commands and step summary<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/824
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
2025-08-07 21:03:44 +00:00
Earl Warren
5f1224ba5f
feat: added info log when container image platform mismatched (#826)
Refs https://github.com/nektos/act/pull/3225

---

* added info log when container image platform mismatched

* inline image architecture comparison into ImageExistsLocally function as per review request

(cherry picked from commit 77d31c96a9486553908fdeb1c3053015238d5a0a)

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/826): <!--number 826 --><!--line 0 --><!--description ZmVhdDogYWRkZWQgaW5mbyBsb2cgd2hlbiBjb250YWluZXIgaW1hZ2UgcGxhdGZvcm0gbWlzbWF0Y2hlZA==-->feat: added info log when container image platform mismatched<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Ryan Fleet <rmfleet@gmail.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/826
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-08-07 13:51:55 +00:00
earl-warren
e22d12ae53
fix: amd64 arch to X64 (#2580) (#819)
(cherry picked from commit c671295aab9192b49e4acc981e9c5b2c1d567884)

Refs https://github.com/nektos/act/pull/2580/files

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/819): <!--number 819 --><!--line 0 --><!--description Zml4OiBhbWQ2NCBhcmNoIHRvIFg2NCAoIzI1ODAp-->fix: amd64 arch to X64 (#2580)<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: derrik <82898438+derrik-fleming@users.noreply.github.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/819
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2025-08-07 09:50:35 +00:00
Earl Warren
7a02f8e402
chore: restore GitHub windows build workflow (#815)
Incorrectly removed in bc716490af

Refs https://code.forgejo.org/forgejo/runner/pulls/767

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/815): <!--number 815 --><!--line 0 --><!--description Y2hvcmU6IHJlc3RvcmUgR2l0SHViIHdpbmRvd3MgYnVpbGQgd29ya2Zsb3c=-->chore: restore GitHub windows build workflow<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/815
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-08-07 08:56:39 +00:00
earl-warren
79285e896b
chore: run_context: add GITHUB_RUN_ATTEMPT (#2458) (#817)
* run_context: add GITHUB_RUN_ATTEMPT

Fixes https://github.com/nektos/act/issues/2451
Fixes https://github.com/nektos/act/issues/1615

* fix whitespace

* fix githubcontext

* fix TestSetupEnv

---------

Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 4178166d289bae351ef6d33414cc569518e62a01)

```
Conflicts:
	act/runner/run_context.go
    trivial context conflict
	act/runner/step_test.go
    the corresponding test was removed in the Forgejo runner
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/817): <!--number 817 --><!--line 0 --><!--description Y2hvcmU6IHJ1bl9jb250ZXh0OiBhZGQgR0lUSFVCX1JVTl9BVFRFTVBUICgjMjQ1OCk=-->chore: run_context: add GITHUB_RUN_ATTEMPT (#2458)<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: Ryan <cattm@protonmail.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/817
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2025-08-07 08:02:28 +00:00
Earl Warren
96891ab314
feat: wait for services to be healthy before starting a job (#805)
If a --health-cmd is defined for a container, block until its status is healthy or unhealthy. The timeout is defined by the server internal logic based on associated --health-* defined delays. If it blocks indefinitely, the job timeout will eventually cancel it.

While waiting, the simplest solution would be to sleep 1 second until the container is healthy or unhealthy. To minimize log verbosity, the sleep interval is instead set to --health-interval and default to one second if it is not defined.

This logic does not apply to host containers as they do not support services. They are assumed to always be healthy.

If --health-cmd is set for the container running a job, the first step will start to run without waiting for the container to become healthy. There may be valid use cases for that but they are not the focus of this implementation.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/805): <!--number 805 --><!--line 0 --><!--description ZmVhdDogd2FpdCBmb3Igc2VydmljZXMgdG8gYmUgaGVhbHRoeSBiZWZvcmUgc3RhcnRpbmcgYSBqb2I=-->feat: wait for services to be healthy before starting a job<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/805
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-07 04:36:26 +00:00
Renovate Bot
8644cc9e07
Update dependency go to v1.23.12 (#814)
This PR contains the following updates:

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

---

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

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/814
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-08-07 04:18:50 +00:00
Renovate Bot
386baae8de
Update dependency forgejo/runner to v9.0.3 (#812)
This PR contains the following updates:

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

---

### Release Notes

<details>
<summary>forgejo/runner (forgejo/runner)</summary>

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

[Compare Source](https://code.forgejo.org/forgejo/runner/compare/v9.0.2...v9.0.3)

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

Release Notes

***

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

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

- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/804): <!--number 804 --><!--line 0 --><!--description ZmVhdDogbHhjLXN5c3RlbWQgZGVmYXVsdHMgdG8gdXNpbmcgRm9yZ2VqbyBydW5uZXIgOS4wLjI=-->feat: lxc-systemd defaults to using Forgejo runner 9.0.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/784): <!--number 784 --><!--line 0 --><!--description ZmVhdDogLS1oZWFsdGgtKiBvcHRpb25zIGFyZSBhbGxvd2VkIGluIGpvYi48aWQ+LnNlcnZpY2VzLjxpZD4ub3B0aW9ucw==-->feat: --health-\* options are allowed in `job.<id>.services.<id>.options`<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/810): <!--number 810 --><!--line 0 --><!--description Zml4OiBsb2cgdGhlIFVSTCBvZiB0aGUgYWN0aW9uIHdoZW4gaXQgZmFpbHMgc2NoZW1hIHZhbGlkYXRpb24=-->fix: log the URL of the action when it fails schema validation<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/798): <!--number 798 --><!--line 0 --><!--description Zml4OiBsaW5nZXJpbmcgc2VydmljZXMvdm9sdW1lcy9uZXR3b3JrcyBhZnRlciBqb2JzIGlmIGNsZWFudXAgdGFrZXMgPjFtaW4=-->fix: lingering services/volumes/networks after jobs if cleanup takes >1min<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/806): <!--number 806 --><!--line 0 --><!--description Y2hvcmU6IHVwZ3JhZGUgbHhjLWhlbHBlcnM=-->chore: upgrade lxc-helpers<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/627): <!--number 627 --><!--line 0 --><!--description Y2hvcmU6IHRlYWNoIHJlbm92YXRlIGFib3V0IGV4YW1wbGVzL2x4Yy1zeXN0ZW1kL2Zvcmdlam8tcnVubmVyLXNlcnZpY2Uuc2g=-->chore: teach renovate about examples/lxc-systemd/forgejo-runner-service.sh<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/807): <!--number 807 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2NvbnRhaW5lcmQvZXJyZGVmcyB0byB2MQ==-->Update module github.com/containerd/errdefs to v1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/803): <!--number 803 --><!--line 0 --><!--description Y2hvcmU6IGV4cGxhaW4gdGhhdCBwYXJ0IG9mIHRoZSBzb3VyY2UgaXMgQXBhY2hlIDI=-->chore: explain that part of the source is Apache 2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/790): <!--number 790 --><!--line 0 --><!--description Y2hvcmUoY2xlYW51cCk6IGRpc3BhdGNoIHdvcmtmbG93cyBhY2NvcmRpbmcgdG8gdGhlIHJvbGUgb2YgdGhlIHJlcG9zaXRvcnk=-->chore(cleanup): dispatch workflows according to the role of the repository<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/797): <!--number 797 --><!--line 0 --><!--description Y2hvcmU6IHVuaWZ5IGZvcmdlam8gaW1hZ2UgbmFtZXMgbG9jYXRpb24=-->chore: unify forgejo image names location<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/799): <!--number 799 --><!--line 0 --><!--description Y2hvcmU6IHJlcGxhY2UgZG9ja2VyIGh1YiB3aXRoIGNvZGUuZm9yZ2Vqby5vcmc=-->chore: replace docker hub with code.forgejo.org<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/802): <!--number 802 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuMy4x-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.3.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/801): <!--number 801 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL29wZW5jb250YWluZXJzL3NlbGludXggdG8gdjEuMTIuMA==-->Update module github.com/opencontainers/selinux to v1.12.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/800): <!--number 800 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLWdpdC9nby1naXQvdjUgdG8gdjUuMTYuMg==-->Update module github.com/go-git/go-git/v5 to v5.16.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/796): <!--number 796 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2RvY2tlci9jbGkgdG8gdjI4LjMuMytpbmNvbXBhdGlibGU=-->Update module github.com/docker/cli to v28.3.3+incompatible<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/795): <!--number 795 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9yZWxlYXNlLW5vdGVzLWFzc2lzdGFudCB0byB2MS40LjA=-->Update dependency forgejo/release-notes-assistant to v1.4.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/794): <!--number 794 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NwZjEzL3BmbGFnIHRvIHYxLjAuNw==-->Update module github.com/spf13/pflag to v1.0.7<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/793): <!--number 793 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL29wZW5jb250YWluZXJzL2ltYWdlLXNwZWMgdG8gdjEuMS4x-->Update module github.com/opencontainers/image-spec to v1.1.1<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/792): <!--number 792 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnby5ldGNkLmlvL2Jib2x0IHRvIHYxLjQuMg==-->Update module go.etcd.io/bbolt to v1.4.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/791): <!--number 791 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3JoeXNkL2FjdGlvbmxpbnQgdG8gdjEuNy43-->Update module github.com/rhysd/actionlint to v1.7.7<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/787): <!--number 787 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLWdpdC9nby1iaWxseS92NSB0byB2NS42LjI=-->Update module github.com/go-git/go-billy/v5 to v5.6.2<!--description-->
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/789): <!--number 789 --><!--line 0 --><!--description Y2hvcmU6IHRoZSByZWxlYXNlIGxpbmsgdG8gUkVMRUFTRS1OT1RFUy5tZCBpcyBubyBsb25nZXIgbmVlZGVkICh0YWtlIDIp-->chore: the release link to RELEASE-NOTES.md is no longer needed (take 2)<!--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 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:eyJjcmVhdGVkSW5WZXIiOiI0MS41MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuNTEuMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/812
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-08-06 13:07:24 +00:00
Earl Warren
8819e2a195
chore: links to container images and documentation in the release (#811)
The 9.0.3 release was manually updated so it shows how it would look.

https://code.forgejo.org/forgejo/runner/releases/tag/v9.0.3

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/811): <!--number 811 --><!--line 0 --><!--description Y2hvcmU6IGxpbmtzIHRvIGNvbnRhaW5lciBpbWFnZXMgYW5kIGRvY3VtZW50YXRpb24gaW4gdGhlIHJlbGVhc2U=-->chore: links to container images and documentation in the release<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/811
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-08-05 14:00:27 +00:00
Earl Warren
8b7e126c1c
fix: log the URL of the action when it fails schema validation (#810)
```
$ go test -v -run='TestRunner_RunEvent$/local-action-fails-schema-validation' ./act/runner
...
[fails-schema-validation/test]     Failure - Main ./local-action-fails-schema-validation/action
[fails-schema-validation/test] failed to validate action.y*ml from action './local-action-fails-schema-validation/action' with path '': Line: 2 Column 3: Failed to match null: Line: 2 Column 3: Expected a scalar got mapping
Line: 2 Column 3: Failed to match inputs-mapping: Line: 3 Column 5: Failed to match null: Line: 3 Column 5: Expected a scalar got mapping
Line: 3 Column 5: Failed to match input-mapping: Line: 3 Column 14: Unknown Variable Access secrets
...
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/810): <!--number 810 --><!--line 0 --><!--description Zml4OiBsb2cgdGhlIFVSTCBvZiB0aGUgYWN0aW9uIHdoZW4gaXQgZmFpbHMgc2NoZW1hIHZhbGlkYXRpb24=-->fix: log the URL of the action when it fails schema validation<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/810
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-08-04 13:20:22 +00:00
cascading-pr
ce0c5b2b78
upgrade lxc-helpers (#806)
cascading-pr from https://code.forgejo.org/forgejo/lxc-helpers/pulls/41

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/806): <!--number 806 --><!--line 0 --><!--description dXBncmFkZSBseGMtaGVscGVycw==-->upgrade lxc-helpers<!--description-->
<!--end release-notes-assistant-->

Co-authored-by: cascading-pr <cascading-pr@example.com>
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/806
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-08-04 08:06:31 +00:00
Earl Warren
9ec950289e
chore: teach renovate about examples/lxc-systemd/forgejo-runner-service.sh (#627)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/627): <!--number 627 --><!--line 0 --><!--description Y2hvcmU6IHRlYWNoIHJlbm92YXRlIGFib3V0IGV4YW1wbGVzL2x4Yy1zeXN0ZW1kL2Zvcmdlam8tcnVubmVyLXNlcnZpY2Uuc2g=-->chore: teach renovate about examples/lxc-systemd/forgejo-runner-service.sh<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/627
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-08-03 17:45:58 +00:00
Renovate Bot
2e9bb84bae
Update module github.com/containerd/errdefs to v1 (#807)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/containerd/errdefs](https://github.com/containerd/errdefs) | `v0.3.0` -> `v1.0.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fcontainerd%2ferrdefs/v1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fcontainerd%2ferrdefs/v0.3.0/v1.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>containerd/errdefs (github.com/containerd/errdefs)</summary>

### [`v1.0.0`](https://github.com/containerd/errdefs/releases/tag/v1.0.0)

[Compare Source](https://github.com/containerd/errdefs/compare/v0.3.0...v1.0.0)

The first major release of errdefs brings a guarantee of stability with the error types and interface. Additional functions for grpc and http error translation and stacktraces can be found in the separate `github.com/containerd/errdefs/pkg` module.

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/807
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-08-03 15:41:13 +00:00
Earl Warren
73797fe7cd
chore: explain that part of the source is Apache 2 (#803)
When ACT was transplanted in the runner, it brought with it Apache 2 licensed code copied from the docker project. Clarify that in the README.

It has no impact on the future relicensing to GPLv3+ because Apache 2 is a compatible license.

Refs: https://code.forgejo.org/forgejo/runner/pulls/773
Refs: https://www.gnu.org/licenses/license-list.en.html#apache2

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/803): <!--number 803 --><!--line 0 --><!--description Y2hvcmU6IGV4cGxhaW4gdGhhdCBwYXJ0IG9mIHRoZSBzb3VyY2UgaXMgQXBhY2hlIDI=-->chore: explain that part of the source is Apache 2<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/803
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-08-03 09:57:41 +00:00
Earl Warren
2b9617c7f8
feat: lxc-systemd defaults to using Forgejo runner 9.0.2 (#804)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/804): <!--number 804 --><!--line 0 --><!--description ZmVhdDogbHhjLXN5c3RlbWQgZGVmYXVsdHMgdG8gdXNpbmcgRm9yZ2VqbyBydW5uZXIgOS4wLjI=-->feat: lxc-systemd defaults to using Forgejo runner 9.0.2<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/804
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-08-03 09:57:24 +00:00
Earl Warren
83e7b4ae10
chore(cleanup): dispatch workflows according to the role of the repository (#790)
The `vars.ROLE` in each repository was set as follows:

- https://code.forgejo.org/forgejo/runner => forgejo-coding
- https://code.forgejo.org/forgejo-integration/runner => forgejo-integration
- https://invisible.forgejo.org/forgejo/runner => forgejo-release

It reflects how Forgejo roles are dispatched. Update all workflows to
use the ROLE to determine if it is relevant for them to run. It is
more straightforward than the previous approach based on the name of
the owner.

There were cases where the logic was wrong and workflows ran
needlessly, for instance because the runner release is now published
from an organization that is forgejo and not forgejo-release.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/790): <!--number 790 --><!--line 0 --><!--description Y2hvcmUoY2xlYW51cCk6IGRpc3BhdGNoIHdvcmtmbG93cyBhY2NvcmRpbmcgdG8gdGhlIHJvbGUgb2YgdGhlIHJlcG9zaXRvcnk=-->chore(cleanup): dispatch workflows according to the role of the repository<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/790
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-08-03 08:34:09 +00:00
Renovate Bot
7c81802bb6
Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.3.1 (#802)
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.3.0` -> `v2.3.1` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgolangci%2fgolangci-lint%2fv2%2fcmd%2fgolangci-lint/v2.3.1?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.3.0/v2.3.1?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.3.1`](https://github.com/golangci/golangci-lint/blob/HEAD/CHANGELOG.md#v231)

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

1. Linters bug fixes
   - `gci`: from 0.13.6 to 0.13.7
   - `gosec`: from 2.22.6 to 2.22.7
   - `noctx`: from 0.3.5 to 0.4.0
   - `wsl`: from 5.1.0 to 5.1.1
   - tagliatelle: force upper case for custom initialisms

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/802
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-08-03 07:20:54 +00:00
Mathieu Fenniak
646a0d761f
fix: longer timeouts on job cleanup without waiting (v2) (#798)
Probably fixes #431 (see investigation notes: https://code.forgejo.org/forgejo/runner/issues/431#issuecomment-50810) by extending the timeout for all cleanup actions from 1 minute to 30 minutes, and run cleanup after the task status is reported back to Forgejo.  Cleanup logging now goes in the runner log rather than the job log, and it was tweaked to be less verbose and contain more useful identifying information on the job in case of error.

Manual testing confirms that Forgejo receives the success/failure status of the task before cleanup begins, that no further logging reaches the task at that point, and that the longer cleanup timeout is applied as expected.

This is an alternate, simplified version of #779.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/798): <!--number 798 --><!--line 0 --><!--description Zml4OiBsb25nZXIgdGltZW91dHMgb24gam9iIGNsZWFudXAgd2l0aG91dCB3YWl0aW5nICh2Mik=-->fix: longer timeouts on job cleanup without waiting (v2)<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/798
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-08-03 07:01:46 +00:00
Earl Warren
65d762d1cc
feat: --health-* options are allowed in job.<id>.services.<id>.options (#784)
they override any similar options from the configuration file since it would not make much sense to define a health check that applies to all containers, it is only ever meaningful for services.

```yaml
jobs:
  mysql:
    runs-on: ubuntu-latest
    container: mysql:8
    services:
      maindb:
        image: mysql:8
        env:
          MYSQL_DATABASE: dbname
          MYSQL_USER: dbuser
          MYSQL_PASSWORD: dbpass
          MYSQL_RANDOM_ROOT_PASSWORD: yes
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
```

they are also allowed in job.<id>.container.options although they are not useful because they are harmless

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

---

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/784): <!--number 784 --><!--line 0 --><!--description ZmVhdDogLS1oZWFsdGgtKiBvcHRpb25zIGFyZSBhbGxvd2VkIGluIGpvYi48aWQ+LnNlcnZpY2VzLjxpZD4ub3B0aW9ucw==-->feat: --health-* options are allowed in job.<id>.services.<id>.options<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/784
Reviewed-by: Gusted <gusted@noreply.code.forgejo.org>
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-02 23:51:09 +00:00
Renovate Bot
6bff61dd7a
Update module github.com/opencontainers/selinux to v1.12.0 (#801)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/opencontainers/selinux](https://github.com/opencontainers/selinux) | `v1.11.0` -> `v1.12.0` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fopencontainers%2fselinux/v1.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fopencontainers%2fselinux/v1.11.0/v1.12.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>opencontainers/selinux (github.com/opencontainers/selinux)</summary>

### [`v1.12.0`](https://github.com/opencontainers/selinux/releases/tag/v1.12.0)

[Compare Source](https://github.com/opencontainers/selinux/compare/v1.11.1...v1.12.0)

This release removes deprecated functions from the `label` package,
and improves documentation and error reporting of `SetCreateKey`.

#### What's Changed

- VERSION: remove by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/217
- CI: add AlmaLinux 8, CentOS Stream 9, and Fedora by [@&#8203;AkihiroSuda](https://github.com/AkihiroSuda) in https://github.com/opencontainers/selinux/pull/221
- ci: install git-core by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/224
- CI: add openSUSE Tumbleweed by [@&#8203;AkihiroSuda](https://github.com/AkihiroSuda) in https://github.com/opencontainers/selinux/pull/223
- Bump Go version, deps, fix some linter issues... by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/218
- label: remove deprecated stuff by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/228
- Improve SetKeyCreate error reporting, fix test flakes by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/227

**Full Changelog**: https://github.com/opencontainers/selinux/compare/v1.11.1...v1.12.0

### [`v1.11.1`](https://github.com/opencontainers/selinux/releases/tag/v1.11.1)

[Compare Source](https://github.com/opencontainers/selinux/compare/v1.11.0...v1.11.1)

#### What's Changed

- Bump to v1.11.0 by [@&#8203;rhatdan](https://github.com/rhatdan) in https://github.com/opencontainers/selinux/pull/197
- fix some error by [@&#8203;ningmingxiao](https://github.com/ningmingxiao) in https://github.com/opencontainers/selinux/pull/200
- ci: update Go 1.21 support by [@&#8203;michalbiesek](https://github.com/michalbiesek) in https://github.com/opencontainers/selinux/pull/202
- Extend `build-cross` target with `riscv64` arch by [@&#8203;michalbiesek](https://github.com/michalbiesek) in https://github.com/opencontainers/selinux/pull/201
- Remove nolint annotations for unix errno comparisons by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/203
- ci: bump some actions by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/205
- Misc nitpicks by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/206
- pwalk, pwalkdir: fix walk vs remove race by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/204
- Update GitHub Actions CI Go matrix for Go v1.22 by [@&#8203;austinvazquez](https://github.com/austinvazquez) in https://github.com/opencontainers/selinux/pull/209
- Update GitHub Actions packages to resolve deprecation warnings. by [@&#8203;austinvazquez](https://github.com/austinvazquez) in https://github.com/opencontainers/selinux/pull/208
- Add dependabot config by [@&#8203;kolyshkin](https://github.com/kolyshkin) in https://github.com/opencontainers/selinux/pull/210
- build(deps): bump tim-actions/get-pr-commits from 1.3.0 to 1.3.1 by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/opencontainers/selinux/pull/211
- build(deps): bump golangci/golangci-lint-action from 4 to 6 by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/opencontainers/selinux/pull/213
- Show SELinux label on failure by [@&#8203;rhatdan](https://github.com/rhatdan) in https://github.com/opencontainers/selinux/pull/216

#### New Contributors

- [@&#8203;ningmingxiao](https://github.com/ningmingxiao) made their first contribution in https://github.com/opencontainers/selinux/pull/200
- [@&#8203;michalbiesek](https://github.com/michalbiesek) made their first contribution in https://github.com/opencontainers/selinux/pull/202
- [@&#8203;dependabot](https://github.com/dependabot) made their first contribution in https://github.com/opencontainers/selinux/pull/211

**Full Changelog**: https://github.com/opencontainers/selinux/compare/v1.11.0...v1.11.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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/801
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-08-02 23:47:31 +00:00
Renovate Bot
6c0ed713ac
Update module github.com/go-git/go-git/v5 to v5.16.2 (#800)
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.13.1` -> `v5.16.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgo-git%2fgo-git%2fv5/v5.16.2?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.13.1/v5.16.2?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.2`](https://github.com/go-git/go-git/releases/tag/v5.16.2)

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

#### What's Changed

- utils: fix diff so subpaths work for sparse checkouts, fixes 1455 to releases/v5.x by [@&#8203;kane8n](https://github.com/kane8n) in https://github.com/go-git/go-git/pull/1567

**Full Changelog**: https://github.com/go-git/go-git/compare/v5.16.1...v5.16.2

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

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

#### What's Changed

- utils: merkletrie, Fix diff on sparse-checkout index. Fixes [#&#8203;1406](https://github.com/go-git/go-git/issues/1406) to releases/v5.x by [@&#8203;kane8n](https://github.com/kane8n) in https://github.com/go-git/go-git/pull/1561

#### New Contributors

- [@&#8203;kane8n](https://github.com/kane8n) made their first contribution in https://github.com/go-git/go-git/pull/1561

**Full Changelog**: https://github.com/go-git/go-git/compare/v5.16.0...v5.16.1

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

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

#### What's Changed

- \[v5] plumbing: support mTLS for HTTPS protocol by [@&#8203;hiddeco](https://github.com/hiddeco) in https://github.com/go-git/go-git/pull/1510
- v5: plumbing: transport, Reintroduce SetHostKeyCallback. Fix [#&#8203;1514](https://github.com/go-git/go-git/issues/1514) by [@&#8203;pjbgf](https://github.com/pjbgf) in https://github.com/go-git/go-git/pull/1515

**Full Changelog**: https://github.com/go-git/go-git/compare/v5.15.0...v5.16.0

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

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

#### What's Changed

- plumbing: add cert auth support to `releases/v5.x` by [@&#8203;Javier-varez](https://github.com/Javier-varez) in https://github.com/go-git/go-git/pull/1482
- v5: Bump dependencies by [@&#8203;pjbgf](https://github.com/pjbgf) in https://github.com/go-git/go-git/pull/1505

**Full Changelog**: https://github.com/go-git/go-git/compare/v5.14.0...v5.15.0

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

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

#### What's Changed

- v5: Bump Go and dependencies to mitigate [GO-2025-3487](https://pkg.go.dev/vuln/GO-2025-3487) by [@&#8203;pjbgf](https://github.com/pjbgf) in https://github.com/go-git/go-git/pull/1436

⚠️ Note that this version requires Go 1.23, due to the bump to `golang.org/x/crypto@v0.35.0` which mitigates the CVE above. User's that can't bump to Go 1.23 will need to remain on the previous v5.13.x release.

**Full Changelog**: https://github.com/go-git/go-git/compare/v5.13.2...v5.14.0

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

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

#### What's Changed

- plumbing: use the correct user agent string. Fixes [#&#8203;883](https://github.com/go-git/go-git/issues/883) by [@&#8203;uragirii](https://github.com/uragirii) in https://github.com/go-git/go-git/pull/1364
- build: bump golang.org/x/sys from 0.28.0 to 0.29.0 in the golang-org group by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/go-git/go-git/pull/1365
- build: bump the golang-org group with 2 updates by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/go-git/go-git/pull/1367
- build: bump github.com/ProtonMail/go-crypto from 1.1.3 to 1.1.4 by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/go-git/go-git/pull/1368
- build: bump github.com/go-git/go-billy/v5 from 5.6.1 to 5.6.2 by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/go-git/go-git/pull/1378
- build: bump github/codeql-action from 3.28.0 to 3.28.1 by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/go-git/go-git/pull/1376
- build: bump github.com/elazarl/goproxy from 1.2.3 to 1.4.0 by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/go-git/go-git/pull/1377
- git: worktree, fix restoring dot slash files (backported to v5). Fixes [#&#8203;1176](https://github.com/go-git/go-git/issues/1176) by [@&#8203;BeChris](https://github.com/BeChris) in https://github.com/go-git/go-git/pull/1361
- build: bump github.com/pjbgf/sha1cd from 0.3.0 to 0.3.2 by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/go-git/go-git/pull/1392
- git: worktree\_status, fix adding dot slash files to working tree (backported to v5). Fixes [#&#8203;1150](https://github.com/go-git/go-git/issues/1150) by [@&#8203;BeChris](https://github.com/BeChris) in https://github.com/go-git/go-git/pull/1359
- build: bump github.com/ProtonMail/go-crypto from 1.1.4 to 1.1.5 by [@&#8203;dependabot](https://github.com/dependabot) in https://github.com/go-git/go-git/pull/1383

**Full Changelog**: https://github.com/go-git/go-git/compare/v5.13.1...v5.13.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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/800
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-08-02 23:00:47 +00:00
Earl Warren
805d83e974
chore: unify forgejo image names location (#797)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/797): <!--number 797 --><!--line 0 --><!--description Y2hvcmU6IHVuaWZ5IGZvcmdlam8gaW1hZ2UgbmFtZXMgbG9jYXRpb24=-->chore: unify forgejo image names location<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/797
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-02 22:05:15 +00:00
Earl Warren
79f6c54675
chore: replace docker hub with code.forgejo.org (#799)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/799): <!--number 799 --><!--line 0 --><!--description Y2hvcmU6IHJlcGxhY2UgZG9ja2VyIGh1YiB3aXRoIGNvZGUuZm9yZ2Vqby5vcmc=-->chore: replace docker hub with code.forgejo.org<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/799
Co-authored-by: Earl Warren <contact@earl-warren.org>
Co-committed-by: Earl Warren <contact@earl-warren.org>
2025-08-02 21:55:57 +00:00
Renovate Bot
c3c6555558
Update module github.com/docker/cli to v28.3.3+incompatible (#796)
This PR contains the following updates:

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

---

### Release Notes

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

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

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

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

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

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

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

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

[Compare Source](https://github.com/docker/cli/compare/v28.2.2...v28.3.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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/796
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-08-02 20:25:54 +00:00
Renovate Bot
545cd0ece5
Update dependency forgejo/release-notes-assistant to v1.4.0 (#795)
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [forgejo/release-notes-assistant](https://code.forgejo.org/forgejo/release-notes-assistant) | minor | `v1.3.6` -> `v1.4.0` |

---

### Release Notes

<details>
<summary>forgejo/release-notes-assistant (forgejo/release-notes-assistant)</summary>

### [`v1.4.0`](https://code.forgejo.org/forgejo/release-notes-assistant/releases/tag/v1.4.0)

[Compare Source](https://code.forgejo.org/forgejo/release-notes-assistant/compare/v1.3.6...v1.4.0)

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

<!--URL:https://code.forgejo.org/forgejo/release-notes-assistant-->

- features
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/104): <!--number 104 --><!--line 0 --><!--description ZmVhdDogc3VwcG9ydCBmZXRjaGluZyBmcm9tIHByaXZhdGUgcmVwb3NpdG9yaWVz-->feat: support fetching from private repositories<!--description-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/102): <!--number 102 --><!--line 0 --><!--description Zml4KHNlY3VyaXR5KTogcmVtb3ZlIHVzZXIgLyBwYXNzd29yZCBmcm9tIHRoZSBVUkw=-->fix(security): remove user / password from the URL<!--description-->
- other
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/93): <!--number 93 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuMy4w-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.3.0<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/103): <!--number 103 --><!--line 0 --><!--description Y2hvcmUoY2kpOiBkbyBub3QgcnVuIHRlc3RzIG9uIHJlbm92YXRlIGJyYW5jaGVz-->chore(ci): do not run tests on renovate branches<!--description-->
  - [PR](https://code.forgejo.org/forgejo/release-notes-assistant/pulls/101): <!--number 101 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL2Zvcmdlam8tcmVsZWFzZSBhY3Rpb24gdG8gdjIuNy4x-->Update https://data.forgejo.org/actions/forgejo-release action to v2.7.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 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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/795
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-08-02 20:13:42 +00:00
Renovate Bot
aa47089005
Update module github.com/spf13/pflag to v1.0.7 (#794)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/spf13/pflag](https://github.com/spf13/pflag) | `v1.0.6` -> `v1.0.7` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fspf13%2fpflag/v1.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fspf13%2fpflag/v1.0.6/v1.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>spf13/pflag (github.com/spf13/pflag)</summary>

### [`v1.0.7`](https://github.com/spf13/pflag/releases/tag/v1.0.7)

[Compare Source](https://github.com/spf13/pflag/compare/v1.0.6...v1.0.7)

#### What's Changed

- Fix defaultIsZeroValue check for generic Value types by [@&#8203;MidnightRocket](https://github.com/MidnightRocket) in https://github.com/spf13/pflag/pull/422
- feat: Use structs for errors returned by pflag. by [@&#8203;eth-p](https://github.com/eth-p) in https://github.com/spf13/pflag/pull/425
- Fix typos by [@&#8203;co63oc](https://github.com/co63oc) in https://github.com/spf13/pflag/pull/428
- fix [#&#8203;423](https://github.com/spf13/pflag/issues/423) : Add helper function and some documentation to parse shorthand go test flags. by [@&#8203;valdar](https://github.com/valdar) in https://github.com/spf13/pflag/pull/424
- add support equivalent to golang flag.TextVar(), also fixes the test failure as described in [#&#8203;368](https://github.com/spf13/pflag/issues/368) by [@&#8203;hujun-open](https://github.com/hujun-open) in https://github.com/spf13/pflag/pull/418
- add support for Func() and BoolFunc() [#&#8203;426](https://github.com/spf13/pflag/issues/426) by [@&#8203;LeGEC](https://github.com/LeGEC) in https://github.com/spf13/pflag/pull/429
- fix: correct argument length check in FlagSet.Parse by [@&#8203;ShawnJeffersonWang](https://github.com/ShawnJeffersonWang) in https://github.com/spf13/pflag/pull/409
- fix usage message for func flags, fix arguments order by [@&#8203;LeGEC](https://github.com/LeGEC) in https://github.com/spf13/pflag/pull/431
- Add support for time.Time flags by [@&#8203;max-frank](https://github.com/max-frank) in https://github.com/spf13/pflag/pull/348

#### New Contributors

- [@&#8203;MidnightRocket](https://github.com/MidnightRocket) made their first contribution in https://github.com/spf13/pflag/pull/422
- [@&#8203;eth-p](https://github.com/eth-p) made their first contribution in https://github.com/spf13/pflag/pull/425
- [@&#8203;co63oc](https://github.com/co63oc) made their first contribution in https://github.com/spf13/pflag/pull/428
- [@&#8203;valdar](https://github.com/valdar) made their first contribution in https://github.com/spf13/pflag/pull/424
- [@&#8203;hujun-open](https://github.com/hujun-open) made their first contribution in https://github.com/spf13/pflag/pull/418
- [@&#8203;LeGEC](https://github.com/LeGEC) made their first contribution in https://github.com/spf13/pflag/pull/429
- [@&#8203;ShawnJeffersonWang](https://github.com/ShawnJeffersonWang) made their first contribution in https://github.com/spf13/pflag/pull/409
- [@&#8203;max-frank](https://github.com/max-frank) made their first contribution in https://github.com/spf13/pflag/pull/348

**Full Changelog**: https://github.com/spf13/pflag/compare/v1.0.6...v1.0.7

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/794
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-08-02 18:51:59 +00:00
Renovate Bot
41379391b6
Update module github.com/opencontainers/image-spec to v1.1.1 (#793)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec) | `v1.1.0` -> `v1.1.1` | [![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fopencontainers%2fimage-spec/v1.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fopencontainers%2fimage-spec/v1.1.0/v1.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>opencontainers/image-spec (github.com/opencontainers/image-spec)</summary>

### [`v1.1.1`](https://github.com/opencontainers/image-spec/releases/tag/v1.1.1)

[Compare Source](https://github.com/opencontainers/image-spec/compare/v1.1.0...v1.1.1)

Vote Passed  `[+5 -0 nv1]`  - https://groups.google.com/a/opencontainers.org/g/dev/c/T-olx0jdT18
**Release PR** : https://github.com/opencontainers/image-spec/pull/1247
**Full Changelog**: https://github.com/opencontainers/image-spec/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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/793
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-08-02 18:44:09 +00:00
Renovate Bot
b6cd1c7287
Update module go.etcd.io/bbolt to v1.4.2 (#792)
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) | `v1.3.10` -> `v1.4.2` | [![age](https://developer.mend.io/api/mc/badges/age/go/go.etcd.io%2fbbolt/v1.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/go/go.etcd.io%2fbbolt/v1.3.10/v1.4.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>etcd-io/bbolt (go.etcd.io/bbolt)</summary>

### [`v1.4.2`](https://github.com/etcd-io/bbolt/releases/tag/v1.4.2)

[Compare Source](https://github.com/etcd-io/bbolt/compare/v1.4.1...v1.4.2)

See the [CHANGELOG/v1.4.2](https://github.com/etcd-io/bbolt/blob/main/CHANGELOG/CHANGELOG-1.4.md#v1422025-06-27) for more details.

### [`v1.4.1`](https://github.com/etcd-io/bbolt/releases/tag/v1.4.1)

[Compare Source](https://github.com/etcd-io/bbolt/compare/v1.4.0...v1.4.1)

See the [CHANGELOG/v1.4.1](https://github.com/etcd-io/bbolt/blob/main/CHANGELOG/CHANGELOG-1.4.md#v1412025-06-10) for more details.

### [`v1.4.0`](https://github.com/etcd-io/bbolt/releases/tag/v1.4.0)

[Compare Source](https://github.com/etcd-io/bbolt/compare/v1.3.11...v1.4.0)

See the [CHANGELOG/v1.4.0](https://github.com/etcd-io/bbolt/blob/main/CHANGELOG/CHANGELOG-1.4.md#v1402025-02-05) for more details.

### [`v1.3.11`](https://github.com/etcd-io/bbolt/releases/tag/v1.3.11)

[Compare Source](https://github.com/etcd-io/bbolt/compare/v1.3.10...v1.3.11)

See the [CHANGELOG/v1.3.11](https://github.com/etcd-io/bbolt/blob/main/CHANGELOG/CHANGELOG-1.3.md#v13112024-08-21) for more details.

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/792
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-08-02 17:58:33 +00:00
Renovate Bot
5285f39e6b
Update module github.com/rhysd/actionlint to v1.7.7 (#791)
This PR contains the following updates:

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

---

### Release Notes

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

### [`v1.7.7`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v177---2025-01-19)

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

- Support runner labels for [Linux arm64 hosted runners](https://github.blog/changelog/2025-01-16-linux-arm64-hosted-runners-now-available-for-free-in-public-repositories-public-preview/). ([#&#8203;503](https://github.com/rhysd/actionlint/issues/503), [#&#8203;504](https://github.com/rhysd/actionlint/issues/504), thanks [@&#8203;martincostello](https://github.com/martincostello))
  - `ubuntu-24.04-arm`
  - `ubuntu-22.04-arm`
- Update Go dependencies to the latest.
- Update the popular actions data set to the latest.
- Add Linux arm64 job to the CI workflow. Now actionlint is tested on the platform. ([#&#8203;507](https://github.com/rhysd/actionlint/issues/507), thanks [@&#8203;cclauss](https://github.com/cclauss))

\[Changes]\[v1.7.7]

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

### [`v1.7.6`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v176---2025-01-04)

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

- Using contexts at specific workflow keys is incorrectly reported as not allowed. Affected workflow keys are as follows. ([#&#8203;495](https://github.com/rhysd/actionlint/issues/495), [#&#8203;497](https://github.com/rhysd/actionlint/issues/497), [#&#8203;498](https://github.com/rhysd/actionlint/issues/498), [#&#8203;500](https://github.com/rhysd/actionlint/issues/500))
  - `jobs.<job_id>.steps.with.args`
  - `jobs.<job_id>.steps.with.entrypoint`
  - `jobs.<job_id>.services.<service_id>.env`
- Update Go dependencies to the latest.

\[Changes]\[v1.7.6]

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

### [`v1.7.5`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v175---2024-12-28)

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

- Strictly check available contexts in `${{ }}` placeholders following the ['Context availability' table](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#context-availability) in the official document.
  - For example, `jobs.<job_id>.defaults.run.shell` allows `env` context but `shell` workflow keys in other places allow no context.
    ```yaml
    defaults:
      run:
    ```

### ERROR: No context is available here

```
    shell: ${{ env.SHELL }}

jobs:
  test:
    runs-on: ubuntu-latest
    defaults:
      run:
```

### OK: 'env' context is available here

```
        shell: ${{ env.SHELL }}
    steps:
      - run: echo hello
```

### ERROR: No context is available here

````
        shell: ${{ env.SHELL}}
```
````

- Check a string literal passed to `fromJSON()` call. This pattern is [popular](https://github.com/search?q=fromJSON%28%27+lang%3Ayaml\&type=code) to create array or object constants because GitHub Actions does not provide the literal syntax for them. See the [document](https://github.com/rhysd/actionlint/blob/main/docs/checks.md#contexts-and-built-in-functions) for more details. ([#&#8203;464](https://github.com/rhysd/actionlint/issues/464))
  ```yaml
  jobs:
    test:
  ```

### ERROR: Key 'mac' does not exist in the object returned by the fromJSON()

```
  runs-on: ${{ fromJSON('{"win":"windows-latest","linux":"ubuntul-latest"}')['mac'] }}
  steps:
    - run: echo This is a special branch!
```

### ERROR: Broken JSON string passed to fromJSON.

```
      if: contains(fromJSON('["main","release","dev"'), github.ref_name)
```

````
- Allow passing command arguments to `-shellcheck` argument. ([#&#8203;483](https://github.com/rhysd/actionlint/issues/483), thanks [@&#8203;anuraaga](https://github.com/anuraaga))
- This is useful when you want to use alternative build of shellcheck like [go-shellcheck](https://github.com/wasilibs/go-shellcheck/).
  ```sh
  actionlint -shellcheck="go run github.com/wasilibs/go-shellcheck/cmd/shellcheck@latest"
  ```
- Support undocumented `repository_visibility`, `artifact_cache_size_limit`, `step_summary`, `output`, `state` properties in `github` context. ([#&#8203;489](https://github.com/rhysd/actionlint/issues/489), thanks [@&#8203;rasa](https://github.com/rasa) for adding `repository_visibility` property)
- Remove `macos-12` runner label from known labels because it was [dropped](https://github.com/actions/runner-images/issues/10721) from GitHub-hosted runners on Dec. 3 and is no longer available.
- Add `windows-2025` runner label to the known labels. The runner is in [public preview](https://github.blog/changelog/2024-12-19-windows-server-2025-is-now-in-public-preview/). ([#&#8203;491](https://github.com/rhysd/actionlint/issues/491), thanks [@&#8203;ericcornelissen](https://github.com/ericcornelissen))
- Add `black` to the list of colors for `branding.color` action metadata. ([#&#8203;485](https://github.com/rhysd/actionlint/issues/485), thanks [@&#8203;eifinger](https://github.com/eifinger))
- Add `table` to the list of icons for `branding.icon` action metadata.
- Fix parsing escaped `{` in `format()` function call's first argument.
- Fix the incorrect `join()` function overload. `join(s1: string, s2: string)` was wrongly accepted.
- Update popular actions data set to the latest.
- Add `download-artifact/v3-node20` to the data set. ([#&#8203;468](https://github.com/rhysd/actionlint/issues/468))
- Fix missing the `reviewdog/action-hadolint@v1` action input. ([#&#8203;487](https://github.com/rhysd/actionlint/issues/487), thanks [@&#8203;mi-wada](https://github.com/mi-wada))
- Link to the documents of the stable version in actionlint `man` page and `-help` output.
- Refactor `LintStdin()` API example and some unit tests. ([#&#8203;472](https://github.com/rhysd/actionlint/issues/472), [#&#8203;475](https://github.com/rhysd/actionlint/issues/475), thanks [@&#8203;alexandear](https://github.com/alexandear))
- Improve the configuration example in `actionlint.yaml` document to explain glob patterns for `paths`. ([#&#8203;481](https://github.com/rhysd/actionlint/issues/481))

[Changes][v1.7.5]

<a id="v1.7.4"></a>
````

### [`v1.7.4`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v174---2024-11-04)

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

- Disallow the usage of popular actions that run on `node16` runner. The `node16` runner [will reach the end of life on November 12](https://github.blog/changelog/2024-09-25-end-of-life-for-actions-node16/).
  - In case of the error, please update your actions to the latest version so that they run on the latest `node20` runner.
  - If you're using self-hosted runner and you cannot upgrade your runner to `node20` soon, please consider to ignore the error by the `paths` configuration described below.
  - If you're using `actions/upload-artifact@v3` and `actions/download-artifact@v3` on GHES, please replace them with `actions/upload-artifact@v3-node20` and `actions/download-artifact@v3-node20`. ([#&#8203;468](https://github.com/rhysd/actionlint/issues/468))
- Provide the configuration for ignoring errors by regular expressions in `actionlint.yml` (or `actionlint.yaml`). Please see the [document](https://github.com/rhysd/actionlint/blob/v1.7.4/docs/config.md) for more details. ([#&#8203;217](https://github.com/rhysd/actionlint/issues/217), [#&#8203;342](https://github.com/rhysd/actionlint/issues/342))
  - The `paths` is a mapping from the file path glob pattern to the corresponding configuration. The `ignore` configuration is a list of regular expressions to match error messages (similar to the `-ignore` command line option).
    ```yaml
    paths:
    ```

### This pattern matches any YAML file under the '.github/workflows/' directory.

```
  .github/workflows/**/*.yaml:
    ignore:
```

### Ignore the specific error from shellcheck

```
      - 'shellcheck reported issue in this script: SC2086:.+'
```

### This pattern only matches '.github/workflows/release.yaml' file.

```
  .github/workflows/release.yaml:
    ignore:
```

### Ignore errors from the old runner check. This may be useful for (outdated) self-hosted runner environment.

````
      - 'the runner of ".+" action is too old to run on GitHub Actions'
```
````

- This configuration was not implemented initially because I wanted to keep the configuration as minimal as possible. However, due to several requests for it, the configuration has now been added.
- Untrusted inputs check is safely skipped inside specific function calls. ([#&#8203;459](https://github.com/rhysd/actionlint/issues/459), thanks [@&#8203;IlyaGulya](https://github.com/IlyaGulya))
  - For example, the following step contains the untrusted input `github.head_ref`, but it is safe because it's passed to the `contains()` argument.
    ```yaml
    - run: echo "is_release_branch=${{ contains(github.head_ref, 'release') }}" >> "$GITHUB_OUTPUT"
    ```
  - For more details, please read the [rule document](https://github.com/rhysd/actionlint/blob/v1.7.4/docs/checks.md#untrusted-inputs).
- Recognize `gcr.io` and `gcr.dev` as the correct container registry hosts. ([#&#8203;463](https://github.com/rhysd/actionlint/issues/463), thanks [@&#8203;takaidohigasi](https://github.com/takaidohigasi))
  - Note that it is recommended explicitly specifying the scheme like `docker://gcr.io/...`.
- Remove `macos-x.0` runner labels which are no longer available. ([#&#8203;452](https://github.com/rhysd/actionlint/issues/452))
- Disable shellcheck [`SC2043`](https://www.shellcheck.net/wiki/SC2043) rule because it can cause false positives on checking `run:`. ([#&#8203;355](https://github.com/rhysd/actionlint/issues/355))
  - The [rule document](https://github.com/rhysd/actionlint/blob/v1.7.4/docs/checks.md#check-shellcheck-integ) was updated as well. ([#&#8203;466](https://github.com/rhysd/actionlint/issues/466), thanks [@&#8203;risu729](https://github.com/risu729))
- Fix the error message was not deterministic when detecting cycles in `needs` dependencies.
- Fix the check for `format()` function was not applied when the function name contains upper case like `Format()`. Note that function names in `${{ }}` placeholders are case-insensitive.
- Update the popular actions data set to the latest.
  - This includes the [new `ref` and `commit` outputs](https://github.com/actions/checkout/pull/1180) of `actions/checkout`.
- Add [`actions/cache/save`](https://github.com/actions/cache/tree/main/save) and [`actions/cache/restore`](https://github.com/actions/cache/tree/main/restore) to the popular actions data set.
- Links in the [README.md](https://github.com/rhysd/actionlint/blob/main/README.md) now point to the document of the latest version tag instead of HEAD of `main` branch.
- Add [`Linter.LintStdin`](https://pkg.go.dev/github.com/rhysd/actionlint#Linter.LintStdin) method dedicated to linting STDIN instead of handling STDIN in `Command`.
- (Dev) Add new [`check-checks` script](https://github.com/rhysd/actionlint/tree/main/scripts/check-checks) to maintain the ['Checks' document](https://github.com/rhysd/actionlint/blob/main/docs/checks.md). It automatically updates the outputs and playground links for example inputs in the document. It also checks the document is up-to-date on CI. Please read the [document](https://github.com/rhysd/actionlint/blob/main/scripts/check-checks/README.md) for more details.

[Documentation](https://github.com/rhysd/actionlint/tree/v1.7.4/docs)

\[Changes]\[v1.7.4]

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

### [`v1.7.3`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v173---2024-09-29)

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

- Remove `macos-11` runner labels because [macOS 11 runner was dropped on 6/28/2024](https://github.blog/changelog/2024-05-20-actions-upcoming-changes-to-github-hosted-macos-runners/#macos-11-deprecation-and-removal). ([#&#8203;451](https://github.com/rhysd/actionlint/issues/451), thanks [@&#8203;muzimuzhi](https://github.com/muzimuzhi))
- Support `macos-15`, `macos-15-large`, and `macos-15-xlarge` runner labels. The macOS 15 runner is not globally available yet, but [they are available in beta](https://github.com/actions/runner-images?tab=readme-ov-file#available-images). ([#&#8203;453](https://github.com/rhysd/actionlint/issues/453), thanks [@&#8203;muzimuzhi](https://github.com/muzimuzhi))
- Release artifact includes checksums for the released binaries. The file name is `actionlint_{version}_checksums.txt`. ([#&#8203;449](https://github.com/rhysd/actionlint/issues/449))
  - For example, the checksums for v1.7.3 can be found [here](https://github.com/rhysd/actionlint/releases/download/v1.7.3/actionlint_1.7.3_checksums.txt).
- Fix `download-path` output is missing in `actions/download-artifact@v3` action. ([#&#8203;442](https://github.com/rhysd/actionlint/issues/442))
  - Note that the latest version `actions/download-artifact@v4` was not affected by this issue.
- Support Go 1.23.

[Documentation](https://github.com/rhysd/actionlint/blob/v1.7.3/docs/checks.md)

\[Changes]\[v1.7.3]

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

### [`v1.7.2`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v172---2024-09-23)

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

- Fix child processes to run in parallel.
- Update the popular actions data set to the latest. ([#&#8203;442](https://github.com/rhysd/actionlint/issues/442), [#&#8203;445](https://github.com/rhysd/actionlint/issues/445), [#&#8203;446](https://github.com/rhysd/actionlint/issues/446), [#&#8203;447](https://github.com/rhysd/actionlint/issues/447), thanks [@&#8203;maikelvdh](https://github.com/maikelvdh))
- Add support for checking branch filters on [`merge_group` event](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#merge_group). ([#&#8203;448](https://github.com/rhysd/actionlint/issues/448), thanks [@&#8203;muzimuzhi](https://github.com/muzimuzhi))
- [The playground](https://rhysd.github.io/actionlint/) now supports both light and dark modes and automatically applies the system's theme.
- Fix releasing a failure on making a new winget package. ([#&#8203;438](https://github.com/rhysd/actionlint/issues/438), thanks [@&#8203;vedantmgoyal9](https://github.com/vedantmgoyal9))

\[Changes]\[v1.7.2]

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

### [`v1.7.1`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v171---2024-05-28)

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

- Support `ubuntu-24.04` runner label, which was [recently introduced as beta](https://github.blog/changelog/2024-05-14-github-hosted-runners-public-beta-of-ubuntu-24-04-is-now-available/). ([#&#8203;425](https://github.com/rhysd/actionlint/issues/425), thanks [@&#8203;bitcoin-tools](https://github.com/bitcoin-tools))
- Remove the support for `macos-10` runner label which was [officially dropped about 2 years ago](https://github.blog/changelog/2022-07-20-github-actions-the-macos-10-15-actions-runner-image-is-being-deprecated-and-will-be-removed-by-8-30-22/).
- Remove the support for `windows-2016` runner label which was [officially dropped about 2 years ago](https://github.blog/changelog/2021-10-19-github-actions-the-windows-2016-runner-image-will-be-removed-from-github-hosted-runners-on-march-15-2022/).
- Document URLs used in help output and links in the playground prefer specific version tag rather than `main` branch. For example,
  - Before: https://github.com/rhysd/actionlint/tree/main/docs
  - After: https://github.com/rhysd/actionlint/tree/v1.7.1/docs
- Fix actionlint wrongly reports an error when using `ghcr.io` or `docker.io` at `image` field of action metadata file of Docker action without `docker://` scheme. ([#&#8203;428](https://github.com/rhysd/actionlint/issues/428))
  ```yaml
  runs:
    using: 'docker'
  ```

### This should be OK

```
image: 'ghcr.io/user/repo:latest'
```

```
- Fix checking `preactjs/compressed-size-action@v2` usage caused a false positive. ([#&#8203;422](https://github.com/rhysd/actionlint/issues/422))
- Fix an error message when invalid escaping is found in globs.
- The design of the [playground page](https://rhysd.github.io/actionlint/) is overhauled following the upgrade of bulma package to v1.
- Current actionlint version is shown in the heading.
- The color theme is changed to the official dark theme.
- The list of useful links is added to the bottom of the page as 'Resources' section.

[Changes][v1.7.1]

<a id="v1.7.0"></a>
```

### [`v1.7.0`](https://github.com/rhysd/actionlint/blob/HEAD/CHANGELOG.md#v170---2024-05-08)

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

- From this version, actionlint starts to check action metadata file `action.yml` (or `action.yaml`). At this point, only very basic checks are implemented and contents of `steps:` are not checked yet.
  - It checks properties under `runs:` section (e.g. `main:` can be specified when it is a JavaScript action), `branding:` properties, and so on.
    ```yaml
    name: 'My action'
    author: '...'
    ```

### ERROR: 'description' section is missing

```
branding:
```

### ERROR: Invalid icon name

```
  icon: dog

runs:
```

### ERROR: Node.js runtime version is too old

```
  using: 'node12'
```

### ERROR: The source file being run by this action does not exist

```
  main: 'this-file-does-not-exist.js'
```

### ERROR: 'env' configuration is only allowed for Docker actions

````
  env:
    SOME_VAR: SOME_VALUE
```
````

- actionlint still focuses on checking workflow files. So there is no way to directly specify `action.yml` as an argument of `actionlint` command. actionlint checks all local actions which are used by given workflows. If you want to use actionlint for your action development, prepare a test/example workflow which uses your action, and check it with actionlint instead.
- Checks for `steps:` contents are planned to be implemented. Since several differences are expected between `steps:` in workflow file and `steps:` in action metadata file (e.g. available contexts), the implementation is delayed to later version. And the current implementation of action metadata parser is ad hoc. I'm planning a large refactorying and breaking changes Go API around it are expected.
- Add `runner.environment` property. ([#&#8203;412](https://github.com/rhysd/actionlint/issues/412))
  ```yaml
  - run: echo 'Run by GitHub-hosted runner'
    if: runner.environment == 'github-hosted'
  ```
- Using outdated popular actions is now detected at error. See [the document](https://github.com/rhysd/actionlint/blob/main/docs/checks.md#detect-outdated-popular-actions) for more details.
  - Here 'outdated' means actions which use runtimes no longer supported by GitHub-hosted runners such as `node12`.
    ```yaml
    ```

### ERROR: actions/checkout@v2 is using the outdated runner 'node12'

````
- uses: actions/checkout@v2
```
````

- Support `attestations` permission which was [recently added to GitHub Actions as beta](https://docs.github.com/en/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds). ([#&#8203;418](https://github.com/rhysd/actionlint/issues/418), thanks [@&#8203;bdehamer](https://github.com/bdehamer))
  ```yaml
  permissions:
    id-token: write
    contents: read
    attestations: write
  ```
- Check comparison expressions more strictly. Arbitrary types of operands can be compared as [the official document](https://docs.github.com/en/actions/learn-github-actions/expressions#operators) explains. However, comparisons between some types are actually meaningless because the values are converted to numbers implicitly. actionlint catches such meaningless comparisons as errors. Please see [the check document](https://github.com/rhysd/actionlint/blob/main/docs/checks.md#check-comparison-types) for more details.
  ```yaml
  on:
    workflow_call:
      inputs:
        timeout:
          type: boolean

  jobs:
    test:
      runs-on: ubuntu-latest
      steps:
        - run: echo 'called!'
  ```

### ERROR: Comparing string to object is always evaluated to false

```
      if: ${{ github.event == 'workflow_call' }}
    - run: echo 'timeout is too long'
```

### ERROR: Comparing boolean value with `>` doesn't make sense

```
      if: ${{ inputs.timeout > 60 }}
```

````
- Follow the update that `macos-latest` is now an alias to `macos-14` runner.
- Support a custom python shell by `pyflakes` rule.
- Add workaround actionlint reports that `dorny/paths-filter`'s `predicate-quantifier` input is not defined. ([#&#8203;416](https://github.com/rhysd/actionlint/issues/416))
- Fix the type of a conditional expression by comparison operators is wider than expected by implementing type narrowing. ([#&#8203;384](https://github.com/rhysd/actionlint/issues/384))
- For example, the type of following expression should be `number` but it was actually `string | number` and actionlint complained that `timeout-minutes` must take a number value.
  ```yaml
  timeout-minutes: ${{ env.FOO && 10 || 60 }}
  ```
- Fix `${{ }}` placeholder is not available at `jobs.<job_id>.services`. ([#&#8203;402](https://github.com/rhysd/actionlint/issues/402))
```yaml
jobs:
  test:
    services: ${{ fromJSON('...') }}
    runs-on: ubuntu-latest
    steps:
      - run: ...
````

- Do not check outputs of `google-github-actions/get-secretmanager-secrets` because this action sets outputs dynamically. ([#&#8203;404](https://github.com/rhysd/actionlint/issues/404))
- Fix `defaults.run` is ignored on detecting the shell used in `run:`. ([#&#8203;409](https://github.com/rhysd/actionlint/issues/409))
  ```yaml
  defaults:
    run:
      shell: pwsh
  jobs:
    test:
      runs-on: ubuntu-latest
      steps:
  ```

### This was wrongly detected as bash script

```
    - run: $Env:FOO = "FOO"
```

````
- Fix parsing a syntax error reported from pyflakes when checking a Python script in `run:`. ([#&#8203;411](https://github.com/rhysd/actionlint/issues/411))
```yaml
- run: print(
  shell: python
````

- Skip checking `exclude:` items in `matrix:` when they are constructed from `${{ }}` dynamically. ([#&#8203;414](https://github.com/rhysd/actionlint/issues/414))
  ```yaml
  matrix:
    foo: ['a', 'b']
    exclude:
  ```

### actionlint complained this value didn't exist in matrix combinations

```
  - foo: ${{ env.EXCLUDE_FOO }}
```

````
- Fix checking `exclude:` items when `${{ }}` is used in nested arrays at matrix items.
```yaml
matrix:
  foo:
    - ["${{ fromJSON('...') }}"]
  exclude:

### actionlint complained this value didn't match to any matrix combinations
    - foo: ['foo']
````

- Update popular actions data set. New major versions are added and the following actions are newly added.
  - `peaceiris/actions-hugo`
  - `actions/attest-build-provenance`
  - `actions/add-to-project`
  - `octokit/graphql-action`
- Update Go dependencies to the latest.
- Reduce the size of `actionlint` executable by removing redundant data from popular actions data set.
  - x86\_64 executable binary size was reduced from 6.9MB to 6.7MB (2.9% smaller).
  - Wasm binary size was reduced from 9.4MB to 8.9MB (5.3% smaller).
- Describe how to [integrate actionlint to Pulsar Edit](https://web.pulsar-edit.dev/packages/linter-github-actions) in [the document](https://github.com/rhysd/actionlint/blob/main/docs/usage.md#pulsar-edit). ([#&#8203;408](https://github.com/rhysd/actionlint/issues/408), thanks [@&#8203;mschuchard](https://github.com/mschuchard))
- Update outdated action versions in the usage document. ([#&#8203;413](https://github.com/rhysd/actionlint/issues/413), thanks [@&#8203;naglis](https://github.com/naglis))

\[Changes]\[v1.7.0]

<a id="v1.6.27"></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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/791
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-08-02 17:56:34 +00:00
Renovate Bot
0301be8d9e
Update module github.com/go-git/go-billy/v5 to v5.6.2 (#787)
This PR contains the following updates:

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

---

### Release Notes

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

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

[Compare Source](https://github.com/go-git/go-billy/compare/v5.6.1...v5.6.2)

#### What's Changed

- Enable the `iofs` adapter to also return other interfaces from `io/fs` by [@&#8203;JAORMX](https://github.com/JAORMX) in https://github.com/go-git/go-billy/pull/102
- build: Bump dependencies by [@&#8203;pjbgf](https://github.com/pjbgf) in https://github.com/go-git/go-billy/pull/103

#### New Contributors

- [@&#8203;JAORMX](https://github.com/JAORMX) made their first contribution in https://github.com/go-git/go-billy/pull/102

**Full Changelog**: https://github.com/go-git/go-billy/compare/v5.6.1...v5.6.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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/787
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-08-02 17:29:04 +00:00
Earl Warren
82f2c1e1f9
chore: the release link to RELEASE-NOTES.md is no longer needed (take 2) (#789)
the previous change updated how the release notes are set when building the release. This only happens in integration and never used

see https://code.forgejo.org/forgejo-integration/runner/releases/tag/v9.0.2 for instance

what matters is how the release notes are set when publishing the release.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/789): <!--number 789 --><!--line 0 --><!--description Y2hvcmU6IHRoZSByZWxlYXNlIGxpbmsgdG8gUkVMRUFTRS1OT1RFUy5tZCBpcyBubyBsb25nZXIgbmVlZGVkICh0YWtlIDIp-->chore: the release link to RELEASE-NOTES.md is no longer needed (take 2)<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/789
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-08-02 11:37:51 +00:00
Earl Warren
b26db065d6
fix: vars context is allowed in default values of action inputs (#786)
Resolves forgejo/runner#785

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- bug fixes
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/786): <!--number 786 --><!--line 0 --><!--description Zml4OiB2YXJzIGNvbnRleHQgaXMgYWxsb3dlZCBpbiBkZWZhdWx0IHZhbHVlcyBvZiBhY3Rpb24gaW5wdXRz-->fix: vars context is allowed in default values of action inputs<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/786
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-08-02 06:38:42 +00:00
Renovate Bot
6b031f4780
Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.4.1 (#788)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [https://data.forgejo.org/forgejo/forgejo-build-publish](https://data.forgejo.org/forgejo/forgejo-build-publish) | action | patch | `v5.4.0` -> `v5.4.1` |

---

### Release Notes

<details>
<summary>forgejo/forgejo-build-publish (https://data.forgejo.org/forgejo/forgejo-build-publish)</summary>

### [`v5.4.1`](https://data.forgejo.org/forgejo/forgejo-build-publish/compare/v5.4.0...v5.4.1)

[Compare Source](https://data.forgejo.org/forgejo/forgejo-build-publish/compare/v5.4.0...v5.4.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:eyJjcmVhdGVkSW5WZXIiOiI0MS40My41IiwidXBkYXRlZEluVmVyIjoiNDEuNDMuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/788
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-08-02 00:33:14 +00:00
Earl Warren
dbd1d4d2e8
feat: use cache-{from,to}: type=gha in the docker/build-push-action example (#783)
Resolves forgejo/runner#208

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/783): <!--number 783 --><!--line 0 --><!--description ZmVhdDogdXNlIGNhY2hlLXtmcm9tLHRvfTogdHlwZT1naGEgaW4gdGhlIGRvY2tlci9idWlsZC1wdXNoLWFjdGlvbiBleGFtcGxl-->feat: use cache-{from,to}: type=gha in the docker/build-push-action example<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/783
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-08-01 17:23:19 +00:00
Earl Warren
aec904c94e
chore: the release link to RELEASE-NOTES.md is no longer needed (#782)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/782): <!--number 782 --><!--line 0 --><!--description Y2hvcmU6IHRoZSByZWxlYXNlIGxpbmsgdG8gUkVMRUFTRS1OT1RFUy5tZCBpcyBubyBsb25nZXIgbmVlZGVk-->chore: the release link to RELEASE-NOTES.md is no longer needed<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/782
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-08-01 17:22:33 +00:00
Earl Warren
a01cb5e6c5
chore(ci): autoremove when running a workflow in a test (#780)
Otherwise resources linger when tests are checking for conditions that
require a workflow to fail.

```sh
earl-warren:~/software/runner$ go test -count=1 -run='TestJobExecutorWorkflows/uses-github-short-sha' ./act/runner
ok  	code.forgejo.org/forgejo/runner/v9/act/runner	0.276s
earl-warren:~/software/runner$ docker network ls | grep WORKFLOW
2e57caeb514d   WORKFLOW-cc93880718786fef12c18e53feecee5c8ef1cc155840bf4c0275a2fca61b99b9_JOB-test-test-network   bridge    local
earl-warren:~/software/runner$
```

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/780): <!--number 780 --><!--line 0 --><!--description Y2hvcmUoY2kpOiBhdXRvcmVtb3ZlIHdoZW4gcnVubmluZyBhIHdvcmtmbG93IGluIGEgdGVzdA==-->chore(ci): autoremove when running a workflow in a test<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/780
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-08-01 14:06:32 +00:00
Earl Warren
51fb504a2e
feat: add an LXC based example of docker/build-push-action usage (#781)
The motivations for this additional example are:

- Using https://github.com/docker/build-push-action/ with the Forgejo runner is a recurring question and there is no example of how to do that
- Reproducing https://code.forgejo.org/forgejo/runner/issues/208 will benefit from this example

---

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- features
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/781): <!--number 781 --><!--line 0 --><!--description ZmVhdDogYWRkIGFuIExYQyBiYXNlZCBleGFtcGxlIG9mIGRvY2tlci9idWlsZC1wdXNoLWFjdGlvbiB1c2FnZSBbc2tpcCBjYXNjYWRlXQ==-->feat: add an LXC based example of docker/build-push-action usage [skip cascade]<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/781
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-08-01 14:04:02 +00:00
Renovate Bot
194c416f29
Update dependency forgejo/release-notes-assistant to v1.3.6 (#778)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/778
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-08-01 05:18:02 +00:00
Earl Warren
ec99579451
chore: to allow the runner to be imported, v9 needs to be in the go module (#777)
It will be imported by Forgejo.

<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/777): <!--number 777 --><!--line 0 --><!--description Y2hvcmU6IHRvIGFsbG93IHRoZSBydW5uZXIgdG8gYmUgaW1wb3J0ZWQsIHY5IG5lZWRzIHRvIGJlIGluIHRoZSBnbyBtb2R1bGU=-->chore: to allow the runner to be imported, v9 needs to be in the go module<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/777
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-07-31 10:35:11 +00:00
Renovate Bot
f94fe37f90
Update module github.com/docker/docker to v28.3.3+incompatible [SECURITY] (#776)
Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/776
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
Co-authored-by: Renovate Bot <bot@kriese.eu>
Co-committed-by: Renovate Bot <bot@kriese.eu>
2025-07-31 08:38:03 +00:00
Earl Warren
10d7d8dded
chore: release notes are now published together with the release (#775)
<!--start release-notes-assistant-->
<!--URL:https://code.forgejo.org/forgejo/runner-->
- other
  - [PR](https://code.forgejo.org/forgejo/runner/pulls/775): <!--number 775 --><!--line 0 --><!--description Y2hvcmU6IHJlbGVhc2Ugbm90ZXMgYXJlIG5vdyBwdWJsaXNoZWQgdG9nZXRoZXIgd2l0aCB0aGUgcmVsZWFzZQ==-->chore: release notes are now published together with the release<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/775
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-07-31 08:02:20 +00:00
Michael Kriese
2e7b2e9281
chore(renovate): ignore all test data 2025-07-31 10:01:23 +02:00
Michael Kriese
c68ca8195b
chore(renovate): ignore act test data 2025-07-31 09:57:36 +02:00
Michael Kriese
d4c1ab636f
chore(renovate): ignore node_modules 2025-07-31 09:51:59 +02:00
239 changed files with 8707 additions and 2379 deletions

46
.forgejo/cascading-forgejo Executable file
View file

@ -0,0 +1,46 @@
#!/bin/bash
set -ex
forgejo=$1
forgejo_pr=$2
runner=$3
runner_pr_or_ref=$4
#
# Get information from the runner
#
cd $runner
#
# code.forgejo.org/forgejo/runner/vN may be
# upgraded to code.forgejo.org/forgejo/runner/vN+1
#
module=$(cat go.mod | head -1 | cut -d' ' -f2)
test "$module"
sha=$(git -C $runner show --no-patch --format=%H)
test "$sha"
#
# Update Forgejo to use the runner at $runner_pr_or_ref
#
cd $forgejo
#
# Update the runner major version if needed
#
find * -name '*.go' -o -name 'go.mod' | xargs sed -i -E -e "s|code.forgejo.org/forgejo/runner/v[0-9]+|$module|"
#
# If it is a pull request, change the module to reference the forked repository so
# go mod tidy can find the SHA from a known branch or tag
#
if test -f "$runner_pr_or_ref"; then
repository=$(jq --raw-output .head.repo.full_name <$runner_pr_or_ref)
test "$repository"
module=$(echo $module | sed -e "s|code.forgejo.org/forgejo/runner|code.forgejo.org/$repository|")
fi
#
# add a "replace code.forgejo.org/forgejo/runner/v?? $sha" line to the forgejo go.mod
# so that it uses the branch or pull request from which the cascade is run.
#
sed -i -e "\|replace $module|d" go.mod
echo "replace $module => $module $sha" >>go.mod
go mod tidy

View file

@ -1,16 +0,0 @@
#!/bin/bash
set -ex
setup_forgejo=$1
setup_forgejo_pr=$2
runner=$3
runner_pr=$4
url=$(jq --raw-output .head.repo.html_url < $runner_pr)
test "$url" != null
branch=$(jq --raw-output .head.ref < $runner_pr)
test "$branch" != null
cd $setup_forgejo
./utils/upgrade-runner.sh $url @$branch
date > last-upgrade

View file

@ -0,0 +1,24 @@
#!/bin/bash
set -ex
setup_forgejo=$1
setup_forgejo_pr=$2
runner=$3
runner_pr_or_ref=$4
if test -f "$runner_pr_or_ref"; then
url=$(jq --raw-output .head.repo.html_url <$runner_pr_or_ref)
test "$url" != null
branch=$(jq --raw-output .head.ref <$runner_pr_or_ref)
else
url=https://code.forgejo.org/forgejo/runner
branch=${runner_pr_or_ref#refs/heads/}
fi
test "$url"
test "$branch"
test "$branch" != null
cd $setup_forgejo
./utils/upgrade-runner.sh $url @$branch
rm -f .forgejo/workflows/integration*.yml
date >last-upgrade

View file

@ -8,7 +8,7 @@ expectedLabels = {
"org.opencontainers.image.source": "https://code.forgejo.org/forgejo/runner",
"org.opencontainers.image.version": "1.2.3",
"org.opencontainers.image.vendor": "Forgejo",
"org.opencontainers.image.licenses": "MIT",
"org.opencontainers.image.licenses": "GPL-3.0-or-later",
"org.opencontainers.image.title": "Forgejo Runner",
"org.opencontainers.image.description": "A runner for Forgejo Actions.",
}

View file

@ -1,78 +0,0 @@
name: act
on:
push:
branches:
- 'main'
pull_request:
env:
GOPROXY: https://goproxy.io,direct
GOPATH: /go_path
GOCACHE: /go_cache
jobs:
unit:
runs-on: docker
container:
image: 'code.forgejo.org/oci/node:22-bookworm'
steps:
- name: cache go path
id: cache-go-path
uses: https://code.forgejo.org/actions/cache@v4
with:
path: /go_path
key: go_path-${{ forge.repository }}-${{ forge.ref_name }}
restore-keys: |
go_path-${{ forge.repository }}-
go_path-
- name: cache go cache
id: cache-go-cache
uses: https://code.forgejo.org/actions/cache@v4
with:
path: /go_cache
key: go_cache-${{ forge.repository }}-${{ forge.ref_name }}
restore-keys: |
go_cache-${{ forge.repository }}-
go_cache-
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://code.forgejo.org/actions/setup-go@v5
with:
go-version-file: go.mod
- name: validate go version
run: |
set -ex
toolchain=$(grep -oP '(?<=toolchain ).+' go.mod)
version=$(go version | cut -d' ' -f3)
if dpkg --compare-versions ${version#go} lt ${toolchain#go}; then
echo "go version too low: $toolchain >= $version"
exit 1
fi
- name: unit test
run: |
go test -short ./act/container
go test ./act/artifactcache/... ./act/workflowpattern/... ./act/filecollector/... ./act/common/... ./act/jobparser ./act/model ./act/exprparser ./act/schema
integration:
runs-on: lxc-bookworm
needs: [unit]
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://code.forgejo.org/actions/setup-go@v5
with:
go-version-file: go.mod
- name: apt install docker.io
run: |
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get -q install -qq -y docker.io
- name: integration test
run: |
go test ./act/container
go test ./act/runner/...

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

@ -18,19 +18,22 @@ on:
enable-email-notifications: true
env:
FORGEJO_VERSION: 11.0.7 # renovate: datasource=docker depName=code.forgejo.org/forgejo/forgejo
jobs:
release-simulation:
runs-on: lxc-bookworm
if: forge.repository_owner != 'forgejo-integration' && forge.repository_owner != 'forgejo-release'
if: vars.ROLE == 'forgejo-coding'
steps:
- uses: actions/checkout@v4
- uses: https://data.forgejo.org/actions/checkout@v4
- id: forgejo
uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.1
uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.4
with:
user: root
password: admin1234
image-version: 1.20
image-version: ${{ env.FORGEJO_VERSION }}
lxc-ip-prefix: 10.0.9
- name: publish

View file

@ -21,9 +21,9 @@ jobs:
release:
runs-on: lxc-bookworm
# root is used for testing, allow it
if: secrets.ROLE == 'forgejo-integration' || forge.repository_owner == 'root'
if: vars.ROLE == 'forgejo-integration' || forge.repository_owner == 'root'
steps:
- uses: actions/checkout@v4
- uses: https://data.forgejo.org/actions/checkout@v4
- name: Increase the verbosity when there are no secrets
id: verbose
@ -60,20 +60,9 @@ jobs:
version=${FORGEJO_REF_NAME##*v}
echo "value=$version" >> "$FORGEJO_OUTPUT"
- name: release notes
id: release-notes
run: |
anchor=${{ steps.tag-version.outputs.value }}
anchor=${anchor//./-}
cat >> "$FORGEJO_OUTPUT" <<EOF
value<<ENDVAR
See https://code.forgejo.org/forgejo/runner/src/branch/main/RELEASE-NOTES.md#$anchor
ENDVAR
EOF
- name: build without TOKEN
if: ${{ secrets.TOKEN == '' }}
uses: https://data.forgejo.org/forgejo/forgejo-build-publish/build@v5.4.0
uses: https://data.forgejo.org/forgejo/forgejo-build-publish/build@v5.4.1
with:
forgejo: "${{ env.FORGEJO_SERVER_URL }}"
owner: "${{ env.FORGEJO_REPOSITORY_OWNER }}"
@ -83,14 +72,13 @@ jobs:
release-version: "${{ steps.tag-version.outputs.value }}"
token: ${{ steps.token.outputs.value }}
platforms: linux/amd64,linux/arm64
release-notes: "${{ steps.release-notes.outputs.value }}"
binary-name: forgejo-runner
binary-path: /bin/forgejo-runner
verbose: ${{ steps.verbose.outputs.value }}
- name: build with TOKEN
if: ${{ secrets.TOKEN != '' }}
uses: https://data.forgejo.org/forgejo/forgejo-build-publish/build@v5.4.0
uses: https://data.forgejo.org/forgejo/forgejo-build-publish/build@v5.4.1
with:
forgejo: "${{ env.FORGEJO_SERVER_URL }}"
owner: "${{ env.FORGEJO_REPOSITORY_OWNER }}"
@ -100,7 +88,6 @@ jobs:
release-version: "${{ steps.tag-version.outputs.value }}"
token: "${{ secrets.TOKEN }}"
platforms: linux/amd64,linux/arm64
release-notes: "${{ steps.release-notes.outputs.value }}"
binary-name: forgejo-runner
binary-path: /bin/forgejo-runner
verbose: ${{ steps.verbose.outputs.value }}

View file

@ -0,0 +1,110 @@
# Copyright 2025 The Forgejo Authors
# SPDX-License-Identifier: MIT
#
# FORGEJO_CASCADING_PR_ORIGIN_TOKEN is a token from the https://code.forgejo.org/cascading-pr user
# with scope write:issue read:repository read:user
# FORGEJO_CASCADING_PR_DESTINATION_TOKEN is a token from the https://codeberg.org/forgejo-cascading-pr user
# with scope write:issue write:repository read:user
#
# To modify this workflow:
#
# - push it to the wip-cascade branch on the repository
# otherwise it will not have access to the secrets required to push
# the cascading PR
#
# - once it works, open a pull request for the sake of keeping track
# of the change even if the PR won't run it because it will use
# whatever is in the default branch instead
#
# - after it is merged, double check it works by setting the
# label on a pull request (any pull request will do)
#
name: cascade
on:
push:
branches:
- 'main'
- 'wip-cascade'
pull_request_target:
types:
- synchronize
- labeled
- closed
enable-email-notifications: true
jobs:
debug:
if: >
vars.DEBUG == 'yes'
runs-on: docker
container:
image: data.forgejo.org/oci/node:22-bookworm
steps:
- name: event
run: |
cat <<'EOF'
${{ toJSON(forge.event.pull_request.labels.*.name) }}
EOF
cat <<'EOF'
push => ${{ forge.event_name == 'push' && ( forge.ref_name == 'main' || forge.ref_name == 'wip-cascade') }}
pull_request_target synchornized => ${{ ( forge.event.action == 'synchronized' && contains(forge.event.pull_request.labels.*.name, 'run-forgejo-tests') ) }}
pull_request_target label_updated => ${{ ( forge.event.action == 'label_updated' && forge.event.label.name == 'run-forgejo-tests' ) }}
contains => ${{ contains(forge.event.pull_request.labels.*.name, 'run-forgejo-tests') }}
contains boolean => ${{ contains(forge.event.pull_request.labels.*.name, 'run-forgejo-tests') == true }}
EOF
cat <<'EOF'
${{ toJSON(forge) }}
EOF
forgejo:
#
# Always run when a commit is pushed to the main or wip-cascade branch
# If this is a pull request, run
# - when the `run-forgejo-tests` label is set (label_updated) (but not if another label is set or if a label is removed)
# - when a new commit is pushed to the pull request (synchronized) if the `run-forgejo-tests` is already present
# - when the pull request is closed, which also happens when it is merged, so that the Forgejo pull request is closed
#
if: >
vars.ROLE == 'forgejo-coding' && (
(
forge.event_name == 'push' && ( forge.ref_name == 'main' || forge.ref_name == 'wip-cascade')
) || (
forge.event_name == 'pull_request_target' && (
forge.event.action == 'closed' ||
( forge.event.action == 'synchronized' && contains(forge.event.pull_request.labels.*.name, 'run-forgejo-tests') ) ||
( forge.event.action == 'label_updated' && forge.event.label.name == 'run-forgejo-tests' )
)
)
)
runs-on: docker
container:
image: data.forgejo.org/oci/node:22-bookworm
steps:
- uses: https://data.forgejo.org/actions/checkout@v4
with:
fetch-depth: '0'
show-progress: 'false'
- uses: https://data.forgejo.org/actions/setup-go@v5
with:
go-version-file: go.mod
- uses: https://data.forgejo.org/actions/cascading-pr@v2.3.0
with:
origin-url: ${{ forge.server_url }}
origin-repo: ${{ forge.repository }}
origin-token: ${{ secrets.FORGEJO_CASCADING_PR_ORIGIN_TOKEN }}
origin-pr: ${{ forge.event.pull_request.number }}
origin-ref: ${{ forge.event_name == 'push' && forge.event.ref || '' }}
destination-url: https://codeberg.org
destination-fork-repo: forgejo-cascading-pr/forgejo
destination-repo: forgejo/forgejo
destination-branch: forgejo
destination-token: ${{ secrets.FORGEJO_CASCADING_PR_DESTINATION_TOKEN }}
prefix: runner
close: true
verbose: ${{ vars.VERBOSE == 'yes' }}
debug: ${{ vars.DEBUG == 'yes' }}
wait-iteration: 120
update: .forgejo/cascading-forgejo

View file

@ -1,31 +1,99 @@
# Copyright 2025 The Forgejo Authors
# SPDX-License-Identifier: MIT
#
# CASCADING_PR_ORIGIN is a token from the https://code.forgejo.org/cascading-pr user
# with scope write:issue read:repository read:user
# CASCADING_PR_DESTINATION is a token from the https://code.forgejo.org/cascading-pr user
# with scope write:issue write:repository read:user
#
# To modify this workflow:
#
# - push it to the wip-cascade branch on the repository
# otherwise it will not have access to the secrets required to push
# the cascading PR
#
# - once it works, open a pull request for the sake of keeping track
# of the change even if the PR won't run it because it will use
# whatever is in the default branch instead
#
# - after it is merged, double check it works by setting the
# label on a pull request (any pull request will do)
#
name: cascade
on:
push:
branches:
- 'wip-cascade'
pull_request_target:
types:
- opened
- synchronize
- labeled
- closed
enable-email-notifications: true
jobs:
cascade:
debug:
if: >
vars.DEBUG == 'yes'
runs-on: docker
container:
image: data.forgejo.org/oci/node:22-bookworm
steps:
- name: event
run: |
cat <<'EOF'
${{ toJSON(forge.event.pull_request.labels.*.name) }}
EOF
cat <<'EOF'
push => ${{ forge.event_name == 'push' && ( forge.ref_name == 'wip-cascade') }}
pull_request_target synchornized => ${{ ( forge.event.action == 'synchronized' && contains(forge.event.pull_request.labels.*.name, 'run-end-to-end-tests') ) }}
pull_request_target label_updated => ${{ ( forge.event.action == 'label_updated' && forge.event.label.name == 'run-end-to-end-tests' ) }}
contains => ${{ contains(forge.event.pull_request.labels.*.name, 'run-end-to-end-tests') }}
contains boolean => ${{ contains(forge.event.pull_request.labels.*.name, 'run-end-to-end-tests') == true }}
EOF
cat <<'EOF'
${{ toJSON(forge) }}
EOF
end-to-end:
#
# Always run when a commit is pushed to the wip-cascade branch
# If this is a pull request, run
# - when the `run-end-to-end-tests` label is set (label_updated) (but not if another label is set or if a label is removed)
# - when a new commit is pushed to the pull request (synchronized) if the `run-end-to-end-tests` is already present
# - when the pull request is closed, which also happens when it is merged, so that the setup-forgejo & end-to-end pull requests are closed
#
if: >
vars.ROLE == 'forgejo-coding' && (
(
forge.event_name == 'push' && ( forge.ref_name == 'wip-cascade' )
) || (
forge.event_name == 'pull_request_target' && (
forge.event.action == 'closed' ||
( forge.event.action == 'synchronized' && contains(forge.event.pull_request.labels.*.name, 'run-end-to-end-tests') ) ||
( forge.event.action == 'label_updated' && forge.event.label.name == 'run-end-to-end-tests' )
)
)
)
runs-on: docker
container:
image: 'code.forgejo.org/oci/node:22-bookworm'
if: >
! contains(forge.event.pull_request.title, '[skip cascade]')
steps:
- uses: https://code.forgejo.org/actions/cascading-pr@v2.2.1
- uses: https://data.forgejo.org/actions/cascading-pr@v2.3.0
with:
origin-url: ${{ env.FORGEJO_SERVER_URL }}
origin-repo: forgejo/runner
origin-url: ${{ forge.server_url }}
origin-repo: ${{ forge.repository }}
origin-token: ${{ secrets.CASCADING_PR_ORIGIN }}
origin-pr: ${{ forge.event.pull_request.number }}
destination-url: ${{ env.FORGEJO_SERVER_URL }}
origin-ref: ${{ forge.event_name == 'push' && forge.event.ref || '' }}
destination-url: ${{ forge.server_url }}
destination-repo: actions/setup-forgejo
destination-fork-repo: cascading-pr/setup-forgejo
destination-branch: main
destination-token: ${{ secrets.CASCADING_PR_DESTINATION }}
close-merge: true
update: .forgejo/cascading-pr-setup-forgejo
close: true
verbose: ${{ vars.VERBOSE == 'yes' }}
debug: ${{ vars.DEBUG == 'yes' }}
update: .forgejo/cascading-setup-forgejo

View file

@ -0,0 +1,85 @@
#
# Example that requires a Forgejo runner with an [LXC backend](https://forgejo.org/docs/latest/admin/actions/runner-installation/#setting-up-the-container-environment).
#
# - Start a Forgejo instance to be used as a container registry
# - Build a container image using the [docker/build-push-action](https://code.forgejo.org/docker/build-push-action) action
# - Push the image to the Forgejo instance
# - Retrieve the image
#
# Runs of this workflow can be seen in [the Forgejo runner](https://code.forgejo.org/forgejo/runner/actions?workflow=docker-build-push-action-in-lxc.yml) logs.
#
name: example
on:
push:
branches:
- 'main'
pull_request:
paths:
- examples/docker-build-push-action/**
- .forgejo/workflows/docker-build-push-action-in-lxc.yml
enable-email-notifications: true
env:
FORGEJO_VERSION: 11.0.7 # renovate: datasource=docker depName=code.forgejo.org/forgejo/forgejo
FORGEJO_USER: root
FORGEJO_PASSWORD: admin1234
jobs:
docker-build-push-action-in-lxc:
if: vars.ROLE == 'forgejo-coding'
runs-on: lxc-bookworm
steps:
- name: install Forgejo so it can be used as a container registry
id: registry
uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.4
with:
user: ${{ env.FORGEJO_USER }}
password: ${{ env.FORGEJO_PASSWORD }}
binary: https://code.forgejo.org/forgejo/forgejo/releases/download/v${{ env.FORGEJO_VERSION }}/forgejo-${{ env.FORGEJO_VERSION }}-linux-amd64
lxc-ip-prefix: 10.0.9
- name: enable insecure / http uploads to the Forgejo registry
run: |-
set -x
# the docker daemon was implicitly installed when Forgejo was
# installed in the previous step. But it will refuse to connect
# to an insecure / http registry by default and must be told
# otherwise
cat > /etc/docker/daemon.json <<EOF
{
"insecure-registries" : ["${{ steps.registry.outputs.host-port }}"]
}
EOF
systemctl restart docker
- uses: https://data.forgejo.org/docker/setup-qemu-action@v3
- uses: https://data.forgejo.org/docker/setup-buildx-action@v2
with:
# insecure / http connections to the registry are allowed
config-inline: |
[registry."${{ steps.registry.outputs.host-port }}"]
http = true
- name: login to the Forgejo registry
uses: https://data.forgejo.org/docker/login-action@v3
with:
registry: ${{ steps.registry.outputs.host-port }}
username: ${{ env.FORGEJO_USER }}
password: ${{ env.FORGEJO_PASSWORD }}
- name: build and push to the Forgejo registry
uses: https://data.forgejo.org/docker/build-push-action@v5
with:
context: examples/docker-build-push-action
push: true
tags: ${{ steps.registry.outputs.host-port }}/root/testimage:latest
cache-from: type=gha,scope=docker-build-push-action-in-lxc
cache-to: type=gha,scope=docker-build-push-action-in-lxc
- name: verify the image can be read from the Forgejo registry
run: |
set -x
docker pull ${{ steps.registry.outputs.host-port }}/root/testimage:latest

View file

@ -12,10 +12,10 @@ enable-email-notifications: true
jobs:
example-docker-compose:
if: forge.repository_owner != 'forgejo-integration' && forge.repository_owner != 'forgejo-experimental' && forge.repository_owner != 'forgejo-release'
if: vars.ROLE == 'forgejo-coding'
runs-on: lxc-bookworm
steps:
- uses: actions/checkout@v4
- uses: https://data.forgejo.org/actions/checkout@v4
- name: Install docker
run: |

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: forge.repository_owner != 'forgejo-integration' && forge.repository_owner != 'forgejo-experimental' && forge.repository_owner != 'forgejo-release'
runs-on: lxc-bookworm
if: vars.ROLE == 'forgejo-coding'
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.1
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
@ -123,8 +124,8 @@ jobs:
started_running=/etc/forgejo-runner/$serial/started-running
killed_gracefully=/etc/forgejo-runner/$serial/killed-gracefully
stopped_gracefully=/etc/forgejo-runner/$serial/stopped-gracefully
retry --delay 5 --times 20 cp -a $started_running /tmp/first-run
retry --delay 1 --times 30 grep --quiet 'Starting runner daemon' /var/log/forgejo-runner/$serial.log
retry --delay 10 --times 20 cp -a $started_running /tmp/first-run
retry --delay 2 --times 30 grep --quiet 'Starting runner daemon' /var/log/forgejo-runner/$serial.log
systemctl stop forgejo-runner@$serial
! systemctl $all status forgejo-runner@$serial
ls -l /etc/forgejo-runner/$serial
@ -136,7 +137,7 @@ jobs:
! test -f $killed_gracefully
! test -f $stopped_gracefully
lifetime=${{ env.LIFETIME }}
# give it time to restart at least once
: give it time to restart at least once
ls -l /etc/forgejo-runner/$serial
sleep $lifetime ; sleep $lifetime
ls -l /etc/forgejo-runner/$serial

View file

@ -8,6 +8,7 @@
# vars.FROM_OWNER: forgejo-integration
# vars.TO_OWNER: forgejo
# vars.DOER: release-team
# vars.ROLE: forgejo-release
# secrets.TOKEN: <generated from code.forgejo.org/release-team>
# secrets.GPG_PRIVATE_KEY: <XYZ>
# secrets.GPG_PASSPHRASE: <ABC>
@ -24,19 +25,27 @@ enable-email-notifications: true
jobs:
publish:
runs-on: lxc-bookworm
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
if: vars.ROLE == 'forgejo-release'
steps:
- uses: https://data.forgejo.org/actions/checkout@v4
- name: copy & sign
uses: https://data.forgejo.org/forgejo/forgejo-build-publish/publish@v5.4.0
uses: https://data.forgejo.org/forgejo/forgejo-build-publish/publish@v5.4.1
with:
from-forgejo: ${{ vars.FORGEJO }}
to-forgejo: ${{ vars.FORGEJO }}
from-owner: ${{ vars.FROM_OWNER }}
to-owner: ${{ vars.TO_OWNER }}
repo: "runner"
release-notes: "See also https://code.forgejo.org/forgejo/runner/src/branch/main/RELEASE-NOTES.md#{ANCHOR}"
release-notes: |
- [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
---
release-notes-assistant: true
ref-name: ${{ forge.ref_name }}
sha: ${{ forge.sha }}

View file

@ -6,16 +6,17 @@ name: issue-labels
on:
pull_request_target:
types:
- opened
- edited
- synchronize
- labeled
env:
RNA_VERSION: v1.3.5 # renovate: datasource=forgejo-releases depName=forgejo/release-notes-assistant registryUrl=https://code.forgejo.org
RNA_VERSION: v1.4.1 # renovate: datasource=forgejo-releases depName=forgejo/release-notes-assistant
jobs:
release-notes:
if: vars.ROLE == 'forgejo-coding'
if: vars.ROLE == 'forgejo-coding' && !contains(forge.event.pull_request.labels.*.name, 'Kind/DependencyUpdate')
runs-on: docker
container:
image: 'data.forgejo.org/oci/ci:1'

View file

@ -14,19 +14,18 @@ env:
FORGEJO_RUNNER_SECRET: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
FORGEJO_SCRIPT: |
/usr/bin/s6-svscan /etc/s6 & sleep 10 ; su -c "forgejo admin user create --admin --username $FORGEJO_ADMIN_USER --password $FORGEJO_ADMIN_PASSWORD --email root@example.com" git && su -c "forgejo forgejo-cli actions register --labels docker --name therunner --secret $FORGEJO_RUNNER_SECRET" git && sleep infinity
GOPROXY: https://goproxy.io,direct
jobs:
build-and-tests:
name: build and test
if: forge.repository_owner != 'forgejo-integration' && forge.repository_owner != 'forgejo-experimental' && forge.repository_owner != 'forgejo-release'
if: vars.ROLE == 'forgejo-coding'
runs-on: docker
container:
image: 'code.forgejo.org/oci/ci:1'
services:
forgejo:
image: codeberg.org/forgejo/forgejo:11
image: code.forgejo.org/forgejo/forgejo:11
env:
FORGEJO__security__INSTALL_LOCK: "true"
FORGEJO__log__LEVEL: "debug"
@ -40,9 +39,9 @@ jobs:
- '/usr/bin/s6-svscan /etc/s6 & sleep 10 ; su -c "forgejo admin user create --admin --username $FORGEJO_ADMIN_USER --password $FORGEJO_ADMIN_PASSWORD --email root@example.com" git && su -c "forgejo forgejo-cli actions register --labels docker --name therunner --secret $FORGEJO_RUNNER_SECRET" git && sleep infinity'
steps:
- uses: actions/checkout@v4
- uses: https://data.forgejo.org/actions/checkout@v4
- uses: actions/setup-go@v5
- uses: https://data.forgejo.org/actions/setup-go@v5
with:
go-version-file: go.mod
@ -60,7 +59,7 @@ jobs:
- run: make build
- uses: https://code.forgejo.org/actions/upload-artifact@v3
- uses: https://data.forgejo.org/actions/upload-artifact@v3
with:
name: forgejo-runner
path: forgejo-runner
@ -74,16 +73,15 @@ jobs:
- run: make FORGEJO_URL=http://$FORGEJO_HOST_PORT test
runner-exec-tests:
needs: [build-and-tests]
name: runner exec tests
if: forge.repository_owner != 'forgejo-integration' && forge.repository_owner != 'forgejo-experimental' && forge.repository_owner != 'forgejo-release'
if: vars.ROLE == 'forgejo-coding'
runs-on: lxc-bookworm
needs: [build-and-tests]
steps:
- uses: actions/checkout@v4
- uses: https://data.forgejo.org/actions/checkout@v4
- uses: https://code.forgejo.org/actions/download-artifact@v3
- uses: https://data.forgejo.org/actions/download-artifact@v3
with:
name: forgejo-runner
@ -127,3 +125,150 @@ jobs:
set -x
./forgejo-runner exec --var MY_VAR=testvariable --workflows .forgejo/testdata/var.yml |& tee /tmp/var.out
grep --quiet 'Success - Main echo "VAR -> testvariable"' /tmp/var.out
integration-tests:
name: integration tests
if: vars.ROLE == 'forgejo-coding'
runs-on: lxc-bookworm
steps:
- uses: https://data.forgejo.org/actions/checkout@v4
- uses: https://data.forgejo.org/actions/setup-go@v5
with:
go-version-file: go.mod
- name: apt install docker.io
run: |
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get -q install -qq -y docker.io
- run: apt-get -q install -qq -y gcc # required for `-race`
- name: integration test
run: |
go test -race ./act/container
go test -race -timeout 30m ./act/runner/...
runner-integration-tests:
name: runner integration tests
if: vars.ROLE == 'forgejo-coding'
runs-on: lxc-bookworm
needs: [build-and-tests]
steps:
- uses: https://data.forgejo.org/actions/checkout@v4
- uses: https://data.forgejo.org/actions/setup-go@v5
with:
go-version-file: go.mod
- name: install docker
run: |
mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"ipv6": true,
"experimental": true,
"ip6tables": true,
"fixed-cidr-v6": "fd05:d0ca:1::/64",
"default-address-pools": [
{
"base": "172.19.0.0/16",
"size": 24
},
{
"base": "fd05:d0ca:2::/104",
"size": 112
}
]
}
EOF
apt --quiet install --yes -qq docker.io make
- name: install LXC
run: |
act/runner/lxc-helpers.sh lxc_prepare_environment
act/runner/lxc-helpers.sh lxc_install_lxc_inside 10.39.28 fdb1
- run: apt-get -q install -qq -y gcc # required for `-race`
- run: make integration-test
validate-mocks:
name: validate mocks
if: vars.ROLE == 'forgejo-coding'
runs-on: docker
container:
image: 'code.forgejo.org/oci/ci:1'
steps:
- uses: https://data.forgejo.org/actions/checkout@v4
- uses: https://data.forgejo.org/actions/setup-go@v5
with:
go-version-file: go.mod
- name: generate mocks
run: |
set -ex
make deps-tools
make generate
make fmt
- name: validate mocks
run: |
git diff --ignore-matching-lines='Code generated by mockery.*DO NOT EDIT' --quiet || {
echo "[ERROR] Please apply the changes mockery suggests:"
git diff --color=always
exit 1
}
validate-pre-commit:
name: validate pre-commit-hooks file
if: vars.ROLE == 'forgejo-coding'
runs-on: docker
container:
image: 'code.forgejo.org/oci/ci:1'
steps:
- uses: https://data.forgejo.org/actions/checkout@v4
- name: install pre-commit
env:
DEBIAN_FRONTEND: noninteractive
PIP_ROOT_USER_ACTION: ignore
PIP_BREAK_SYSTEM_PACKAGES: 1
PIP_PROGRESS_BAR: off
run: |
apt-get update -qq
apt-get -q install -qq -y python3-pip
python3 -m pip install 'pre-commit>=3.2.0'
- name: validate .pre-commit-hooks.yaml
run: pre-commit validate-manifest .pre-commit-hooks.yaml
# Will fail due to `act/runner/testdata/local-action-fails-schema-validation/action/action.yml`
- name: check pre-commit hook against local action files (should fail)
continue-on-error: true
run: |
pre-commit try-repo --all-files --verbose . forgejo-runner-validate
- name: check that a bad workflow file doesnt validate (should fail)
continue-on-error: true
run: |
mkdir -p test-repo
cd test-repo
git config set advice.defaultBranchName false
git init --quiet
mkdir -p .forgejo/workflows
cp ../act/runner/testdata/local-action-fails-schema-validation/action/action.yml ./
touch .forgejo/workflows/bad-workflow.yml
cat > .pre-commit-config.yaml <<EOF
repos:
- repo: ..
rev: ${{ forge.sha }}
hooks:
- id: forgejo-runner-validate
EOF
git add .
pre-commit run --all-files --verbose forgejo-runner-validate

View file

@ -16,6 +16,7 @@ linters:
- staticcheck
- unconvert
- unused
- usetesting
- wastedassign
settings:
depguard:

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

13
.pre-commit-hooks.yaml Normal file
View file

@ -0,0 +1,13 @@
- id: forgejo-runner-validate
name: Validate Forgejo Actions files
description: This hook validates Forgejo Actions action and workflow files.
language: golang
entry: runner validate
args: ['--directory', '.']
pass_filenames: false
files: (?:(?:^|/)action|^\.(?:forgejo|github|gitea)/workflows/[^/\n]+)\.ya?ml$
types: [yaml]
# 3.2.0 is when the pre-* `stages` used here were added.
# 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]

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
@ -32,7 +32,7 @@ LABEL maintainer="contact@forgejo.org" \
org.opencontainers.image.source="https://code.forgejo.org/forgejo/runner" \
org.opencontainers.image.version="${RELEASE_VERSION}" \
org.opencontainers.image.vendor="Forgejo" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.licenses="GPL-3.0-or-later" \
org.opencontainers.image.title="Forgejo Runner" \
org.opencontainers.image.description="A runner for Forgejo Actions."

688
LICENSE
View file

@ -1,20 +1,674 @@
Copyright (c) 2023-2025 The Forgejo Authors
Copyright (c) 2022 The Gitea Authors
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Preamble
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View file

@ -13,8 +13,8 @@ WINDOWS_ARCHS ?= windows/amd64
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.4 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.3.0 # renovate: datasource=go
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.5.0 # renovate: datasource=go
DOCKER_IMAGE ?= gitea/act_runner
DOCKER_TAG ?= nightly
@ -62,18 +62,18 @@ else
endif
endif
GO_PACKAGES_TO_VET ?= $(filter-out code.forgejo.org/forgejo/runner/internal/pkg/client/mocks,$(shell $(GO) list ./...))
GO_PACKAGES_TO_VET ?= $(filter-out code.forgejo.org/forgejo/runner/v11/internal/pkg/client/mocks code.forgejo.org/forgejo/runner/v11/act/artifactcache/mock_caches.go,$(shell $(GO) list ./...))
TAGS ?=
LDFLAGS ?= -X "code.forgejo.org/forgejo/runner/internal/pkg/ver.version=v$(RELEASE_VERSION)"
LDFLAGS ?= -X "code.forgejo.org/forgejo/runner/v11/internal/pkg/ver.version=v$(RELEASE_VERSION)"
all: build
.PHONY: lint
.PHONY: lint-check
lint-check:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS)
.PHONY: lint-fix
.PHONY: lint
lint:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run $(GOLANGCI_LINT_ARGS) --fix
@ -106,7 +106,12 @@ fmt-check:
fi;
test: lint-check fmt-check
@$(GO) test -v -cover -coverprofile coverage.txt ./internal/... && echo "\n==>\033[32m Ok\033[m\n" || exit 1
$(GO) test -v -race -short -cover -coverprofile coverage.txt ./internal/...
$(GO) test -race -short ./act/container
$(GO) test -race ./act/artifactcache/... ./act/workflowpattern/... ./act/filecollector/... ./act/common/... ./act/jobparser ./act/model ./act/exprparser ./act/schema
integration-test:
@$(GO) test -race -v ./internal/app/run/...
.PHONY: vet
vet:
@ -115,7 +120,7 @@ vet:
.PHONY: generate
generate:
$(GO) generate ./internal/...
$(GO) generate ./...
install: $(GOFILES)
$(GO) install -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)'

101
README.md
View file

@ -1,15 +1,15 @@
# Forgejo Runner
**WARNING:** this is [alpha release quality](https://en.wikipedia.org/wiki/Software_release_life_cycle#Alpha) code and should not be considered secure enough to deploy in production.
A daemon that connects to a Forgejo instance and runs jobs for continuous integration. The [installation and usage instructions](https://forgejo.org/docs/next/admin/actions/) are part of the Forgejo documentation.
# Reporting bugs
When filing a bug in [the issue tracker](https://code.forgejo.org/forgejo/runner/issues), it is very helpful to propose a pull request [in the end-to-end tests](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions) repository that adds a reproducer. It will fail the CI and unambiguously demonstrate that the problem exists. In most cases it is enough to add a workflow ([see the echo example](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions/example-echo)). For more complicated cases it is also possible to add a runner config file as well as shell scripts to setup and teardown the test case ([see the service example](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions/example-service)).
# Reporting security-related issues
Sensitive security-related issues should be reported to [security@forgejo.org](mailto:security@forgejo.org) using [encryption](https://keyoxide.org/security@forgejo.org).
## License
The Forgejo runner is distributed under the terms of the [GPL version 3.0](LICENSE) or any later version.
# Architectures & OS
The Forgejo runner is supported and tested on `amd64` and `arm64` ([binaries](https://code.forgejo.org/forgejo/runner/releases) and [containers](https://code.forgejo.org/forgejo/-/packages/container/runner/versions)) on Operating Systems based on the Linux kernel.
@ -30,77 +30,44 @@ The Forgejo runner is a dependency of the [setup-forgejo action](https://code.fo
- Install [Go](https://go.dev/doc/install) and `make(1)`
- `make build`
The [test workflow](.forgejo/workflows/test.yml) is a full example that builds the binary, runs the tests and launches the runner binary against a live Forgejo instance.
## Linting
## Generate mocks
- `make lint-check`
- `make lint` # will fix some lint errors
- `make deps-tools`
- `make generate`
## Testing
If there are changes, commit them to the repository.
The [workflow](.forgejo/workflows/test.yml) that runs in the CI uses similar commands.
## Local debug
### Without a Forgejo instance
The repositories are checked out in the same directory:
- Install [Docker](https://docs.docker.com/engine/install/)
- `make test integration-test`
- **runner**: [Forgejo runner](https://code.forgejo.org/forgejo/runner)
- **setup-forgejo**: [setup-forgejo](https://code.forgejo.org/actions/setup-forgejo)
The `TestRunner_RunEvent` test suite contains most integration tests
with real-world workflows and is time-consuming to run. During
development, it is helpful to run a specific test through a targeted
command such as this:
### Install dependencies
- `go test -count=1 -run='TestRunner_RunEvent$/local-action-dockerfile$' ./act/runner`
The dependencies are installed manually or with:
### With a Forgejo instance
```shell
setup-forgejo/forgejo-dependencies.sh
- Run a Forgejo instance locally (for instance at http://0.0.0.0:8080) and create as shared secret
```sh
export FORGEJO_RUNNER_SECRET='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
export FORGEJO_URL=http://0.0.0.0:8080
forgejo forgejo-cli actions register --labels docker --name therunner --secret $FORGEJO_RUNNER_SECRET
```
- `make test integration-test` # which will run addional tests because FORGEJO_URL is set
### Build the Forgejo runner
### end-to-end
```shell
cd runner ; rm -f forgejo-runner ; make forgejo-runner
```
### Launch Forgejo and the runner
A Forgejo instance is launched with:
```shell
cd setup-forgejo
./forgejo.sh setup
firefox $(cat forgejo-url)
```
The user is `root` with password `admin1234`. The runner is registered with:
```
cd setup-forgejo
docker exec --user 1000 forgejo forgejo actions generate-runner-token > forgejo-runner-token
../runner/forgejo-runner register --no-interactive --instance "$(cat forgejo-url)" --name runner --token $(cat forgejo-runner-token) --labels docker:docker://node:22-bookworm,self-hosted:host,lxc:lxc://debian:bookworm
```
And launched with:
```shell
cd setup-forgejo ; ../runner/forgejo-runner --config runner-config.yml daemon
```
Note that the `runner-config.yml` is required in that particular case
to configure the network in `bridge` mode, otherwise the runner will
create a network that cannot reach the forgejo instance.
### Try a sample workflow
From the Forgejo web interface, create a repository and add the
following to `.forgejo/workflows/try.yaml`. It will launch the job and
the result can be observed from the `actions` tab.
```yaml
on: [push]
jobs:
ls:
runs-on: docker
steps:
- uses: actions/checkout@v4
- run: |
ls ${{ github.workspace }}
```
- Follow the instructions from the end-to-end tests to [run actions tests locally](https://code.forgejo.org/forgejo/end-to-end#running-from-locally-built-binary).
- `./end-to-end.sh actions_teardown` # stop the Forgejo and runner daemons running in the end-to-end environment
- `( cd ~/clone-of-the-runner-repo ; make build ; cp forgejo-runner /tmp/forgejo-end-to-end/forgejo-runner )` # install the runner built from sources
- `./end-to-end.sh actions_setup 13.0` # start Forgejo v13.0 and the runner daemon in the end-to-end environment
- `./end-to-end.sh actions_verify_example echo` # run the [echo workflow](https://code.forgejo.org/forgejo/end-to-end/src/branch/main/actions/example-echo/.forgejo/workflows/test.yml)
- `xdg-open http://127.0.0.1:3000/root/example-echo/actions/runs/1` # see the logs workflow
- `less /tmp/forgejo-end-to-end/forgejo-runner.log` # analyze the runner logs
- `less /tmp/forgejo-end-to-end/forgejo-work-path/log/forgejo.log` # analyze the Forgejo logs

View file

@ -1,8 +1,6 @@
# Release Notes
## 9.0.0
* Breaking change: forgejo-runner exec --artifact-server-* options are deprecated. In order to test workflows using the artifact server, a local Forgejo instance can be used.
As of [Forgejo runner v9.0.0](https://code.forgejo.org/forgejo/runner/releases/tag/v9.0.0) the release notes are published in the release itself and this file will no longer be updated.
## 8.0.1

324
act/artifactcache/caches.go Normal file
View file

@ -0,0 +1,324 @@
package artifactcache
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"regexp"
"sync/atomic"
"time"
"github.com/sirupsen/logrus"
"github.com/timshannon/bolthold"
"go.etcd.io/bbolt"
)
//go:generate mockery --inpackage --name caches
type caches interface {
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)
exist(id uint64) (bool, error)
write(id, offset uint64, reader io.Reader) error
}
type cachesImpl struct {
dir string
storage *Storage
logger logrus.FieldLogger
secret string
db *bolthold.Store
gcing atomic.Bool
gcAt time.Time
}
func newCaches(dir, secret string, logger logrus.FieldLogger) (caches, error) {
c := &cachesImpl{
secret: secret,
}
c.logger = logger
if dir == "" {
home, err := os.UserHomeDir()
if err != nil {
return nil, err
}
dir = filepath.Join(home, ".cache", "actcache")
}
if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, err
}
c.dir = dir
storage, err := NewStorage(filepath.Join(dir, "cache"))
if err != nil {
return nil, err
}
c.storage = storage
file := filepath.Join(c.dir, "bolt.db")
db, err := bolthold.Open(file, 0o644, &bolthold.Options{
Encoder: json.Marshal,
Decoder: json.Unmarshal,
Options: &bbolt.Options{
Timeout: 5 * time.Second,
NoGrowSync: bbolt.DefaultOptions.NoGrowSync,
FreelistType: bbolt.DefaultOptions.FreelistType,
},
})
if err != nil {
return nil, fmt.Errorf("Open(%s): %w", file, err)
}
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) {
cache, err := findCache(db, repo, keys, version, writeIsolationKey)
if err != nil {
return nil, err
}
// If read was scoped to WriteIsolationKey and didn't find anything, we can fallback to the non-isolated cache read
if cache == nil && writeIsolationKey != "" {
cache, err = findCache(db, repo, keys, version, "")
if err != nil {
return nil, err
}
}
return cache, nil
}
// if not found, return (nil, nil) instead of an error.
func findCache(db *bolthold.Store, repo string, keys []string, version, writeIsolationKey string) (*Cache, error) {
cache := &Cache{}
for _, prefix := range keys {
// if a key in the list matches exactly, don't return partial matches
if err := db.FindOne(cache,
bolthold.Where("Repo").Eq(repo).Index("Repo").
And("Key").Eq(prefix).
And("Version").Eq(version).
And("WriteIsolationKey").Eq(writeIsolationKey).
And("Complete").Eq(true).
SortBy("CreatedAt").Reverse()); err == nil || !errors.Is(err, bolthold.ErrNotFound) {
if err != nil {
return nil, fmt.Errorf("find cache entry equal to %s: %w", prefix, err)
}
return cache, nil
}
prefixPattern := fmt.Sprintf("^%s", regexp.QuoteMeta(prefix))
re, err := regexp.Compile(prefixPattern)
if err != nil {
continue
}
if err := db.FindOne(cache,
bolthold.Where("Repo").Eq(repo).Index("Repo").
And("Key").RegExp(re).
And("Version").Eq(version).
And("WriteIsolationKey").Eq(writeIsolationKey).
And("Complete").Eq(true).
SortBy("CreatedAt").Reverse()); err != nil {
if errors.Is(err, bolthold.ErrNotFound) {
continue
}
return nil, fmt.Errorf("find cache entry starting with %s: %w", prefix, err)
}
return cache, nil
}
return nil, nil
}
func insertCache(db *bolthold.Store, cache *Cache) error {
if err := db.Insert(bolthold.NextSequence(), cache); err != nil {
return fmt.Errorf("insert cache: %w", err)
}
// write back id to db
if err := db.Update(cache.ID, cache); err != nil {
return fmt.Errorf("write back id to db: %w", err)
}
return nil
}
func (c *cachesImpl) readCache(id uint64, repo string) (*Cache, error) {
db := c.getDB()
cache := &Cache{}
if err := db.Get(id, cache); err != nil {
return nil, fmt.Errorf("readCache: Get(%v): %w", id, err)
}
if cache.Repo != repo {
return nil, fmt.Errorf("readCache: Get(%v): cache.Repo %s != repo %s", id, cache.Repo, repo)
}
return cache, nil
}
func (c *cachesImpl) useCache(id uint64) error {
db := c.getDB()
cache := &Cache{}
if err := db.Get(id, cache); err != nil {
return fmt.Errorf("useCache: Get(%v): %w", id, err)
}
cache.UsedAt = time.Now().Unix()
if err := db.Update(cache.ID, cache); err != nil {
return fmt.Errorf("useCache: Update(%v): %v", cache.ID, err)
}
return nil
}
func (c *cachesImpl) serve(w http.ResponseWriter, r *http.Request, id uint64) {
c.storage.Serve(w, r, id)
}
func (c *cachesImpl) commit(id uint64, size int64) (int64, error) {
return c.storage.Commit(id, size)
}
func (c *cachesImpl) exist(id uint64) (bool, error) {
return c.storage.Exist(id)
}
func (c *cachesImpl) write(id, offset uint64, reader io.Reader) error {
return c.storage.Write(id, offset, reader)
}
const (
keepUsed = 30 * 24 * time.Hour
keepUnused = 7 * 24 * time.Hour
keepTemp = 5 * time.Minute
keepOld = 5 * time.Minute
)
func (c *cachesImpl) setgcAt(at time.Time) {
c.gcAt = at
}
func (c *cachesImpl) gcCache() {
if c.gcing.Load() {
return
}
if !c.gcing.CompareAndSwap(false, true) {
return
}
defer c.gcing.Store(false)
if time.Since(c.gcAt) < time.Hour {
c.logger.Debugf("skip gc: %v", c.gcAt.String())
return
}
c.gcAt = time.Now()
c.logger.Debugf("gc: %v", c.gcAt.String())
db := c.getDB()
// Remove the caches which are not completed for a while, they are most likely to be broken.
var caches []*Cache
if err := db.Find(&caches, bolthold.
Where("UsedAt").Lt(time.Now().Add(-keepTemp).Unix()).
And("Complete").Eq(false),
); err != nil {
fatal(c.logger, fmt.Errorf("gc caches not completed: %v", err))
} else {
for _, cache := range caches {
c.storage.Remove(cache.ID)
if err := db.Delete(cache.ID, cache); err != nil {
c.logger.Errorf("delete cache: %v", err)
continue
}
c.logger.Infof("deleted cache: %+v", cache)
}
}
// Remove the old caches which have not been used recently.
caches = caches[:0]
if err := db.Find(&caches, bolthold.
Where("UsedAt").Lt(time.Now().Add(-keepUnused).Unix()),
); err != nil {
fatal(c.logger, fmt.Errorf("gc caches old not used: %v", err))
} else {
for _, cache := range caches {
c.storage.Remove(cache.ID)
if err := db.Delete(cache.ID, cache); err != nil {
c.logger.Warnf("delete cache: %v", err)
continue
}
c.logger.Infof("deleted cache: %+v", cache)
}
}
// Remove the old caches which are too old.
caches = caches[:0]
if err := db.Find(&caches, bolthold.
Where("CreatedAt").Lt(time.Now().Add(-keepUsed).Unix()),
); err != nil {
fatal(c.logger, fmt.Errorf("gc caches too old: %v", err))
} else {
for _, cache := range caches {
c.storage.Remove(cache.ID)
if err := db.Delete(cache.ID, cache); err != nil {
c.logger.Warnf("delete cache: %v", err)
continue
}
c.logger.Infof("deleted cache: %+v", cache)
}
}
// Remove the old caches with the same key and version, keep the latest one.
// Also keep the olds which have been used recently for a while in case of the cache is still in use.
if results, err := db.FindAggregate(
&Cache{},
bolthold.Where("Complete").Eq(true),
"Key", "Version",
); err != nil {
fatal(c.logger, fmt.Errorf("gc aggregate caches: %v", err))
} else {
for _, result := range results {
if result.Count() <= 1 {
continue
}
result.Sort("CreatedAt")
caches = caches[:0]
result.Reduction(&caches)
for _, cache := range caches[:len(caches)-1] {
if time.Since(time.Unix(cache.UsedAt, 0)) < keepOld {
// Keep it since it has been used recently, even if it's old.
// Or it could break downloading in process.
continue
}
c.storage.Remove(cache.ID)
if err := db.Delete(cache.ID, cache); err != nil {
c.logger.Warnf("delete cache: %v", err)
continue
}
c.logger.Infof("deleted cache: %+v", cache)
}
}
}
}

View file

@ -0,0 +1,53 @@
package artifactcache
import (
"testing"
"time"
"github.com/sirupsen/logrus"
"github.com/timshannon/bolthold"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
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)
assert.ErrorIs(t, err, bolthold.ErrNotFound)
})
repo := "repository"
cache := &Cache{
Repo: repo,
Key: "key",
Version: "version",
Size: 444,
}
now := time.Now().Unix()
cache.CreatedAt = now
cache.UsedAt = now
cache.Repo = repo
t.Run("Insert", func(t *testing.T) {
db := caches.getDB()
assert.NoError(t, insertCache(db, cache))
})
t.Run("Found", func(t *testing.T) {
found, err := caches.readCache(cache.ID, cache.Repo)
require.NoError(t, err)
assert.Equal(t, cache.ID, found.ID)
})
t.Run("InvalidRepo", func(t *testing.T) {
invalidRepo := "INVALID REPO"
found, err := caches.readCache(cache.ID, invalidRepo)
assert.Nil(t, found)
assert.ErrorContains(t, err, invalidRepo)
})
}

View file

@ -7,46 +7,56 @@ import (
"io"
"net"
"net/http"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync/atomic"
"time"
"github.com/julienschmidt/httprouter"
"github.com/sirupsen/logrus"
"github.com/timshannon/bolthold"
"go.etcd.io/bbolt"
"code.forgejo.org/forgejo/runner/act/cacheproxy"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
)
const (
urlBase = "/_apis/artifactcache"
)
type Handler struct {
dir string
storage *Storage
var fatal = func(logger logrus.FieldLogger, err error) {
logger.Errorf("unrecoverable error in the cache: %v", err)
if err := suicide(); err != nil {
logger.Errorf("unrecoverable error in the cache: failed to send the TERM signal to shutdown the daemon %v", err)
}
}
type Handler interface {
ExternalURL() string
Close() error
isClosed() bool
getCaches() caches
setCaches(caches caches)
find(w http.ResponseWriter, r *http.Request, params httprouter.Params)
reserve(w http.ResponseWriter, r *http.Request, params httprouter.Params)
upload(w http.ResponseWriter, r *http.Request, params httprouter.Params)
commit(w http.ResponseWriter, r *http.Request, params httprouter.Params)
get(w http.ResponseWriter, r *http.Request, params httprouter.Params)
clean(w http.ResponseWriter, r *http.Request, _ httprouter.Params)
middleware(handler httprouter.Handle) httprouter.Handle
responseJSON(w http.ResponseWriter, r *http.Request, code int, v ...any)
}
type handler struct {
caches caches
router *httprouter.Router
listener net.Listener
server *http.Server
logger logrus.FieldLogger
secret string
gcing atomic.Bool
gcAt time.Time
outboundIP string
}
func StartHandler(dir, outboundIP string, port uint16, secret string, logger logrus.FieldLogger) (*Handler, error) {
h := &Handler{
secret: secret,
}
func StartHandler(dir, outboundIP string, port uint16, secret string, logger logrus.FieldLogger) (Handler, error) {
h := &handler{}
if logger == nil {
discard := logrus.New()
@ -56,24 +66,11 @@ func StartHandler(dir, outboundIP string, port uint16, secret string, logger log
logger = logger.WithField("module", "artifactcache")
h.logger = logger
if dir == "" {
home, err := os.UserHomeDir()
if err != nil {
return nil, err
}
dir = filepath.Join(home, ".cache", "actcache")
}
if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, err
}
h.dir = dir
storage, err := NewStorage(filepath.Join(dir, "cache"))
caches, err := newCaches(dir, secret, logger)
if err != nil {
return nil, err
}
h.storage = storage
h.caches = caches
if outboundIP != "" {
h.outboundIP = outboundIP
@ -93,8 +90,6 @@ func StartHandler(dir, outboundIP string, port uint16, secret string, logger log
h.router = router
h.gcCache()
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) // listen on all interfaces
if err != nil {
return nil, err
@ -114,18 +109,22 @@ func StartHandler(dir, outboundIP string, port uint16, secret string, logger log
return h, nil
}
func (h *Handler) ExternalURL() string {
func (h *handler) ExternalURL() string {
port := strconv.Itoa(h.listener.Addr().(*net.TCPAddr).Port)
// TODO: make the external url configurable if necessary
return fmt.Sprintf("http://%s", net.JoinHostPort(h.outboundIP, port))
}
func (h *Handler) Close() error {
func (h *handler) Close() error {
if h == nil {
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 {
@ -146,22 +145,25 @@ func (h *Handler) Close() error {
return retErr
}
func (h *Handler) openDB() (*bolthold.Store, error) {
return bolthold.Open(filepath.Join(h.dir, "bolt.db"), 0o644, &bolthold.Options{
Encoder: json.Marshal,
Decoder: json.Unmarshal,
Options: &bbolt.Options{
Timeout: 5 * time.Second,
NoGrowSync: bbolt.DefaultOptions.NoGrowSync,
FreelistType: bbolt.DefaultOptions.FreelistType,
},
})
func (h *handler) isClosed() bool {
return h.listener == nil && h.server == nil
}
func (h *handler) getCaches() caches {
return h.caches
}
func (h *handler) setCaches(caches caches) {
if h.caches != nil {
h.caches.close()
}
h.caches = caches
}
// GET /_apis/artifactcache/cache
func (h *Handler) find(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
func (h *handler) find(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
rundata := runDataFromHeaders(r)
repo, err := h.validateMac(rundata)
repo, err := h.caches.validateMac(rundata)
if err != nil {
h.responseJSON(w, r, 403, err)
return
@ -174,16 +176,11 @@ func (h *Handler) find(w http.ResponseWriter, r *http.Request, params httprouter
}
version := r.URL.Query().Get("version")
db, err := h.openDB()
if err != nil {
h.responseJSON(w, r, 500, err)
return
}
defer db.Close()
db := h.caches.getDB()
cache, err := findCache(db, repo, keys, version)
cache, err := findCacheWithIsolationKeyFallback(db, repo, keys, version, rundata.WriteIsolationKey)
if err != nil {
h.responseJSON(w, r, 500, err)
h.responseFatalJSON(w, r, err)
return
}
if cache == nil {
@ -191,7 +188,7 @@ func (h *Handler) find(w http.ResponseWriter, r *http.Request, params httprouter
return
}
if ok, err := h.storage.Exist(cache.ID); err != nil {
if ok, err := h.caches.exist(cache.ID); err != nil {
h.responseJSON(w, r, 500, err)
return
} else if !ok {
@ -208,9 +205,9 @@ func (h *Handler) find(w http.ResponseWriter, r *http.Request, params httprouter
}
// POST /_apis/artifactcache/caches
func (h *Handler) reserve(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
func (h *handler) reserve(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
rundata := runDataFromHeaders(r)
repo, err := h.validateMac(rundata)
repo, err := h.caches.validateMac(rundata)
if err != nil {
h.responseJSON(w, r, 403, err)
return
@ -225,17 +222,13 @@ func (h *Handler) reserve(w http.ResponseWriter, r *http.Request, params httprou
api.Key = strings.ToLower(api.Key)
cache := api.ToCache()
db, err := h.openDB()
if err != nil {
h.responseJSON(w, r, 500, err)
return
}
defer db.Close()
db := h.caches.getDB()
now := time.Now().Unix()
cache.CreatedAt = now
cache.UsedAt = now
cache.Repo = repo
cache.WriteIsolationKey = rundata.WriteIsolationKey
if err := insertCache(db, cache); err != nil {
h.responseJSON(w, r, 500, err)
return
@ -246,9 +239,9 @@ func (h *Handler) reserve(w http.ResponseWriter, r *http.Request, params httprou
}
// PATCH /_apis/artifactcache/caches/:id
func (h *Handler) upload(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
func (h *handler) upload(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
rundata := runDataFromHeaders(r)
repo, err := h.validateMac(rundata)
repo, err := h.caches.validateMac(rundata)
if err != nil {
h.responseJSON(w, r, 403, err)
return
@ -260,19 +253,18 @@ func (h *Handler) upload(w http.ResponseWriter, r *http.Request, params httprout
return
}
cache, err := h.readCache(id)
cache, err := h.caches.readCache(id, repo)
if err != nil {
if errors.Is(err, bolthold.ErrNotFound) {
h.responseJSON(w, r, 404, fmt.Errorf("cache %d: not reserved", id))
return
}
h.responseJSON(w, r, 500, fmt.Errorf("cache Get: %w", err))
h.responseFatalJSON(w, r, fmt.Errorf("cache Get: %w", err))
return
}
// Should not happen
if cache.Repo != repo {
h.responseJSON(w, r, 500, fmt.Errorf("cache repo is not valid"))
if cache.WriteIsolationKey != rundata.WriteIsolationKey {
h.responseJSON(w, r, 403, fmt.Errorf("cache authorized for write isolation %q, but attempting to operate on %q", rundata.WriteIsolationKey, cache.WriteIsolationKey))
return
}
@ -285,11 +277,11 @@ func (h *Handler) upload(w http.ResponseWriter, r *http.Request, params httprout
h.responseJSON(w, r, 400, fmt.Errorf("cache parseContentRange(%s): %w", r.Header.Get("Content-Range"), err))
return
}
if err := h.storage.Write(cache.ID, start, r.Body); err != nil {
if err := h.caches.write(cache.ID, start, r.Body); err != nil {
h.responseJSON(w, r, 500, fmt.Errorf("cache storage.Write: %w", err))
return
}
if err := h.useCache(id); err != nil {
if err := h.caches.useCache(id); err != nil {
h.responseJSON(w, r, 500, fmt.Errorf("cache useCache: %w", err))
return
}
@ -297,9 +289,9 @@ func (h *Handler) upload(w http.ResponseWriter, r *http.Request, params httprout
}
// POST /_apis/artifactcache/caches/:id
func (h *Handler) commit(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
func (h *handler) commit(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
rundata := runDataFromHeaders(r)
repo, err := h.validateMac(rundata)
repo, err := h.caches.validateMac(rundata)
if err != nil {
h.responseJSON(w, r, 403, err)
return
@ -311,19 +303,18 @@ func (h *Handler) commit(w http.ResponseWriter, r *http.Request, params httprout
return
}
cache, err := h.readCache(id)
cache, err := h.caches.readCache(id, repo)
if err != nil {
if errors.Is(err, bolthold.ErrNotFound) {
h.responseJSON(w, r, 404, fmt.Errorf("cache %d: not reserved", id))
return
}
h.responseJSON(w, r, 500, fmt.Errorf("cache Get: %w", err))
h.responseFatalJSON(w, r, fmt.Errorf("cache Get: %w", err))
return
}
// Should not happen
if cache.Repo != repo {
h.responseJSON(w, r, 500, fmt.Errorf("cache repo is not valid"))
if cache.WriteIsolationKey != rundata.WriteIsolationKey {
h.responseJSON(w, r, 403, fmt.Errorf("cache authorized for write isolation %q, but attempting to operate on %q", rundata.WriteIsolationKey, cache.WriteIsolationKey))
return
}
@ -332,20 +323,15 @@ func (h *Handler) commit(w http.ResponseWriter, r *http.Request, params httprout
return
}
size, err := h.storage.Commit(cache.ID, cache.Size)
size, err := h.caches.commit(cache.ID, cache.Size)
if err != nil {
h.responseJSON(w, r, 500, err)
h.responseJSON(w, r, 500, fmt.Errorf("commit(%v): %w", cache.ID, err))
return
}
// 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.openDB()
if err != nil {
h.responseJSON(w, r, 500, err)
return
}
defer db.Close()
db := h.caches.getDB()
cache.Complete = true
if err := db.Update(cache.ID, cache); err != nil {
@ -357,9 +343,9 @@ func (h *Handler) commit(w http.ResponseWriter, r *http.Request, params httprout
}
// GET /_apis/artifactcache/artifacts/:id
func (h *Handler) get(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
func (h *handler) get(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
rundata := runDataFromHeaders(r)
repo, err := h.validateMac(rundata)
repo, err := h.caches.validateMac(rundata)
if err != nil {
h.responseJSON(w, r, 403, err)
return
@ -371,33 +357,33 @@ func (h *Handler) get(w http.ResponseWriter, r *http.Request, params httprouter.
return
}
cache, err := h.readCache(id)
cache, err := h.caches.readCache(id, repo)
if err != nil {
if errors.Is(err, bolthold.ErrNotFound) {
h.responseJSON(w, r, 404, fmt.Errorf("cache %d: not reserved", id))
return
}
h.responseJSON(w, r, 500, fmt.Errorf("cache Get: %w", err))
h.responseFatalJSON(w, r, fmt.Errorf("cache Get: %w", err))
return
}
// Should not happen
if cache.Repo != repo {
h.responseJSON(w, r, 500, fmt.Errorf("cache repo is not valid"))
// reads permitted against caches w/ the same isolation key, or no isolation key
if cache.WriteIsolationKey != rundata.WriteIsolationKey && cache.WriteIsolationKey != "" {
h.responseJSON(w, r, 403, fmt.Errorf("cache authorized for write isolation %q, but attempting to operate on %q", rundata.WriteIsolationKey, cache.WriteIsolationKey))
return
}
if err := h.useCache(id); err != nil {
if err := h.caches.useCache(id); err != nil {
h.responseJSON(w, r, 500, fmt.Errorf("cache useCache: %w", err))
return
}
h.storage.Serve(w, r, id)
h.caches.serve(w, r, id)
}
// POST /_apis/artifactcache/clean
func (h *Handler) clean(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
func (h *handler) clean(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
rundata := runDataFromHeaders(r)
_, err := h.validateMac(rundata)
_, err := h.caches.validateMac(rundata)
if err != nil {
h.responseJSON(w, r, 403, err)
return
@ -408,204 +394,20 @@ func (h *Handler) clean(w http.ResponseWriter, r *http.Request, _ httprouter.Par
h.responseJSON(w, r, 200)
}
func (h *Handler) middleware(handler httprouter.Handle) httprouter.Handle {
func (h *handler) middleware(handler httprouter.Handle) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
h.logger.Debugf("%s %s", r.Method, r.RequestURI)
handler(w, r, params)
go h.gcCache()
go h.caches.gcCache()
}
}
// if not found, return (nil, nil) instead of an error.
func findCache(db *bolthold.Store, repo string, keys []string, version string) (*Cache, error) {
cache := &Cache{}
for _, prefix := range keys {
// if a key in the list matches exactly, don't return partial matches
if err := db.FindOne(cache,
bolthold.Where("Repo").Eq(repo).
And("Key").Eq(prefix).
And("Version").Eq(version).
And("Complete").Eq(true).
SortBy("CreatedAt").Reverse()); err == nil || !errors.Is(err, bolthold.ErrNotFound) {
if err != nil {
return nil, fmt.Errorf("find cache: %w", err)
}
return cache, nil
}
prefixPattern := fmt.Sprintf("^%s", regexp.QuoteMeta(prefix))
re, err := regexp.Compile(prefixPattern)
if err != nil {
continue
}
if err := db.FindOne(cache,
bolthold.Where("Repo").Eq(repo).
And("Key").RegExp(re).
And("Version").Eq(version).
And("Complete").Eq(true).
SortBy("CreatedAt").Reverse()); err != nil {
if errors.Is(err, bolthold.ErrNotFound) {
continue
}
return nil, fmt.Errorf("find cache: %w", err)
}
return cache, nil
}
return nil, nil
func (h *handler) responseFatalJSON(w http.ResponseWriter, r *http.Request, err error) {
h.responseJSON(w, r, 500, err)
fatal(h.logger, err)
}
func insertCache(db *bolthold.Store, cache *Cache) error {
if err := db.Insert(bolthold.NextSequence(), cache); err != nil {
return fmt.Errorf("insert cache: %w", err)
}
// write back id to db
if err := db.Update(cache.ID, cache); err != nil {
return fmt.Errorf("write back id to db: %w", err)
}
return nil
}
func (h *Handler) readCache(id uint64) (*Cache, error) {
db, err := h.openDB()
if err != nil {
return nil, err
}
defer db.Close()
cache := &Cache{}
if err := db.Get(id, cache); err != nil {
return nil, err
}
return cache, nil
}
func (h *Handler) useCache(id uint64) error {
db, err := h.openDB()
if err != nil {
return err
}
defer db.Close()
cache := &Cache{}
if err := db.Get(id, cache); err != nil {
return err
}
cache.UsedAt = time.Now().Unix()
return db.Update(cache.ID, cache)
}
const (
keepUsed = 30 * 24 * time.Hour
keepUnused = 7 * 24 * time.Hour
keepTemp = 5 * time.Minute
keepOld = 5 * time.Minute
)
func (h *Handler) gcCache() {
if h.gcing.Load() {
return
}
if !h.gcing.CompareAndSwap(false, true) {
return
}
defer h.gcing.Store(false)
if time.Since(h.gcAt) < time.Hour {
h.logger.Debugf("skip gc: %v", h.gcAt.String())
return
}
h.gcAt = time.Now()
h.logger.Debugf("gc: %v", h.gcAt.String())
db, err := h.openDB()
if err != nil {
return
}
defer db.Close()
// Remove the caches which are not completed for a while, they are most likely to be broken.
var caches []*Cache
if err := db.Find(&caches, bolthold.
Where("UsedAt").Lt(time.Now().Add(-keepTemp).Unix()).
And("Complete").Eq(false),
); err != nil {
h.logger.Warnf("find caches: %v", err)
} else {
for _, cache := range caches {
h.storage.Remove(cache.ID)
if err := db.Delete(cache.ID, cache); err != nil {
h.logger.Warnf("delete cache: %v", err)
continue
}
h.logger.Infof("deleted cache: %+v", cache)
}
}
// Remove the old caches which have not been used recently.
caches = caches[:0]
if err := db.Find(&caches, bolthold.
Where("UsedAt").Lt(time.Now().Add(-keepUnused).Unix()),
); err != nil {
h.logger.Warnf("find caches: %v", err)
} else {
for _, cache := range caches {
h.storage.Remove(cache.ID)
if err := db.Delete(cache.ID, cache); err != nil {
h.logger.Warnf("delete cache: %v", err)
continue
}
h.logger.Infof("deleted cache: %+v", cache)
}
}
// Remove the old caches which are too old.
caches = caches[:0]
if err := db.Find(&caches, bolthold.
Where("CreatedAt").Lt(time.Now().Add(-keepUsed).Unix()),
); err != nil {
h.logger.Warnf("find caches: %v", err)
} else {
for _, cache := range caches {
h.storage.Remove(cache.ID)
if err := db.Delete(cache.ID, cache); err != nil {
h.logger.Warnf("delete cache: %v", err)
continue
}
h.logger.Infof("deleted cache: %+v", cache)
}
}
// Remove the old caches with the same key and version, keep the latest one.
// Also keep the olds which have been used recently for a while in case of the cache is still in use.
if results, err := db.FindAggregate(
&Cache{},
bolthold.Where("Complete").Eq(true),
"Key", "Version",
); err != nil {
h.logger.Warnf("find aggregate caches: %v", err)
} else {
for _, result := range results {
if result.Count() <= 1 {
continue
}
result.Sort("CreatedAt")
caches = caches[:0]
result.Reduction(&caches)
for _, cache := range caches[:len(caches)-1] {
if time.Since(time.Unix(cache.UsedAt, 0)) < keepOld {
// Keep it since it has been used recently, even if it's old.
// Or it could break downloading in process.
continue
}
h.storage.Remove(cache.ID)
if err := db.Delete(cache.ID, cache); err != nil {
h.logger.Warnf("delete cache: %v", err)
continue
}
h.logger.Infof("deleted cache: %+v", cache)
}
}
}
}
func (h *Handler) responseJSON(w http.ResponseWriter, r *http.Request, code int, v ...any) {
func (h *handler) responseJSON(w http.ResponseWriter, r *http.Request, code int, v ...any) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
var data []byte
if len(v) == 0 || v[0] == nil {
@ -638,11 +440,20 @@ func parseContentRange(s string) (uint64, uint64, error) {
return start, stop, nil
}
func runDataFromHeaders(r *http.Request) cacheproxy.RunData {
return cacheproxy.RunData{
type RunData struct {
RepositoryFullName string
RunNumber string
Timestamp string
RepositoryMAC string
WriteIsolationKey string
}
func runDataFromHeaders(r *http.Request) RunData {
return RunData{
RepositoryFullName: r.Header.Get("Forgejo-Cache-Repo"),
RunNumber: r.Header.Get("Forgejo-Cache-RunNumber"),
Timestamp: r.Header.Get("Forgejo-Cache-Timestamp"),
RepositoryMAC: r.Header.Get("Forgejo-Cache-MAC"),
WriteIsolationKey: r.Header.Get("Forgejo-Cache-WriteIsolationKey"),
}
}

View file

@ -4,48 +4,71 @@ import (
"bytes"
"crypto/rand"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"code.forgejo.org/forgejo/runner/v11/testutils"
"github.com/julienschmidt/httprouter"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/mock"
"github.com/timshannon/bolthold"
"go.etcd.io/bbolt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const (
cacheRepo = "testuser/repo"
cacheRunnum = "1"
cacheTimestamp = "0"
cacheMac = "c13854dd1ac599d1d61680cd93c26b77ba0ee10f374a3408bcaea82f38ca1865"
cacheMac = "bc2e9167f9e310baebcead390937264e4c0b21d2fdd49f5b9470d54406099360"
)
var handlerExternalURL string
type AuthHeaderTransport struct {
T http.RoundTripper
T http.RoundTripper
WriteIsolationKey string
OverrideDefaultMac string
}
func (t *AuthHeaderTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Set("Forgejo-Cache-Repo", cacheRepo)
req.Header.Set("Forgejo-Cache-RunNumber", cacheRunnum)
req.Header.Set("Forgejo-Cache-Timestamp", cacheTimestamp)
req.Header.Set("Forgejo-Cache-MAC", cacheMac)
if t.OverrideDefaultMac != "" {
req.Header.Set("Forgejo-Cache-MAC", t.OverrideDefaultMac)
} else {
req.Header.Set("Forgejo-Cache-MAC", cacheMac)
}
req.Header.Set("Forgejo-Cache-Host", handlerExternalURL)
if t.WriteIsolationKey != "" {
req.Header.Set("Forgejo-Cache-WriteIsolationKey", t.WriteIsolationKey)
}
return t.T.RoundTrip(req)
}
var (
httpClientTransport = AuthHeaderTransport{http.DefaultTransport}
httpClientTransport = AuthHeaderTransport{T: http.DefaultTransport}
httpClient = http.Client{Transport: &httpClientTransport}
)
func TestHandler(t *testing.T) {
defer testutils.MockVariable(&fatal, func(_ logrus.FieldLogger, err error) {
t.Fatalf("unexpected call to fatal(%v)", err)
})()
dir := filepath.Join(t.TempDir(), "artifactcache")
handler, err := StartHandler(dir, "", 0, "secret", nil)
require.NoError(t, err)
@ -54,10 +77,8 @@ func TestHandler(t *testing.T) {
base := fmt.Sprintf("%s%s", handler.ExternalURL(), urlBase)
defer func() {
t.Run("inpect db", func(t *testing.T) {
db, err := handler.openDB()
require.NoError(t, err)
defer db.Close()
t.Run("inspect db", func(t *testing.T) {
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)
@ -67,8 +88,7 @@ func TestHandler(t *testing.T) {
})
t.Run("close", func(t *testing.T) {
require.NoError(t, handler.Close())
assert.Nil(t, handler.server)
assert.Nil(t, handler.listener)
assert.True(t, handler.isClosed())
_, err := httpClient.Post(fmt.Sprintf("%s/caches/%d", base, 1), "", nil)
assert.Error(t, err)
})
@ -88,7 +108,7 @@ func TestHandler(t *testing.T) {
content := make([]byte, 100)
_, err := rand.Read(content)
require.NoError(t, err)
uploadCacheNormally(t, base, key, version, content)
uploadCacheNormally(t, base, key, version, "", content)
})
t.Run("clean", func(t *testing.T) {
@ -380,7 +400,7 @@ func TestHandler(t *testing.T) {
_, err := rand.Read(content)
require.NoError(t, err)
uploadCacheNormally(t, base, key, version, content)
uploadCacheNormally(t, base, key, version, "", content)
// Perform the request with the custom `httpClient` which will send correct MAC data
resp, err := httpClient.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
@ -416,7 +436,7 @@ func TestHandler(t *testing.T) {
for i := range contents {
_, err := rand.Read(contents[i])
require.NoError(t, err)
uploadCacheNormally(t, base, keys[i], version, contents[i])
uploadCacheNormally(t, base, keys[i], version, "", contents[i])
time.Sleep(time.Second) // ensure CreatedAt of caches are different
}
@ -454,13 +474,98 @@ func TestHandler(t *testing.T) {
assert.Equal(t, contents[except], content)
})
t.Run("find can't match without WriteIsolationKey match", func(t *testing.T) {
defer func() { httpClientTransport.WriteIsolationKey = "" }()
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20"
key := strings.ToLower(t.Name())
uploadCacheNormally(t, base, key, version, "TestWriteKey", make([]byte, 64))
func() {
defer overrideWriteIsolationKey("AnotherTestWriteKey")()
resp, err := httpClient.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
require.NoError(t, err)
require.Equal(t, 204, resp.StatusCode)
}()
{
resp, err := httpClient.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
require.NoError(t, err)
require.Equal(t, 204, resp.StatusCode)
}
func() {
defer overrideWriteIsolationKey("TestWriteKey")()
resp, err := httpClient.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode)
}()
})
t.Run("find prefers WriteIsolationKey match", func(t *testing.T) {
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d21"
key := strings.ToLower(t.Name())
// Between two values with the same `key`...
uploadCacheNormally(t, base, key, version, "TestWriteKey", make([]byte, 64))
uploadCacheNormally(t, base, key, version, "", make([]byte, 128))
// We should read the value with the matching WriteIsolationKey from the cache...
func() {
defer overrideWriteIsolationKey("TestWriteKey")()
resp, err := httpClient.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode)
got := struct {
ArchiveLocation string `json:"archiveLocation"`
}{}
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
contentResp, err := httpClient.Get(got.ArchiveLocation)
require.NoError(t, err)
require.Equal(t, 200, contentResp.StatusCode)
content, err := io.ReadAll(contentResp.Body)
require.NoError(t, err)
// Which we finally check matches the correct WriteIsolationKey's content here.
assert.Equal(t, make([]byte, 64), content)
}()
})
t.Run("find falls back if matching WriteIsolationKey not available", func(t *testing.T) {
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d21"
key := strings.ToLower(t.Name())
uploadCacheNormally(t, base, key, version, "", make([]byte, 128))
func() {
defer overrideWriteIsolationKey("TestWriteKey")()
resp, err := httpClient.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode)
got := struct {
ArchiveLocation string `json:"archiveLocation"`
}{}
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
contentResp, err := httpClient.Get(got.ArchiveLocation)
require.NoError(t, err)
require.Equal(t, 200, contentResp.StatusCode)
content, err := io.ReadAll(contentResp.Body)
require.NoError(t, err)
assert.Equal(t, make([]byte, 128), content)
}()
})
t.Run("case insensitive", func(t *testing.T) {
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20"
key := strings.ToLower(t.Name())
content := make([]byte, 100)
_, err := rand.Read(content)
require.NoError(t, err)
uploadCacheNormally(t, base, key+"_ABC", version, content)
uploadCacheNormally(t, base, key+"_ABC", version, "", content)
{
reqKey := key + "_aBc"
@ -494,7 +599,7 @@ func TestHandler(t *testing.T) {
for i := range contents {
_, err := rand.Read(contents[i])
require.NoError(t, err)
uploadCacheNormally(t, base, keys[i], version, contents[i])
uploadCacheNormally(t, base, keys[i], version, "", contents[i])
time.Sleep(time.Second) // ensure CreatedAt of caches are different
}
@ -545,7 +650,7 @@ func TestHandler(t *testing.T) {
for i := range contents {
_, err := rand.Read(contents[i])
require.NoError(t, err)
uploadCacheNormally(t, base, keys[i], version, contents[i])
uploadCacheNormally(t, base, keys[i], version, "", contents[i])
time.Sleep(time.Second) // ensure CreatedAt of caches are different
}
@ -581,9 +686,166 @@ func TestHandler(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, contents[expect], content)
})
t.Run("upload across WriteIsolationKey", func(t *testing.T) {
defer overrideWriteIsolationKey("CorrectKey")()
key := strings.ToLower(t.Name())
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20"
content := make([]byte, 256)
var id uint64
// reserve
{
body, err := json.Marshal(&Request{
Key: key,
Version: version,
Size: int64(len(content)),
})
require.NoError(t, err)
resp, err := httpClient.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
require.NoError(t, err)
assert.Equal(t, 200, resp.StatusCode)
got := struct {
CacheID uint64 `json:"cacheId"`
}{}
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
id = got.CacheID
}
// upload, but with the incorrect write isolation key relative to the cache obj created
func() {
defer overrideWriteIsolationKey("WrongKey")()
req, err := http.NewRequest(http.MethodPatch,
fmt.Sprintf("%s/caches/%d", base, id), bytes.NewReader(content))
require.NoError(t, err)
req.Header.Set("Content-Type", "application/octet-stream")
req.Header.Set("Content-Range", "bytes 0-99/*")
resp, err := httpClient.Do(req)
require.NoError(t, err)
assert.Equal(t, 403, resp.StatusCode)
}()
})
t.Run("commit across WriteIsolationKey", func(t *testing.T) {
defer overrideWriteIsolationKey("CorrectKey")()
key := strings.ToLower(t.Name())
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d20"
content := make([]byte, 256)
var id uint64
// reserve
{
body, err := json.Marshal(&Request{
Key: key,
Version: version,
Size: int64(len(content)),
})
require.NoError(t, err)
resp, err := httpClient.Post(fmt.Sprintf("%s/caches", base), "application/json", bytes.NewReader(body))
require.NoError(t, err)
assert.Equal(t, 200, resp.StatusCode)
got := struct {
CacheID uint64 `json:"cacheId"`
}{}
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
id = got.CacheID
}
// upload
{
req, err := http.NewRequest(http.MethodPatch,
fmt.Sprintf("%s/caches/%d", base, id), bytes.NewReader(content))
require.NoError(t, err)
req.Header.Set("Content-Type", "application/octet-stream")
req.Header.Set("Content-Range", "bytes 0-99/*")
resp, err := httpClient.Do(req)
require.NoError(t, err)
assert.Equal(t, 200, resp.StatusCode)
}
// commit, but with the incorrect write isolation key relative to the cache obj created
func() {
defer overrideWriteIsolationKey("WrongKey")()
resp, err := httpClient.Post(fmt.Sprintf("%s/caches/%d", base, id), "", nil)
require.NoError(t, err)
assert.Equal(t, 403, resp.StatusCode)
}()
})
t.Run("get across WriteIsolationKey", func(t *testing.T) {
defer func() { httpClientTransport.WriteIsolationKey = "" }()
version := "c19da02a2bd7e77277f1ac29ab45c09b7d46a4ee758284e26bb3045ad11d9d21"
key := strings.ToLower(t.Name())
uploadCacheNormally(t, base, key, version, "", make([]byte, 128))
keyIsolated := strings.ToLower(t.Name()) + "_isolated"
uploadCacheNormally(t, base, keyIsolated, version, "CorrectKey", make([]byte, 128))
// Perform the 'get' without the right WriteIsolationKey for the cache entry... should be OK for `key` since it
// was written with WriteIsolationKey "" meaning it is available for non-isolated access
func() {
defer overrideWriteIsolationKey("WhoopsWrongKey")()
resp, err := httpClient.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, key, version))
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode)
got := struct {
ArchiveLocation string `json:"archiveLocation"`
}{}
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
contentResp, err := httpClient.Get(got.ArchiveLocation)
require.NoError(t, err)
require.Equal(t, 200, contentResp.StatusCode)
httpClientTransport.WriteIsolationKey = "CorrectKey" // reset for next find
}()
// Perform the 'get' without the right WriteIsolationKey for the cache entry... should be 403 for `keyIsolated`
// because it was written with a different WriteIsolationKey.
{
got := func() struct {
ArchiveLocation string `json:"archiveLocation"`
} {
defer overrideWriteIsolationKey("CorrectKey")() // for test purposes make the `find` successful...
resp, err := httpClient.Get(fmt.Sprintf("%s/cache?keys=%s&version=%s", base, keyIsolated, version))
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode)
got := struct {
ArchiveLocation string `json:"archiveLocation"`
}{}
require.NoError(t, json.NewDecoder(resp.Body).Decode(&got))
return got
}()
func() {
defer overrideWriteIsolationKey("WhoopsWrongKey")() // but then access w/ the wrong key for `get`
contentResp, err := httpClient.Get(got.ArchiveLocation)
require.NoError(t, err)
require.Equal(t, 403, contentResp.StatusCode)
}()
}
})
}
func uploadCacheNormally(t *testing.T, base, key, version string, content []byte) {
func overrideWriteIsolationKey(writeIsolationKey string) func() {
originalWriteIsolationKey := httpClientTransport.WriteIsolationKey
originalMac := httpClientTransport.OverrideDefaultMac
httpClientTransport.WriteIsolationKey = writeIsolationKey
httpClientTransport.OverrideDefaultMac = ComputeMac("secret", cacheRepo, cacheRunnum, cacheTimestamp, httpClientTransport.WriteIsolationKey)
return func() {
httpClientTransport.WriteIsolationKey = originalWriteIsolationKey
httpClientTransport.OverrideDefaultMac = originalMac
}
}
func uploadCacheNormally(t *testing.T, base, key, version, writeIsolationKey string, content []byte) {
if writeIsolationKey != "" {
defer overrideWriteIsolationKey(writeIsolationKey)()
}
var id uint64
{
body, err := json.Marshal(&Request{
@ -642,6 +904,130 @@ func uploadCacheNormally(t *testing.T, base, key, version string, content []byte
}
}
func TestHandlerAPIFatalErrors(t *testing.T) {
for _, testCase := range []struct {
name string
prepare func(message string) func()
caches func(t *testing.T, message string) caches
call func(t *testing.T, handler Handler, w http.ResponseWriter)
}{
{
name: "find",
prepare: func(message string) func() {
return testutils.MockVariable(&findCacheWithIsolationKeyFallback, func(db *bolthold.Store, repo string, keys []string, version, writeIsolationKey string) (*Cache, error) {
return nil, errors.New(message)
})
},
caches: func(t *testing.T, message string) caches {
caches, err := newCaches(t.TempDir(), "secret", logrus.New())
require.NoError(t, err)
return caches
},
call: func(t *testing.T, handler Handler, w http.ResponseWriter) {
keyOne := "ONE"
req, err := http.NewRequest("GET", fmt.Sprintf("http://example.com/cache?keys=%s", keyOne), nil)
require.NoError(t, err)
req.Header.Set("Forgejo-Cache-Repo", cacheRepo)
req.Header.Set("Forgejo-Cache-RunNumber", cacheRunnum)
req.Header.Set("Forgejo-Cache-Timestamp", cacheTimestamp)
req.Header.Set("Forgejo-Cache-MAC", cacheMac)
req.Header.Set("Forgejo-Cache-Host", "http://example.com")
handler.find(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
},
call: func(t *testing.T, handler Handler, w http.ResponseWriter) {
id := 1234
req, err := http.NewRequest("PATCH", fmt.Sprintf("http://example.com/caches/%d", id), nil)
require.NoError(t, err)
handler.upload(w, req, httprouter.Params{
httprouter.Param{Key: "id", Value: fmt.Sprintf("%d", id)},
})
},
},
{
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
},
call: func(t *testing.T, handler Handler, w http.ResponseWriter) {
id := 1234
req, err := http.NewRequest("POST", fmt.Sprintf("http://example.com/caches/%d", id), nil)
require.NoError(t, err)
handler.commit(w, req, httprouter.Params{
httprouter.Param{Key: "id", Value: fmt.Sprintf("%d", id)},
})
},
},
{
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
},
call: func(t *testing.T, handler Handler, w http.ResponseWriter) {
id := 1234
req, err := http.NewRequest("GET", fmt.Sprintf("http://example.com/artifacts/%d", id), nil)
require.NoError(t, err)
handler.get(w, req, httprouter.Params{
httprouter.Param{Key: "id", Value: fmt.Sprintf("%d", id)},
})
},
},
// it currently is a noop
//{
//name: "clean",
//}
} {
t.Run(testCase.name, func(t *testing.T) {
message := "ERROR MESSAGE"
if testCase.prepare != nil {
defer testCase.prepare(message)()
}
fatalMessage := "<unset>"
defer testutils.MockVariable(&fatal, func(_ logrus.FieldLogger, err error) {
fatalMessage = err.Error()
})()
assertFatalMessage := func(t *testing.T, expected string) {
t.Helper()
assert.Contains(t, fatalMessage, expected)
}
dir := filepath.Join(t.TempDir(), "artifactcache")
handler, err := StartHandler(dir, "", 0, "secret", nil)
require.NoError(t, err)
defer handler.Close()
fatalMessage = "<unset>"
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)
require.Equal(t, 500, w.Code)
assertFatalMessage(t, message)
})
}
}
func TestHandler_gcCache(t *testing.T) {
dir := filepath.Join(t.TempDir(), "artifactcache")
handler, err := StartHandler(dir, "", 0, "", nil)
@ -725,18 +1111,15 @@ func TestHandler_gcCache(t *testing.T) {
},
}
db, err := handler.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.gcAt = time.Time{} // ensure gcCache will not skip
handler.gcCache()
handler.getCaches().setgcAt(time.Time{}) // ensure gcCache will not skip
handler.getCaches().gcCache()
db, err = handler.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{}
@ -748,7 +1131,6 @@ func TestHandler_gcCache(t *testing.T) {
}
})
}
require.NoError(t, db.Close())
}
func TestHandler_ExternalURL(t *testing.T) {
@ -759,8 +1141,7 @@ func TestHandler_ExternalURL(t *testing.T) {
assert.Equal(t, handler.ExternalURL(), "http://127.0.0.1:34567")
require.NoError(t, handler.Close())
assert.Nil(t, handler.server)
assert.Nil(t, handler.listener)
assert.True(t, handler.isClosed())
})
t.Run("reports correct URL on IPv6 zero host", func(t *testing.T) {
@ -770,8 +1151,7 @@ func TestHandler_ExternalURL(t *testing.T) {
assert.Equal(t, handler.ExternalURL(), "http://[2001:db8::]:34567")
require.NoError(t, handler.Close())
assert.Nil(t, handler.server)
assert.Nil(t, handler.listener)
assert.True(t, handler.isClosed())
})
t.Run("reports correct URL on IPv6", func(t *testing.T) {
@ -781,7 +1161,45 @@ func TestHandler_ExternalURL(t *testing.T) {
assert.Equal(t, handler.ExternalURL(), "http://[2001:db8::1:2:3:4]:34567")
require.NoError(t, handler.Close())
assert.Nil(t, handler.server)
assert.Nil(t, handler.listener)
assert.True(t, handler.isClosed())
})
}
var (
settleTime = 100 * time.Millisecond
fatalWaitingTime = 30 * time.Second
)
func waitSig(t *testing.T, c <-chan os.Signal, sig os.Signal) {
t.Helper()
// Sleep multiple times to give the kernel more tries to
// deliver the signal.
start := time.Now()
timer := time.NewTimer(settleTime / 10)
defer timer.Stop()
for time.Since(start) < fatalWaitingTime {
select {
case s := <-c:
if s == sig {
return
}
t.Fatalf("signal was %v, want %v", s, sig)
case <-timer.C:
timer.Reset(settleTime / 10)
}
}
t.Fatalf("timeout after %v waiting for %v", fatalWaitingTime, sig)
}
func TestHandler_fatal(t *testing.T) {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGTERM)
defer signal.Stop(c)
discard := logrus.New()
discard.Out = io.Discard
fatal(discard, errors.New("fatal error"))
waitSig(t, c, syscall.SIGTERM)
}

View file

@ -10,19 +10,17 @@ import (
"errors"
"strconv"
"time"
"code.forgejo.org/forgejo/runner/act/cacheproxy"
)
var ErrValidation = errors.New("validation error")
func (h *Handler) validateMac(rundata cacheproxy.RunData) (string, error) {
func (c *cachesImpl) validateMac(rundata RunData) (string, error) {
// TODO: allow configurable max age
if !validateAge(rundata.Timestamp) {
return "", ErrValidation
}
expectedMAC := computeMac(h.secret, rundata.RepositoryFullName, rundata.RunNumber, rundata.Timestamp)
expectedMAC := ComputeMac(c.secret, rundata.RepositoryFullName, rundata.RunNumber, rundata.Timestamp, rundata.WriteIsolationKey)
if hmac.Equal([]byte(expectedMAC), []byte(rundata.RepositoryMAC)) {
return rundata.RepositoryFullName, nil
}
@ -40,12 +38,14 @@ func validateAge(ts string) bool {
return true
}
func computeMac(secret, repo, run, ts string) string {
func ComputeMac(secret, repo, run, ts, writeIsolationKey string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(repo))
mac.Write([]byte(">"))
mac.Write([]byte(run))
mac.Write([]byte(">"))
mac.Write([]byte(ts))
mac.Write([]byte(">"))
mac.Write([]byte(writeIsolationKey))
return hex.EncodeToString(mac.Sum(nil))
}

View file

@ -5,12 +5,11 @@ import (
"testing"
"time"
"code.forgejo.org/forgejo/runner/act/cacheproxy"
"github.com/stretchr/testify/require"
)
func TestMac(t *testing.T) {
handler := &Handler{
cache := &cachesImpl{
secret: "secret for testing",
}
@ -19,15 +18,15 @@ func TestMac(t *testing.T) {
run := "1"
ts := strconv.FormatInt(time.Now().Unix(), 10)
mac := computeMac(handler.secret, name, run, ts)
rundata := cacheproxy.RunData{
mac := ComputeMac(cache.secret, name, run, ts, "")
rundata := RunData{
RepositoryFullName: name,
RunNumber: run,
Timestamp: ts,
RepositoryMAC: mac,
}
repoName, err := handler.validateMac(rundata)
repoName, err := cache.validateMac(rundata)
require.NoError(t, err)
require.Equal(t, name, repoName)
})
@ -37,15 +36,15 @@ func TestMac(t *testing.T) {
run := "1"
ts := "9223372036854775807" // This should last us for a while...
mac := computeMac(handler.secret, name, run, ts)
rundata := cacheproxy.RunData{
mac := ComputeMac(cache.secret, name, run, ts, "")
rundata := RunData{
RepositoryFullName: name,
RunNumber: run,
Timestamp: ts,
RepositoryMAC: mac,
}
_, err := handler.validateMac(rundata)
_, err := cache.validateMac(rundata)
require.Error(t, err)
})
@ -54,14 +53,14 @@ func TestMac(t *testing.T) {
run := "1"
ts := strconv.FormatInt(time.Now().Unix(), 10)
rundata := cacheproxy.RunData{
rundata := RunData{
RepositoryFullName: name,
RunNumber: run,
Timestamp: ts,
RepositoryMAC: "this is not the right mac :D",
}
repoName, err := handler.validateMac(rundata)
repoName, err := cache.validateMac(rundata)
require.Error(t, err)
require.Equal(t, "", repoName)
})
@ -72,9 +71,12 @@ func TestMac(t *testing.T) {
run := "42"
ts := "1337"
mac := computeMac(secret, name, run, ts)
expectedMac := "f666f06f917acb7186e152195b2a8c8d36d068ce683454be0878806e08e04f2b" // * Precomputed, anytime the computeMac function changes this needs to be recalculated
mac := ComputeMac(secret, name, run, ts, "")
expectedMac := "4754474b21329e8beadd2b4054aa4be803965d66e710fa1fee091334ed804f29" // * Precomputed, anytime the ComputeMac function changes this needs to be recalculated
require.Equal(t, expectedMac, mac)
require.Equal(t, mac, expectedMac)
mac = ComputeMac(secret, name, run, ts, "refs/pull/12/head")
expectedMac = "9ca8f4cb5e1b083ee8cd215215bc00f379b28511d3ef7930bf054767de34766d" // * Precomputed, anytime the ComputeMac function changes this needs to be recalculated
require.Equal(t, expectedMac, mac)
})
}

View file

@ -0,0 +1,225 @@
// Code generated by mockery v2.53.5. DO NOT EDIT.
package artifactcache
import (
http "net/http"
bolthold "github.com/timshannon/bolthold"
io "io"
mock "github.com/stretchr/testify/mock"
time "time"
)
// mockCaches is an autogenerated mock type for the caches type
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)
if len(ret) == 0 {
panic("no return value specified for commit")
}
var r0 int64
var r1 error
if rf, ok := ret.Get(0).(func(uint64, int64) (int64, error)); ok {
return rf(id, size)
}
if rf, ok := ret.Get(0).(func(uint64, int64) int64); ok {
r0 = rf(id, size)
} else {
r0 = ret.Get(0).(int64)
}
if rf, ok := ret.Get(1).(func(uint64, int64) error); ok {
r1 = rf(id, size)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// exist provides a mock function with given fields: id
func (_m *mockCaches) exist(id uint64) (bool, error) {
ret := _m.Called(id)
if len(ret) == 0 {
panic("no return value specified for exist")
}
var r0 bool
var r1 error
if rf, ok := ret.Get(0).(func(uint64) (bool, error)); ok {
return rf(id)
}
if rf, ok := ret.Get(0).(func(uint64) bool); ok {
r0 = rf(id)
} else {
r0 = ret.Get(0).(bool)
}
if rf, ok := ret.Get(1).(func(uint64) error); ok {
r1 = rf(id)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// gcCache provides a mock function with no fields
func (_m *mockCaches) gcCache() {
_m.Called()
}
// 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 getDB")
}
var r0 *bolthold.Store
if rf, ok := ret.Get(0).(func() *bolthold.Store); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*bolthold.Store)
}
}
return r0
}
// readCache provides a mock function with given fields: id, repo
func (_m *mockCaches) readCache(id uint64, repo string) (*Cache, error) {
ret := _m.Called(id, repo)
if len(ret) == 0 {
panic("no return value specified for readCache")
}
var r0 *Cache
var r1 error
if rf, ok := ret.Get(0).(func(uint64, string) (*Cache, error)); ok {
return rf(id, repo)
}
if rf, ok := ret.Get(0).(func(uint64, string) *Cache); ok {
r0 = rf(id, repo)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*Cache)
}
}
if rf, ok := ret.Get(1).(func(uint64, string) error); ok {
r1 = rf(id, repo)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// serve provides a mock function with given fields: w, r, id
func (_m *mockCaches) serve(w http.ResponseWriter, r *http.Request, id uint64) {
_m.Called(w, r, id)
}
// setgcAt provides a mock function with given fields: at
func (_m *mockCaches) setgcAt(at time.Time) {
_m.Called(at)
}
// useCache provides a mock function with given fields: id
func (_m *mockCaches) useCache(id uint64) error {
ret := _m.Called(id)
if len(ret) == 0 {
panic("no return value specified for useCache")
}
var r0 error
if rf, ok := ret.Get(0).(func(uint64) error); ok {
r0 = rf(id)
} else {
r0 = ret.Error(0)
}
return r0
}
// validateMac provides a mock function with given fields: rundata
func (_m *mockCaches) validateMac(rundata RunData) (string, error) {
ret := _m.Called(rundata)
if len(ret) == 0 {
panic("no return value specified for validateMac")
}
var r0 string
var r1 error
if rf, ok := ret.Get(0).(func(RunData) (string, error)); ok {
return rf(rundata)
}
if rf, ok := ret.Get(0).(func(RunData) string); ok {
r0 = rf(rundata)
} else {
r0 = ret.Get(0).(string)
}
if rf, ok := ret.Get(1).(func(RunData) error); ok {
r1 = rf(rundata)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// write provides a mock function with given fields: id, offset, reader
func (_m *mockCaches) write(id uint64, offset uint64, reader io.Reader) error {
ret := _m.Called(id, offset, reader)
if len(ret) == 0 {
panic("no return value specified for write")
}
var r0 error
if rf, ok := ret.Get(0).(func(uint64, uint64, io.Reader) error); ok {
r0 = rf(id, offset, reader)
} else {
r0 = ret.Error(0)
}
return r0
}
// newMockCaches creates a new instance of mockCaches. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func newMockCaches(t interface {
mock.TestingT
Cleanup(func())
},
) *mockCaches {
mock := &mockCaches{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View file

@ -24,12 +24,13 @@ func (c *Request) ToCache() *Cache {
}
type Cache struct {
ID uint64 `json:"id" boltholdKey:"ID"`
Repo string `json:"repo" boltholdIndex:"Repo"`
Key string `json:"key" boltholdIndex:"Key"`
Version string `json:"version" boltholdIndex:"Version"`
Size int64 `json:"cacheSize"`
Complete bool `json:"complete" boltholdIndex:"Complete"`
UsedAt int64 `json:"usedAt" boltholdIndex:"UsedAt"`
CreatedAt int64 `json:"createdAt" boltholdIndex:"CreatedAt"`
ID uint64 `json:"id" boltholdKey:"ID"`
Repo string `json:"repo" boltholdIndex:"Repo"`
Key string `json:"key"`
Version string `json:"version"`
Size int64 `json:"cacheSize"`
Complete bool `json:"complete"`
UsedAt int64 `json:"usedAt"`
CreatedAt int64 `json:"createdAt"`
WriteIsolationKey string `json:"writeIsolationKey"`
}

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

@ -4,9 +4,6 @@
package cacheproxy
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"io"
@ -22,7 +19,8 @@ import (
"github.com/julienschmidt/httprouter"
"github.com/sirupsen/logrus"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/artifactcache"
"code.forgejo.org/forgejo/runner/v11/act/common"
)
const (
@ -39,31 +37,26 @@ type Handler struct {
outboundIP string
cacheServerHost string
cacheServerHost string
cacheProxyHostOverride string
cacheSecret string
runs sync.Map
}
type RunData struct {
RepositoryFullName string
RunNumber string
Timestamp string
RepositoryMAC string
}
func (h *Handler) CreateRunData(fullName, runNumber, timestamp string) RunData {
mac := computeMac(h.cacheSecret, fullName, runNumber, timestamp)
return RunData{
func (h *Handler) CreateRunData(fullName, runNumber, timestamp, writeIsolationKey string) artifactcache.RunData {
mac := artifactcache.ComputeMac(h.cacheSecret, fullName, runNumber, timestamp, writeIsolationKey)
return artifactcache.RunData{
RepositoryFullName: fullName,
RunNumber: runNumber,
Timestamp: timestamp,
RepositoryMAC: mac,
WriteIsolationKey: writeIsolationKey,
}
}
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 {
@ -71,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
@ -85,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()
@ -140,11 +134,12 @@ func (h *Handler) newReverseProxy(targetHost string) (*httputil.ReverseProxy, er
h.logger.Warn(fmt.Sprintf("Tried starting a cache proxy with id %s, which does not exist.", id))
return
}
runData := data.(RunData)
runData := data.(artifactcache.RunData)
uri := matches[2]
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)
@ -152,26 +147,31 @@ func (h *Handler) newReverseProxy(targetHost string) (*httputil.ReverseProxy, er
r.Out.Header.Set("Forgejo-Cache-Timestamp", runData.Timestamp)
r.Out.Header.Set("Forgejo-Cache-MAC", runData.RepositoryMAC)
r.Out.Header.Set("Forgejo-Cache-Host", h.ExternalURL())
if runData.WriteIsolationKey != "" {
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)))
}
// Informs the proxy of a workflow run that can make cache requests.
// The RunData contains the information about the repository.
// The function returns the 32-bit random key which the run will use to identify itself.
func (h *Handler) AddRun(data RunData) (string, error) {
for retries := 0; retries < 3; retries++ {
key, err := common.RandName(4)
if err != nil {
return "", errors.New("Could not generate the run id")
}
func (h *Handler) AddRun(data artifactcache.RunData) (string, error) {
for range 3 {
key := common.MustRandName(4)
_, loaded := h.runs.LoadOrStore(key, data)
if !loaded {
// The key was unique and added successfully
@ -210,13 +210,3 @@ func (h *Handler) Close() error {
}
return retErr
}
func computeMac(secret, repo, run, ts string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(repo))
mac.Write([]byte(">"))
mac.Write([]byte(run))
mac.Write([]byte(">"))
mac.Write([]byte(ts))
return hex.EncodeToString(mac.Sum(nil))
}

View file

@ -1,9 +1,9 @@
package common
// CartesianProduct takes map of lists and returns list of unique tuples
func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interface{} {
func CartesianProduct(mapOfLists map[string][]any) []map[string]any {
listNames := make([]string, 0)
lists := make([][]interface{}, 0)
lists := make([][]any, 0)
for k, v := range mapOfLists {
listNames = append(listNames, k)
lists = append(lists, v)
@ -11,9 +11,9 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac
listCart := cartN(lists...)
rtn := make([]map[string]interface{}, 0)
rtn := make([]map[string]any, 0)
for _, list := range listCart {
vMap := make(map[string]interface{})
vMap := make(map[string]any)
for i, v := range list {
vMap[listNames[i]] = v
}
@ -22,7 +22,7 @@ func CartesianProduct(mapOfLists map[string][]interface{}) []map[string]interfac
return rtn
}
func cartN(a ...[]interface{}) [][]interface{} {
func cartN(a ...[]any) [][]any {
c := 1
for _, a := range a {
c *= len(a)
@ -30,8 +30,8 @@ func cartN(a ...[]interface{}) [][]interface{} {
if c == 0 || len(a) == 0 {
return nil
}
p := make([][]interface{}, c)
b := make([]interface{}, c*len(a))
p := make([][]any, c)
b := make([]any, c*len(a))
n := make([]int, len(a))
s := 0
for i := range p {

View file

@ -8,7 +8,7 @@ import (
func TestCartesianProduct(t *testing.T) {
assert := assert.New(t)
input := map[string][]interface{}{
input := map[string][]any{
"foo": {1, 2, 3, 4},
"bar": {"a", "b", "c"},
"baz": {false, true},
@ -25,7 +25,7 @@ func TestCartesianProduct(t *testing.T) {
assert.Contains(v, "baz")
}
input = map[string][]interface{}{
input = map[string][]any{
"foo": {1, 2, 3, 4},
"bar": {},
"baz": {false, true},
@ -33,7 +33,7 @@ func TestCartesianProduct(t *testing.T) {
output = CartesianProduct(input)
assert.Len(output, 0)
input = map[string][]interface{}{}
input = map[string][]any{}
output = CartesianProduct(input)
assert.Len(output, 0)
}

View file

@ -127,11 +127,8 @@ func (p *Pen) DrawBoxes(labels ...string) *Drawing {
// Draw to writer
func (d *Drawing) Draw(writer io.Writer, centerOnWidth int) {
padSize := (centerOnWidth - d.GetWidth()) / 2
if padSize < 0 {
padSize = 0
}
for _, l := range strings.Split(d.buf.String(), "\n") {
padSize := max((centerOnWidth-d.GetWidth())/2, 0)
for l := range strings.SplitSeq(d.buf.String(), "\n") {
if len(l) > 0 {
padding := strings.Repeat(" ", padSize)
fmt.Fprintf(writer, "%s%s\n", padding, l)

View file

@ -18,7 +18,7 @@ func (w Warning) Error() string {
}
// Warningf create a warning
func Warningf(format string, args ...interface{}) Warning {
func Warningf(format string, args ...any) Warning {
w := Warning{
Message: fmt.Sprintf(format, args...),
}
@ -32,7 +32,7 @@ type Executor func(ctx context.Context) error
type Conditional func(ctx context.Context) bool
// NewInfoExecutor is an executor that logs messages
func NewInfoExecutor(format string, args ...interface{}) Executor {
func NewInfoExecutor(format string, args ...any) Executor {
return func(ctx context.Context) error {
logger := Logger(ctx)
logger.Infof(format, args...)
@ -41,7 +41,7 @@ func NewInfoExecutor(format string, args ...interface{}) Executor {
}
// NewDebugExecutor is an executor that logs messages
func NewDebugExecutor(format string, args ...interface{}) Executor {
func NewDebugExecutor(format string, args ...any) Executor {
return func(ctx context.Context) error {
logger := Logger(ctx)
logger.Debugf(format, args...)
@ -109,14 +109,14 @@ func NewParallelExecutor(parallel int, executors ...Executor) Executor {
}(work, errs)
}
for i := 0; i < len(executors); i++ {
for i := range executors {
work <- executors[i]
}
close(work)
// Executor waits all executors to cleanup these resources.
var firstErr error
for i := 0; i < len(executors); i++ {
for range executors {
err := <-errs
if firstErr == nil {
firstErr = err

View file

@ -3,6 +3,7 @@ package common
import (
"context"
"fmt"
"sync/atomic"
"testing"
"time"
@ -12,7 +13,7 @@ import (
func TestNewWorkflow(t *testing.T) {
assert := assert.New(t)
ctx := context.Background()
ctx := t.Context()
// empty
emptyWorkflow := NewPipelineExecutor()
@ -40,7 +41,7 @@ func TestNewWorkflow(t *testing.T) {
func TestNewConditionalExecutor(t *testing.T) {
assert := assert.New(t)
ctx := context.Background()
ctx := t.Context()
trueCount := 0
falseCount := 0
@ -77,39 +78,50 @@ func TestNewConditionalExecutor(t *testing.T) {
func TestNewParallelExecutor(t *testing.T) {
assert := assert.New(t)
ctx := context.Background()
ctx := t.Context()
var count atomic.Int32
var activeCount atomic.Int32
var maxCount atomic.Int32
count := 0
activeCount := 0
maxCount := 0
emptyWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
count++
count.Add(1)
activeCount++
if activeCount > maxCount {
maxCount = activeCount
currentActive := activeCount.Add(1)
// maxCount = max(maxCount, currentActive) -- but concurrent-safe by using CompareAndSwap.
for {
currentMax := maxCount.Load()
if currentActive <= currentMax {
break
}
if maxCount.CompareAndSwap(currentMax, currentActive) {
break
}
// If CompareAndSwap failed, retry due to concurrent update by another goroutine.
}
time.Sleep(2 * time.Second)
activeCount--
activeCount.Add(-1)
return nil
})
err := NewParallelExecutor(2, emptyWorkflow, emptyWorkflow, emptyWorkflow)(ctx)
assert.Equal(3, count, "should run all 3 executors")
assert.Equal(2, maxCount, "should run at most 2 executors in parallel")
assert.Equal(int32(3), count.Load(), "should run all 3 executors")
assert.Equal(int32(2), maxCount.Load(), "should run at most 2 executors in parallel")
assert.Nil(err)
// Reset to test running the executor with 0 parallelism
count = 0
activeCount = 0
maxCount = 0
count.Store(0)
activeCount.Store(0)
maxCount.Store(0)
errSingle := NewParallelExecutor(0, emptyWorkflow, emptyWorkflow, emptyWorkflow)(ctx)
assert.Equal(3, count, "should run all 3 executors")
assert.Equal(1, maxCount, "should run at most 1 executors in parallel")
assert.Equal(int32(3), count.Load(), "should run all 3 executors")
assert.Equal(int32(1), maxCount.Load(), "should run at most 1 executors in parallel")
assert.Nil(errSingle)
}
@ -119,13 +131,13 @@ func TestNewParallelExecutorFailed(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
count := 0
var count atomic.Int32
errorWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
count++
count.Add(1)
return fmt.Errorf("fake error")
})
err := NewParallelExecutor(1, errorWorkflow)(ctx)
assert.Equal(1, count)
assert.Equal(int32(1), count.Load())
assert.ErrorIs(context.Canceled, err)
}
@ -137,16 +149,16 @@ func TestNewParallelExecutorCanceled(t *testing.T) {
errExpected := fmt.Errorf("fake error")
count := 0
var count atomic.Int32
successWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
count++
count.Add(1)
return nil
})
errorWorkflow := NewPipelineExecutor(func(ctx context.Context) error {
count++
count.Add(1)
return errExpected
})
err := NewParallelExecutor(3, errorWorkflow, successWorkflow, successWorkflow)(ctx)
assert.Equal(3, count)
assert.Equal(int32(3), count.Load())
assert.Error(errExpected, err)
}

View file

@ -19,7 +19,7 @@ import (
"github.com/mattn/go-isatty"
log "github.com/sirupsen/logrus"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
)
var (
@ -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()
@ -340,7 +340,7 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor {
logger.Errorf("Unable to resolve %s: %v", input.Ref, err)
}
if hash.String() != input.Ref && strings.HasPrefix(hash.String(), input.Ref) {
if hash.String() != input.Ref && len(input.Ref) >= 4 && strings.HasPrefix(hash.String(), input.Ref) {
return &Error{
err: ErrShortRef,
commit: hash.String(),

View file

@ -1,7 +1,6 @@
package git
import (
"context"
"fmt"
"os"
"os/exec"
@ -13,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
)
func TestFindGitSlug(t *testing.T) {
@ -54,13 +53,6 @@ func TestFindGitSlug(t *testing.T) {
}
}
func testDir(t *testing.T) string {
basedir, err := os.MkdirTemp("", "act-test")
require.NoError(t, err)
t.Cleanup(func() { _ = os.RemoveAll(basedir) })
return basedir
}
func cleanGitHooks(dir string) error {
hooksDir := filepath.Join(dir, ".git", "hooks")
files, err := os.ReadDir(hooksDir)
@ -85,7 +77,7 @@ func cleanGitHooks(dir string) error {
func TestFindGitRemoteURL(t *testing.T) {
assert := assert.New(t)
basedir := testDir(t)
basedir := t.TempDir()
gitConfig()
err := gitCmd("init", basedir)
assert.NoError(err)
@ -96,20 +88,20 @@ func TestFindGitRemoteURL(t *testing.T) {
err = gitCmd("-C", basedir, "remote", "add", "origin", remoteURL)
assert.NoError(err)
u, err := findGitRemoteURL(context.Background(), basedir, "origin")
u, err := findGitRemoteURL(t.Context(), basedir, "origin")
assert.NoError(err)
assert.Equal(remoteURL, u)
remoteURL = "git@github.com/AwesomeOwner/MyAwesomeRepo.git"
err = gitCmd("-C", basedir, "remote", "add", "upstream", remoteURL)
assert.NoError(err)
u, err = findGitRemoteURL(context.Background(), basedir, "upstream")
u, err = findGitRemoteURL(t.Context(), basedir, "upstream")
assert.NoError(err)
assert.Equal(remoteURL, u)
}
func TestGitFindRef(t *testing.T) {
basedir := testDir(t)
basedir := t.TempDir()
gitConfig()
for name, tt := range map[string]struct {
@ -174,8 +166,6 @@ func TestGitFindRef(t *testing.T) {
},
},
} {
tt := tt
name := name
t.Run(name, func(t *testing.T) {
dir := filepath.Join(basedir, name)
require.NoError(t, os.MkdirAll(dir, 0o755))
@ -184,7 +174,7 @@ func TestGitFindRef(t *testing.T) {
require.NoError(t, gitCmd("-C", dir, "config", "user.email", "user@example.com"))
require.NoError(t, cleanGitHooks(dir))
tt.Prepare(t, dir)
ref, err := FindGitRef(context.Background(), dir)
ref, err := FindGitRef(t.Context(), dir)
tt.Assert(t, ref, err)
})
}
@ -220,10 +210,10 @@ func TestGitCloneExecutor(t *testing.T) {
clone := NewGitCloneExecutor(NewGitCloneExecutorInput{
URL: tt.URL,
Ref: tt.Ref,
Dir: testDir(t),
Dir: t.TempDir(),
})
err := clone(context.Background())
err := clone(t.Context())
if tt.Err != nil {
assert.Error(t, err)
assert.Equal(t, tt.Err, err)
@ -263,7 +253,7 @@ func gitCmd(args ...string) error {
func TestCloneIfRequired(t *testing.T) {
tempDir := t.TempDir()
ctx := context.Background()
ctx := t.Context()
t.Run("clone", func(t *testing.T) {
repo, err := CloneIfRequired(ctx, "refs/heads/main", NewGitCloneExecutorInput{

View file

@ -5,12 +5,21 @@ package common
import (
"crypto/rand"
"encoding/hex"
"fmt"
)
func RandName(size int) (string, error) {
func randName(size int) (string, error) {
randBytes := make([]byte, size)
if _, err := rand.Read(randBytes); err != nil {
return "", err
}
return hex.EncodeToString(randBytes), nil
}
func MustRandName(size int) string {
name, err := randName(size)
if err != nil {
panic(fmt.Errorf("RandName(%d): %v", size, err))
}
return name
}

View file

@ -3,8 +3,9 @@ package container
import (
"context"
"io"
"time"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
"github.com/docker/go-connections/nat"
)
@ -34,9 +35,6 @@ type NewContainerInput struct {
ConfigOptions string
JobOptions string
// Gitea specific
AutoRemove bool
ValidVolumes []string
}
@ -63,6 +61,7 @@ type Container interface {
Remove() common.Executor
Close() common.Executor
ReplaceLogWriter(io.Writer, io.Writer) (io.Writer, io.Writer)
IsHealthy(ctx context.Context) (time.Duration, error)
}
// NewDockerBuildExecutorInput the input for the NewDockerBuildExecutor function

View file

@ -1,4 +1,4 @@
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd))
package container
@ -6,7 +6,7 @@ import (
"context"
"strings"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/credentials"
"github.com/docker/docker/api/types/registry"

View file

@ -1,4 +1,4 @@
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd))
package container
@ -14,7 +14,7 @@ import (
"github.com/moby/patternmatcher"
"github.com/moby/patternmatcher/ignorefile"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
)
// NewDockerBuildExecutor function to create a run executor for the container

View file

@ -1,4 +1,4 @@
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd))
// This file is exact copy of https://github.com/docker/cli/blob/9ac8584acfd501c3f4da0e845e3a40ed15c85041/cli/command/container/opts.go
// appended with license information.
@ -13,6 +13,7 @@ package container
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"os"
"path"
@ -32,7 +33,6 @@ import (
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/errdefs"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
)
@ -331,7 +331,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
// Validate the input mac address
if copts.macAddress != "" {
if _, err := opts.ValidateMACAddress(copts.macAddress); err != nil {
return nil, errors.Errorf("%s is not a valid mac address", copts.macAddress)
return nil, fmt.Errorf("%s is not a valid mac address", copts.macAddress)
}
}
if copts.stdin {
@ -347,7 +347,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
swappiness := copts.swappiness
if swappiness != -1 && (swappiness < 0 || swappiness > 100) {
return nil, errors.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
return nil, fmt.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
}
mounts := copts.mounts.Value()
@ -430,7 +430,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
// Merge in exposed ports to the map of published ports
for _, e := range copts.expose.GetSlice() {
if strings.Contains(e, ":") {
return nil, errors.Errorf("invalid port format for --expose: %s", e)
return nil, fmt.Errorf("invalid port format for --expose: %s", e)
}
// support two formats for expose, original format <portnum>/[<proto>]
// or <startport-endport>/[<proto>]
@ -439,7 +439,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
// if expose a port, the start and end port are the same
start, end, err := nat.ParsePortRange(port)
if err != nil {
return nil, errors.Errorf("invalid range format for --expose: %s, error: %s", e, err)
return nil, fmt.Errorf("invalid range format for --expose: %s, error: %s", e, err)
}
for i := start; i <= end; i++ {
p, err := nat.NewPort(proto, strconv.FormatUint(i, 10))
@ -488,22 +488,22 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
pidMode := container.PidMode(copts.pidMode)
if !pidMode.Valid() {
return nil, errors.Errorf("--pid: invalid PID mode")
return nil, errors.New("--pid: invalid PID mode")
}
utsMode := container.UTSMode(copts.utsMode)
if !utsMode.Valid() {
return nil, errors.Errorf("--uts: invalid UTS mode")
return nil, errors.New("--uts: invalid UTS mode")
}
usernsMode := container.UsernsMode(copts.usernsMode)
if !usernsMode.Valid() {
return nil, errors.Errorf("--userns: invalid USER mode")
return nil, errors.New("--userns: invalid USER mode")
}
cgroupnsMode := container.CgroupnsMode(copts.cgroupnsMode)
if !cgroupnsMode.Valid() {
return nil, errors.Errorf("--cgroupns: invalid CGROUP mode")
return nil, errors.New("--cgroupns: invalid CGROUP mode")
}
restartPolicy, err := opts.ParseRestartPolicy(copts.restartPolicy)
@ -537,7 +537,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
copts.healthRetries != 0
if copts.noHealthcheck {
if haveHealthSettings {
return nil, errors.Errorf("--no-healthcheck conflicts with --health-* options")
return nil, errors.New("--no-healthcheck conflicts with --health-* options")
}
test := strslice.StrSlice{"NONE"}
healthConfig = &container.HealthConfig{Test: test}
@ -548,16 +548,16 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
probe = strslice.StrSlice(args)
}
if copts.healthInterval < 0 {
return nil, errors.Errorf("--health-interval cannot be negative")
return nil, errors.New("--health-interval cannot be negative")
}
if copts.healthTimeout < 0 {
return nil, errors.Errorf("--health-timeout cannot be negative")
return nil, errors.New("--health-timeout cannot be negative")
}
if copts.healthRetries < 0 {
return nil, errors.Errorf("--health-retries cannot be negative")
return nil, errors.New("--health-retries cannot be negative")
}
if copts.healthStartPeriod < 0 {
return nil, fmt.Errorf("--health-start-period cannot be negative")
return nil, errors.New("--health-start-period cannot be negative")
}
healthConfig = &container.HealthConfig{
@ -677,7 +677,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
}
if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() {
return nil, errors.Errorf("Conflicting options: --restart and --rm")
return nil, errors.New("Conflicting options: --restart and --rm")
}
// only set this value if the user provided the flag, else it should default to nil
@ -741,7 +741,7 @@ func parseNetworkOpts(copts *containerOptions) (map[string]*networktypes.Endpoin
return nil, err
}
if _, ok := endpoints[n.Target]; ok {
return nil, errdefs.InvalidParameter(errors.Errorf("network %q is specified multiple times", n.Target))
return nil, errdefs.InvalidParameter(fmt.Errorf("network %q is specified multiple times", n.Target))
}
// For backward compatibility: if no custom options are provided for the network,
@ -838,7 +838,7 @@ func convertToStandardNotation(ports []string) ([]string, error) {
for _, param := range strings.Split(publish, ",") {
opt := strings.Split(param, "=")
if len(opt) < 2 {
return optsList, errors.Errorf("invalid publish opts format (should be name=value but got '%s')", param)
return optsList, fmt.Errorf("invalid publish opts format (should be name=value but got '%s')", param)
}
params[opt[0]] = opt[1]
@ -854,7 +854,7 @@ func convertToStandardNotation(ports []string) ([]string, error) {
func parseLoggingOpts(loggingDriver string, loggingOpts []string) (map[string]string, error) {
loggingOptsMap := opts.ConvertKVStringsToMap(loggingOpts)
if loggingDriver == "none" && len(loggingOpts) > 0 {
return map[string]string{}, errors.Errorf("invalid logging opts for driver %s", loggingDriver)
return map[string]string{}, fmt.Errorf("invalid logging opts for driver %s", loggingDriver)
}
return loggingOptsMap, nil
}
@ -867,17 +867,17 @@ func parseSecurityOpts(securityOpts []string) ([]string, error) {
if strings.Contains(opt, ":") {
con = strings.SplitN(opt, ":", 2)
} else {
return securityOpts, errors.Errorf("Invalid --security-opt: %q", opt)
return securityOpts, fmt.Errorf("Invalid --security-opt: %q", opt)
}
}
if con[0] == "seccomp" && con[1] != "unconfined" {
f, err := os.ReadFile(con[1])
if err != nil {
return securityOpts, errors.Errorf("opening seccomp profile (%s) failed: %v", con[1], err)
return securityOpts, fmt.Errorf("opening seccomp profile (%s) failed: %v", con[1], err)
}
b := bytes.NewBuffer(nil)
if err := json.Compact(b, f); err != nil {
return securityOpts, errors.Errorf("compacting json for seccomp profile (%s) failed: %v", con[1], err)
return securityOpts, fmt.Errorf("compacting json for seccomp profile (%s) failed: %v", con[1], err)
}
securityOpts[key] = fmt.Sprintf("seccomp=%s", b.Bytes())
}
@ -913,7 +913,7 @@ func parseStorageOpts(storageOpts []string) (map[string]string, error) {
opt := strings.SplitN(option, "=", 2)
m[opt[0]] = opt[1]
} else {
return nil, errors.Errorf("invalid storage option")
return nil, errors.New("invalid storage option")
}
}
return m, nil
@ -927,7 +927,7 @@ func parseDevice(device, serverOS string) (container.DeviceMapping, error) {
case "windows":
return parseWindowsDevice(device)
}
return container.DeviceMapping{}, errors.Errorf("unknown server OS: %s", serverOS)
return container.DeviceMapping{}, fmt.Errorf("unknown server OS: %s", serverOS)
}
// parseLinuxDevice parses a device mapping string to a container.DeviceMapping struct
@ -950,7 +950,7 @@ func parseLinuxDevice(device string) (container.DeviceMapping, error) {
case 1:
src = arr[0]
default:
return container.DeviceMapping{}, errors.Errorf("invalid device specification: %s", device)
return container.DeviceMapping{}, fmt.Errorf("invalid device specification: %s", device)
}
if dst == "" {
@ -980,7 +980,7 @@ func validateDeviceCgroupRule(val string) (string, error) {
return val, nil
}
return val, errors.Errorf("invalid device cgroup format '%s'", val)
return val, fmt.Errorf("invalid device cgroup format '%s'", val)
}
// validDeviceMode checks if the mode for device is valid or not.
@ -1012,7 +1012,7 @@ func validateDevice(val, serverOS string) (string, error) {
// Windows does validation entirely server-side
return val, nil
}
return "", errors.Errorf("unknown server OS: %s", serverOS)
return "", fmt.Errorf("unknown server OS: %s", serverOS)
}
// validateLinuxPath is the implementation of validateDevice knowing that the
@ -1027,12 +1027,12 @@ func validateLinuxPath(val string, validator func(string) bool) (string, error)
var mode string
if strings.Count(val, ":") > 2 {
return val, errors.Errorf("bad format for path: %s", val)
return val, fmt.Errorf("bad format for path: %s", val)
}
split := strings.SplitN(val, ":", 3)
if split[0] == "" {
return val, errors.Errorf("bad format for path: %s", val)
return val, fmt.Errorf("bad format for path: %s", val)
}
switch len(split) {
case 1:
@ -1051,13 +1051,13 @@ func validateLinuxPath(val string, validator func(string) bool) (string, error)
containerPath = split[1]
mode = split[2]
if isValid := validator(split[2]); !isValid {
return val, errors.Errorf("bad mode specified: %s", mode)
return val, fmt.Errorf("bad mode specified: %s", mode)
}
val = fmt.Sprintf("%s:%s:%s", split[0], containerPath, mode)
}
if !path.IsAbs(containerPath) {
return val, errors.Errorf("%s is not an absolute path", containerPath)
return val, fmt.Errorf("%s is not an absolute path", containerPath)
}
return val, nil
}
@ -1070,13 +1070,13 @@ func validateAttach(val string) (string, error) {
return s, nil
}
}
return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR")
return val, errors.New("valid streams are STDIN, STDOUT and STDERR")
}
func validateAPIVersion(c *containerConfig, serverAPIVersion string) error {
for _, m := range c.HostConfig.Mounts {
if m.BindOptions != nil && m.BindOptions.NonRecursive && versions.LessThan(serverAPIVersion, "1.40") {
return errors.Errorf("bind-nonrecursive requires API v1.40 or later")
return errors.New("bind-nonrecursive requires API v1.40 or later")
}
}
return nil

View file

@ -10,6 +10,7 @@
package container
import (
"errors"
"fmt"
"io"
"os"
@ -21,7 +22,6 @@ import (
"github.com/docker/docker/api/types/container"
networktypes "github.com/docker/docker/api/types/network"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
@ -288,7 +288,7 @@ func compareRandomizedStrings(a, b, c, d string) error {
if a == d && b == c {
return nil
}
return errors.Errorf("strings don't match")
return errors.New("strings don't match")
}
// Simple parse with MacAddress validation

View file

@ -1,4 +1,4 @@
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd))
package container
@ -6,6 +6,7 @@ import (
"context"
"fmt"
"code.forgejo.org/forgejo/runner/v11/act/common"
cerrdefs "github.com/containerd/errdefs"
"github.com/docker/docker/api/types/image"
)
@ -26,10 +27,15 @@ func ImageExistsLocally(ctx context.Context, imageName, platform string) (bool,
return false, err
}
if platform == "" || platform == "any" || fmt.Sprintf("%s/%s", inspectImage.Os, inspectImage.Architecture) == platform {
imagePlatform := fmt.Sprintf("%s/%s", inspectImage.Os, inspectImage.Architecture)
if platform == "" || platform == "any" || imagePlatform == platform {
return true, nil
}
logger := common.Logger(ctx)
logger.Infof("image found but platform does not match: %s (image) != %s (platform)\n", imagePlatform, platform)
return false, nil
}

View file

@ -1,7 +1,6 @@
package container
import (
"context"
"io"
"testing"
@ -19,7 +18,7 @@ func TestImageExistsLocally(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := context.Background()
ctx := t.Context()
// to help make this test reliable and not flaky, we need to have
// an image that will exist, and onew that won't exist
@ -36,7 +35,7 @@ func TestImageExistsLocally(t *testing.T) {
// pull an image
cli, err := client.NewClientWithOpts(client.FromEnv)
assert.Nil(t, err)
cli.NegotiateAPIVersion(context.Background())
cli.NegotiateAPIVersion(t.Context())
// Chose alpine latest because it's so small
// maybe we should build an image instead so that tests aren't reliable on dockerhub

View file

@ -1,4 +1,4 @@
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd))
package container
@ -74,7 +74,7 @@ func logDockerResponse(logger logrus.FieldLogger, dockerResponse io.ReadCloser,
return nil
}
func writeLog(logger logrus.FieldLogger, isError bool, format string, args ...interface{}) {
func writeLog(logger logrus.FieldLogger, isError bool, format string, args ...any) {
if isError {
logger.Errorf(format, args...)
} else {

View file

@ -1,11 +1,11 @@
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd))
package container
import (
"context"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
"github.com/docker/docker/api/types/network"
)

View file

@ -1,4 +1,4 @@
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd))
package container
@ -13,7 +13,7 @@ import (
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/registry"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
)
// NewDockerPullExecutor function to create a run executor for the container

View file

@ -1,7 +1,6 @@
package container
import (
"context"
"testing"
"github.com/docker/cli/cli/config"
@ -29,13 +28,13 @@ func TestCleanImage(t *testing.T) {
}
for _, table := range tables {
imageOut := cleanImage(context.Background(), table.imageIn)
imageOut := cleanImage(t.Context(), table.imageIn)
assert.Equal(t, table.imageOut, imageOut)
}
}
func TestGetImagePullOptions(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
config.SetDir("/non-existent/docker")

View file

@ -1,4 +1,4 @@
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd))
package container
@ -15,7 +15,9 @@ import (
"runtime"
"strconv"
"strings"
"time"
"dario.cat/mergo"
"github.com/Masterminds/semver"
"github.com/docker/cli/cli/compose/loader"
"github.com/docker/cli/cli/connhelper"
@ -30,15 +32,14 @@ import (
"github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
"github.com/gobwas/glob"
"github.com/imdario/mergo"
"github.com/joho/godotenv"
"github.com/kballard/go-shellquote"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/pflag"
"golang.org/x/term"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/filecollector"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/filecollector"
)
// NewContainer creates a reference to a container
@ -191,6 +192,47 @@ func (cr *containerReference) Remove() common.Executor {
).IfNot(common.Dryrun)
}
func (cr *containerReference) inspect(ctx context.Context) (container.InspectResponse, error) {
resp, err := cr.cli.ContainerInspect(ctx, cr.id)
if err != nil {
err = fmt.Errorf("service %v: %s", cr.input.NetworkAliases, err)
}
return resp, err
}
func (cr *containerReference) IsHealthy(ctx context.Context) (time.Duration, error) {
resp, err := cr.inspect(ctx)
if err != nil {
return 0, err
}
return cr.isHealthy(ctx, resp)
}
func (cr *containerReference) isHealthy(ctx context.Context, resp container.InspectResponse) (time.Duration, error) {
logger := common.Logger(ctx)
if resp.Config == nil || resp.Config.Healthcheck == nil || resp.State == nil || resp.State.Health == nil || len(resp.Config.Healthcheck.Test) == 1 && strings.EqualFold(resp.Config.Healthcheck.Test[0], "NONE") {
logger.Debugf("no container health check defined, hope for the best")
return 0, nil
}
switch resp.State.Health.Status {
case container.Starting:
wait := resp.Config.Healthcheck.Interval
if wait <= 0 {
wait = time.Second
}
logger.Infof("service %v: container health check %s (%s) is starting, waiting %v", cr.input.NetworkAliases, cr.id, resp.Config.Image, wait)
return wait, nil
case container.Healthy:
logger.Infof("service %v: container health check %s (%s) is healthy", cr.input.NetworkAliases, cr.id, resp.Config.Image)
return 0, nil
case container.Unhealthy:
return 0, fmt.Errorf("service %v: container health check %s (%s) is not healthy", cr.input.NetworkAliases, cr.id, resp.Config.Image)
default:
return 0, fmt.Errorf("service %v: unexpected health status %s (%s) %v", cr.input.NetworkAliases, cr.id, resp.Config.Image, resp.State.Health.Status)
}
}
func (cr *containerReference) ReplaceLogWriter(stdout, stderr io.Writer) (io.Writer, io.Writer) {
out := cr.input.Stdout
err := cr.input.Stderr
@ -412,6 +454,11 @@ func (cr *containerReference) mergeJobOptions(ctx context.Context, config *conta
logger := common.Logger(ctx)
if jobConfig.Config.Healthcheck != nil && len(jobConfig.Config.Healthcheck.Test) > 0 {
logger.Debugf("--health-* options %+v", jobConfig.Config.Healthcheck)
config.Healthcheck = jobConfig.Config.Healthcheck
}
if len(jobConfig.Config.Volumes) > 0 {
logger.Debugf("--volume options (except bind) %v", jobConfig.Config.Volumes)
err = mergo.Merge(&config.Volumes, jobConfig.Config.Volumes, mergo.WithOverride, mergo.WithAppendSlice)
@ -436,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
@ -530,7 +585,6 @@ func (cr *containerReference) create(capAdd, capDrop []string) common.Executor {
Privileged: input.Privileged,
UsernsMode: container.UsernsMode(input.UsernsMode),
PortBindings: input.PortBindings,
AutoRemove: input.AutoRemove,
}
logger.Debugf("Common container.HostConfig ==> %+v", hostConfig)
@ -788,7 +842,7 @@ func (cr *containerReference) CopyTarStream(ctx context.Context, destPath string
// Copy Content
err = cr.cli.CopyToContainer(ctx, cr.id, destPath, tarStream, container.CopyToContainerOptions{})
if err != nil {
return fmt.Errorf("failed to copy content to container: %w", err)
return fmt.Errorf("copyTarStream: failed to copy content to container: %w", err)
}
// If this fails, then folders have wrong permissions on non root container
if cr.UID != 0 || cr.GID != 0 {
@ -864,7 +918,7 @@ func (cr *containerReference) copyDir(dstPath, srcPath string, useGitIgnore bool
}
err = cr.cli.CopyToContainer(ctx, cr.id, "/", tarFile, container.CopyToContainerOptions{})
if err != nil {
return fmt.Errorf("failed to copy content to container: %w", err)
return fmt.Errorf("copyDir: failed to copy content to container: %w", err)
}
return nil
}
@ -898,7 +952,7 @@ func (cr *containerReference) copyContent(dstPath string, files ...*FileEntry) c
logger.Debugf("Extracting content to '%s'", dstPath)
err := cr.cli.CopyToContainer(ctx, cr.id, dstPath, &buf, container.CopyToContainerOptions{})
if err != nil {
return fmt.Errorf("failed to copy content to container: %w", err)
return fmt.Errorf("copyContent: failed to copy content to container: %w", err)
}
return nil
}

View file

@ -11,7 +11,7 @@ import (
"testing"
"time"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
@ -26,7 +26,7 @@ func TestDocker(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
ctx := context.Background()
ctx := t.Context()
client, err := GetDockerClient(ctx)
assert.NoError(t, err)
defer client.Close()
@ -152,7 +152,7 @@ func TestDockerExecAbort(t *testing.T) {
}
func TestDockerExecFailure(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
conn := &mockConn{}
@ -183,7 +183,7 @@ func TestDockerExecFailure(t *testing.T) {
}
func TestDockerCopyTarStream(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
conn := &mockConn{}
@ -205,7 +205,7 @@ func TestDockerCopyTarStream(t *testing.T) {
}
func TestDockerCopyTarStreamErrorInCopyFiles(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
conn := &mockConn{}
@ -230,7 +230,7 @@ func TestDockerCopyTarStreamErrorInCopyFiles(t *testing.T) {
}
func TestDockerCopyTarStreamErrorInMkdir(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
conn := &mockConn{}
@ -318,7 +318,7 @@ func TestCheckVolumes(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
logger, _ := test.NewNullLogger()
ctx := common.WithLogger(context.Background(), logger)
ctx := common.WithLogger(t.Context(), logger)
cr := &containerReference{
input: &NewContainerInput{
ValidVolumes: tc.validVolumes,
@ -338,11 +338,18 @@ func TestMergeJobOptions(t *testing.T) {
hostConfig *container.HostConfig
}{
{
name: "ok",
options: "--volume /frob:/nitz --volume somevolume --tmpfs /tmp:exec,noatime --hostname alternatehost",
name: "Ok",
options: `--volume /frob:/nitz --volume somevolume --tmpfs /tmp:exec,noatime --hostname alternatehost --health-cmd "healthz one" --health-interval 10s --health-timeout 5s --health-retries 3 --health-start-period 30s`,
config: &container.Config{
Volumes: map[string]struct{}{"somevolume": {}},
Hostname: "alternatehost",
Healthcheck: &container.HealthConfig{
Test: []string{"CMD-SHELL", "healthz one"},
Interval: 10 * time.Second,
Timeout: 5 * time.Second,
StartPeriod: 30 * time.Second,
Retries: 3,
},
},
hostConfig: &container.HostConfig{
Binds: []string{"/frob:/nitz"},
@ -350,7 +357,17 @@ func TestMergeJobOptions(t *testing.T) {
},
},
{
name: "ignore",
name: "DisableHealthCheck",
options: `--no-healthcheck`,
config: &container.Config{
Healthcheck: &container.HealthConfig{
Test: []string{"NONE"},
},
},
hostConfig: &container.HostConfig{},
},
{
name: "Ignore",
options: "--pid=host --device=/dev/sda",
config: &container.Config{},
hostConfig: &container.HostConfig{},
@ -362,10 +379,86 @@ func TestMergeJobOptions(t *testing.T) {
JobOptions: testCase.options,
},
}
config, hostConfig, err := cr.mergeJobOptions(context.Background(), &container.Config{}, &container.HostConfig{})
config, hostConfig, err := cr.mergeJobOptions(t.Context(), &container.Config{}, &container.HostConfig{})
require.NoError(t, err)
assert.EqualValues(t, testCase.config, config)
assert.EqualValues(t, testCase.hostConfig, hostConfig)
})
}
}
func TestDockerRun_isHealthy(t *testing.T) {
cr := containerReference{
id: "containerid",
input: &NewContainerInput{
NetworkAliases: []string{"servicename"},
},
}
ctx := t.Context()
makeInspectResponse := func(interval time.Duration, status container.HealthStatus, test []string) container.InspectResponse {
return container.InspectResponse{
Config: &container.Config{
Image: "example.com/some/image",
Healthcheck: &container.HealthConfig{
Interval: interval,
Test: test,
},
},
ContainerJSONBase: &container.ContainerJSONBase{
State: &container.State{
Health: &container.Health{
Status: status,
},
},
},
}
}
t.Run("IncompleteResponseOrNoHealthCheck", func(t *testing.T) {
wait, err := cr.isHealthy(ctx, container.InspectResponse{})
assert.Zero(t, wait)
assert.NoError(t, err)
// --no-healthcheck translates into a NONE test command
resp := makeInspectResponse(0, container.NoHealthcheck, []string{"NONE"})
wait, err = cr.isHealthy(ctx, resp)
assert.Zero(t, wait)
assert.NoError(t, err)
})
t.Run("StartingUndefinedIntervalIsNotZero", func(t *testing.T) {
resp := makeInspectResponse(0, container.Starting, nil)
wait, err := cr.isHealthy(ctx, resp)
assert.NotZero(t, wait)
assert.NoError(t, err)
})
t.Run("StartingWithInterval", func(t *testing.T) {
expectedWait := time.Duration(42)
resp := makeInspectResponse(expectedWait, container.Starting, nil)
actualWait, err := cr.isHealthy(ctx, resp)
assert.Equal(t, expectedWait, actualWait)
assert.NoError(t, err)
})
t.Run("Unhealthy", func(t *testing.T) {
resp := makeInspectResponse(0, container.Unhealthy, nil)
wait, err := cr.isHealthy(ctx, resp)
assert.Zero(t, wait)
assert.ErrorContains(t, err, "is not healthy")
})
t.Run("Healthy", func(t *testing.T) {
resp := makeInspectResponse(0, container.Healthy, nil)
wait, err := cr.isHealthy(ctx, resp)
assert.Zero(t, wait)
assert.NoError(t, err)
})
t.Run("UnknownStatus", func(t *testing.T) {
resp := makeInspectResponse(0, container.NoHealthcheck, nil)
wait, err := cr.isHealthy(ctx, resp)
assert.Zero(t, wait)
assert.ErrorContains(t, err, "unexpected")
})
}

View file

@ -1,15 +1,15 @@
//go:build WITHOUT_DOCKER || !(linux || darwin || windows || netbsd)
//go:build WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd)
package container
import (
"context"
"errors"
"runtime"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/system"
"github.com/pkg/errors"
)
// ImageExistsLocally returns a boolean indicating if an image with the

View file

@ -1,16 +1,17 @@
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd))
//go:build !(WITHOUT_DOCKER || !(linux || darwin || windows || netbsd || freebsd))
package container
import (
"context"
"slices"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/volume"
)
func NewDockerVolumeRemoveExecutor(volumeName string, force bool) common.Executor {
func NewDockerVolumesRemoveExecutor(volumeNames []string) common.Executor {
return func(ctx context.Context) error {
cli, err := GetDockerClient(ctx)
if err != nil {
@ -24,17 +25,18 @@ func NewDockerVolumeRemoveExecutor(volumeName string, force bool) common.Executo
}
for _, vol := range list.Volumes {
if vol.Name == volumeName {
return removeExecutor(volumeName, force)(ctx)
if slices.Contains(volumeNames, vol.Name) {
if err := removeExecutor(vol.Name)(ctx); err != nil {
return err
}
}
}
// Volume not found - do nothing
return nil
}
}
func removeExecutor(volume string, force bool) common.Executor {
func removeExecutor(volume string) common.Executor {
return func(ctx context.Context) error {
logger := common.Logger(ctx)
logger.Debugf("%sdocker volume rm %s", logPrefix, volume)
@ -49,6 +51,7 @@ func removeExecutor(volume string, force bool) common.Executor {
}
defer cli.Close()
force := false
return cli.VolumeRemove(ctx, volume, force)
}
}

View file

@ -12,7 +12,7 @@ type ExecutionsEnvironment interface {
GetPathVariableName() string
DefaultPathVariable() string
JoinPathVariable(...string) string
GetRunnerContext(ctx context.Context) map[string]interface{}
GetRunnerContext(ctx context.Context) map[string]any
// On windows PATH and Path are the same key
IsEnvironmentCaseInsensitive() bool
}

View file

@ -13,6 +13,7 @@ import (
"path/filepath"
"runtime"
"strings"
"sync/atomic"
"time"
"github.com/go-git/go-billy/v5/helper/polyfill"
@ -20,9 +21,9 @@ import (
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
"golang.org/x/term"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/filecollector"
"code.forgejo.org/forgejo/runner/act/lookpath"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/filecollector"
"code.forgejo.org/forgejo/runner/v11/act/lookpath"
)
type HostEnvironment struct {
@ -33,7 +34,6 @@ type HostEnvironment struct {
Workdir string
ActPath string
Root string
CleanUp func()
StdOut io.Writer
LXC bool
}
@ -191,12 +191,12 @@ func (e *HostEnvironment) Start(_ bool) common.Executor {
type ptyWriter struct {
Out io.Writer
AutoStop bool
AutoStop atomic.Bool
dirtyLine bool
}
func (w *ptyWriter) Write(buf []byte) (int, error) {
if w.AutoStop && len(buf) > 0 && buf[len(buf)-1] == 4 {
if w.AutoStop.Load() && len(buf) > 0 && buf[len(buf)-1] == 4 {
n, err := w.Out.Write(buf[:len(buf)-1])
if err != nil {
return n, err
@ -365,7 +365,7 @@ func (e *HostEnvironment) exec(ctx context.Context, commandparam []string, cmdli
return fmt.Errorf("RUN %w", err)
}
if tty != nil {
writer.AutoStop = true
writer.AutoStop.Store(true)
if _, err := tty.Write([]byte("\x04")); err != nil {
common.Logger(ctx).Debug("Failed to write EOT")
}
@ -388,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
}
@ -403,10 +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
}
return os.RemoveAll(e.Path)
return os.RemoveAll(e.Root)
}
}
@ -462,6 +464,7 @@ func (*HostEnvironment) JoinPathVariable(paths ...string) string {
// https://docs.github.com/en/actions/learn-github-actions/contexts#runner-context
func goArchToActionArch(arch string) string {
archMapper := map[string]string{
"amd64": "X64",
"x86_64": "X64",
"386": "X86",
"aarch64": "ARM64",
@ -484,8 +487,8 @@ func goOsToActionOs(os string) string {
return os
}
func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]interface{} {
return map[string]interface{}{
func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]any {
return map[string]any{
"os": goOsToActionOs(runtime.GOOS),
"arch": goArchToActionArch(runtime.GOARCH),
"temp": e.TmpDir,
@ -493,6 +496,10 @@ func (e *HostEnvironment) GetRunnerContext(_ context.Context) map[string]interfa
}
}
func (e *HostEnvironment) IsHealthy(ctx context.Context) (time.Duration, error) {
return 0, nil
}
func (e *HostEnvironment) ReplaceLogWriter(stdout, _ io.Writer) (io.Writer, io.Writer) {
org := e.StdOut
e.StdOut = stdout

View file

@ -2,7 +2,6 @@ package container
import (
"archive/tar"
"context"
"io"
"os"
"path"
@ -16,10 +15,8 @@ import (
var _ ExecutionsEnvironment = &HostEnvironment{}
func TestCopyDir(t *testing.T) {
dir, err := os.MkdirTemp("", "test-host-env-*")
assert.NoError(t, err)
defer os.RemoveAll(dir)
ctx := context.Background()
dir := t.TempDir()
ctx := t.Context()
e := &HostEnvironment{
Path: filepath.Join(dir, "path"),
TmpDir: filepath.Join(dir, "tmp"),
@ -32,15 +29,13 @@ func TestCopyDir(t *testing.T) {
_ = os.MkdirAll(e.TmpDir, 0o700)
_ = os.MkdirAll(e.ToolCache, 0o700)
_ = os.MkdirAll(e.ActPath, 0o700)
err = e.CopyDir(e.Workdir, e.Path, true)(ctx)
err := e.CopyDir(e.Workdir, e.Path, true)(ctx)
assert.NoError(t, err)
}
func TestGetContainerArchive(t *testing.T) {
dir, err := os.MkdirTemp("", "test-host-env-*")
assert.NoError(t, err)
defer os.RemoveAll(dir)
ctx := context.Background()
dir := t.TempDir()
ctx := t.Context()
e := &HostEnvironment{
Path: filepath.Join(dir, "path"),
TmpDir: filepath.Join(dir, "tmp"),
@ -54,7 +49,7 @@ func TestGetContainerArchive(t *testing.T) {
_ = os.MkdirAll(e.ToolCache, 0o700)
_ = os.MkdirAll(e.ActPath, 0o700)
expectedContent := []byte("sdde/7sh")
err = os.WriteFile(filepath.Join(e.Path, "action.yml"), expectedContent, 0o600)
err := os.WriteFile(filepath.Join(e.Path, "action.yml"), expectedContent, 0o600)
assert.NoError(t, err)
archive, err := e.GetContainerArchive(ctx, e.Path)
assert.NoError(t, err)

View file

@ -76,8 +76,8 @@ func (*LinuxContainerEnvironmentExtensions) JoinPathVariable(paths ...string) st
return strings.Join(paths, ":")
}
func (l *LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]interface{} {
return map[string]interface{}{
func (l *LinuxContainerEnvironmentExtensions) GetRunnerContext(ctx context.Context) map[string]any {
return map[string]any{
"os": "Linux",
"arch": RunnerArch(ctx),
"temp": "/tmp",

View file

@ -35,18 +35,13 @@ func TestContainerPath(t *testing.T) {
{fmt.Sprintf("/mnt/%v/act", rootDriveLetter), "act", fmt.Sprintf("%s\\", rootDrive)},
} {
if v.workDir != "" {
if err := os.Chdir(v.workDir); err != nil {
log.Error(err)
t.Fail()
}
t.Chdir(v.workDir)
}
assert.Equal(t, v.destinationPath, linuxcontainerext.ToContainerPath(v.sourcePath))
}
if err := os.Chdir(cwd); err != nil {
log.Error(err)
}
t.Chdir(cwd)
} else {
cwd, err := os.Getwd()
if err != nil {

View file

@ -8,7 +8,7 @@ import (
"io"
"strings"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
)
func parseEnvFile(e Container, srcPath string, env *map[string]string) common.Executor {

View file

@ -15,7 +15,7 @@ import (
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/model"
"github.com/rhysd/actionlint"
)
@ -165,12 +165,12 @@ func (impl *interperterImpl) toJSON(value reflect.Value) (string, error) {
return string(json), nil
}
func (impl *interperterImpl) fromJSON(value reflect.Value) (interface{}, error) {
func (impl *interperterImpl) fromJSON(value reflect.Value) (any, error) {
if value.Kind() != reflect.String {
return nil, fmt.Errorf("Cannot parse non-string type %v as JSON", value.Kind())
}
var data interface{}
var data any
err := json.Unmarshal([]byte(value.String()), &data)
if err != nil {

View file

@ -4,14 +4,14 @@ import (
"path/filepath"
"testing"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/model"
"github.com/stretchr/testify/assert"
)
func TestFunctionContains(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"contains('search', 'item') }}", false, "contains-str-str"},
@ -31,6 +31,13 @@ func TestFunctionContains(t *testing.T) {
{`contains(fromJSON('[3.14,"second"]'), 3.14) }}`, true, "contains-item-number-number"},
{`contains(fromJSON('["","second"]'), fromJSON('[]')) }}`, false, "contains-item-str-arr"},
{`contains(fromJSON('["","second"]'), fromJSON('{}')) }}`, false, "contains-item-str-obj"},
{`contains(fromJSON('[{ "first": { "result": "success" }},{ "second": { "result": "success" }}]').first.result, 'success') }}`, true, "multiple-contains-item"},
{`contains(fromJSON('[{ "result": "success" },{ "result": "failure" }]').*.result, 'failure') }}`, true, "multiple-contains-dereferenced-failure-item"},
{`contains(fromJSON('[{ "result": "failure" },{ "result": "success" }]').*.result, 'success') }}`, true, "multiple-contains-dereferenced-success-item"},
{`contains(fromJSON('[{ "result": "failure" },{ "result": "success" }]').*.result, 'notthere') }}`, false, "multiple-contains-dereferenced-missing-item"},
{`contains(fromJSON('[{ "result": "failure", "outputs": { "key": "val1" } },{ "result": "success", "outputs": { "key": "val2" } }]').*.outputs.key, 'val1') }}`, true, "multiple-contains-dereferenced-output-item"},
{`contains(fromJSON('[{ "result": "failure", "outputs": { "key": "val1" } },{ "result": "success", "outputs": { "key": "val2" } }]').*.outputs.key, 'val2') }}`, true, "multiple-contains-dereferenced-output-item-2"},
{`contains(fromJSON('[{ "result": "failure", "outputs": { "key": "val1" } },{ "result": "success", "outputs": { "key": "val2" } }]').*.outputs.key, 'missing') }}`, false, "multiple-contains-dereferenced-output-misssing-item"},
}
env := &EvaluationEnvironment{}
@ -51,7 +58,7 @@ func TestFunctionContains(t *testing.T) {
func TestFunctionStartsWith(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"startsWith('search', 'se') }}", true, "startswith-string"},
@ -83,7 +90,7 @@ func TestFunctionStartsWith(t *testing.T) {
func TestFunctionEndsWith(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"endsWith('search', 'ch') }}", true, "endsWith-string"},
@ -115,7 +122,7 @@ func TestFunctionEndsWith(t *testing.T) {
func TestFunctionJoin(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"join(fromJSON('[\"a\", \"b\"]'), ',')", "a,b", "join-arr"},
@ -145,7 +152,7 @@ func TestFunctionJoin(t *testing.T) {
func TestFunctionToJSON(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"toJSON(env) }}", "{\n \"key\": \"value\"\n}", "toJSON"},
@ -174,10 +181,10 @@ func TestFunctionToJSON(t *testing.T) {
func TestFunctionFromJSON(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"fromJSON('{\"foo\":\"bar\"}') }}", map[string]interface{}{
{"fromJSON('{\"foo\":\"bar\"}') }}", map[string]any{
"foo": "bar",
}, "fromJSON"},
}
@ -200,7 +207,7 @@ func TestFunctionFromJSON(t *testing.T) {
func TestFunctionHashFiles(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"hashFiles('**/non-extant-files') }}", "", "hash-non-existing-file"},
@ -230,8 +237,8 @@ func TestFunctionHashFiles(t *testing.T) {
func TestFunctionFormat(t *testing.T) {
table := []struct {
input string
expected interface{}
error interface{}
expected any
error any
name string
}{
{"format('text')", "text", nil, "format-plain-string"},
@ -270,3 +277,23 @@ func TestFunctionFormat(t *testing.T) {
_, err := NewInterpeter(env, Config{}).Evaluate("format()", DefaultStatusCheckNone)
assert.Error(t, err)
}
func TestMapContains(t *testing.T) {
env := &EvaluationEnvironment{
Needs: map[string]Needs{
"first-job": {
Outputs: map[string]string{},
Result: "success",
},
"second-job": {
Outputs: map[string]string{},
Result: "failure",
},
},
}
output, err := NewInterpeter(env, Config{}).Evaluate("contains(needs.*.result, 'failure')", DefaultStatusCheckNone)
assert.NoError(t, err)
assert.Equal(t, true, output)
}

View file

@ -7,7 +7,7 @@ import (
"reflect"
"strings"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/model"
"github.com/rhysd/actionlint"
)
@ -17,14 +17,14 @@ type EvaluationEnvironment struct {
Job *model.JobContext
Jobs *map[string]*model.WorkflowCallResult
Steps map[string]*model.StepResult
Runner map[string]interface{}
Runner map[string]any
Secrets map[string]string
Vars map[string]string
Strategy map[string]interface{}
Matrix map[string]interface{}
Strategy map[string]any
Matrix map[string]any
Needs map[string]Needs
Inputs map[string]interface{}
HashFiles func([]reflect.Value) (interface{}, error)
Inputs map[string]any
HashFiles func([]reflect.Value) (any, error)
}
type Needs struct {
@ -63,7 +63,7 @@ func (dsc DefaultStatusCheck) String() string {
}
type Interpreter interface {
Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (interface{}, error)
Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (any, error)
}
type interperterImpl struct {
@ -78,7 +78,7 @@ func NewInterpeter(env *EvaluationEnvironment, config Config) Interpreter {
}
}
func (impl *interperterImpl) Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (interface{}, error) {
func (impl *interperterImpl) Evaluate(input string, defaultStatusCheck DefaultStatusCheck) (any, error) {
input = strings.TrimPrefix(input, "${{")
if defaultStatusCheck != DefaultStatusCheckNone && input == "" {
input = "success()"
@ -117,7 +117,7 @@ func (impl *interperterImpl) Evaluate(input string, defaultStatusCheck DefaultSt
return result, err2
}
func (impl *interperterImpl) evaluateNode(exprNode actionlint.ExprNode) (interface{}, error) {
func (impl *interperterImpl) evaluateNode(exprNode actionlint.ExprNode) (any, error) {
switch node := exprNode.(type) {
case *actionlint.VariableNode:
return impl.evaluateVariable(node)
@ -150,7 +150,7 @@ func (impl *interperterImpl) evaluateNode(exprNode actionlint.ExprNode) (interfa
}
}
func (impl *interperterImpl) evaluateVariable(variableNode *actionlint.VariableNode) (interface{}, error) {
func (impl *interperterImpl) evaluateVariable(variableNode *actionlint.VariableNode) (any, error) {
switch strings.ToLower(variableNode.Name) {
case "github":
return impl.env.Github, nil
@ -158,6 +158,8 @@ func (impl *interperterImpl) evaluateVariable(variableNode *actionlint.VariableN
return impl.env.Github, nil
case "forge":
return impl.env.Github, nil
case "forgejo":
return impl.env.Github, nil
case "env":
return impl.env.Env, nil
case "job":
@ -192,7 +194,7 @@ func (impl *interperterImpl) evaluateVariable(variableNode *actionlint.VariableN
}
}
func (impl *interperterImpl) evaluateIndexAccess(indexAccessNode *actionlint.IndexAccessNode) (interface{}, error) {
func (impl *interperterImpl) evaluateIndexAccess(indexAccessNode *actionlint.IndexAccessNode) (any, error) {
left, err := impl.evaluateNode(indexAccessNode.Operand)
if err != nil {
return nil, err
@ -227,16 +229,20 @@ func (impl *interperterImpl) evaluateIndexAccess(indexAccessNode *actionlint.Ind
}
}
func (impl *interperterImpl) evaluateObjectDeref(objectDerefNode *actionlint.ObjectDerefNode) (interface{}, error) {
func (impl *interperterImpl) evaluateObjectDeref(objectDerefNode *actionlint.ObjectDerefNode) (any, error) {
left, err := impl.evaluateNode(objectDerefNode.Receiver)
if err != nil {
return nil, err
}
_, receiverIsDeref := objectDerefNode.Receiver.(*actionlint.ArrayDerefNode)
if receiverIsDeref {
return impl.getPropertyValueDereferenced(reflect.ValueOf(left), objectDerefNode.Property)
}
return impl.getPropertyValue(reflect.ValueOf(left), objectDerefNode.Property)
}
func (impl *interperterImpl) evaluateArrayDeref(arrayDerefNode *actionlint.ArrayDerefNode) (interface{}, error) {
func (impl *interperterImpl) evaluateArrayDeref(arrayDerefNode *actionlint.ArrayDerefNode) (any, error) {
left, err := impl.evaluateNode(arrayDerefNode.Receiver)
if err != nil {
return nil, err
@ -245,7 +251,7 @@ func (impl *interperterImpl) evaluateArrayDeref(arrayDerefNode *actionlint.Array
return impl.getSafeValue(reflect.ValueOf(left)), nil
}
func (impl *interperterImpl) getPropertyValue(left reflect.Value, property string) (value interface{}, err error) {
func (impl *interperterImpl) getPropertyValue(left reflect.Value, property string) (value any, err error) {
switch left.Kind() {
case reflect.Ptr:
return impl.getPropertyValue(left.Elem(), property)
@ -299,7 +305,7 @@ func (impl *interperterImpl) getPropertyValue(left reflect.Value, property strin
return nil, nil
case reflect.Slice:
var values []interface{}
var values []any
for i := 0; i < left.Len(); i++ {
value, err := impl.getPropertyValue(left.Index(i).Elem(), property)
@ -316,7 +322,30 @@ func (impl *interperterImpl) getPropertyValue(left reflect.Value, property strin
return nil, nil
}
func (impl *interperterImpl) getMapValue(value reflect.Value) (interface{}, error) {
func (impl *interperterImpl) getPropertyValueDereferenced(left reflect.Value, property string) (value any, err error) {
switch left.Kind() {
case reflect.Map:
iter := left.MapRange()
var values []any
for iter.Next() {
value, err := impl.getPropertyValue(iter.Value(), property)
if err != nil {
return nil, err
}
values = append(values, value)
}
return values, nil
case reflect.Ptr, reflect.Struct, reflect.Slice:
return impl.getPropertyValue(left, property)
}
return nil, nil
}
func (impl *interperterImpl) getMapValue(value reflect.Value) (any, error) {
if value.Kind() == reflect.Ptr {
return impl.getMapValue(value.Elem())
}
@ -324,7 +353,7 @@ func (impl *interperterImpl) getMapValue(value reflect.Value) (interface{}, erro
return value.Interface(), nil
}
func (impl *interperterImpl) evaluateNot(notNode *actionlint.NotOpNode) (interface{}, error) {
func (impl *interperterImpl) evaluateNot(notNode *actionlint.NotOpNode) (any, error) {
operand, err := impl.evaluateNode(notNode.Operand)
if err != nil {
return nil, err
@ -333,7 +362,7 @@ func (impl *interperterImpl) evaluateNot(notNode *actionlint.NotOpNode) (interfa
return !IsTruthy(operand), nil
}
func (impl *interperterImpl) evaluateCompare(compareNode *actionlint.CompareOpNode) (interface{}, error) {
func (impl *interperterImpl) evaluateCompare(compareNode *actionlint.CompareOpNode) (any, error) {
left, err := impl.evaluateNode(compareNode.Left)
if err != nil {
return nil, err
@ -350,7 +379,7 @@ func (impl *interperterImpl) evaluateCompare(compareNode *actionlint.CompareOpNo
return impl.compareValues(leftValue, rightValue, compareNode.Kind)
}
func (impl *interperterImpl) compareValues(leftValue, rightValue reflect.Value, kind actionlint.CompareOpNodeKind) (interface{}, error) {
func (impl *interperterImpl) compareValues(leftValue, rightValue reflect.Value, kind actionlint.CompareOpNodeKind) (any, error) {
if leftValue.Kind() != rightValue.Kind() {
if !impl.isNumber(leftValue) {
leftValue = impl.coerceToNumber(leftValue)
@ -500,7 +529,7 @@ func (impl *interperterImpl) compareNumber(left, right float64, kind actionlint.
}
}
func IsTruthy(input interface{}) bool {
func IsTruthy(input any) bool {
value := reflect.ValueOf(input)
switch value.Kind() {
case reflect.Bool:
@ -536,7 +565,7 @@ func (impl *interperterImpl) isNumber(value reflect.Value) bool {
}
}
func (impl *interperterImpl) getSafeValue(value reflect.Value) interface{} {
func (impl *interperterImpl) getSafeValue(value reflect.Value) any {
switch value.Kind() {
case reflect.Invalid:
return nil
@ -550,7 +579,7 @@ func (impl *interperterImpl) getSafeValue(value reflect.Value) interface{} {
return value.Interface()
}
func (impl *interperterImpl) evaluateLogicalCompare(compareNode *actionlint.LogicalOpNode) (interface{}, error) {
func (impl *interperterImpl) evaluateLogicalCompare(compareNode *actionlint.LogicalOpNode) (any, error) {
left, err := impl.evaluateNode(compareNode.Left)
if err != nil {
return nil, err
@ -579,7 +608,7 @@ func (impl *interperterImpl) evaluateLogicalCompare(compareNode *actionlint.Logi
return nil, fmt.Errorf("Unable to compare incompatibles types '%s' and '%s'", leftValue.Kind(), rightValue.Kind())
}
func (impl *interperterImpl) evaluateFuncCall(funcCallNode *actionlint.FuncCallNode) (interface{}, error) {
func (impl *interperterImpl) evaluateFuncCall(funcCallNode *actionlint.FuncCallNode) (any, error) {
args := make([]reflect.Value, 0)
for _, arg := range funcCallNode.Args {

View file

@ -4,14 +4,14 @@ import (
"math"
"testing"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/model"
"github.com/stretchr/testify/assert"
)
func TestLiterals(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"true", true, "true"},
@ -40,7 +40,7 @@ func TestLiterals(t *testing.T) {
func TestOperators(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
error string
}{
@ -68,7 +68,7 @@ func TestOperators(t *testing.T) {
{`true && false`, false, "and", ""},
{`true || false`, true, "or", ""},
{`fromJSON('{}') && true`, true, "and-boolean-object", ""},
{`fromJSON('{}') || false`, make(map[string]interface{}), "or-boolean-object", ""},
{`fromJSON('{}') || false`, make(map[string]any), "or-boolean-object", ""},
{"github.event.commits[0].author.username != github.event.commits[1].author.username", true, "property-comparison1", ""},
{"github.event.commits[0].author.username1 != github.event.commits[1].author.username", true, "property-comparison2", ""},
{"github.event.commits[0].author.username != github.event.commits[1].author.username1", true, "property-comparison3", ""},
@ -79,15 +79,15 @@ func TestOperators(t *testing.T) {
env := &EvaluationEnvironment{
Github: &model.GithubContext{
Action: "push",
Event: map[string]interface{}{
"commits": []interface{}{
map[string]interface{}{
"author": map[string]interface{}{
Event: map[string]any{
"commits": []any{
map[string]any{
"author": map[string]any{
"username": "someone",
},
},
map[string]interface{}{
"author": map[string]interface{}{
map[string]any{
"author": map[string]any{
"username": "someone-else",
},
},
@ -114,7 +114,7 @@ func TestOperators(t *testing.T) {
func TestOperatorsCompare(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"!null", true, "not-null"},
@ -162,7 +162,7 @@ func TestOperatorsCompare(t *testing.T) {
func TestOperatorsBooleanEvaluation(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
// true &&
@ -529,7 +529,7 @@ func TestOperatorsBooleanEvaluation(t *testing.T) {
func TestContexts(t *testing.T) {
table := []struct {
input string
expected interface{}
expected any
name string
}{
{"github.action", "push", "github-context"},
@ -562,6 +562,8 @@ func TestContexts(t *testing.T) {
{"matrix.os", "Linux", "matrix-context"},
{"needs.job-id.outputs.output-name", "value", "needs-context"},
{"needs.job-id.result", "success", "needs-context"},
{"contains(needs.*.result, 'success')", true, "needs-wildcard-context-contains-success"},
{"contains(needs.*.result, 'failure')", false, "needs-wildcard-context-contains-failure"},
{"inputs.name", "value", "inputs-context"},
}
@ -586,7 +588,7 @@ func TestContexts(t *testing.T) {
Conclusion: model.StepStatusSkipped,
},
},
Runner: map[string]interface{}{
Runner: map[string]any{
"os": "Linux",
"temp": "/tmp",
"tool_cache": "/opt/hostedtoolcache",
@ -597,10 +599,10 @@ func TestContexts(t *testing.T) {
Vars: map[string]string{
"name": "value",
},
Strategy: map[string]interface{}{
Strategy: map[string]any{
"fail-fast": true,
},
Matrix: map[string]interface{}{
Matrix: map[string]any{
"os": "Linux",
},
Needs: map[string]Needs{
@ -610,8 +612,14 @@ func TestContexts(t *testing.T) {
},
Result: "success",
},
"another-job-id": {
Outputs: map[string]string{
"output-name": "value",
},
Result: "success",
},
},
Inputs: map[string]interface{}{
Inputs: map[string]any{
"name": "value",
},
}

View file

@ -2,7 +2,6 @@ package filecollector
import (
"archive/tar"
"context"
"io"
"path/filepath"
"strings"
@ -27,7 +26,7 @@ func (mfs *memoryFs) walk(root string, fn filepath.WalkFunc) error {
if err != nil {
return err
}
for i := 0; i < len(dir); i++ {
for i := range dir {
filename := filepath.Join(root, dir[i].Name())
err = fn(filename, dir[i], nil)
if dir[i].IsDir() {
@ -104,7 +103,7 @@ func TestIgnoredTrackedfile(t *testing.T) {
TarWriter: tw,
},
}
err := fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
err := fc.Fs.Walk("mygitrepo", fc.CollectFiles(t.Context(), []string{}))
assert.NoError(t, err, "successfully collect files")
tw.Close()
_, _ = tmpTar.Seek(0, io.SeekStart)
@ -153,7 +152,7 @@ func TestSymlinks(t *testing.T) {
TarWriter: tw,
},
}
err = fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
err = fc.Fs.Walk("mygitrepo", fc.CollectFiles(t.Context(), []string{}))
assert.NoError(t, err, "successfully collect files")
tw.Close()
_, _ = tmpTar.Seek(0, io.SeekStart)

View file

@ -5,8 +5,8 @@ import (
"regexp"
"strings"
"code.forgejo.org/forgejo/runner/act/exprparser"
"gopkg.in/yaml.v3"
"code.forgejo.org/forgejo/runner/v11/act/exprparser"
"go.yaml.in/yaml/v3"
)
// ExpressionEvaluator is copied from runner.expressionEvaluator,
@ -19,7 +19,7 @@ func NewExpressionEvaluator(interpreter exprparser.Interpreter) *ExpressionEvalu
return &ExpressionEvaluator{interpreter: interpreter}
}
func (ee ExpressionEvaluator) evaluate(in string, defaultStatusCheck exprparser.DefaultStatusCheck) (interface{}, error) {
func (ee ExpressionEvaluator) evaluate(in string, defaultStatusCheck exprparser.DefaultStatusCheck) (any, error) {
evaluated, err := ee.interpreter.Evaluate(in, defaultStatusCheck)
return evaluated, err

View file

@ -1,9 +1,9 @@
package jobparser
import (
"code.forgejo.org/forgejo/runner/act/exprparser"
"code.forgejo.org/forgejo/runner/act/model"
"gopkg.in/yaml.v3"
"code.forgejo.org/forgejo/runner/v11/act/exprparser"
"code.forgejo.org/forgejo/runner/v11/act/model"
"go.yaml.in/yaml/v3"
)
// NewInterpeter returns an interpeter used in the server,
@ -12,12 +12,13 @@ import (
func NewInterpeter(
jobID string,
job *model.Job,
matrix map[string]interface{},
matrix map[string]any,
gitCtx *model.GithubContext,
results map[string]*JobResult,
vars map[string]string,
inputs map[string]any,
) exprparser.Interpreter {
strategy := make(map[string]interface{})
strategy := make(map[string]any)
if job.Strategy != nil {
strategy["fail-fast"] = job.Strategy.FailFast
strategy["max-parallel"] = job.Strategy.MaxParallel
@ -62,7 +63,7 @@ func NewInterpeter(
Strategy: strategy,
Matrix: matrix,
Needs: using,
Inputs: nil, // not supported yet
Inputs: inputs,
Vars: vars,
}
@ -75,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

@ -6,9 +6,9 @@ import (
"sort"
"strings"
"gopkg.in/yaml.v3"
"go.yaml.in/yaml/v3"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/model"
)
func Parse(content []byte, validate bool, options ...ParseOption) ([]*SingleWorkflow, error) {
@ -48,7 +48,7 @@ func Parse(content []byte, validate bool, options ...ParseOption) ([]*SingleWork
}
for _, matrix := range matricxes {
job := job.Clone()
evaluator := NewExpressionEvaluator(NewInterpeter(id, origin.GetJob(id), matrix, pc.gitContext, results, pc.vars))
evaluator := NewExpressionEvaluator(NewInterpeter(id, origin.GetJob(id), matrix, pc.gitContext, results, pc.vars, nil))
if job.Name == "" {
job.Name = nameWithMatrix(id, matrix)
} else {
@ -103,7 +103,7 @@ type parseContext struct {
type ParseOption func(c *parseContext)
func getMatrixes(job *model.Job) ([]map[string]interface{}, error) {
func getMatrixes(job *model.Job) ([]map[string]any, error) {
ret, err := job.GetMatrixes()
if err != nil {
return nil, fmt.Errorf("GetMatrixes: %w", err)
@ -114,13 +114,13 @@ func getMatrixes(job *model.Job) ([]map[string]interface{}, error) {
return ret, nil
}
func encodeMatrix(matrix map[string]interface{}) yaml.Node {
func encodeMatrix(matrix map[string]any) yaml.Node {
if len(matrix) == 0 {
return yaml.Node{}
}
value := map[string][]interface{}{}
value := map[string][]any{}
for k, v := range matrix {
value[k] = []interface{}{v}
value[k] = []any{v}
}
node := yaml.Node{}
_ = node.Encode(value)
@ -137,7 +137,7 @@ func encodeRunsOn(runsOn []string) yaml.Node {
return node
}
func nameWithMatrix(name string, m map[string]interface{}) string {
func nameWithMatrix(name string, m map[string]any) string {
if len(m) == 0 {
return name
}
@ -145,7 +145,7 @@ func nameWithMatrix(name string, m map[string]interface{}) string {
return name + " " + matrixName(m)
}
func matrixName(m map[string]interface{}) string {
func matrixName(m map[string]any) string {
ks := make([]string, 0, len(m))
for k := range m {
ks = append(ks, k)

View file

@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
"go.yaml.in/yaml/v3"
)
func TestParse(t *testing.T) {
@ -42,6 +42,16 @@ func TestParse(t *testing.T) {
options: nil,
wantErr: false,
},
{
name: "job_concurrency",
options: nil,
wantErr: false,
},
{
name: "job_concurrency_eval",
options: nil,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View file

@ -2,9 +2,10 @@ package jobparser
import (
"fmt"
"strings"
"code.forgejo.org/forgejo/runner/act/model"
"gopkg.in/yaml.v3"
"code.forgejo.org/forgejo/runner/v11/act/model"
"go.yaml.in/yaml/v3"
)
// SingleWorkflow is a workflow with single job and single matrix
@ -80,8 +81,9 @@ type Job struct {
Defaults Defaults `yaml:"defaults,omitempty"`
Outputs map[string]string `yaml:"outputs,omitempty"`
Uses string `yaml:"uses,omitempty"`
With map[string]interface{} `yaml:"with,omitempty"`
With map[string]any `yaml:"with,omitempty"`
RawSecrets yaml.Node `yaml:"secrets,omitempty"`
RawConcurrency *model.RawConcurrency `yaml:"concurrency,omitempty"`
}
func (j *Job) Clone() *Job {
@ -104,6 +106,7 @@ func (j *Job) Clone() *Job {
Uses: j.Uses,
With: j.With,
RawSecrets: j.RawSecrets,
RawConcurrency: j.RawConcurrency,
}
}
@ -190,35 +193,63 @@ func (evt *Event) Schedules() []map[string]string {
return evt.schedules
}
// 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 "", nil, fmt.Errorf("failed to encode concurrency: %w", err)
}
if err := evaluator.EvaluateYamlNode(&node); err != nil {
return "", nil, fmt.Errorf("failed to evaluate concurrency: %w", err)
}
var evaluated model.RawConcurrency
if err := node.Decode(&evaluated); err != nil {
return "", nil, fmt.Errorf("failed to unmarshal evaluated concurrency: %w", err)
}
if evaluated.RawExpression != "" {
return evaluated.RawExpression, nil, nil
}
if evaluated.CancelInProgress == "" {
return evaluated.Group, nil, nil
}
cancelInProgress := evaluated.CancelInProgress == "true"
return evaluated.Group, &cancelInProgress, nil
}
func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
switch rawOn.Kind {
case yaml.ScalarNode:
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},
}, nil
case yaml.SequenceNode:
var val []interface{}
var val []any
err := rawOn.Decode(&val)
if err != nil {
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
case yaml.MappingNode:
events, triggers, err := parseMappingNode[interface{}](rawOn)
events, triggers, err := parseMappingNode[any](rawOn)
if err != nil {
return nil, err
}
@ -233,17 +264,7 @@ 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]interface{}:
case map[string]any:
acts := make(map[string][]string, len(t))
for act, branches := range t {
switch b := branches.(type) {
@ -251,20 +272,20 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
acts[act] = []string{b}
case []string:
acts[act] = b
case []interface{}:
case []any:
acts[act] = make([]string, len(b))
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]interface{}:
if isInvalidOnType(k, act) {
return nil, fmt.Errorf("unknown on type: %#v", v)
case map[string]any:
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" {
@ -274,21 +295,24 @@ func ParseRawOn(rawOn *yaml.Node) ([]*Event, error) {
Name: k,
acts: acts,
})
case []interface{}:
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]interface{})
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)
}
}
}
@ -297,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
}
return fmt.Errorf("workflow_dispatch only supports key \"inputs\", but key %q was found", subKey)
}
if onType == "workflow_call" && (subKey == "inputs" || subKey == "outputs") {
return false
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 true
return fmt.Errorf("unexpected key %q.%q", onType, subKey)
}
// parseMappingNode parse a mapping node and preserve order.

View file

@ -5,17 +5,18 @@ import (
"strings"
"testing"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
"go.yaml.in/yaml/v3"
)
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)
assert.NoError(t, err)
assert.EqualValues(t, kase.result, events, fmt.Sprintf("%#v", events))
if kase.err != "" {
assert.ErrorContains(t, err, kase.err)
} else {
assert.NoError(t, err)
assert.EqualValues(t, kase.result, events, fmt.Sprintf("%#v", events))
}
})
}
}
@ -261,66 +320,66 @@ func TestParseMappingNode(t *testing.T) {
tests := []struct {
input string
scalars []string
datas []interface{}
datas []any
}{
{
input: "on:\n push:\n branches:\n - master",
scalars: []string{"push"},
datas: []interface{}{
map[string]interface{}{
"branches": []interface{}{"master"},
datas: []any{
map[string]any{
"branches": []any{"master"},
},
},
},
{
input: "on:\n branch_protection_rule:\n types: [created, deleted]",
scalars: []string{"branch_protection_rule"},
datas: []interface{}{
map[string]interface{}{
"types": []interface{}{"created", "deleted"},
datas: []any{
map[string]any{
"types": []any{"created", "deleted"},
},
},
},
{
input: "on:\n project:\n types: [created, deleted]\n milestone:\n types: [opened, deleted]",
scalars: []string{"project", "milestone"},
datas: []interface{}{
map[string]interface{}{
"types": []interface{}{"created", "deleted"},
datas: []any{
map[string]any{
"types": []any{"created", "deleted"},
},
map[string]interface{}{
"types": []interface{}{"opened", "deleted"},
map[string]any{
"types": []any{"opened", "deleted"},
},
},
},
{
input: "on:\n pull_request:\n types:\n - opened\n branches:\n - 'releases/**'",
scalars: []string{"pull_request"},
datas: []interface{}{
map[string]interface{}{
"types": []interface{}{"opened"},
"branches": []interface{}{"releases/**"},
datas: []any{
map[string]any{
"types": []any{"opened"},
"branches": []any{"releases/**"},
},
},
},
{
input: "on:\n push:\n branches:\n - main\n pull_request:\n types:\n - opened\n branches:\n - '**'",
scalars: []string{"push", "pull_request"},
datas: []interface{}{
map[string]interface{}{
"branches": []interface{}{"main"},
datas: []any{
map[string]any{
"branches": []any{"main"},
},
map[string]interface{}{
"types": []interface{}{"opened"},
"branches": []interface{}{"**"},
map[string]any{
"types": []any{"opened"},
"branches": []any{"**"},
},
},
},
{
input: "on:\n schedule:\n - cron: '20 6 * * *'",
scalars: []string{"schedule"},
datas: []interface{}{
[]interface{}{map[string]interface{}{
datas: []any{
[]any{map[string]any{
"cron": "20 6 * * *",
}},
},
@ -332,10 +391,137 @@ func TestParseMappingNode(t *testing.T) {
workflow, err := model.ReadWorkflow(strings.NewReader(test.input), false)
assert.NoError(t, err)
scalars, datas, err := parseMappingNode[interface{}](&workflow.RawOn)
scalars, datas, err := parseMappingNode[any](&workflow.RawOn)
assert.NoError(t, err)
assert.EqualValues(t, test.scalars, scalars, fmt.Sprintf("%#v", scalars))
assert.EqualValues(t, test.datas, datas, fmt.Sprintf("%#v", datas))
})
}
}
func TestEvaluateConcurrency(t *testing.T) {
tests := []struct {
name string
input model.RawConcurrency
group string
cancelInProgressNil bool
cancelInProgress bool
}{
{
name: "basic",
input: model.RawConcurrency{
Group: "group-name",
CancelInProgress: "true",
},
group: "group-name",
cancelInProgress: true,
},
{
name: "undefined",
input: model.RawConcurrency{},
group: "",
cancelInProgressNil: true,
},
{
name: "group-evaluation",
input: model.RawConcurrency{
Group: "${{ github.workflow }}-${{ github.ref }}",
},
group: "test_workflow-main",
cancelInProgressNil: true,
},
{
name: "cancel-evaluation-true",
input: model.RawConcurrency{
Group: "group-name",
CancelInProgress: "${{ !contains(github.ref, 'release/')}}",
},
group: "group-name",
cancelInProgress: true,
},
{
name: "cancel-evaluation-false",
input: model.RawConcurrency{
Group: "group-name",
CancelInProgress: "${{ contains(github.ref, 'release/')}}",
},
group: "group-name",
cancelInProgress: false,
},
{
name: "event-evaluation",
input: model.RawConcurrency{
Group: "user-${{ github.event.commits[0].author.username }}",
},
group: "user-someone",
cancelInProgressNil: true,
},
{
name: "arbitrary-var",
input: model.RawConcurrency{
Group: "${{ vars.eval_arbitrary_var }}",
},
group: "123",
cancelInProgressNil: true,
},
{
name: "arbitrary-input",
input: model.RawConcurrency{
Group: "${{ inputs.eval_arbitrary_input }}",
},
group: "456",
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 := EvaluateWorkflowConcurrency(
&test.input,
// gitCtx
&model.GithubContext{
Workflow: "test_workflow",
Ref: "main",
Event: map[string]any{
"commits": []any{
map[string]any{
"author": map[string]any{
"username": "someone",
},
},
map[string]any{
"author": map[string]any{
"username": "someone-else",
},
},
},
},
},
// vars
map[string]string{
"eval_arbitrary_var": "123",
},
// inputs
map[string]any{
"eval_arbitrary_input": "456",
},
)
assert.NoError(t, err)
assert.EqualValues(t, test.group, group)
if test.cancelInProgressNil {
assert.Nil(t, cancelInProgress)
} else {
require.NotNil(t, cancelInProgress)
assert.EqualValues(t, test.cancelInProgress, *cancelInProgress)
}
})
}
}

View file

@ -0,0 +1,9 @@
name: test
jobs:
job1:
runs-on: linux
concurrency:
group: major-tests
cancel-in-progress: true
steps:
- run: uname -a

View file

@ -0,0 +1,10 @@
name: test
jobs:
job1:
name: job1
runs-on: linux
steps:
- run: uname -a
concurrency:
group: major-tests
cancel-in-progress: "true"

View file

@ -0,0 +1,9 @@
name: test
jobs:
job1:
runs-on: linux
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: ${{ !contains(github.ref, 'release/')}}
steps:
- run: uname -a

View file

@ -0,0 +1,10 @@
name: test
jobs:
job1:
name: job1
runs-on: linux
steps:
- run: uname -a
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: ${{ !contains(github.ref, 'release/')}}

View file

@ -6,7 +6,7 @@ import (
"path/filepath"
"testing"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/model"
"github.com/stretchr/testify/require"
)

View file

@ -5,14 +5,14 @@ import (
"io"
"strings"
"code.forgejo.org/forgejo/runner/act/schema"
"gopkg.in/yaml.v3"
"code.forgejo.org/forgejo/runner/v11/act/schema"
"go.yaml.in/yaml/v3"
)
// ActionRunsUsing is the type of runner for the action
type ActionRunsUsing string
func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(interface{}) error) error {
func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(any) error) error {
var using string
if err := unmarshal(&using); err != nil {
return err
@ -21,7 +21,7 @@ func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(interface{}) error) error
// Force input to lowercase for case insensitive comparison
format := ActionRunsUsing(strings.ToLower(using))
switch format {
case ActionRunsUsingNode20, ActionRunsUsingNode16, ActionRunsUsingNode12, ActionRunsUsingDocker, ActionRunsUsingComposite, ActionRunsUsingGo, ActionRunsUsingSh:
case ActionRunsUsingNode24, ActionRunsUsingNode20, ActionRunsUsingNode16, ActionRunsUsingNode12, ActionRunsUsingDocker, ActionRunsUsingComposite, ActionRunsUsingGo, ActionRunsUsingSh:
*a = format
default:
return fmt.Errorf("The runs.using key in action.yml must be one of: %v, got %s", []string{
@ -30,6 +30,7 @@ func (a *ActionRunsUsing) UnmarshalYAML(unmarshal func(interface{}) error) error
ActionRunsUsingNode12,
ActionRunsUsingNode16,
ActionRunsUsingNode20,
ActionRunsUsingNode24,
ActionRunsUsingGo,
ActionRunsUsingSh,
}, format)
@ -44,6 +45,8 @@ const (
ActionRunsUsingNode16 = "node16"
// ActionRunsUsingNode20 for running with node20
ActionRunsUsingNode20 = "node20"
// ActionRunsUsingNode24 for running with node24
ActionRunsUsingNode24 = "node24"
// ActionRunsUsingDocker for running with docker
ActionRunsUsingDocker = "docker"
// ActionRunsUsingComposite for running composite
@ -69,6 +72,22 @@ type ActionRuns struct {
Steps []Step `yaml:"steps"`
}
func (actionRuns *ActionRuns) UnmarshalYAML(value *yaml.Node) error {
type ActionRunsDefault ActionRuns
if err := value.Decode((*ActionRunsDefault)(actionRuns)); err != nil {
return err
}
for i := range actionRuns.Steps {
step := &actionRuns.Steps[i]
// Set `Number` and `ID` on each step based upon their position in the steps array:
if step.ID == "" {
step.ID = fmt.Sprintf("%d", i)
}
step.Number = i
}
return nil
}
// Action describes a metadata file for GitHub actions. The metadata filename must be either action.yml or action.yaml. The data in the metadata file defines the inputs, outputs and main entrypoint for your action.
type Action struct {
Name string `yaml:"name"`

View file

@ -5,43 +5,44 @@ import (
"fmt"
"strings"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/common/git"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common/git"
)
type GithubContext struct {
Event map[string]interface{} `json:"event"`
EventPath string `json:"event_path"`
Workflow string `json:"workflow"`
RunID string `json:"run_id"`
RunNumber string `json:"run_number"`
Actor string `json:"actor"`
Repository string `json:"repository"`
EventName string `json:"event_name"`
Sha string `json:"sha"`
Ref string `json:"ref"`
RefName string `json:"ref_name"`
RefType string `json:"ref_type"`
HeadRef string `json:"head_ref"`
BaseRef string `json:"base_ref"`
Token string `json:"token"`
Workspace string `json:"workspace"`
Action string `json:"action"`
ActionPath string `json:"action_path"`
ActionRef string `json:"action_ref"`
ActionRepository string `json:"action_repository"`
Job string `json:"job"`
JobName string `json:"job_name"`
RepositoryOwner string `json:"repository_owner"`
RetentionDays string `json:"retention_days"`
RunnerPerflog string `json:"runner_perflog"`
RunnerTrackingID string `json:"runner_tracking_id"`
ServerURL string `json:"server_url"`
APIURL string `json:"api_url"`
GraphQLURL string `json:"graphql_url"`
Event map[string]any `json:"event"`
EventPath string `json:"event_path"`
Workflow string `json:"workflow"`
RunAttempt string `json:"run_attempt"`
RunID string `json:"run_id"`
RunNumber string `json:"run_number"`
Actor string `json:"actor"`
Repository string `json:"repository"`
EventName string `json:"event_name"`
Sha string `json:"sha"`
Ref string `json:"ref"`
RefName string `json:"ref_name"`
RefType string `json:"ref_type"`
HeadRef string `json:"head_ref"`
BaseRef string `json:"base_ref"`
Token string `json:"token"`
Workspace string `json:"workspace"`
Action string `json:"action"`
ActionPath string `json:"action_path"`
ActionRef string `json:"action_ref"`
ActionRepository string `json:"action_repository"`
Job string `json:"job"`
JobName string `json:"job_name"`
RepositoryOwner string `json:"repository_owner"`
RetentionDays string `json:"retention_days"`
RunnerPerflog string `json:"runner_perflog"`
RunnerTrackingID string `json:"runner_tracking_id"`
ServerURL string `json:"server_url"`
APIURL string `json:"api_url"`
GraphQLURL string `json:"graphql_url"`
}
func asString(v interface{}) string {
func asString(v any) string {
if v == nil {
return ""
} else if s, ok := v.(string); ok {
@ -50,7 +51,7 @@ func asString(v interface{}) string {
return ""
}
func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}) {
func nestedMapLookup(m map[string]any, ks ...string) (rval any) {
var ok bool
if len(ks) == 0 { // degenerate input
@ -60,20 +61,20 @@ func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{})
return nil
} else if len(ks) == 1 { // we've reached the final key
return rval
} else if m, ok = rval.(map[string]interface{}); !ok {
} else if m, ok = rval.(map[string]any); !ok {
return nil
}
// 1+ more keys
return nestedMapLookup(m, ks[1:]...)
}
func withDefaultBranch(ctx context.Context, b string, event map[string]interface{}) map[string]interface{} {
func withDefaultBranch(ctx context.Context, b string, event map[string]any) map[string]any {
repoI, ok := event["repository"]
if !ok {
repoI = make(map[string]interface{})
repoI = make(map[string]any)
}
repo, ok := repoI.(map[string]interface{})
repo, ok := repoI.(map[string]any)
if !ok {
common.Logger(ctx).Warnf("unable to set default branch to %v", b)
return event
@ -170,7 +171,7 @@ func (ghc *GithubContext) SetRepositoryAndOwner(ctx context.Context, githubInsta
if ghc.Repository == "" {
repo, err := git.FindGithubRepo(ctx, repoPath, githubInstance, remoteName)
if err != nil {
common.Logger(ctx).Warningf("unable to get git repo (githubInstance: %v; remoteName: %v, repoPath: %v): %v", githubInstance, remoteName, repoPath, err)
common.Logger(ctx).Debugf("unable to get git repo (githubInstance: %v; remoteName: %v, repoPath: %v): %v", githubInstance, remoteName, repoPath, err)
return
}
ghc.Repository = repo

View file

@ -27,19 +27,19 @@ func TestSetRef(t *testing.T) {
tables := []struct {
eventName string
event map[string]interface{}
event map[string]any
ref string
refName string
}{
{
eventName: "pull_request_target",
event: map[string]interface{}{},
event: map[string]any{},
ref: "refs/heads/master",
refName: "master",
},
{
eventName: "pull_request",
event: map[string]interface{}{
event: map[string]any{
"number": 1234.,
},
ref: "refs/pull/1234/merge",
@ -47,8 +47,8 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "deployment",
event: map[string]interface{}{
"deployment": map[string]interface{}{
event: map[string]any{
"deployment": map[string]any{
"ref": "refs/heads/somebranch",
},
},
@ -57,8 +57,8 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "release",
event: map[string]interface{}{
"release": map[string]interface{}{
event: map[string]any{
"release": map[string]any{
"tag_name": "v1.0.0",
},
},
@ -67,7 +67,7 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "push",
event: map[string]interface{}{
event: map[string]any{
"ref": "refs/heads/somebranch",
},
ref: "refs/heads/somebranch",
@ -75,8 +75,8 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "unknown",
event: map[string]interface{}{
"repository": map[string]interface{}{
event: map[string]any{
"repository": map[string]any{
"default_branch": "main",
},
},
@ -85,7 +85,7 @@ func TestSetRef(t *testing.T) {
},
{
eventName: "no-event",
event: map[string]interface{}{},
event: map[string]any{},
ref: "refs/heads/master",
refName: "master",
},
@ -99,7 +99,7 @@ func TestSetRef(t *testing.T) {
Event: table.event,
}
ghc.SetRef(context.Background(), "main", "/some/dir")
ghc.SetRef(t.Context(), "main", "/some/dir")
ghc.SetRefTypeAndName()
assert.Equal(t, table.ref, ghc.Ref)
@ -114,10 +114,10 @@ func TestSetRef(t *testing.T) {
ghc := &GithubContext{
EventName: "no-default-branch",
Event: map[string]interface{}{},
Event: map[string]any{},
}
ghc.SetRef(context.Background(), "", "/some/dir")
ghc.SetRef(t.Context(), "", "/some/dir")
assert.Equal(t, "refs/heads/master", ghc.Ref)
})
@ -141,14 +141,14 @@ func TestSetSha(t *testing.T) {
tables := []struct {
eventName string
event map[string]interface{}
event map[string]any
sha string
}{
{
eventName: "pull_request_target",
event: map[string]interface{}{
"pull_request": map[string]interface{}{
"base": map[string]interface{}{
event: map[string]any{
"pull_request": map[string]any{
"base": map[string]any{
"sha": "pr-base-sha",
},
},
@ -157,15 +157,15 @@ func TestSetSha(t *testing.T) {
},
{
eventName: "pull_request",
event: map[string]interface{}{
event: map[string]any{
"number": 1234.,
},
sha: "1234fakesha",
},
{
eventName: "deployment",
event: map[string]interface{}{
"deployment": map[string]interface{}{
event: map[string]any{
"deployment": map[string]any{
"sha": "deployment-sha",
},
},
@ -173,12 +173,12 @@ func TestSetSha(t *testing.T) {
},
{
eventName: "release",
event: map[string]interface{}{},
event: map[string]any{},
sha: "1234fakesha",
},
{
eventName: "push",
event: map[string]interface{}{
event: map[string]any{
"after": "push-sha",
"deleted": false,
},
@ -186,12 +186,12 @@ func TestSetSha(t *testing.T) {
},
{
eventName: "unknown",
event: map[string]interface{}{},
event: map[string]any{},
sha: "1234fakesha",
},
{
eventName: "no-event",
event: map[string]interface{}{},
event: map[string]any{},
sha: "1234fakesha",
},
}
@ -204,7 +204,7 @@ func TestSetSha(t *testing.T) {
Event: table.event,
}
ghc.SetSha(context.Background(), "/some/dir")
ghc.SetSha(t.Context(), "/some/dir")
assert.Equal(t, table.sha, ghc.Sha)
})

View file

@ -8,7 +8,7 @@ import (
"os"
"path/filepath"
"regexp"
"sort"
"slices"
log "github.com/sirupsen/logrus"
)
@ -286,11 +286,8 @@ func (wp *workflowPlanner) GetEvents() []string {
for _, w := range wp.workflows {
found := false
for _, e := range events {
for _, we := range w.On() {
if e == we {
found = true
break
}
if slices.Contains(w.On(), e) {
found = true
}
if found {
break
@ -303,9 +300,7 @@ func (wp *workflowPlanner) GetEvents() []string {
}
// sort the list based on depth of dependencies
sort.Slice(events, func(i, j int) bool {
return events[i] < events[j]
})
slices.Sort(events)
return events
}
@ -336,7 +331,7 @@ func (s *Stage) GetJobIDs() []string {
// Merge stages with existing stages in plan
func (p *Plan) mergeStages(stages []*Stage) {
newStages := make([]*Stage, int(math.Max(float64(len(p.Stages)), float64(len(stages)))))
for i := 0; i < len(newStages); i++ {
for i := range newStages {
newStages[i] = new(Stage)
if i >= len(p.Stages) {
newStages[i].Runs = append(newStages[i].Runs, stages[i].Runs...)

View file

@ -4,16 +4,19 @@ import (
"errors"
"fmt"
"io"
"maps"
"path/filepath"
"reflect"
"regexp"
"slices"
"strconv"
"strings"
"sync"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/schema"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/schema"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"go.yaml.in/yaml/v3"
)
// Workflow is the structure of the files in .github/workflows
@ -25,7 +28,8 @@ type Workflow struct {
Jobs map[string]*Job `yaml:"jobs"`
Defaults Defaults `yaml:"defaults"`
RawNotifications yaml.Node `yaml:"enable-email-notifications"`
RawNotifications yaml.Node `yaml:"enable-email-notifications"`
RawConcurrency *RawConcurrency `yaml:"concurrency"` // For Gitea
}
// On events for the workflow
@ -46,7 +50,7 @@ func (w *Workflow) On() []string {
}
return val
case yaml.MappingNode:
var val map[string]interface{}
var val map[string]any
err := w.RawOn.Decode(&val)
if err != nil {
log.Fatal(err)
@ -60,9 +64,9 @@ func (w *Workflow) On() []string {
return nil
}
func (w *Workflow) OnEvent(event string) interface{} {
func (w *Workflow) OnEvent(event string) any {
if w.RawOn.Kind == yaml.MappingNode {
var val map[string]interface{}
var val map[string]any
if !decodeNode(w.RawOn, &val) {
return nil
}
@ -78,10 +82,10 @@ func (w *Workflow) OnSchedule() []string {
}
switch val := schedules.(type) {
case []interface{}:
case []any:
allSchedules := []string{}
for _, v := range val {
for k, cron := range v.(map[string]interface{}) {
for k, cron := range v.(map[string]any) {
if k != "cron" {
continue
}
@ -136,10 +140,8 @@ func (w *Workflow) WorkflowDispatchConfig() *WorkflowDispatch {
if !decodeNode(w.RawOn, &val) {
return nil
}
for _, v := range val {
if v == "workflow_dispatch" {
return &WorkflowDispatch{}
}
if slices.Contains(val, "workflow_dispatch") {
return &WorkflowDispatch{}
}
case yaml.MappingNode:
var val map[string]yaml.Node
@ -159,10 +161,10 @@ func (w *Workflow) WorkflowDispatchConfig() *WorkflowDispatch {
}
type WorkflowCallInput struct {
Description string `yaml:"description"`
Required bool `yaml:"required"`
Default string `yaml:"default"`
Type string `yaml:"type"`
Description string `yaml:"description"`
Required bool `yaml:"required"`
Default yaml.Node `yaml:"default"`
Type string `yaml:"type"`
}
type WorkflowCallOutput struct {
@ -205,7 +207,7 @@ type Job struct {
RawNeeds yaml.Node `yaml:"needs"`
RawRunsOn yaml.Node `yaml:"runs-on"`
Env yaml.Node `yaml:"env"`
If yaml.Node `yaml:"if"`
RawIf yaml.Node `yaml:"if"`
Steps []*Step `yaml:"steps"`
TimeoutMinutes string `yaml:"timeout-minutes"`
Services map[string]*ContainerSpec `yaml:"services"`
@ -214,9 +216,11 @@ type Job struct {
Defaults Defaults `yaml:"defaults"`
Outputs map[string]string `yaml:"outputs"`
Uses string `yaml:"uses"`
With map[string]interface{} `yaml:"with"`
With map[string]any `yaml:"with"`
RawSecrets yaml.Node `yaml:"secrets"`
Result string
Result string
ResultMutex sync.Mutex
}
// Strategy for the job
@ -335,14 +339,21 @@ func (j *Job) Needs() []string {
// RunsOn list for Job
func (j *Job) RunsOn() []string {
switch j.RawRunsOn.Kind {
return FlattenRunsOnNode(j.RawRunsOn)
}
// Given an already expression-evaluated `runs-on` yaml node from a job, compute all the labels that will be run for a
// job. Can be a single string label, an array of labels, or an object { group: "...", labels: [...] };
// FlattenRunsOnNode will flatten all the options down to a []string.
func FlattenRunsOnNode(runsOn yaml.Node) []string {
switch runsOn.Kind {
case yaml.MappingNode:
var val struct {
Group string
Labels yaml.Node
}
if !decodeNode(j.RawRunsOn, &val) {
if !decodeNode(runsOn, &val) {
return nil
}
@ -354,10 +365,17 @@ func (j *Job) RunsOn() []string {
return labels
default:
return nodeAsStringSlice(j.RawRunsOn)
return nodeAsStringSlice(runsOn)
}
}
func (j *Job) IfClause() string {
if j.RawIf.Value == "" {
return "success()"
}
return j.RawIf.Value
}
func nodeAsStringSlice(node yaml.Node) []string {
switch node.Kind {
case yaml.ScalarNode:
@ -392,9 +410,9 @@ func (j *Job) Environment() map[string]string {
}
// Matrix decodes RawMatrix YAML node
func (j *Job) Matrix() map[string][]interface{} {
func (j *Job) Matrix() map[string][]any {
if j.Strategy.RawMatrix.Kind == yaml.MappingNode {
var val map[string][]interface{}
var val map[string][]any
if !decodeNode(j.Strategy.RawMatrix, &val) {
return nil
}
@ -405,20 +423,20 @@ func (j *Job) Matrix() map[string][]interface{} {
// GetMatrixes returns the matrix cross product
// It skips includes and hard fails excludes for non-existing keys
func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
matrixes := make([]map[string]interface{}, 0)
func (j *Job) GetMatrixes() ([]map[string]any, error) {
matrixes := make([]map[string]any, 0)
if j.Strategy != nil {
j.Strategy.FailFast = j.Strategy.GetFailFast()
j.Strategy.MaxParallel = j.Strategy.GetMaxParallel()
if m := j.Matrix(); m != nil {
includes := make([]map[string]interface{}, 0)
extraIncludes := make([]map[string]interface{}, 0)
includes := make([]map[string]any, 0)
extraIncludes := make([]map[string]any, 0)
for _, v := range m["include"] {
switch t := v.(type) {
case []interface{}:
case []any:
for _, i := range t {
i := i.(map[string]interface{})
i := i.(map[string]any)
extraInclude := true
for k := range i {
if _, ok := m[k]; ok {
@ -431,8 +449,8 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
extraIncludes = append(extraIncludes, i)
}
}
case interface{}:
v := v.(map[string]interface{})
case any:
v := v.(map[string]any)
extraInclude := true
for k := range v {
if _, ok := m[k]; ok {
@ -448,9 +466,9 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
}
delete(m, "include")
excludes := make([]map[string]interface{}, 0)
excludes := make([]map[string]any, 0)
for _, e := range m["exclude"] {
e := e.(map[string]interface{})
e := e.(map[string]any)
for k := range e {
if _, ok := m[k]; ok {
excludes = append(excludes, e)
@ -479,9 +497,7 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
if commonKeysMatch2(matrix, include, m) {
matched = true
log.Debugf("Adding include values '%v' to existing entry", include)
for k, v := range include {
matrix[k] = v
}
maps.Copy(matrix, include)
}
}
if !matched {
@ -493,19 +509,19 @@ func (j *Job) GetMatrixes() ([]map[string]interface{}, error) {
matrixes = append(matrixes, include)
}
if len(matrixes) == 0 {
matrixes = append(matrixes, make(map[string]interface{}))
matrixes = append(matrixes, make(map[string]any))
}
} else {
matrixes = append(matrixes, make(map[string]interface{}))
matrixes = append(matrixes, make(map[string]any))
}
} else {
matrixes = append(matrixes, make(map[string]interface{}))
matrixes = append(matrixes, make(map[string]any))
log.Debugf("Empty Strategy, matrixes=%v", matrixes)
}
return matrixes, nil
}
func commonKeysMatch(a, b map[string]interface{}) bool {
func commonKeysMatch(a, b map[string]any) bool {
for aKey, aVal := range a {
if bVal, ok := b[aKey]; ok && !reflect.DeepEqual(aVal, bVal) {
return false
@ -514,7 +530,7 @@ func commonKeysMatch(a, b map[string]interface{}) bool {
return true
}
func commonKeysMatch2(a, b map[string]interface{}, m map[string][]interface{}) bool {
func commonKeysMatch2(a, b map[string]any, m map[string][]any) bool {
for aKey, aVal := range a {
_, useKey := m[aKey]
if bVal, ok := b[aKey]; useKey && ok && !reflect.DeepEqual(aVal, bVal) {
@ -578,6 +594,24 @@ func (j *Job) Type() (JobType, error) {
return JobTypeDefault, nil
}
func (j *Job) UnmarshalYAML(value *yaml.Node) error {
type JobDefault Job
if err := value.Decode((*JobDefault)(j)); err != nil {
return err
}
for i, step := range j.Steps {
if step == nil {
continue
}
// Set `Number` and `ID` on each step based upon their position in the steps array:
if step.ID == "" {
step.ID = fmt.Sprintf("%d", i)
}
step.Number = i
}
return nil
}
// ContainerSpec is the specification of the container to use for the job
type ContainerSpec struct {
Image string `yaml:"image"`
@ -604,7 +638,7 @@ type Step struct {
Uses string `yaml:"uses"`
Run string `yaml:"run"`
WorkingDirectory string `yaml:"working-directory"`
Shell string `yaml:"shell"`
RawShell string `yaml:"shell"`
Env yaml.Node `yaml:"env"`
With map[string]string `yaml:"with"`
RawContinueOnError string `yaml:"continue-on-error"`
@ -640,32 +674,6 @@ func (s *Step) GetEnv() map[string]string {
return env
}
// ShellCommand returns the command for the shell
func (s *Step) ShellCommand() string {
var shellCommand string
// Reference: https://github.com/actions/runner/blob/8109c962f09d9acc473d92c595ff43afceddb347/src/Runner.Worker/Handlers/ScriptHandlerHelpers.cs#L9-L17
switch s.Shell {
case "", "bash":
shellCommand = "bash --noprofile --norc -e -o pipefail {0}"
case "pwsh":
shellCommand = "pwsh -command . '{0}'"
case "python":
shellCommand = "python {0}"
case "sh":
shellCommand = "sh -e {0}"
case "cmd":
shellCommand = "cmd /D /E:ON /V:OFF /S /C \"CALL \"{0}\"\""
case "powershell":
shellCommand = "powershell -command . '{0}'"
case "node":
shellCommand = "node {0}"
default:
shellCommand = s.Shell
}
return shellCommand
}
// StepType describes what type of step we are about to run
type StepType int
@ -759,9 +767,6 @@ func (w *Workflow) GetJob(jobID string) *Job {
if j.Name == "" {
j.Name = id
}
if j.If.Value == "" {
j.If.Value = "success()"
}
return j
}
}
@ -777,11 +782,11 @@ func (w *Workflow) GetJobIDs() []string {
return ids
}
var OnDecodeNodeError = func(node yaml.Node, out interface{}, err error) {
var OnDecodeNodeError = func(node yaml.Node, out any, err error) {
log.Errorf("Failed to decode node %v into %T: %v", node, out, err)
}
func decodeNode(node yaml.Node, out interface{}) bool {
func decodeNode(node yaml.Node, out any) bool {
if err := node.Decode(out); err != nil {
if OnDecodeNodeError != nil {
OnDecodeNodeError(node, out, err)
@ -806,3 +811,28 @@ func (w *Workflow) Notifications() (bool, error) {
return false, fmt.Errorf("enable-email-notifications: unknown type: %v", w.RawNotifications.Kind)
}
}
// For Gitea
// RawConcurrency represents a workflow concurrency or a job concurrency with uninterpolated options
type RawConcurrency struct {
Group string `yaml:"group,omitempty"`
CancelInProgress string `yaml:"cancel-in-progress,omitempty"`
RawExpression string `yaml:"-,omitempty"`
}
type objectConcurrency RawConcurrency
func (r *RawConcurrency) UnmarshalYAML(n *yaml.Node) error {
if err := n.Decode(&r.RawExpression); err == nil {
return nil
}
return n.Decode((*objectConcurrency)(r))
}
func (r *RawConcurrency) MarshalYAML() (any, error) {
if r.RawExpression != "" {
return r.RawExpression, nil
}
return (*objectConcurrency)(r), nil
}

View file

@ -493,24 +493,24 @@ func TestReadWorkflow_Strategy(t *testing.T) {
job := wf.Jobs["strategy-only-max-parallel"]
matrixes, err := job.GetMatrixes()
assert.NoError(t, err)
assert.Equal(t, matrixes, []map[string]interface{}{{}})
assert.Equal(t, job.Matrix(), map[string][]interface{}(nil))
assert.Equal(t, matrixes, []map[string]any{{}})
assert.Equal(t, job.Matrix(), map[string][]any(nil))
assert.Equal(t, job.Strategy.MaxParallel, 2)
assert.Equal(t, job.Strategy.FailFast, true)
job = wf.Jobs["strategy-only-fail-fast"]
matrixes, err = job.GetMatrixes()
assert.NoError(t, err)
assert.Equal(t, matrixes, []map[string]interface{}{{}})
assert.Equal(t, job.Matrix(), map[string][]interface{}(nil))
assert.Equal(t, matrixes, []map[string]any{{}})
assert.Equal(t, job.Matrix(), map[string][]any(nil))
assert.Equal(t, job.Strategy.MaxParallel, 4)
assert.Equal(t, job.Strategy.FailFast, false)
job = wf.Jobs["strategy-no-matrix"]
matrixes, err = job.GetMatrixes()
assert.NoError(t, err)
assert.Equal(t, matrixes, []map[string]interface{}{{}})
assert.Equal(t, job.Matrix(), map[string][]interface{}(nil))
assert.Equal(t, matrixes, []map[string]any{{}})
assert.Equal(t, job.Matrix(), map[string][]any(nil))
assert.Equal(t, job.Strategy.MaxParallel, 2)
assert.Equal(t, job.Strategy.FailFast, false)
@ -518,7 +518,7 @@ func TestReadWorkflow_Strategy(t *testing.T) {
matrixes, err = job.GetMatrixes()
assert.NoError(t, err)
assert.Equal(t, matrixes,
[]map[string]interface{}{
[]map[string]any{
{"datacenter": "site-c", "node-version": "14.x", "site": "staging"},
{"datacenter": "site-c", "node-version": "16.x", "site": "staging"},
{"datacenter": "site-d", "node-version": "16.x", "site": "staging"},
@ -528,15 +528,15 @@ func TestReadWorkflow_Strategy(t *testing.T) {
},
)
assert.Equal(t, job.Matrix(),
map[string][]interface{}{
map[string][]any{
"datacenter": {"site-c", "site-d"},
"exclude": {
map[string]interface{}{"datacenter": "site-d", "node-version": "14.x", "site": "staging"},
map[string]any{"datacenter": "site-d", "node-version": "14.x", "site": "staging"},
},
"include": {
map[string]interface{}{"php-version": 5.4},
map[string]interface{}{"datacenter": "site-a", "node-version": "10.x", "site": "prod"},
map[string]interface{}{"datacenter": "site-b", "node-version": "12.x", "site": "dev"},
map[string]any{"php-version": 5.4},
map[string]any{"datacenter": "site-a", "node-version": "10.x", "site": "prod"},
map[string]any{"datacenter": "site-b", "node-version": "12.x", "site": "dev"},
},
"node-version": {"14.x", "16.x"},
"site": {"staging"},
@ -546,25 +546,6 @@ func TestReadWorkflow_Strategy(t *testing.T) {
assert.Equal(t, job.Strategy.FailFast, false)
}
func TestStep_ShellCommand(t *testing.T) {
tests := []struct {
shell string
want string
}{
{"pwsh -v '. {0}'", "pwsh -v '. {0}'"},
{"pwsh", "pwsh -command . '{0}'"},
{"powershell", "powershell -command . '{0}'"},
{"node", "node {0}"},
{"python", "python {0}"},
}
for _, tt := range tests {
t.Run(tt.shell, func(t *testing.T) {
got := (&Step{Shell: tt.shell}).ShellCommand()
assert.Equal(t, got, tt.want)
})
}
}
func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
yaml := `
name: local-action-docker-url
@ -702,3 +683,48 @@ func TestStepUsesHash(t *testing.T) {
})
}
}
func TestReadWorkflow_Concurrency(t *testing.T) {
for _, testCase := range []struct {
expected *RawConcurrency
err string
snippet string
}{
{
expected: nil,
snippet: "# nothing",
},
{
expected: &RawConcurrency{Group: "${{ github.workflow }}-${{ github.ref }}", CancelInProgress: ""},
snippet: "concurrency: { group: \"${{ github.workflow }}-${{ github.ref }}\" }",
},
{
expected: &RawConcurrency{Group: "example-group", CancelInProgress: "true"},
snippet: "concurrency: { group: example-group, cancel-in-progress: true }",
},
} {
t.Run(testCase.snippet, func(t *testing.T) {
yaml := fmt.Sprintf(`
name: name-455
on: push
%s
jobs:
valid-JOB-Name-455:
runs-on: docker
steps:
- run: echo hi
`, testCase.snippet)
workflow, err := ReadWorkflow(strings.NewReader(yaml), true)
if testCase.err != "" {
assert.ErrorContains(t, err, testCase.err)
} else {
assert.NoError(t, err, "read workflow should succeed")
concurrency := workflow.RawConcurrency
// assert.NoError(t, err)
assert.Equal(t, testCase.expected, concurrency)
}
})
}
}

View file

@ -16,9 +16,9 @@ import (
"github.com/kballard/go-shellquote"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/container"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/container"
"code.forgejo.org/forgejo/runner/v11/act/model"
)
type actionStep interface {
@ -45,7 +45,7 @@ func readActionImpl(ctx context.Context, step *model.Step, actionDir, actionPath
allErrors := []error{}
addError := func(fileName string, err error) {
if err != nil {
allErrors = append(allErrors, fmt.Errorf("failed to read '%s' from action '%s' with path '%s' of step %w", fileName, step.String(), actionPath, err))
allErrors = append(allErrors, fmt.Errorf("failed to read '%s' from action '%s' with path '%s': %w", fileName, step.String(), actionPath, err))
} else {
// One successful read, clear error state
allErrors = nil
@ -112,6 +112,9 @@ func readActionImpl(ctx context.Context, step *model.Step, actionDir, actionPath
defer closer.Close()
action, err := model.ReadAction(reader)
if err != nil {
err = fmt.Errorf("failed to validate action.y*ml from action '%s' with path '%s': %v", step.String(), actionPath, err)
}
logger.Debugf("Read action %v from '%s'", action, "Unknown")
return action, err
}
@ -179,7 +182,7 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction
logger.Debugf("type=%v actionDir=%s actionPath=%s workdir=%s actionCacheDir=%s actionName=%s containerActionDir=%s", stepModel.Type(), actionDir, actionPath, rc.Config.Workdir, rc.ActionCacheDir(), actionName, containerActionDir)
switch action.Runs.Using {
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20:
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20, model.ActionRunsUsingNode24:
if err := maybeCopyToActionDir(ctx, step, actionDir, actionPath, containerActionDir); err != nil {
return err
}
@ -234,6 +237,7 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction
model.ActionRunsUsingNode12,
model.ActionRunsUsingNode16,
model.ActionRunsUsingNode20,
model.ActionRunsUsingNode24,
model.ActionRunsUsingComposite,
model.ActionRunsUsingGo,
model.ActionRunsUsingSh,
@ -273,7 +277,6 @@ func removeGitIgnore(ctx context.Context, directory string) error {
return nil
}
// TODO: break out parts of function to reduce complexicity
func execAsDocker(ctx context.Context, step actionStep, actionName, basedir string, localAction bool) error {
logger := common.Logger(ctx)
rc := step.getRunContext()
@ -282,15 +285,16 @@ func execAsDocker(ctx context.Context, step actionStep, actionName, basedir stri
var prepImage common.Executor
var image string
forcePull := false
if strings.HasPrefix(action.Runs.Image, "docker://") {
image = strings.TrimPrefix(action.Runs.Image, "docker://")
if after, ok := strings.CutPrefix(action.Runs.Image, "docker://"); ok {
image = after
// Apply forcePull only for prebuild docker images
forcePull = rc.Config.ForcePull
} else {
// "-dockeraction" enshures that "./", "./test " won't get converted to "act-:latest", "act-test-:latest" which are invalid docker image names
image = fmt.Sprintf("%s-dockeraction:%s", regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-"), "latest")
image = fmt.Sprintf("act-%s", strings.TrimLeft(image, "-"))
image = strings.ToLower(image)
if localAction {
image = fmt.Sprintf("runner-local-docker-action-%s:latest", common.MustRandName(16))
} else {
image = fmt.Sprintf("runner-remote-docker-action-%s:latest", common.Sha256(step.getStepModel().Uses))
}
contextDir, fileName := filepath.Split(filepath.Join(basedir, action.Runs.Image))
anyArchExists, err := container.ImageExistsLocally(ctx, image, "any")
@ -424,7 +428,7 @@ func newStepContainer(ctx context.Context, step step, image string, cmd, entrypo
envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_ARCH", container.RunnerArch(ctx)))
envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TEMP", "/tmp"))
binds, mounts := rc.GetBindsAndMounts()
binds, mounts, validVolumes := rc.GetBindsAndMounts(ctx)
networkMode := fmt.Sprintf("container:%s", rc.jobContainerName())
if rc.IsHostEnv(ctx) {
networkMode = "default"
@ -447,8 +451,7 @@ func newStepContainer(ctx context.Context, step step, image string, cmd, entrypo
Privileged: rc.Config.Privileged,
UsernsMode: rc.Config.UsernsMode,
Platform: rc.Config.ContainerArchitecture,
AutoRemove: rc.Config.AutoRemove,
ValidVolumes: rc.Config.ValidVolumes,
ValidVolumes: validVolumes,
ConfigOptions: rc.Config.ContainerOptions,
})
@ -527,6 +530,7 @@ func hasPreStep(step actionStep) common.Conditional {
((action.Runs.Using == model.ActionRunsUsingNode12 ||
action.Runs.Using == model.ActionRunsUsingNode16 ||
action.Runs.Using == model.ActionRunsUsingNode20 ||
action.Runs.Using == model.ActionRunsUsingNode24 ||
action.Runs.Using == model.ActionRunsUsingGo ||
action.Runs.Using == model.ActionRunsUsingSh) &&
action.Runs.Pre != "")
@ -543,7 +547,7 @@ func runPreStep(step actionStep) common.Executor {
action := step.getActionModel()
switch action.Runs.Using {
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20, model.ActionRunsUsingSh:
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20, model.ActionRunsUsingNode24, model.ActionRunsUsingSh:
// defaults in pre steps were missing, however provided inputs are available
populateEnvsFromInput(ctx, step.getEnv(), action, rc)
// todo: refactor into step
@ -669,6 +673,7 @@ func hasPostStep(step actionStep) common.Conditional {
((action.Runs.Using == model.ActionRunsUsingNode12 ||
action.Runs.Using == model.ActionRunsUsingNode16 ||
action.Runs.Using == model.ActionRunsUsingNode20 ||
action.Runs.Using == model.ActionRunsUsingNode24 ||
action.Runs.Using == model.ActionRunsUsingGo ||
action.Runs.Using == model.ActionRunsUsingSh) &&
action.Runs.Post != "")
@ -705,9 +710,10 @@ func runPostStep(step actionStep) common.Executor {
_, containerActionDir := getContainerActionPaths(stepModel, actionLocation, rc)
switch action.Runs.Using {
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20:
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20, model.ActionRunsUsingNode24:
populateEnvsFromSavedState(step.getEnv(), step, rc)
populateEnvsFromInput(ctx, step.getEnv(), step.getActionModel(), rc)
containerArgs := []string{"node", path.Join(containerActionDir, action.Runs.Post)}
logger.Debugf("executing remote job container: %s", containerArgs)

View file

@ -18,7 +18,7 @@ import (
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
)
type ActionCache interface {
@ -39,10 +39,7 @@ func (c GoGitActionCache) Fetch(ctx context.Context, cacheDir, url, ref, token s
if err != nil {
return "", err
}
branchName, err := common.RandName(12)
if err != nil {
return "", err
}
branchName := common.MustRandName(12)
var auth transport.AuthMethod
if token != "" {

View file

@ -3,7 +3,6 @@ package runner
import (
"archive/tar"
"bytes"
"context"
"io"
"os"
"testing"
@ -17,7 +16,7 @@ func TestActionCache(t *testing.T) {
cache := &GoGitActionCache{
Path: os.TempDir(),
}
ctx := context.Background()
ctx := t.Context()
cacheDir := "nektos/act-test-actions"
repo := "https://code.forgejo.org/forgejo/act-test-actions"
refs := []struct {
@ -58,9 +57,10 @@ func TestActionCache(t *testing.T) {
return
}
atar, err := cache.GetTarArchive(ctx, c.CacheDir, sha, "js")
if !a.NoError(err) || !a.NotEmpty(atar) {
if !a.NoError(err) {
return
}
defer atar.Close()
mytar := tar.NewReader(atar)
th, err := mytar.Next()
if !a.NoError(err) || !a.NotEqual(0, th.Size) {

View file

@ -6,8 +6,8 @@ import (
"regexp"
"strings"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/model"
)
func evaluateCompositeInputAndEnv(ctx context.Context, parent *RunContext, step actionStep) map[string]string {
@ -136,17 +136,16 @@ func (rc *RunContext) compositeExecutor(action *model.Action) *compositeSteps {
sf := &stepFactoryImpl{}
for i, step := range action.Runs.Steps {
if step.ID == "" {
step.ID = fmt.Sprintf("%d", i)
for i, stepModel := range action.Runs.Steps {
if stepModel.Number != i {
return &compositeSteps{
pre: func(ctx context.Context) error { return nil },
main: common.NewErrorExecutor(fmt.Errorf("internal error: invalid Step: Number expected %v, was actually %v", i, stepModel.Number)),
post: func(ctx context.Context) error { return nil },
}
}
step.Number = i
// create a copy of the step, since this composite action could
// run multiple times and we might modify the instance
stepcopy := step
step, err := sf.newStep(&stepcopy, rc)
step, err := sf.newStep(&stepModel, rc)
if err != nil {
return &compositeSteps{
main: common.NewErrorExecutor(err),

View file

@ -7,7 +7,7 @@ import (
"strings"
"testing"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
@ -130,7 +130,7 @@ runs:
closerMock.On("Close")
}
action, err := readActionImpl(context.Background(), tt.step, "actionDir", "actionPath", readFile, writeFile)
action, err := readActionImpl(t.Context(), tt.step, "actionDir", "actionPath", readFile, writeFile)
assert.Nil(t, err)
assert.Equal(t, tt.expected, action)
@ -222,7 +222,7 @@ func TestActionRunner(t *testing.T) {
for _, tt := range table {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
ctx := t.Context()
cm := &containerMock{}
cm.On("CopyDir", "/var/run/act/actions/dir/", "dir/", false).Return(func(ctx context.Context) error { return nil })

View file

@ -5,7 +5,9 @@ import (
"regexp"
"strings"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
"github.com/sirupsen/logrus"
)
var (
@ -43,11 +45,12 @@ func (rc *RunContext) commandHandler(ctx context.Context) common.LineHandler {
}
if resumeCommand != "" && command != resumeCommand {
logger.Infof(" \U00002699 %s", line)
logger.WithFields(logrus.Fields{"command": "ignored", "raw": line}).Infof(" \U00002699 %s", line)
return false
}
arg = unescapeCommandData(arg)
kvPairs = unescapeKvPairs(kvPairs)
defCommandLogger := logger.WithFields(logrus.Fields{"command": command, "kvPairs": kvPairs, "arg": arg, "raw": line})
switch command {
case "set-env":
rc.setEnv(ctx, kvPairs, arg)
@ -56,27 +59,27 @@ func (rc *RunContext) commandHandler(ctx context.Context) common.LineHandler {
case "add-path":
rc.addPath(ctx, arg)
case "debug":
logger.Infof(" \U0001F4AC %s", line)
defCommandLogger.Debugf(" \U0001F4AC %s", line)
case "warning":
logger.Infof(" \U0001F6A7 %s", line)
defCommandLogger.Warnf(" \U0001F6A7 %s", line)
case "error":
logger.Infof(" \U00002757 %s", line)
defCommandLogger.Errorf(" \U00002757 %s", line)
case "add-mask":
rc.AddMask(arg)
logger.Infof(" \U00002699 %s", "***")
defCommandLogger.Infof(" \U00002699 %s", "***")
case "stop-commands":
resumeCommand = arg
logger.Infof(" \U00002699 %s", line)
defCommandLogger.Infof(" \U00002699 %s", line)
case resumeCommand:
resumeCommand = ""
logger.Infof(" \U00002699 %s", line)
defCommandLogger.Infof(" \U00002699 %s", line)
case "save-state":
logger.Infof(" \U0001f4be %s", line)
defCommandLogger.Infof(" \U0001f4be %s", line)
rc.saveState(ctx, kvPairs, arg)
case "add-matcher":
logger.Infof(" \U00002753 add-matcher %s", arg)
defCommandLogger.Infof(" \U00002753 add-matcher %s", arg)
default:
logger.Infof(" \U00002753 %s", line)
defCommandLogger.Infof(" \U00002753 %s", line)
}
// return true to let gitea's logger handle these special outputs also
@ -86,7 +89,7 @@ func (rc *RunContext) commandHandler(ctx context.Context) common.LineHandler {
func (rc *RunContext) setEnv(ctx context.Context, kvPairs map[string]string, arg string) {
name := kvPairs["name"]
common.Logger(ctx).Infof(" \U00002699 ::set-env:: %s=%s", name, arg)
common.Logger(ctx).WithFields(logrus.Fields{"command": "set-env", "name": name, "arg": arg}).Infof(" \U00002699 ::set-env:: %s=%s", name, arg)
if rc.Env == nil {
rc.Env = make(map[string]string)
}
@ -119,12 +122,12 @@ func (rc *RunContext) setOutput(ctx context.Context, kvPairs map[string]string,
return
}
logger.Infof(" \U00002699 ::set-output:: %s=%s", outputName, arg)
logger.WithFields(logrus.Fields{"command": "set-output", "name": outputName, "arg": arg}).Infof(" \U00002699 ::set-output:: %s=%s", outputName, arg)
result.Outputs[outputName] = arg
}
func (rc *RunContext) addPath(ctx context.Context, arg string) {
common.Logger(ctx).Infof(" \U00002699 ::add-path:: %s", arg)
common.Logger(ctx).WithFields(logrus.Fields{"command": "add-path", "arg": arg}).Infof(" \U00002699 ::add-path:: %s", arg)
extraPath := []string{arg}
for _, v := range rc.ExtraPath {
if v != arg {
@ -136,8 +139,8 @@ func (rc *RunContext) addPath(ctx context.Context, arg string) {
func parseKeyValuePairs(kvPairs, separator string) map[string]string {
rtn := make(map[string]string)
kvPairList := strings.Split(kvPairs, separator)
for _, kvPair := range kvPairList {
kvPairList := strings.SplitSeq(kvPairs, separator)
for kvPair := range kvPairList {
kv := strings.Split(kvPair, "=")
if len(kv) == 2 {
rtn[kv[0]] = kv[1]

View file

@ -2,7 +2,6 @@ package runner
import (
"bytes"
"context"
"io"
"os"
"testing"
@ -10,13 +9,13 @@ import (
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/assert"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/model"
)
func TestCommandSetEnv(t *testing.T) {
a := assert.New(t)
ctx := context.Background()
ctx := t.Context()
rc := new(RunContext)
handler := rc.commandHandler(ctx)
@ -26,7 +25,7 @@ func TestCommandSetEnv(t *testing.T) {
func TestCommandSetOutput(t *testing.T) {
a := assert.New(t)
ctx := context.Background()
ctx := t.Context()
rc := new(RunContext)
rc.StepResults = make(map[string]*model.StepResult)
handler := rc.commandHandler(ctx)
@ -56,7 +55,7 @@ func TestCommandSetOutput(t *testing.T) {
func TestCommandAddpath(t *testing.T) {
a := assert.New(t)
ctx := context.Background()
ctx := t.Context()
rc := new(RunContext)
handler := rc.commandHandler(ctx)
@ -71,7 +70,7 @@ func TestCommandStopCommands(t *testing.T) {
logger, hook := test.NewNullLogger()
a := assert.New(t)
ctx := common.WithLogger(context.Background(), logger)
ctx := common.WithLogger(t.Context(), logger)
rc := new(RunContext)
handler := rc.commandHandler(ctx)
@ -94,7 +93,7 @@ func TestCommandStopCommands(t *testing.T) {
func TestCommandAddpathADO(t *testing.T) {
a := assert.New(t)
ctx := context.Background()
ctx := t.Context()
rc := new(RunContext)
handler := rc.commandHandler(ctx)
@ -109,7 +108,7 @@ func TestCommandAddmask(t *testing.T) {
logger, hook := test.NewNullLogger()
a := assert.New(t)
ctx := context.Background()
ctx := t.Context()
loggerCtx := common.WithLogger(ctx, logger)
rc := new(RunContext)
@ -163,8 +162,8 @@ func TestCommandAddmaskUsemask(t *testing.T) {
}
re := captureOutput(t, func() {
ctx := context.Background()
ctx = WithJobLogger(ctx, "0", "testjob", config, &rc.Masks, map[string]interface{}{})
ctx := t.Context()
ctx = WithJobLogger(ctx, "0", "testjob", config, &rc.Masks, map[string]any{})
handler := rc.commandHandler(ctx)
handler("::add-mask::secret\n")
@ -180,7 +179,7 @@ func TestCommandSaveState(t *testing.T) {
StepResults: map[string]*model.StepResult{},
}
ctx := context.Background()
ctx := t.Context()
handler := rc.commandHandler(ctx)
handler("::save-state name=state-name::state-value\n")

View file

@ -4,8 +4,8 @@ import (
"context"
"io"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/container"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/container"
"github.com/stretchr/testify/mock"
)

View file

@ -4,6 +4,7 @@ import (
"bytes"
"context"
"fmt"
"maps"
"path"
"reflect"
"regexp"
@ -12,16 +13,16 @@ import (
_ "embed"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/container"
"code.forgejo.org/forgejo/runner/act/exprparser"
"code.forgejo.org/forgejo/runner/act/model"
"gopkg.in/yaml.v3"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/container"
"code.forgejo.org/forgejo/runner/v11/act/exprparser"
"code.forgejo.org/forgejo/runner/v11/act/model"
"go.yaml.in/yaml/v3"
)
// ExpressionEvaluator is the interface for evaluating expressions
type ExpressionEvaluator interface {
evaluate(context.Context, string, exprparser.DefaultStatusCheck) (interface{}, error)
evaluate(context.Context, string, exprparser.DefaultStatusCheck) (any, error)
EvaluateYamlNode(context.Context, *yaml.Node) error
Interpolate(context.Context, string) string
}
@ -36,7 +37,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map
// todo: cleanup EvaluationEnvironment creation
using := make(map[string]exprparser.Needs)
strategy := make(map[string]interface{})
strategy := make(map[string]any)
if rc.Run != nil {
job := rc.Run.Job()
if job != nil && job.Strategy != nil {
@ -64,9 +65,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map
result := model.WorkflowCallResult{
Outputs: map[string]string{},
}
for k, v := range job.Outputs {
result.Outputs[k] = v
}
maps.Copy(result.Outputs, job.Outputs)
workflowCallResult[jobName] = &result
}
}
@ -108,9 +107,22 @@ var hashfiles string
// NewStepExpressionEvaluator creates a new evaluator
func (rc *RunContext) NewStepExpressionEvaluator(ctx context.Context, step step) ExpressionEvaluator {
return rc.NewStepExpressionEvaluatorExt(ctx, step, false)
}
// NewStepExpressionEvaluatorExt creates a new evaluator
func (rc *RunContext) NewStepExpressionEvaluatorExt(ctx context.Context, step step, rcInputs bool) ExpressionEvaluator {
ghc := rc.getGithubContext(ctx)
if rcInputs {
return rc.newStepExpressionEvaluator(ctx, step, ghc, getEvaluatorInputs(ctx, rc, nil, ghc))
}
return rc.newStepExpressionEvaluator(ctx, step, ghc, getEvaluatorInputs(ctx, rc, step, ghc))
}
func (rc *RunContext) newStepExpressionEvaluator(ctx context.Context, step step, ghc *model.GithubContext, inputs map[string]any) ExpressionEvaluator {
// todo: cleanup EvaluationEnvironment creation
job := rc.Run.Job()
strategy := make(map[string]interface{})
strategy := make(map[string]any)
if job.Strategy != nil {
strategy["fail-fast"] = job.Strategy.FailFast
strategy["max-parallel"] = job.Strategy.MaxParallel
@ -127,9 +139,6 @@ func (rc *RunContext) NewStepExpressionEvaluator(ctx context.Context, step step)
}
}
ghc := rc.getGithubContext(ctx)
inputs := getEvaluatorInputs(ctx, rc, step, ghc)
ee := &exprparser.EvaluationEnvironment{
Github: step.getGithubContext(ctx),
Env: *step.getEnv(),
@ -157,8 +166,8 @@ func (rc *RunContext) NewStepExpressionEvaluator(ctx context.Context, step step)
}
}
func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.Value) (interface{}, error) {
hashFiles := func(v []reflect.Value) (interface{}, error) {
func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.Value) (any, error) {
hashFiles := func(v []reflect.Value) (any, error) {
if rc.JobContainer != nil {
timeed, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
@ -182,9 +191,7 @@ func getHashFilesFunction(ctx context.Context, rc *RunContext) func(v []reflect.
patterns = append(patterns, s)
}
env := map[string]string{}
for k, v := range rc.Env {
env[k] = v
}
maps.Copy(env, rc.Env)
env["patterns"] = strings.Join(patterns, "\n")
if followSymlink {
env["followSymbolicLinks"] = "true"
@ -222,7 +229,7 @@ type expressionEvaluator struct {
interpreter exprparser.Interpreter
}
func (ee expressionEvaluator) evaluate(ctx context.Context, in string, defaultStatusCheck exprparser.DefaultStatusCheck) (interface{}, error) {
func (ee expressionEvaluator) evaluate(ctx context.Context, in string, defaultStatusCheck exprparser.DefaultStatusCheck) (any, error) {
logger := common.Logger(ctx)
logger.Debugf("evaluating expression '%s'", in)
evaluated, err := ee.interpreter.Evaluate(in, defaultStatusCheck)
@ -469,10 +476,8 @@ func rewriteSubExpression(ctx context.Context, in string, forceFormat bool) (str
return out, nil
}
func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]interface{} {
inputs := map[string]interface{}{}
setupWorkflowInputs(ctx, &inputs, rc)
func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]any {
inputs := map[string]any{}
var env map[string]string
if step != nil {
@ -482,12 +487,14 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod
}
for k, v := range env {
if strings.HasPrefix(k, "INPUT_") {
inputs[strings.ToLower(strings.TrimPrefix(k, "INPUT_"))] = v
if after, ok := strings.CutPrefix(k, "INPUT_"); ok {
inputs[strings.ToLower(after)] = v
}
}
if ghc.EventName == "workflow_dispatch" {
setupWorkflowInputs(ctx, &inputs, rc)
if rc.caller == nil && ghc.EventName == "workflow_dispatch" {
config := rc.Run.Workflow.WorkflowDispatchConfig()
if config != nil && config.Inputs != nil {
for k, v := range config.Inputs {
@ -510,7 +517,7 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod
for k, v := range config.Inputs {
value := nestedMapLookup(ghc.Event, "inputs", k)
if value == nil {
value = v.Default
_ = v.Default.Decode(&value)
}
if v.Type == "boolean" {
inputs[k] = value == "true"
@ -523,27 +530,30 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod
return inputs
}
func setupWorkflowInputs(ctx context.Context, inputs *map[string]interface{}, rc *RunContext) {
func setupWorkflowInputs(ctx context.Context, inputs *map[string]any, rc *RunContext) {
if rc.caller != nil {
config := rc.Run.Workflow.WorkflowCallConfig()
for name, input := range config.Inputs {
value := rc.caller.runContext.Run.Job().With[name]
if value != nil {
if str, ok := value.(string); ok {
node := yaml.Node{}
_ = node.Encode(value)
if rc.caller.runContext.ExprEval != nil {
// evaluate using the calling RunContext (outside)
value = rc.caller.runContext.ExprEval.Interpolate(ctx, str)
_ = rc.caller.runContext.ExprEval.EvaluateYamlNode(ctx, &node)
}
_ = node.Decode(&value)
}
if value == nil && config != nil && config.Inputs != nil {
value = input.Default
def := input.Default
if rc.ExprEval != nil {
if str, ok := value.(string); ok {
// evaluate using the called RunContext (inside)
value = rc.ExprEval.Interpolate(ctx, str)
}
// evaluate using the called RunContext (inside)
_ = rc.ExprEval.EvaluateYamlNode(ctx, &def)
}
_ = def.Decode(&value)
}
(*inputs)[name] = value
@ -554,21 +564,21 @@ func setupWorkflowInputs(ctx context.Context, inputs *map[string]interface{}, rc
func getWorkflowSecrets(ctx context.Context, rc *RunContext) map[string]string {
if rc.caller != nil {
job := rc.caller.runContext.Run.Job()
secrets := job.Secrets()
rawSecrets := job.Secrets()
if secrets == nil && job.InheritSecrets() {
secrets = rc.caller.runContext.Config.Secrets
if rawSecrets == nil && job.InheritSecrets() {
rawSecrets = rc.caller.runContext.Config.Secrets
}
if secrets == nil {
secrets = map[string]string{}
if rawSecrets == nil {
return map[string]string{}
}
for k, v := range secrets {
secrets[k] = rc.caller.runContext.ExprEval.Interpolate(ctx, v)
interpolatedSecrets := make(map[string]string, len(rawSecrets))
for k, v := range rawSecrets {
interpolatedSecrets[k] = rc.caller.runContext.ExprEval.Interpolate(ctx, v)
}
return secrets
return interpolatedSecrets
}
return rc.Config.Secrets

View file

@ -1,18 +1,17 @@
package runner
import (
"context"
"testing"
"code.forgejo.org/forgejo/runner/act/exprparser"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/exprparser"
"code.forgejo.org/forgejo/runner/v11/act/model"
assert "github.com/stretchr/testify/assert"
yaml "gopkg.in/yaml.v3"
yaml "go.yaml.in/yaml/v3"
)
func createRunContext(t *testing.T) *RunContext {
var yml yaml.Node
err := yml.Encode(map[string][]interface{}{
err := yml.Encode(map[string][]any{
"os": {"Linux", "Windows"},
"foo": {"bar", "baz"},
})
@ -44,7 +43,7 @@ func createRunContext(t *testing.T) *RunContext {
},
},
},
Matrix: map[string]interface{}{
Matrix: map[string]any{
"os": "Linux",
"foo": "bar",
},
@ -76,11 +75,11 @@ func createRunContext(t *testing.T) *RunContext {
func TestExpressionEvaluateRunContext(t *testing.T) {
rc := createRunContext(t)
ee := rc.NewExpressionEvaluator(context.Background())
ee := rc.NewExpressionEvaluator(t.Context())
tables := []struct {
in string
out interface{}
out any
errMesg string
}{
{" 1 ", 1, ""},
@ -134,10 +133,9 @@ func TestExpressionEvaluateRunContext(t *testing.T) {
}
for _, table := range tables {
table := table
t.Run(table.in, func(t *testing.T) {
assertObject := assert.New(t)
out, err := ee.evaluate(context.Background(), table.in, exprparser.DefaultStatusCheckNone)
out, err := ee.evaluate(t.Context(), table.in, exprparser.DefaultStatusCheckNone)
if table.errMesg == "" {
assertObject.NoError(err, table.in)
assertObject.Equal(table.out, out, table.in)
@ -155,11 +153,11 @@ func TestExpressionEvaluateStep(t *testing.T) {
RunContext: rc,
}
ee := rc.NewStepExpressionEvaluator(context.Background(), step)
ee := rc.NewStepExpressionEvaluator(t.Context(), step)
tables := []struct {
in string
out interface{}
out any
errMesg string
}{
{"steps.idwithnothing.conclusion", model.StepStatusSuccess.String(), ""},
@ -174,10 +172,9 @@ func TestExpressionEvaluateStep(t *testing.T) {
}
for _, table := range tables {
table := table
t.Run(table.in, func(t *testing.T) {
assertObject := assert.New(t)
out, err := ee.evaluate(context.Background(), table.in, exprparser.DefaultStatusCheckNone)
out, err := ee.evaluate(t.Context(), table.in, exprparser.DefaultStatusCheckNone)
if table.errMesg == "" {
assertObject.NoError(err, table.in)
assertObject.Equal(table.out, out, table.in)
@ -217,7 +214,7 @@ func TestExpressionInterpolate(t *testing.T) {
},
},
}
ee := rc.NewExpressionEvaluator(context.Background())
ee := rc.NewExpressionEvaluator(t.Context())
tables := []struct {
in string
out string
@ -257,10 +254,9 @@ func TestExpressionInterpolate(t *testing.T) {
}
for _, table := range tables {
table := table
t.Run("interpolate", func(t *testing.T) {
assertObject := assert.New(t)
out := ee.Interpolate(context.Background(), table.in)
out := ee.Interpolate(t.Context(), table.in)
assertObject.Equal(table.out, out, table.in)
})
}
@ -287,7 +283,7 @@ func TestExpressionRewriteSubExpression(t *testing.T) {
for _, table := range table {
t.Run("TestRewriteSubExpression", func(t *testing.T) {
assertObject := assert.New(t)
out, err := rewriteSubExpression(context.Background(), table.in, false)
out, err := rewriteSubExpression(t.Context(), table.in, false)
if err != nil {
t.Fatal(err)
}
@ -311,7 +307,7 @@ func TestExpressionRewriteSubExpressionForceFormat(t *testing.T) {
for _, table := range table {
t.Run("TestRewriteSubExpressionForceFormat", func(t *testing.T) {
assertObject := assert.New(t)
out, err := rewriteSubExpression(context.Background(), table.in, true)
out, err := rewriteSubExpression(t.Context(), table.in, true)
if err != nil {
t.Fatal(err)
}

View file

@ -5,13 +5,14 @@ import (
"fmt"
"time"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/container"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/container"
"code.forgejo.org/forgejo/runner/v11/act/model"
"github.com/sirupsen/logrus"
)
type jobInfo interface {
matrix() map[string]interface{}
matrix() map[string]any
steps() []*model.Step
startContainer() common.Executor
stopContainer() common.Executor
@ -20,6 +21,8 @@ type jobInfo interface {
result(result string)
}
const cleanupTimeout = 30 * time.Minute
func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executor {
steps := make([]common.Executor, 0)
preSteps := make([]common.Executor, 0)
@ -54,16 +57,11 @@ func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executo
})
for i, stepModel := range infoSteps {
stepModel := stepModel
if stepModel == nil {
return func(ctx context.Context) error {
return fmt.Errorf("invalid Step %v: missing run or uses key", i)
}
return common.NewErrorExecutor(fmt.Errorf("invalid Step %v: missing run or uses key", i))
} else if stepModel.Number != i {
return common.NewErrorExecutor(fmt.Errorf("internal error: invalid Step: Number expected %v, was actually %v", i, stepModel.Number))
}
if stepModel.ID == "" {
stepModel.ID = fmt.Sprintf("%d", i)
}
stepModel.Number = i
step, err := sf.newStep(stepModel, rc)
if err != nil {
@ -107,37 +105,40 @@ func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executo
}
}
postExecutor = postExecutor.Finally(func(ctx context.Context) error {
setJobResults := func(ctx context.Context) error {
jobError := common.JobError(ctx)
// Fresh context to ensure job result output works even if prev. context was a cancelled job
ctx, cancel := context.WithTimeout(common.WithLogger(context.Background(), common.Logger(ctx)), time.Minute)
defer cancel()
setJobResult(ctx, info, rc, jobError == nil)
return nil
}
cleanupJob := func(_ context.Context) error {
var err error
if rc.Config.AutoRemove || jobError == nil {
// always allow 1 min for stopping and removing the runner, even if we were cancelled
ctx, cancel := context.WithTimeout(common.WithLogger(context.Background(), common.Logger(ctx)), time.Minute)
defer cancel()
logger := common.Logger(ctx)
logger.Infof("Cleaning up container for job %s", rc.JobName)
if err = info.stopContainer()(ctx); err != nil {
logger.Errorf("Error while stop job container: %v", err)
}
// Separate timeout for cleanup tasks; logger is cleared so that cleanup logs go to runner, not job
ctx, cancel := context.WithTimeout(context.Background(), cleanupTimeout)
defer cancel()
if !rc.IsHostEnv(ctx) && rc.Config.ContainerNetworkMode == "" {
// clean network in docker mode only
// if the value of `ContainerNetworkMode` is empty string,
// it means that the network to which containers are connecting is created by `act_runner`,
// so, we should remove the network at last.
networkName, _ := rc.networkName()
logger.Infof("Cleaning up network for job %s, and network name is: %s", rc.JobName, networkName)
if err := container.NewDockerNetworkRemoveExecutor(networkName)(ctx); err != nil {
logger.Errorf("Error while cleaning network: %v", err)
}
logger := common.Logger(ctx)
logger.Debugf("Cleaning up container for job %s", rc.jobContainerName())
if err = info.stopContainer()(ctx); err != nil {
logger.Errorf("Error while stop job container %s: %v", rc.jobContainerName(), err)
}
if !rc.IsHostEnv(ctx) && rc.getNetworkCreated(ctx) {
networkName := rc.getNetworkName(ctx)
logger.Debugf("Cleaning up network %s for job %s", networkName, rc.jobContainerName())
if err := container.NewDockerNetworkRemoveExecutor(networkName)(ctx); err != nil {
logger.Errorf("Error while cleaning network %s: %v", networkName, err)
}
}
setJobResult(ctx, info, rc, jobError == nil)
setJobOutputs(ctx, rc)
return err
})
}
pipeline := make([]common.Executor, 0)
pipeline = append(pipeline, preSteps...)
@ -149,18 +150,25 @@ func newJobExecutor(info jobInfo, sf stepFactory, rc *RunContext) common.Executo
if ctx.Err() == context.Canceled {
// in case of an aborted run, we still should execute the
// post steps to allow cleanup.
ctx, cancel = context.WithTimeout(common.WithLogger(context.Background(), common.Logger(ctx)), 5*time.Minute)
ctx, cancel = context.WithTimeout(common.WithLogger(context.Background(), common.Logger(ctx)), cleanupTimeout)
defer cancel()
}
return postExecutor(ctx)
}).
Finally(info.interpolateOutputs()).
Finally(setJobResults).
Finally(cleanupJob).
Finally(info.closeContainer()))
}
func setJobResult(ctx context.Context, info jobInfo, rc *RunContext, success bool) {
logger := common.Logger(ctx)
// As we're reading the matrix build's status (`rc.Run.Job().Result`), it's possible for it change in another
// goroutine running `setJobResult` and invoking `.result(...)`. Prevent concurrent execution of `setJobResult`...
rc.Run.Job().ResultMutex.Lock()
defer rc.Run.Job().ResultMutex.Unlock()
jobResult := "success"
// we have only one result for a whole matrix build, so we need
// to keep an existing result state if we run a matrix
@ -172,33 +180,42 @@ 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
logger.WithField("jobResult", jobResult).Infof("\U0001F3C1 Job %s", jobResultMessage)
}
func setJobOutputs(ctx context.Context, rc *RunContext) {
if rc.caller != nil {
// map outputs for reusable workflows
callerOutputs := make(map[string]string)
ee := rc.NewExpressionEvaluator(ctx)
for k, v := range rc.Run.Workflow.WorkflowCallConfig().Outputs {
callerOutputs[k] = ee.Interpolate(ctx, ee.Interpolate(ctx, v.Value))
}
rc.caller.runContext.Run.Job().Outputs = callerOutputs
}
logger.
WithFields(logrus.Fields{
"jobResult": jobResult,
"jobOutputs": jobOutputs,
}).
Infof("\U0001F3C1 Job %s", jobResultMessage)
}
func useStepLogger(rc *RunContext, stepModel *model.Step, stage stepStage, executor common.Executor) common.Executor {

View file

@ -4,29 +4,36 @@ import (
"context"
"fmt"
"io"
"slices"
"sync"
"testing"
"time"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/act/container"
"code.forgejo.org/forgejo/runner/act/model"
"code.forgejo.org/forgejo/runner/v11/act/common"
"code.forgejo.org/forgejo/runner/v11/act/container"
"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"
)
//go:generate mockery --srcpkg=github.com/sirupsen/logrus --name=FieldLogger
func TestJobExecutor(t *testing.T) {
tables := []TestJobFileInfo{
{workdir, "uses-and-run-in-one-step", "push", "Invalid run/uses syntax for job:test step:Test", platforms, secrets},
{workdir, "uses-github-empty", "push", "Expected format {org}/{repo}[/path]@ref", platforms, secrets},
{workdir, "uses-github-empty", "push", "job:test step:empty", platforms, secrets},
{workdir, "uses-github-noref", "push", "Expected format {org}/{repo}[/path]@ref", platforms, secrets},
{workdir, "uses-github-root", "push", "", platforms, secrets},
{workdir, "uses-github-path", "push", "", platforms, secrets},
{workdir, "uses-docker-url", "push", "", platforms, secrets},
{workdir, "uses-github-full-sha", "push", "", platforms, secrets},
{workdir, "uses-github-short-sha", "push", "Unable to resolve action `actions/hello-world-docker-action@b136eb8`, the provided ref `b136eb8` is the shortened version of a commit SHA, which is not supported. Please use the full commit SHA `b136eb8894c5cb1dd5807da824be97ccdf9b5423` instead", platforms, secrets},
{workdir, "uses-github-short-sha", "push", "Please use the full commit SHA", platforms, secrets},
{workdir, "job-nil-step", "push", "invalid Step 0: missing run or uses key", platforms, secrets},
}
// These tests are sufficient to only check syntax.
ctx := common.WithDryrun(context.Background(), true)
ctx := common.WithDryrun(t.Context(), true)
for _, table := range tables {
t.Run(table.workflowPath, func(t *testing.T) {
table.runTest(ctx, t, &Config{})
@ -38,9 +45,9 @@ type jobInfoMock struct {
mock.Mock
}
func (jim *jobInfoMock) matrix() map[string]interface{} {
func (jim *jobInfoMock) matrix() map[string]any {
args := jim.Called()
return args.Get(0).(map[string]interface{})
return args.Get(0).(map[string]any)
}
func (jim *jobInfoMock) steps() []*model.Step {
@ -124,8 +131,9 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
executedSteps: []string{
"startContainer",
"step1",
"stopContainer",
"interpolateOutputs",
"setJobResults",
"stopContainer",
"closeContainer",
},
result: "success",
@ -142,6 +150,8 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
"startContainer",
"step1",
"interpolateOutputs",
"setJobResults",
"stopContainer",
"closeContainer",
},
result: "failure",
@ -158,8 +168,9 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
"startContainer",
"pre1",
"step1",
"stopContainer",
"interpolateOutputs",
"setJobResults",
"stopContainer",
"closeContainer",
},
result: "success",
@ -176,8 +187,9 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
"startContainer",
"step1",
"post1",
"stopContainer",
"interpolateOutputs",
"setJobResults",
"stopContainer",
"closeContainer",
},
result: "success",
@ -195,8 +207,9 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
"pre1",
"step1",
"post1",
"stopContainer",
"interpolateOutputs",
"setJobResults",
"stopContainer",
"closeContainer",
},
result: "success",
@ -205,11 +218,14 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
{
name: "stepsWithPreAndPost",
steps: []*model.Step{{
ID: "1",
ID: "1",
Number: 0,
}, {
ID: "2",
ID: "2",
Number: 1,
}, {
ID: "3",
ID: "3",
Number: 2,
}},
preSteps: []bool{true, false, true},
postSteps: []bool{false, true, true},
@ -222,8 +238,9 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
"step3",
"post3",
"post2",
"stopContainer",
"interpolateOutputs",
"setJobResults",
"stopContainer",
"closeContainer",
},
result: "success",
@ -232,19 +249,34 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
}
contains := func(needle string, haystack []string) bool {
for _, item := range haystack {
if item == needle {
return true
}
}
return false
return slices.Contains(haystack, needle)
}
for _, tt := range table {
t.Run(tt.name, func(t *testing.T) {
fmt.Printf("::group::%s\n", tt.name)
ctx := common.WithJobErrorContainer(context.Background())
executorOrder := make([]string, 0)
mockLogger := mocks.NewFieldLogger(t)
mockLogger.On("Debugf", mock.Anything, mock.Anything).Return(0).Maybe()
mockLogger.On("Warningf", mock.Anything, mock.Anything).Return(0).Maybe()
mockLogger.On("WithField", mock.Anything, mock.Anything).Return(&logrus.Entry{Logger: &logrus.Logger{}}).Maybe()
// When `WithFields()` is called with jobResult & jobOutputs field, add `setJobResults` to executorOrder.
mockLogger.On("WithFields",
mock.MatchedBy(func(fields logrus.Fields) bool {
_, okJobResult := fields["jobResult"]
_, okJobOutput := fields["jobOutputs"]
return okJobOutput && okJobResult
})).
Run(func(args mock.Arguments) {
executorOrder = append(executorOrder, "setJobResults")
}).
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)
jim := &jobInfoMock{}
sfm := &stepFactoryMock{}
rc := &RunContext{
@ -260,7 +292,6 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
Config: &Config{},
}
rc.ExprEval = rc.NewExpressionEvaluator(ctx)
executorOrder := make([]string, 0)
jim.On("steps").Return(tt.steps)
@ -272,9 +303,6 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
}
for i, stepModel := range tt.steps {
i := i
stepModel := stepModel
sm := &stepMock{}
sfm.On("newStep", stepModel, rc).Return(sm, nil)
@ -305,7 +333,7 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
}
if len(tt.steps) > 0 {
jim.On("matrix").Return(map[string]interface{}{})
jim.On("matrix").Return(map[string]any{})
jim.On("interpolateOutputs").Return(func(ctx context.Context) error {
executorOrder = append(executorOrder, "interpolateOutputs")
@ -339,3 +367,153 @@ func TestJobExecutorNewJobExecutor(t *testing.T) {
})
}
}
func TestSetJobResultConcurrency(t *testing.T) {
jim := &jobInfoMock{}
job := model.Job{
Result: "success",
}
// Distinct RunContext objects are used to replicate realistic setJobResult in matrix build
rc1 := &RunContext{
Run: &model.Run{
JobID: "test",
Workflow: &model.Workflow{
Jobs: map[string]*model.Job{
"test": &job,
},
},
},
}
rc2 := &RunContext{
Run: &model.Run{
JobID: "test",
Workflow: &model.Workflow{
Jobs: map[string]*model.Job{
"test": &job,
},
},
},
}
// Hack: Job() invokes GetJob() which can mutate the job name, this will trip the data race detector if it is
// encountered later when `setJobResult()` is being tested. This is a false-positive caused by this test invoking
// setJobResult outside of the regular RunContext, so it's invoked here before the goroutines are spawned to prevent
// the false positive.
rc1.Run.Job()
rc2.Run.Job()
jim.On("matrix").Return(map[string]interface{}{
"python": []string{"3.10", "3.11", "3.12"},
})
// Synthesize a race condition in setJobResult where, by reading data from the job matrix earlier and then
// performing unsynchronzied writes to the same shared data structure, it can overwrite a failure status.
//
// Goroutine 1: Start marking job as success
// (artificially suspended
// by result() mock)
// Goroutine 2: Mark job as failure
// Goroutine 1: Finish marking job as success
//
// Correct behavior: Job is marked as a failure
// Bug behavior: Job is marked as a success
var lastResult string
jim.On("result", mock.Anything).Run(func(args mock.Arguments) {
result := args.String(0)
// Artificially suspend the "success" case so that the failure case races past it.
if result == "success" {
time.Sleep(1 * time.Second)
}
job.Result = result
lastResult = result
})
var wg sync.WaitGroup
wg.Add(2)
// Goroutine 1, mark as success:
go func() {
defer wg.Done()
setJobResult(t.Context(), jim, rc1, true)
}()
// Goroutine 2, mark as failure:
go func() {
defer wg.Done()
setJobResult(t.Context(), jim, rc2, false)
}()
wg.Wait()
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

@ -12,7 +12,7 @@ import (
"path/filepath"
"strings"
"code.forgejo.org/forgejo/runner/act/filecollector"
"code.forgejo.org/forgejo/runner/v11/act/filecollector"
)
type LocalRepositoryCache struct {

View file

@ -5,11 +5,12 @@ import (
"context"
"fmt"
"io"
"maps"
"os"
"strings"
"sync"
"code.forgejo.org/forgejo/runner/act/common"
"code.forgejo.org/forgejo/runner/v11/act/common"
"github.com/sirupsen/logrus"
"golang.org/x/term"
@ -72,7 +73,7 @@ func WithJobLoggerFactory(ctx context.Context, factory JobLoggerFactory) context
}
// WithJobLogger attaches a new logger to context that is aware of steps
func WithJobLogger(ctx context.Context, jobID, jobName string, config *Config, masks *[]string, matrix map[string]interface{}) context.Context {
func WithJobLogger(ctx context.Context, jobID, jobName string, config *Config, masks *[]string, matrix map[string]any) context.Context {
ctx = WithMasks(ctx, masks)
var logger *logrus.Logger
@ -145,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,
@ -158,6 +179,7 @@ func withStepLogger(ctx context.Context, stepNumber int, stepID, stepName, stage
type entryProcessor func(entry *logrus.Entry) *logrus.Entry
func valueMasker(insecureSecrets bool, secrets map[string]string) entryProcessor {
secrets = maps.Clone(secrets)
return func(entry *logrus.Entry) *logrus.Entry {
if insecureSecrets {
return entry

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