Setting Up GitHub Actions Locally and Quickly
Posted on by Gentaro "hibariya" Terada
In software development, a feedback loop that takes time and effort could be a major bottleneck. Especially if we have to run things on remote servers and figuring out what's going on requires lots of effort, debugging could make frustrations. Today, I'm going to introduce a couple of tools that help to debug GitHub Actions workflows from local machines.
Act
With act command, you can run workflows on your local machine. Once you run act
command it reads YAML files under .github/workflows
and runs the jobs in Docker containers immediately. We can make sure if there's any major problem in the YAML without making commit and pushing to GitHub. Although act
does not provide 100% compatible environment with GitHub Actions, it helps a lot when you start writing workflow settings. For example, it is useful to find any errors and mistakes in the YAML file structure, dependencies between jobs, calling actions, and steps written in shell scripts.
Besides, act
could be used as a task runner for your local machine instead of repeating similar task definitions for another tool like make
. CJ Avilla and I are trying to use act
that way (stripe-samples/sample-ci#6).
You can tell how great act
is by reading its README. In this article, I'd like to share things to be careful I encountered.
Checkout and PAT
When defining jobs, usually actions/checkout
is necessary to check out source code. Since it requires GitHub personal access token (PAT), you have to pass the token as a secret no matter the repository is private/public. act
reads .secrets
file by default. The easiest way to pass the secret is to create it like below:
GITHUB_TOKEN=...
Differences and Workarounds
Act's built-in images do not have several packages/commands out of the box. For example, there is no sudo
, and no Docker. To make the steps on a job compatible with both GitHub Actions and act, some tricky changes might be needed. Act provides a special environment variable ACT
. You can use it to tell whether the running environment is act
or not like this:
if [ -n "$ACT" ]; then
# https://docs.docker.com/engine/install/debian/
# https://docs.docker.com/compose/install/
curl -fsSL https://get.docker.com | sh -
curl -L "https://github.com/docker/compose/releases/download/1.28.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
fi
docker-compose build...
Also, there is an alternative runner image that corresponding GitHub runner.
Running with Docker Daemon which Enables User Namespace Remapping
If you running Docker daemon with user namespace options for security reasons, fixing file permissions problem, or other reasons; perhaps act
needs additional --userns=host
option because of the user namespaces’ limitations. Since act
uses Docker with host network mode, the containers cannot be run remapping user namespace. Without disabling remapping, you will stumble upon error messages as follows:
Error: Error response from daemon: cannot share the host's network namespace when user namespaces are enabled
User namespace remapping can be disabled temporarily by passing --userns=host
when creating a container. I got this error when I tried to run act
on my computer for the first time and sent a patch to support that option.
action-tmate
Although act
is useful, sometimes we want to know what's going on in the actual running environment. It's great if there's a way to connect to the environment with ssh
like Circle CI or Travis CI. action-tmate is an action for this purpose.
Tmate allows you to share terminal sessions. mxschmitt/action-tmate provides a way to debug jobs via SSH using Tmate. All you have to do is call this action around the step you need to investigate and you will be able to connect to the environment with ssh
.
- name: Setup tmate session
uses: mxschmitt/action-tmate@v3
if: ${{ always() }}
if: ${{ always() }}
will be necessary if some of the steps before the action-tmate step are failing. Without it, the following steps of the failing step won't run. Also, you will have to pass sudo: false
option if the environment does not have sudo
. See the README.md for more details.
About the Combination with Act
action-tmate does not work in act
out of the box. As mentioned, the built-in images of act
are not 100% compatible with the one that GitHub Actions provides. However, probably Tmate is not necessary when you run jobs locally with act
in the first place. You can just insert sleep
and start a shell in the container like docker exec CONTAINER_ID /bin/bash
.