act for testing Github Action locally
Following my previous article about GitHub Actions, here is a new one that will explain how to locally test your Actions. Unlike the good old Jenkins on which you can copy/paste your pipeline code in a test job and run it (that’s dirty but it works), GitHub Actions requires to always commit and push your changes and wait for the runner to take it. When you’re like me and using a die and retry development process, it’s a waste of time.
Yep, that’s my way to do things, I’m more practice than theory - Daffy Duck © Warner Bros
To answer this problem, I’ve found and tested act, a community tool that allow to run locally a GitHub Actions workflow. Act is based on Docker API, and require it, and uses Ubuntu images installed as GitHub do it for its own runners (environments variables and filesystem are the same). However, it’s a limited tool as it can’t run a Windows or macOS-based runner and some Actions may not work as the default images does not contains all the tools GitHub Actions offers. However, you can still use alternative runners images.
The test material
For this article, I’ve made a quick and dirty test repository that contains an empty Hugo website that will be built and published on GitHub Pages by an Actions workflow.
The workflow is available in the .github/workflows/build_and_publish_site.yml
file and is very simple : checkout the repository, use a community Hugo setup action, build the site, and use a community GitHub Page publish Action.
BTW, I’ve was surprised to see there is no official GitHub Actions for a built-in service like Pages…
## this workflow build and publish the Hugo website
name: 'Build and Publish hugo website'
on:
push:
branches:
- master
workflow_dispatch:
jobs:
hugo:
runs-on: ubuntu-latest
steps:
- name: 'Checkout code'
uses: actions/checkout@v3
with:
submodules: true
fetch-depth: 0
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.97.0'
- name: Build
run: hugo
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: ${{ github.ref == 'refs/heads/master' }}
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
While testing it, this sample workflow became an ideal example for act
usage because I’ve had a failure and tried two options. So let’s test it locally and see if it’s working in my container.
Installation with Podman
To install act
on Linux, I’ve simply downloaded the latest Linux tgz release and unpacked it in my /usr/local/bin
folder.
However, as a Fedora user, I don’t have Docker installed but Podman. Act is clear : Podman is not officially supported, but you can still use it thanks to a few tricks. I’ll let you read the debates in the linked issue, that’s not the purpose of this article and I’ll go straight to the point : I’ve made the following alias in my profile.
alias act='systemctl enable --now --user podman.socket && export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock && act --bind --container-daemon-socket $XDG_RUNTIME_DIR/podman/podman.sock'
And voilà.
Running a Workflow
Reload your environment and go to a repository clone where you have a workflow (in my case, this article example workflow) and try it like this :
act -W .github/workflows/build_and_publish_site.yml
? Please choose the default image you want to use with act:
- Large size image: +20GB Docker image, includes almost all tools used on GitHub Actions (IMPORTANT: currently only ubuntu-18.04 platform is available)
- Medium size image: ~500MB, includes only necessary tools to bootstrap actions and aims to be compatible with all actions
- Micro size image: <200MB, contains only NodeJS required to bootstrap actions, doesn't work with all actions
Default image and other options can be changed manually in ~/.actrc (please refer to https://github.com/nektos/act#configuration for additional information about file structure) [Use arrows to move, type to filter, ? for more help]
Large
> Medium
Micro
You’ll notice a question about the image size. I’ve used the medium one.
You’ll also notice the runner is setup in debug mode by default, very helpful. And after a test run, I see I have the same issue as in the official runner (that’s normal, it’s hugo
failing, not a GitHub tool).
[Build and Publish hugo website/hugo] 🐳 docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/2] user= workdir=
| Start building sites …
| hugo v0.97.0-c07f3626e7c8160943591f4d209977efa02c3dca linux/amd64 BuildDate=2022-04-14T08:45:07Z VendorInfo=gohugoio
Error: Error building site: TOCSS: failed to transform "ananke/css/main.css" (text/css). Check your Hugo installation; you need the extended version to build SCSS/SASS.: this feature is not available in your current Hugo version, see https://goo.gl/YMrWcn for more information
| Total in 495 ms
[Build and Publish hugo website/hugo] ❌ Failure - Build
[Build and Publish hugo website/hugo] exit with `FAILURE`: 255
Error: Job 'hugo' failed
I think that’s just because at a time I’ve added the --minify
option and now it’s failing because the Hugo installation is not the extended one and the Ananke theme looks like to require it in some cases. Let’s try to modify the workflow locally by adding the extended: true
setting the the Hugo setup action.
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.97.0'
extended: true
Let’s fire it again !
act -W .github/workflows/build_and_publish_site.yml
[Build and Publish hugo website/hugo] 🐳 docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/2] user= workdir=
| Start building sites …
| hugo v0.97.0-c07f3626e7c8160943591f4d209977efa02c3dca+extended linux/amd64 BuildDate=2022-04-14T08:45:07Z VendorInfo=gohugoio
| | EN
| -------------------+-----
| Pages | 7
| Paginator pages | 0
| Non-page files | 0
| Static files | 2
| Processed images | 0
| Aliases | 0
| Sitemaps | 1
| Cleaned | 0
|
| Total in 65 ms
[Build and Publish hugo website/hugo] ✅ Success - Build
Perfect ! But …
[Build and Publish hugo website/hugo] 🐳 docker exec cmd=[node /var/run/act/actions/peaceiris-actions-gh-pages@v3/lib/index.js] user= workdir=
| [INFO] Usage https://github.com/peaceiris/actions-gh-pages#readme
[Build and Publish hugo website/hugo] ❓ ::group::Dump inputs
(...)
[Build and Publish hugo website/hugo] ❓ ::endgroup::
[Build and Publish hugo website/hugo] ❗ ::error::Action failed with "Cannot read properties of undefined (reading 'fork')"
[Build and Publish hugo website/hugo] ❌ Failure - Deploy
I think that’s because the workflow is supposed to use the secrets.GITHUB_TOKEN
secret value. If your not familiar with GitHub Actions, the GITHUB_TOKEN
is a token generated during runtime used for read and write on the repository with the required grants. As act
is a local process, no token was generated, so maybe it’s an authentication issue ?
Using secrets
To try answer this issue, you’ll need to use a Personal Access Token from your account and give it to act
. You’ll need at least the repo
scope (well, I suppose, the GitHub token scopes are sometimes very cryptic, sometimes too large or too small, if you ask me…).
Now, call back the command and add this option :
act -W .github/workflows/build_and_publish_site.yml -s GITHUB_TOKEN
You’ll be prompted with the expected value. It is possible to give it directly inline like -s GITHUB_TOKEN=mytoken
but it’s strongly not recommended as the token may be written in your history. You can also use a file that contain the secrets in the format KEY=VALUE
and provide it like this : --secret-file my-secret-file.txt
.
However, after adding the token, it looks like the issue is not an authentication problem. But the previous issue is locally fixed, so now we can try in the actual Actions runner and see how is it going.
I’ve committed the fixed workflow and pushed it on GitHub, the workflow is triggered by the Push action on the master
branch. And it’s a success !
Neat !
Let’s check the test site.
Neat ! (bis)
So I think the problem I’ve encountered locally is more a compatibility issue than a workflow design. BTW, about the GITHUB_TOKEN
, there was still an error because the Action explains to use the personal_token
variable instead of github_token
when using one. However, it didn’t work, so it seems to be another issue.
Conclusion
act is a nice tool that permit to test and learn GitHub Actions without throwing hundreds of commits in your history (of course, a squash commits merge strategy fix this problem) and without waiting for the workflow to start. It has its limitations, so in case of doubts, try the live version.