7 Commits

Author SHA1 Message Date
silverwind
0f7efae806 chore(deps): update workflow action versions (#792)
## Summary
- `actions/checkout`: v4/v5 → v6
- `actions/setup-go`: v5 → v6
- `docker/build-push-action`: v5 → v6

All other actions (`goreleaser/goreleaser-action@v6`, `docker/setup-qemu-action@v3`, `docker/setup-buildx-action@v3`, `docker/login-action@v3`, `crazy-max/ghaction-import-gpg@v6`) were already at their latest major versions.

No breaking changes affect the current workflow configurations. The main changes in the updated actions are Node.js 24 runtime upgrades and minor feature additions.

Reviewed-on: https://gitea.com/gitea/act_runner/pulls/792
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-02-18 06:05:34 +00:00
silverwind
aab249000c chore(deps): update act to v0.261.8 (#791)
## Summary
- Update `gitea.com/gitea/act` from pseudo-version `v0.261.7-0.20251202193638-5417d3ac6742` to `v0.261.8`
- Update yaml import in `workflow.go` from `gopkg.in/yaml.v3` to `go.yaml.in/yaml/v4` to match act's yaml v4 migration
- Add tests to verify yaml/v4 upgrade works correctly

## Changes included in act v0.261.8
- Recover from panics in parallel executor workers ([gitea/act#153](https://gitea.com/gitea/act/pulls/153))
- Fix max-parallel support for matrix jobs ([gitea/act#150](https://gitea.com/gitea/act/pulls/150))
- Fix yaml with prefixed newline broken setjob + yaml v4 ([gitea/act#144](https://gitea.com/gitea/act/pulls/144))
- Fixed typo ([gitea/act#151](https://gitea.com/gitea/act/pulls/151))

## Tests added
- **`Test_generateWorkflow`**: 7 new cases (was 1), covering: no needs, needs as list, workflow env/triggers, container+services, matrix strategy, special YAML characters, and invalid YAML error handling
- **`Test_yamlV4NodeRoundTrip`**: Directly exercises `go.yaml.in/yaml/v4` — `yaml.Node` construction, marshal/unmarshal round-trip, and node kind constants

Fixes: https://gitea.com/gitea/act_runner/issues/371
Fixes: https://gitea.com/gitea/act_runner/issues/772
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/791
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-02-18 05:37:21 +00:00
stecklars
c82077e6b5 examples: improve DIND rootless network performance (#786)
## Summary
- Add `DOCKERD_ROOTLESS_ROOTLESSKIT_NET=slirp4netns` and `DOCKERD_ROOTLESS_ROOTLESSKIT_MTU=65520` to the DIND docker-compose example
- The `docker:dind-rootless` base image defaults to vpnkit as the network driver, which has substantially lower throughput than slirp4netns

## The problem

I noticed that pulling containers as well as downloading data within the container when running act_runner as DIND was very slow (see Ookla speedtest results in the following). While analysing the issue, I found that this was caused by the usage of vpnkit.

The `docker:dind-rootless` base image defaults to vpnkit as the network driver. slirp4netns was [added as an opt-in option](https://github.com/docker-library/docker/pull/543) and must be explicitly enabled via `DOCKERD_ROOTLESS_ROOTLESSKIT_NET=slirp4netns`.

This means anyone following the current DIND example gets vpnkit, which has significantly lower network throughput. This affects **all** network operations in the container — image pulls, package installs, and CI tasks.

Per the [rootlesskit iperf3 benchmarks](https://github.com/rootless-containers/rootlesskit/blob/master/docs/network.md):

| Driver | MTU 1500 | MTU 65520 |
|--------|----------|-----------|
| **vpnkit** | 0.60 Gbps | not supported |
| **slirp4netns** | 1.06 Gbps | 7.55 Gbps |

## Real-world benchmark results (Ookla speedtest, same server)

| | Download | Upload |
|---|---|---|
| **Default (vpnkit)** | ~130 Mbps | ~126 Mbps |
| **slirp4netns + MTU 65520** | ~958 Mbps | ~462 Mbps |

## References
- [docker-library/docker#543](https://github.com/docker-library/docker/pull/543) — added slirp4netns to dind-rootless as opt-in (vpnkit remains default)
- [rootlesskit network docs](https://github.com/rootless-containers/rootlesskit/blob/master/docs/network.md) — iperf3 benchmarks

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-on: https://gitea.com/gitea/act_runner/pulls/786
Reviewed-by: silverwind <silverwind@noreply.gitea.com>
Co-authored-by: stecklars <stecklars@noreply.gitea.com>
Co-committed-by: stecklars <stecklars@noreply.gitea.com>
2026-02-16 07:56:45 +00:00
silverwind
9f91fdd0eb chore(deps): bump Go version to 1.26 in Dockerfile and Makefile (#788)
## Summary
- Bump Dockerfile builder image from `golang:1.24-alpine` to `golang:1.26-alpine`
- Bump Makefile `XGO_VERSION` from `go-1.24.x` to `go-1.26.x`

These were missed in #787 which bumped `go.mod` to Go 1.26.0, causing CI build failures.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://gitea.com/gitea/act_runner/pulls/788
Reviewed-by: ChristopherHX <christopherhx@noreply.gitea.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-02-14 10:32:16 +00:00
silverwind
7a7a5d9051 chore(deps): bump Go version to 1.26.0 (#787)
## Summary
- Bumps Go version from 1.24.0 (toolchain go1.24.11) to 1.26.0
- Fixes CI `govulncheck` failures caused by three standard library vulnerabilities in go1.24.11:
  - GO-2026-4341: Memory exhaustion in `net/url` query parameter parsing
  - GO-2026-4340: Handshake messages at incorrect encryption level in `crypto/tls`
  - GO-2026-4337: Unexpected session resumption in `crypto/tls`

## Test plan
- [x] `make vet` passes
- [x] `make build` passes
- [x] `make test` passes (includes `govulncheck` and all unit tests)

Reviewed-on: https://gitea.com/gitea/act_runner/pulls/787
Reviewed-by: ChristopherHX <christopherhx@noreply.gitea.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-02-14 10:19:45 +00:00
mkesper
90d11b8692 Remove duplicate assignment of DIST (#777)
The assignment already happens at line 1.

Signed-off-by: mkesper <mkesper@noreply.gitea.com>

Reviewed-on: https://gitea.com/gitea/act_runner/pulls/777
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: mkesper <mkesper@noreply.gitea.com>
Co-committed-by: mkesper <mkesper@noreply.gitea.com>
2025-12-26 00:38:38 +00:00
Christopher Homberger
c4b57fbcb2 chore(deps): upgrade dependencies (#775)
CI uses latest go 24, we may need a cron job after go updates.

Closes https://gitea.com/gitea/act_runner/issues/774

Reviewed-on: https://gitea.com/gitea/act_runner/pulls/775
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Christopher Homberger <christopher.homberger@web.de>
Co-committed-by: Christopher Homberger <christopher.homberger@web.de>
2025-12-20 23:35:15 +00:00
10 changed files with 282 additions and 33 deletions

View File

@@ -17,10 +17,10 @@ jobs:
goreleaser: goreleaser:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-go@v5 - uses: actions/setup-go@v6
with: with:
go-version-file: "go.mod" go-version-file: "go.mod"
- name: goreleaser - name: goreleaser
@@ -52,7 +52,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
with: with:
fetch-depth: 0 # all history for all branches and tags fetch-depth: 0 # all history for all branches and tags

View File

@@ -9,10 +9,10 @@ jobs:
goreleaser: goreleaser:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 # all history for all branches and tags fetch-depth: 0 # all history for all branches and tags
- uses: actions/setup-go@v5 - uses: actions/setup-go@v6
with: with:
go-version-file: "go.mod" go-version-file: "go.mod"
- name: Import GPG key - name: Import GPG key
@@ -46,7 +46,7 @@ jobs:
DOCKER_LATEST: latest DOCKER_LATEST: latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v6
with: with:
fetch-depth: 0 # all history for all branches and tags fetch-depth: 0 # all history for all branches and tags
@@ -69,7 +69,7 @@ jobs:
echo REPO_VERSION=${GITHUB_REF_NAME#v} >> $GITHUB_OUTPUT echo REPO_VERSION=${GITHUB_REF_NAME#v} >> $GITHUB_OUTPUT
- name: Build and push - name: Build and push
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile
@@ -83,7 +83,7 @@ jobs:
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }} ${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}
- name: Build and push dind - name: Build and push dind
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile
@@ -97,7 +97,7 @@ jobs:
${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}-dind ${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}-dind
- name: Build and push dind-rootless - name: Build and push dind-rootless
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ./Dockerfile file: ./Dockerfile

View File

@@ -8,8 +8,8 @@ jobs:
name: check and test name: check and test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- uses: actions/setup-go@v5 - uses: actions/setup-go@v6
with: with:
go-version-file: 'go.mod' go-version-file: 'go.mod'
- name: vet checks - name: vet checks

View File

@@ -1,7 +1,7 @@
### BUILDER STAGE ### BUILDER STAGE
# #
# #
FROM golang:1.24-alpine AS builder FROM golang:1.26-alpine AS builder
# Do not remove `git` here, it is required for getting runner version when executing `make build` # Do not remove `git` here, it is required for getting runner version when executing `make build`
RUN apk add --no-cache make git RUN apk add --no-cache make git

View File

@@ -1,13 +1,12 @@
DIST := dist DIST := dist
EXECUTABLE := act_runner EXECUTABLE := act_runner
GOFMT ?= gofumpt -l GOFMT ?= gofumpt -l
DIST := dist
DIST_DIRS := $(DIST)/binaries $(DIST)/release DIST_DIRS := $(DIST)/binaries $(DIST)/release
GO ?= go GO ?= go
SHASUM ?= shasum -a 256 SHASUM ?= shasum -a 256
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" ) HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
XGO_VERSION := go-1.24.x XGO_VERSION := go-1.26.x
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10 GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
LINUX_ARCHS ?= linux/amd64,linux/arm64 LINUX_ARCHS ?= linux/amd64,linux/arm64

View File

@@ -53,6 +53,9 @@
environment: environment:
- GITEA_INSTANCE_URL=<instance url> - GITEA_INSTANCE_URL=<instance url>
- DOCKER_HOST=unix:///var/run/user/1000/docker.sock - DOCKER_HOST=unix:///var/run/user/1000/docker.sock
# Use slirp4netns instead of vpnkit for significantly better network throughput.
- DOCKERD_ROOTLESS_ROOTLESSKIT_NET=slirp4netns
- DOCKERD_ROOTLESS_ROOTLESSKIT_MTU=65520
# When using Docker Secrets, it's also possible to use # When using Docker Secrets, it's also possible to use
# GITEA_RUNNER_REGISTRATION_TOKEN_FILE to pass the location. # GITEA_RUNNER_REGISTRATION_TOKEN_FILE to pass the location.
# The env var takes precedence. # The env var takes precedence.

8
go.mod
View File

@@ -1,8 +1,6 @@
module gitea.com/gitea/act_runner module gitea.com/gitea/act_runner
go 1.24.0 go 1.26.0
toolchain go1.24.11
require ( require (
code.gitea.io/actions-proto-go v0.4.1 code.gitea.io/actions-proto-go v0.4.1
@@ -23,6 +21,8 @@ require (
gotest.tools/v3 v3.5.1 gotest.tools/v3 v3.5.1
) )
require go.yaml.in/yaml/v4 v4.0.0-rc.2
require ( require (
cyphar.com/go-pathrs v0.2.1 // indirect cyphar.com/go-pathrs v0.2.1 // indirect
dario.cat/mergo v1.0.0 // indirect dario.cat/mergo v1.0.0 // indirect
@@ -102,7 +102,7 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
) )
replace github.com/nektos/act => gitea.com/gitea/act v0.261.7-0.20251202193638-5417d3ac6742 replace github.com/nektos/act => gitea.com/gitea/act v0.261.8
replace github.com/go-git/go-git/v5 => github.com/go-git/go-git/v5 v5.16.2 replace github.com/go-git/go-git/v5 => github.com/go-git/go-git/v5 v5.16.2

20
go.sum
View File

@@ -8,8 +8,8 @@ cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
gitea.com/gitea/act v0.261.7-0.20251202193638-5417d3ac6742 h1:ulcquQluJbmNASkh6ina70LvcHEa9eWYfQ+DeAZ0VEE= gitea.com/gitea/act v0.261.8 h1:rUWB5GOZOubfe2VteKb7XP3HRIbcW3UUmfh7bVAgQcA=
gitea.com/gitea/act v0.261.7-0.20251202193638-5417d3ac6742/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok= gitea.com/gitea/act v0.261.8/go.mod h1:lTp4136rwbZiZS3ZVQeHCvd4qRAZ7LYeiRBqOSdMY/4=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
@@ -51,8 +51,6 @@ github.com/docker/cli v25.0.3+incompatible h1:KLeNs7zws74oFuVhgZQ5ONGZiXUUdgsdy6
github.com/docker/cli v25.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v25.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v25.0.6+incompatible h1:5cPwbwriIcsua2REJe8HqQV+6WlWc1byg2QSXzBxBGg=
github.com/docker/docker v25.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v25.0.13+incompatible h1:YeBrkUd3q0ZoRDNoEzuopwCLU+uD8GZahDHwBdsTnkU= github.com/docker/docker v25.0.13+incompatible h1:YeBrkUd3q0ZoRDNoEzuopwCLU+uD8GZahDHwBdsTnkU=
github.com/docker/docker v25.0.13+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v25.0.13+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
@@ -229,12 +227,12 @@ go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s=
go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
@@ -248,8 +246,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -271,20 +267,16 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -11,7 +11,7 @@ import (
runnerv1 "code.gitea.io/actions-proto-go/runner/v1" runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
"github.com/nektos/act/pkg/model" "github.com/nektos/act/pkg/model"
"gopkg.in/yaml.v3" "go.yaml.in/yaml/v4"
) )
func generateWorkflow(task *runnerv1.Task) (*model.Workflow, string, error) { func generateWorkflow(task *runnerv1.Task) (*model.Workflow, string, error) {

View File

@@ -9,6 +9,7 @@ import (
runnerv1 "code.gitea.io/actions-proto-go/runner/v1" runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
"github.com/nektos/act/pkg/model" "github.com/nektos/act/pkg/model"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.yaml.in/yaml/v4"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
) )
@@ -62,13 +63,267 @@ jobs:
want1: "job9", want1: "job9",
wantErr: false, wantErr: false,
}, },
{
name: "no needs",
args: args{
task: &runnerv1.Task{
WorkflowPayload: []byte(`
name: Simple workflow
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: echo "hello"
`),
Needs: map[string]*runnerv1.TaskNeed{},
},
},
assert: func(t *testing.T, wf *model.Workflow) {
job := wf.GetJob("test")
assert.DeepEqual(t, job.Needs(), []string{})
assert.Equal(t, len(job.Steps), 2)
},
want1: "test",
wantErr: false,
},
{
name: "needs list",
args: args{
task: &runnerv1.Task{
WorkflowPayload: []byte(`
name: Workflow with list needs
on: push
jobs:
deploy:
needs: [build, test, lint]
runs-on: ubuntu-latest
steps:
- run: echo "deploying"
`),
Needs: map[string]*runnerv1.TaskNeed{
"build": {
Outputs: map[string]string{},
Result: runnerv1.Result_RESULT_SUCCESS,
},
"test": {
Outputs: map[string]string{
"coverage": "80%",
},
Result: runnerv1.Result_RESULT_SUCCESS,
},
"lint": {
Outputs: map[string]string{},
Result: runnerv1.Result_RESULT_FAILURE,
},
},
},
},
assert: func(t *testing.T, wf *model.Workflow) {
job := wf.GetJob("deploy")
needs := job.Needs()
assert.DeepEqual(t, needs, []string{"build", "lint", "test"})
assert.Equal(t, wf.Jobs["test"].Outputs["coverage"], "80%")
assert.Equal(t, wf.Jobs["lint"].Result, "failure")
},
want1: "deploy",
wantErr: false,
},
{
name: "workflow env and defaults",
args: args{
task: &runnerv1.Task{
WorkflowPayload: []byte(`
name: Complex workflow
on:
push:
branches: [main, develop]
pull_request:
types: [opened, synchronize]
env:
NODE_ENV: production
CI: "true"
jobs:
build:
runs-on: ubuntu-latest
env:
BUILD_TYPE: release
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "18"
- run: npm ci
- run: npm run build
`),
Needs: map[string]*runnerv1.TaskNeed{},
},
},
assert: func(t *testing.T, wf *model.Workflow) {
assert.Equal(t, wf.Name, "Complex workflow")
assert.Equal(t, wf.Env["NODE_ENV"], "production")
assert.Equal(t, wf.Env["CI"], "true")
job := wf.GetJob("build")
assert.Equal(t, len(job.Steps), 4)
},
want1: "build",
wantErr: false,
},
{
name: "job with container and services",
args: args{
task: &runnerv1.Task{
WorkflowPayload: []byte(`
name: Integration tests
on: push
jobs:
integration:
runs-on: ubuntu-latest
container:
image: node:18
services:
postgres:
image: postgres:15
steps:
- uses: actions/checkout@v3
- run: npm test
`),
Needs: map[string]*runnerv1.TaskNeed{},
},
},
assert: func(t *testing.T, wf *model.Workflow) {
job := wf.GetJob("integration")
container := job.Container()
assert.Equal(t, container.Image, "node:18")
assert.Equal(t, job.Services["postgres"].Image, "postgres:15")
},
want1: "integration",
wantErr: false,
},
{
name: "job with matrix strategy",
args: args{
task: &runnerv1.Task{
WorkflowPayload: []byte(`
name: Matrix build
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ["1.21", "1.22"]
steps:
- uses: actions/checkout@v3
- run: go test ./...
`),
Needs: map[string]*runnerv1.TaskNeed{},
},
},
assert: func(t *testing.T, wf *model.Workflow) {
job := wf.GetJob("test")
matrixes, err := job.GetMatrixes()
require.NoError(t, err)
assert.Equal(t, len(matrixes), 2)
},
want1: "test",
wantErr: false,
},
{
name: "special yaml characters in values",
args: args{
task: &runnerv1.Task{
WorkflowPayload: []byte("name: \"Special: characters & test\"\non: push\n\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: 'echo \"hello: world\"'\n - run: 'echo \"quotes & ampersands\"'\n - run: |\n echo \"multiline\"\n echo \"script\"\n"),
Needs: map[string]*runnerv1.TaskNeed{},
},
},
assert: func(t *testing.T, wf *model.Workflow) {
assert.Equal(t, wf.Name, "Special: characters & test")
job := wf.GetJob("test")
assert.Equal(t, len(job.Steps), 3)
},
want1: "test",
wantErr: false,
},
{
name: "invalid yaml",
args: args{
task: &runnerv1.Task{
WorkflowPayload: []byte(`
name: Bad workflow
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: echo "ok"
bad-indent: true
`),
Needs: map[string]*runnerv1.TaskNeed{},
},
},
assert: nil,
want1: "",
wantErr: true,
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got, got1, err := generateWorkflow(tt.args.task) got, got1, err := generateWorkflow(tt.args.task)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err) require.NoError(t, err)
tt.assert(t, got) tt.assert(t, got)
assert.Equal(t, got1, tt.want1) assert.Equal(t, got1, tt.want1)
}) })
} }
} }
func Test_yamlV4NodeRoundTrip(t *testing.T) {
t.Run("marshal sequence node", func(t *testing.T) {
node := yaml.Node{
Kind: yaml.SequenceNode,
Content: []*yaml.Node{
{Kind: yaml.ScalarNode, Value: "a"},
{Kind: yaml.ScalarNode, Value: "b"},
{Kind: yaml.ScalarNode, Value: "c"},
},
}
out, err := yaml.Marshal(&node)
require.NoError(t, err)
assert.Equal(t, string(out), "- a\n- b\n- c\n")
})
t.Run("unmarshal and re-marshal workflow", func(t *testing.T) {
input := []byte("name: test\non: push\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - run: echo hello\n")
var wf map[string]interface{}
err := yaml.Unmarshal(input, &wf)
require.NoError(t, err)
assert.Equal(t, wf["name"], "test")
out, err := yaml.Marshal(wf)
require.NoError(t, err)
var wf2 map[string]interface{}
err = yaml.Unmarshal(out, &wf2)
require.NoError(t, err)
assert.Equal(t, wf2["name"], "test")
})
t.Run("node kind constants", func(t *testing.T) {
// Verify yaml/v4 node kind constants are usable (same API as v3)
require.NotEqual(t, yaml.ScalarNode, yaml.SequenceNode)
require.NotEqual(t, yaml.SequenceNode, yaml.MappingNode)
})
}