Skip to content

Commit db9a610

Browse files
committed
docs: add tutorial on running GitHub Actions locally with act
Explains using act to run the existing docker-build.yml workflow (job: build) locally before pushing. Notes act cannot run the windows-build.yml job. Verified locally with act -j build — job succeeded.
1 parent 6e0f6c4 commit db9a610

2 files changed

Lines changed: 142 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ See **[BUILDING.md](BUILDING.md)** for CMake configuration, Docker usage (includ
227227
- [Memory Error Detection with AddressSanitizer and Valgrind](docs/memory_leaking_valgrind.md)
228228
- [Generating and Debugging Dump File](docs/generating_and_debugging_dump_file.md)
229229
- [Static analysis and linting with clang-tidy](docs/clang_tidy.md)
230+
- [Running GitHub Actions locally with `act` (test CI before you push)](docs/run_github_actions_locally_with_act.md)
230231

231232
## Data File Storage Parsing
232233

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Running GitHub Actions Locally with `act`
2+
3+
Push, wait for GitHub, watch it fail, fix, push again — that loop is slow.
4+
[`act`](https://github.com/nektos/act) runs your **existing** GitHub Actions
5+
workflows on your own machine inside Docker, using the **same
6+
`.github/workflows/*.yml` files** — no extra config, no duplicated scripts.
7+
Get it green locally, *then* push.
8+
9+
> This is the plain, standard tool most developers use. There is nothing to
10+
> customize: `act` reads the workflow you already have.
11+
12+
---
13+
14+
## 1. Prerequisite: Docker
15+
16+
`act` runs each job in a container, so Docker must be installed and running:
17+
18+
```bash
19+
docker --version # must succeed
20+
docker ps # daemon must be up
21+
```
22+
23+
If Docker isn't installed, see https://docs.docker.com/engine/install/.
24+
25+
---
26+
27+
## 2. Install `act`
28+
29+
Pick whichever fits your setup — they all install the same tool:
30+
31+
```bash
32+
# a) One-line install script (Linux/macOS) → installs to ./bin or a path you give
33+
curl -sSL https://raw.githubusercontent.com/nektos/act/master/install.sh | bash -s -- -b ~/.local/bin
34+
35+
# b) As a GitHub CLI extension (if you already have `gh`)
36+
gh extension install nektos/gh-act # then run it as: gh act ...
37+
38+
# c) Package managers
39+
brew install act # macOS / Linuxbrew
40+
# Arch: sudo pacman -S act
41+
# Windows (choco): choco install act-cli
42+
```
43+
44+
Verify:
45+
46+
```bash
47+
act --version
48+
```
49+
50+
---
51+
52+
## 3. First run: choose an image size
53+
54+
The **first** time you run `act`, it asks which runner image to use. Pick
55+
**Medium** — it's the standard `catthehacker/ubuntu` image that has git, curl,
56+
build-essential, etc. (The choice is saved to `~/.actrc`.)
57+
58+
```
59+
? Please choose the default image you want to use with act:
60+
- Large (~17GB, closest to GitHub's runner)
61+
> Medium (~500MB, has the common tools) ← choose this
62+
- Micro (~200MB, node only)
63+
```
64+
65+
---
66+
67+
## 4. Everyday commands
68+
69+
```bash
70+
act -l # list the jobs act found in .github/workflows
71+
act # run the default event (push) — runs all matching jobs
72+
act -j build # run ONE job by id (recommended)
73+
act pull_request # simulate a pull_request event instead of push
74+
act -n # dry run: print the plan, execute nothing
75+
act -v # verbose, when something misbehaves
76+
```
77+
78+
### For THIS repo
79+
80+
The CI here builds inside Docker (`docker-build.yml`, job id **`build`**,
81+
runner `ubuntu-24.04`):
82+
83+
```bash
84+
act -j build
85+
```
86+
87+
`act` automatically shares your host's Docker daemon with the job, so the
88+
workflow's own `docker build ...` steps work without extra flags.
89+
90+
---
91+
92+
## 5. The workflow: green locally → push
93+
94+
```bash
95+
act -j build # 1. run CI locally
96+
# ...fix anything that fails, repeat until green...
97+
git add -A && git commit -m "..."
98+
git push # 2. push only once it passed locally
99+
```
100+
101+
That's the whole idea — no scripts, no hooks required.
102+
103+
### Optional: make it automatic before every push
104+
105+
If you want the check to run on its own, add a one-line Git `pre-push` hook.
106+
This is optional; `act` on its own is already enough.
107+
108+
```bash
109+
cat > .git/hooks/pre-push <<'EOF'
110+
#!/usr/bin/env bash
111+
act -j build || { echo "❌ local CI failed — push aborted"; exit 1; }
112+
EOF
113+
chmod +x .git/hooks/pre-push
114+
```
115+
116+
Bypass it any time with `git push --no-verify`.
117+
118+
---
119+
120+
## 6. Good to know (limitations)
121+
122+
- **`act` ≈ GitHub, not identical.** It uses `catthehacker` images, not
123+
GitHub's exact runner image. Close enough to catch the vast majority of
124+
failures; for maximum parity choose the **Large** image.
125+
- **Linux jobs only.** `act` cannot run `windows-latest` or `macos-latest`
126+
jobs. This repo's `windows-build.yml` therefore **cannot** run under `act`
127+
only the Linux `docker-build.yml` job does.
128+
- **First run is slow** — it pulls the runner image (and here, builds the
129+
project's Docker image). Later runs reuse cached layers and are much faster.
130+
- **Secrets:** pass them with `act -s NAME=value` or `--secret-file` if a
131+
workflow needs them (this repo's build doesn't).
132+
133+
---
134+
135+
## TL;DR
136+
137+
```bash
138+
docker ps # Docker running?
139+
act -l # what jobs exist?
140+
act -j build # run CI locally → green? then git push
141+
```

0 commit comments

Comments
 (0)