Written by Andrew Evans✏️
The act project is a powerful tool that you can use with GitHub Actions to quickly test and refine a continuous integration and continuous delivery (CI/CD) pipeline. With act, you can use Docker containers locally to directly run steps in GitHub Actions. act helps developers run independent stages in a pipeline, and it generally improves the feedback loop whenever you’re building pipelines with GitHub Actions.
In this article, we’ll introduce act in a sample project, install it, and then cover the different ways that act can improve your experience building and testing GitHub Actions. To follow along, check out my sample project on GitHub. Let’s get started!
Jump ahead:
What are GitHub Actions?
Before we begin working with act, we should have a basic understanding of how GitHub Actions work. Similar to CI/CD tools like CircleCI, Jenkins, and more, GitHub Actions allow you to define a pipeline in a YAML file. GitHub will then run your pipeline on specific events, which could include opening a pull request or merging into the master branch.
GitHub Actions’ syntax looks like the following:
name: Node.js CI
'on':
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js 16.x
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: npm
- run: npm install
- run: npm run build
In the example above, a GitHub Action is defined with a build job that checks out your code, does an npm install, and builds the project. You could have additional jobs that are reliant on this one, but the steps can also be their own actions. For example, if you wanted to cache the node modules, you could just add the following code:
- run: npm install
- run: npm run build
- name: Cache node modules
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: >-
${{ runner.os }}-build-${{ env.cache-name }}-${{
hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
The actions/cache@v3 is its own action that is run as a step in this pipeline. You can also build out these actions. For example, by enabling them in your GitHub repo, you can run CI/CD on pushes to master and other events. In GitHub, this looks like the following:
You can drill down into the different stages and even see a history of the actions as they run. In the GitHub Actions documentation, there is a detailed definition of this syntax; I recommend checking it out.
In the next sections, we’ll learn how to do all of this locally instead of having to rely on the GitHub console and events to test out our pipeline.
How do you use act?
act acts as a CLI on your local machine, supporting Linux, Mac, and Windows. I work on a Mac, so I used brew to install act with the following command:
brew install act
To learn more about the installation, check out the instructions in the GitHub repo.
Once you have act installed, using it is easy. Inside the .github folder in your repo, call the CLI directly with act from a terminal inside a project that has a GitHub action YAML file setup. If you don’t have GitHub Actions set up yet, click the actions option at the top of your GitHub project, and GitHub will walk you through creating a starter YAML file:
There are a lot of different options, but I found the following to be the most useful:
# List all the actions in your YAML file
act -l
# List actions for a specific event (here the event is push)
act push -l
# Get Act to run the workflow as if a specific push to master event occured
act push
# Get Act to run a specific job
act -j test
# pass secrets into a job so that the GitHub action can consume them
act -s MY_TOKEN_SECRET=<token> -s MY_NETLIFY_SITE_ID=<site_id>
# run a GitHub action that uses artifacts between jobs
act --artifact-server-path /tmp/artifacts push
When these commands run, act builds a Docker container to run your GitHub actions inside. The images listed on the act GitHub project include the following:
If your GitHub Action job specifies an image to use, it will pull the image and run it in the act container to do the work.
Seeing act in action
As I stated in the intro, I used a sample project with Act to test out some of the features. The project is a very simple, basic to-do list app with React. I included one test that I could create a stage in the pipeline for, and I also included a stage to deploy to Netlify.
The code below represents the actual YAML file that I built for the GitHub Actions in this project:
name: Node.js CI
'on':
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js 16.x
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: npm
- run: npm install
- run: npm run build
- name: Cache node modules
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: >-
${{ runner.os }}-build-${{ env.cache-name }}-${{
hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
- name: Archive production