How do I quickly test github workflows on my local dev machine even for self-hosted runners?
Write-up also at https://juliusgamanyi.com/2022/04/27/run-github-actions-workflows-locally-using-act
I’m spending more time recently working with GitHub actions and runners.
I’ve found it helpful to test the GitHub Actions workflows on my local dev machine to get quick feedback and to also not populate my git histoy with “fix” commits.
Prerequisite: I have docker running on my machine
- Download and configure
actand test initial run
- Clone the repo https://github.com/juliusgb/til
actto use non-default docker image with env vars and secrets
actfor self-hosted runners
actwith debug to see what
Download and Configure act
Download act from the https://github.com/nektos/act/releases or clone the repo.
act --dryrun so that
act creates its default config file in
$HOME/.actrc. Since I’m using windows, I’ll use the file path separator.
act --dryrun --workflows .github\workflows\test-ci.yml --verbose --list
$HOME/.actrc, these default entries should exist:
1 2 3 -P ubuntu-latest=ghcr.io/catthehacker/ubuntu:act-latest -P ubuntu-20.04=ghcr.io/catthehacker/ubuntu:act-20.04 -P ubuntu-18.04=ghcr.io/catthehacker/ubuntu:act-18.04
Configure act to use non-default docker image with env vars and secrets
The images that
act used are listed in a table - https://github.com/nektos/act#runners. What does that table mean?
In a workflow file, say my markdown-lint.yml, the job definition looks like this:
1 2 3 4 . . . jobs: lint: runs-on: ubuntu-latest
runs-on tag tells the runner to use the
ubuntu-latest image when executing the job.
When running the job locally,
act has to somehow know which docker image to use when it sees the
ubuntu-latest in the workflow yml file.
- This mapping exists in the
ubuntu-latesttag points to the docker image
In a simplified way,
act does the following:
- reads the workflow yml
- finds that the job should run on
- looks up its config, sees
ubuntu-latestis mapped to
- somehow prepares
- runs the workflow yml job on
If I’d like to use another docker image, then I update the
act config file,
$HOME/.actrc, and add the following entry:
1 -P ubuntu-latest=localhost:5000/my-awesome-docker-image:0.1.0
act will run the workflow on docker image
Setup for self-hosted runners
If I’m using self-hosted runners, then the job definition in the workflow yml would look like this:
1 2 3 4 . . . jobs: prep: runs-on: [self-hosted, my-awesome-runner]
Then I update the
act config file,
$HOME/.actrc and add the following entries:
1 2 -P self-hosted=localhost:5000/myawesomeselfhostedrunner:0.2.0 -P my-awesome-runner=localhost:5000/myawesomeselfhostedrunner:0.2.0
act runs, it will this docker image.
If I want to run a custom
runs-on tag against the
act default images, replacing the above, i.e.,
ghcr.io/catthehacker/ubuntu:act-latest would also work:
1 2 -P self-hosted=ghcr.io/catthehacker/ubuntu:act-latest -P my-awesome-runner=ghcr.io/catthehacker/ubuntu:act-latest
Run act with debug to see more details
--verbose option to see more details on what
act is doing when listing the jobs available in the workflow yml file.
- I’ve added a
.secretsfile in case some GitHub Actions require a token to do something. To avoid accidentally committing these, add them to
- There’s also an .env file.
The CLI options are also documented at https://github.com/nektos/act#configuration. Since I’m running the code from the cloned
til repo directory, the paths to
run-github-actions-workflow-locally-with-act.secrets work for me. Adjust them as needed.
act --env-file github-actions\run-github-actions-workflows-locally-with-act.env --secret-file github-actions\run-github-actions-workflow-locally-with-act.secrets --workflows .github\workflows\test-ci.yml --verbose --list
The output would look like this:
|Stage||Job ID||Job name||Workflow name||Workflow file||Events|
Run a specific job (remove
--dryrun and add
act --env-file github-actions\run-github-actions-workflows-locally-with-act.env --secret-file github-actions\run-github-actions-workflow-locally-with-act.secrets --workflows .github\workflows\test-ci.yml --verbose --job prep
Run when a specific event (such as
push) occurs on the repository:
act --env-file github-actions\run-github-actions-workflows-locally-with-act.env --secret-file github-actions\run-github-actions-workflow-locally-with-act.secrets --workflows .github\workflows\test-ci.yml --verbose push
Output looks like: