Debug Github Actions locally with Act

GitHub Actions is a tool that allows developers to automate workflows related to their GitHub repositories. With GitHub Actions, developers can build, test, and deploy their code directly from GitHub. While GitHub Actions can be very useful, they can also be difficult to debug when things go wrong. When an action fails, it can be challenging to figure out what went wrong and how to fix it, since they can only run on Github, and you end up sending mock commits one after another to iterate through bugfixes. Moreover, it can be costly, as Github Actions are billed per minute. In this post, I will talk about a tool called Act, which allows developers to run Github Actions locally on your machine.

What are Github Actions?

Github Actions is a tool (system) developed by Microsoft to make day-to-day development tasks easier. It allows CI/CD (Continuous Integration/Continuous Deployment) integration with existing Github workflows. One of the main benefits of GitHub Actions is that it is very easy to set up and get started with, even for developers who are new to CI/CD systems. In addition to its simplicity, GitHub Actions is also relatively inexpensive compared to other CI/CD tools, making it a good choice for developers who are working on a budget. Another advantage of GitHub Actions is its strong community of users and developers, who can provide support and guidance when working with the tool. Overall, GitHub Actions is a powerful and user-friendly CI/CD system that is well-suited to developers of all skill levels. On the image above you can see the typical steps in a CI/CD system.


Why are they hard to debug?

Debugging and developing GitHub Actions can be challenging, especially for developers who are new to the tool. One of the main difficulties of working with GitHub Actions is that it can be difficult to run and debug actions locally, as they are executed on cloud servers. This can make it hard to test and troubleshoot actions before they are deployed, as developers must rely on logs and other remote debugging techniques. This can be especially frustrating for developers who are used to being able to run and test their code locally. They may find themselves pushing empty commits to trigger pipelines to run and fail again, thus wasting valuable time and resources.

If only we could run these actions locally! This would make them so much easier to develop and debug, while making it cheaper at the same time. Luckily for us, there exists just the tool to do this: act.


How does Act work?

Act is a CLI tool, written in Go, which closely mimics Github Actions’ own behavior Act reads in the GitHub Actions defined in the .github/workflows/ directory and determines which actions need to be run based on the dependencies defined in the workflow files. To execute these actions, act uses the Docker API to pull or build the necessary images, as specified in the workflow files. Once the images are prepared, act determines the execution path based on the dependencies and then uses the Docker API to run containers for each action based on the prepared images. This process closely mirrors the way that GitHub Actions are executed, with the environment variables and filesystem configured to match the GitHub environment. Overall, act provides a convenient way for developers to test and debug their GitHub Actions locally before deploying them.


How to install Act

Before installing Act, you need to make sure your system meets the prerequisites. Act relies on Docker, so you need to make sure you have it installed and have docker command available in your terminal. You can follow these instructions on how to install Docker on your system: Windows, Linux, macOS.

After installing Docker, you can proceed to install act. Here are the instructions based on the platform of your choice:

Linux (AUR):

yay -Syu act

Linux (COPR):

dnf copr enable rubemlrm/act-cli
dnf install act-cli

Linux (NIX):

nix-env -iA nixpkgs.act

Linux/macOS (Bash script):

curl <https://raw.githubusercontent.com/nektos/act/master/install.sh> | sudo bash

macOS (Homebrew):

brew install act

macOS (MacPorts):

port install act

Windows (Chocolatey):

choco install act-cli

Windows (Scoop):

scoop install act

If none of these work for you, you can always download a binary and put in your PATH.

These instructions are retrieved in early 2023, and may become outdated. Refer to the project repo for updates.


How to use Act

