When building a new GitHub Action, repeatedly testing on GitHub is slow. With act you can validate locally to some extent and then run it on GitHub.
Installation
Requires a Docker environment.
On macOS:
brew install act
If Go is installed (non‑Mac as well):
go install github.com/nektos/act@latest
On Apple Silicon (M1/M2), pass --container-architecture linux/amd64
.
You may hit this yarn issue:
Specify a platform with -P/--platform
; as in the issue, -P ubuntu-latest=ghcr.io/catthehacker/ubuntu:js-latest
allowed yarn to run.
Put these in ~/.actrc
so you don’t have to type them every time:
--container-architecture linux/amd64
-P ubuntu-latest=ghcr.io/catthehacker/ubuntu:js-latest
Basic usage
With no args, act runs workflows triggered by push:
act
To trigger a pull_request
workflow:
act pull_request
List workflows for an event
Add -l/--list
after the event:
act pull_request -l
Stage Job ID Job name Workflow name Workflow file Events
0 helloworld helloworld Hello World helloworld.yaml pull_request
Run a specific workflow
Use -W/--workflows
to point to a file:
act -W .github/workflows/helloworld.yaml pull_request
Simulate merging a Pull Request locally
Create a test workflow that prints “hello world” on merge (.github/workflows/helloworld.yaml
):
name: Hello World
on:
pull_request:
types: [closed]
jobs:
hello-world:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- run: echo "Hello World!"
Running locally now fails because the event payload is missing:
act -W .github/workflows/helloworld.yaml pull_request
Error: ❌ Error in if-expression: "if: github.event.pull_request.merged == true" (Unable to dereference 'merged' on non-struct 'invalid')
Work around this by providing an event JSON via -e/--eventpath
.
cat pull_request.json
{
"pull_request": {
"merged": true
}
}
act -W .github/workflows/helloworld.yaml pull_request -e pull_request.json
[Hello World/hello-world] 🚀 Start image=ghcr.io/catthehacker/ubuntu:js-latest
...
| Hello World!
[Hello World/hello-world] ✅ Success - echo "Hello World!"
If you change merged
to false in pull_request.json
, it won’t run.