Apr 15, 2022

Run GitHub Actions Locally — Notes on act

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.

nektos/act GitHub Repository

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.

Reference: https://github.com/nektos/act/wiki/Beginner's-guide#using-event-file-to-provide-complete-event-payload

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.