To run your Github Action locally, navigate into your project folder (where .github/workflows is located and run:

$ act

That is it! By default, it will run your push action. To view all available actions, you can run:

$ act -l

To run a specific action, run:

$ act <ACTION NAME>

When you run Act for the first time, you will be prompted to choose a Docker image for your runner. Read their descriptions and choose one depending on how complex your workflows are. I chose β€œmicro” for my basic JS testing workflow. This is the output I got when running act on my React project:

[Node.js CI/build] πŸš€  Start image=node:16-buster-slim
[Node.js CI/build]   🐳  docker pull image=node:16-buster-slim platform= username= forcePull=false
[Node.js CI/build]   🐳  docker create image=node:16-buster-slim platform= entrypoint=["tail" "-f" "/dev/null"] cmd=[]
[Node.js CI/build]   🐳  docker run image=node:16-buster-slim platform= entrypoint=["tail" "-f" "/dev/null"] cmd=[]
[Node.js CI/build]   ☁  git clone '<https://github.com/actions/setup-node>' # ref=v1
[Node.js CI/build] πŸ§ͺ  Matrix: map[node-version:18.x]
Node.js CI/build] ⭐ Run Main actions/checkout@v2
[Node.js CI/build]   🐳  docker cp src=/home/mk/Documents/Projects/react-sandbox/. dst=/home/mk/Documents/Projects/react-sandbox
[Node.js CI/build]   βœ…  Success - Main actions/checkout@v2
[Node.js CI/build] ⭐ Run Main Use Node.js 18.x
[Node.js CI/build]   🐳  docker cp src=/home/mk/.cache/act/actions-setup-node@v1/ dst=/var/run/act/actions/actions-setup-node@v1/
[Node.js CI/build]   🐳  docker exec cmd=[node /var/run/act/actions/actions-setup-node@v1/dist/index.js] user= workdir=
[Node.js CI/build]   πŸ’¬  ::debug::isExplicit:
[Node.js CI/build]   πŸ’¬  ::debug::explicit? false
[Node.js CI/build]   πŸ’¬  ::debug::evaluating 0 versions
[Node.js CI/build]   πŸ’¬  ::debug::match not found
[Node.js CI/build]   πŸ’¬  ::debug::evaluating 553 versions
[Node.js CI/build]   πŸ’¬  ::debug::matched: v18.12.1
[Node.js CI/build]   πŸ’¬  ::debug::isExplicit: 18.12.1
[Node.js CI/build]   πŸ’¬  ::debug::explicit? true
[Node.js CI/build]   πŸ’¬  ::debug::checking cache: /opt/hostedtoolcache/node/18.12.1/x64
[Node.js CI/build]   πŸ’¬  ::debug::not found
[Node.js CI/build]   πŸ’¬  ::debug::Downloading <https://nodejs.org/dist/v18.12.1/node-v18.12.1-linux-x64.tar.gz>
[Node.js CI/build]   πŸ’¬  ::debug::Destination /tmp/1dd90780-7651-4890-b0f5-5bac82fa4228
[Node.js CI/build]   πŸ’¬  ::debug::download complete
[Node.js CI/build]   πŸ’¬  ::debug::Checking tar --version
[Node.js CI/build]   πŸ’¬  ::debug::tar (GNU tar) 1.30%0ACopyright (C) 2017 Free Software Foundation, Inc.%0ALicense GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.%0AThis is free software: you are free to change and redistribute it.%0AThere is NO WARRANTY, to the extent permitted by law.%0A%0AWritten by John Gilmore and Jay Fenlason.
[Node.js CI/build]   πŸ’¬  ::debug::Caching tool node 18.12.1 x64
[Node.js CI/build]   πŸ’¬  ::debug::source dir: /tmp/a6b40c33-d3ce-43a7-b507-023e90ab51c4/node-v18.12.1-linux-x64
[Node.js CI/build]   πŸ’¬  ::debug::destination /opt/hostedtoolcache/node/18.12.1/x64
[Node.js CI/build]   πŸ’¬  ::debug::finished caching tool
| [command]/opt/hostedtoolcache/node/18.12.1/x64/bin/node --version
| v18.12.1
| [command]/opt/hostedtoolcache/node/18.12.1/x64/bin/npm --version
| 8.19.2
[Node.js CI/build]   ❓  ##[add-matcher]/run/act/actions/actions-setup-node@v1/.github/tsc.json
[Node.js CI/build]   ❓  ##[add-matcher]/run/act/actions/actions-setup-node@v1/.github/eslint-stylish.json
[Node.js CI/build]   ❓  ##[add-matcher]/run/act/actions/actions-setup-node@v1/.github/eslint-compact.json
[Node.js CI/build]   βœ…  Success - Main Use Node.js 18.x
[Node.js CI/build]   βš™  ::add-path:: /opt/hostedtoolcache/node/18.12.1/x64/bin
[Node.js CI/build] ⭐ Run Main npm ci
[Node.js CI/build]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/2] user= workdir=
| npm WARN deprecated [email protected]: Use your platform's native performance.now() and performance.timeOrigin.
| npm WARN deprecated [email protected]: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
| npm WARN deprecated [email protected]: Please use @jridgewell/sourcemap-codec instead
| npm WARN deprecated [email protected]: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility>
| npm WARN deprecated [email protected]: This SVGO version is no longer supported. Upgrade to v2.x.x.
|
| added 1467 packages, and audited 1468 packages in 55s
|
| 227 packages are looking for funding
|   run `npm fund` for details
|
| 6 high severity vulnerabilities
|
| To address all issues (including breaking changes), run:
|   npm audit fix --force
|
| Run `npm audit` for details.
[Node.js CI/build]   βœ…  Success - Main npm ci
[Node.js CI/build] ⭐ Run Main npm run build --if-present
[Node.js CI/build]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/3] user= workdir=
|
| > [email protected] build
| > react-scripts build
|
| Creating an optimized production build...
| Compiled successfully.
|
| File sizes after gzip:
|
|   46.61 kB  build/static/js/main.56dd61fd.js
|   1.79 kB   build/static/js/787.60ffb363.chunk.js
|   541 B     build/static/css/main.073c9b0a.css
|
| The project was built assuming it is hosted at /.
| You can control this with the homepage field in your package.json.
|
| The build folder is ready to be deployed.
| You may serve it with a static server:
|
|   npm install -g serve
|   serve -s build
|
| Find out more about deployment here:
|
|   <https://cra.link/deployment>
|
[Node.js CI/build]   βœ…  Success - Main npm run build --if-present
[Node.js CI/build] ⭐ Run Main npm test
[Node.js CI/build]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/4] user= workdir=
|
| > [email protected] test
| > react-scripts test
|
|  PASS  src/App.test.js
|   βœ“ renders learn react link (37 ms)
|
Test Suites: 1 passed, 1 total
| Tests:       1 passed, 1 total
| Snapshots:   0 total
| Time:        1.856 s
| Ran all test suites.
[Node.js CI/build]   βœ…  Success - Main npm test
[Node.js CI/build] 🏁  Job succeeded

You can see that Act successfully read my YAML file and ran basic JS tests in a docker container.

You can also add your Github Actions variables and secrets to Act to complete your testing. Just put them in .env file (for variables) and .secrets file (for secrets) like this:

SOME_API_KEY=ABCDEF
ANOTHER_API_KEY=XYZ

Pros & Cons

Act is a wonderful tool for many reasons:

  • It is much easier, faster, and cheaper to debug Github Actions locally before pushing them to the server
  • Act works out-of-the-box with no additional configuration
  • Mimics Github Actions behavior precisely

However, Act has a few shortcomings that may prevent some developers from using its full potential:

  • Very large Docker image sizes; the full image that aims to provide all Github Actions features weighs 20+GB
  • Cannot use custom containers feature; Github allows you to use custom Docker containers for yous jobs; you cannot do this with Act
  • Cannot use non-linux containers; Github allows you to use Windows containers for your jobs, and Act cannot do that
  • Act does not support Docker Context, so any jobs that rely on that will not work
  • Github Actions Services are not supported; any job that uses those will fail

Conclusion

Act shows much promise, but it is still in early stages of development and it is hard to see how it can be used beyond the most basic Github Actions in hobby projects. I will follow closely the development of Act for more exiting features and parity with the mainstream Actions. I hope you enjoyed the read, and please let me know in the comment what do you think about Act!

Get new content delivered to your mailbox:

leave a comment