gacils - GitHub Actions CI Local Simulator

Run your GitHub Actions workflows locally with Docker β including matrix jobs, parallel execution, service containers, cache, artifacts, and automatic secrets masking.
β¨ Why gacils?
| Problem |
gacils Solution |
| Waiting for GitHub runners |
Local Docker execution |
| Paying for CI minutes |
100% free |
| Slow iteration |
Instant feedback |
| Matrix testing pain |
Full matrix expansion |
| Secrets in logs |
Automatic masking |
| No local cache |
Host-mapped cache |
π Features
Core Execution
- Docker Isolation: Runs job steps inside isolated Docker containers using offical or custom images.
- Workspace Context: Mounts your local project repository directly into container environments (
/github/workspace).
- Multi-Step Execution: Executes sequential
run steps, uses actions, and inline shell commands.
Workflow Logic
- Matrix Expansion: Full support for
strategy.matrix, including include and exclude combinations.
- Job DAG & Dependencies: Inter-job dependency resolution (
needs) running independent jobs concurrently in parallel goroutines.
- Conditional Execution: Evaluates
if expressions at job and step levels (e.g. success(), failure(), always()).
- Timeouts & Controls: Per-job step timeout enforcement and failure handling (
continue-on-error).
Expression Engine
- Context Access: Expression parsing for
github, matrix, env, vars, secrets, steps, needs, and job.
- Built-in Functions: Supports
contains(), startsWith(), endsWith(), format(), join(), toJSON(), fromJSON(), hashFiles(), etc.
- Operators & Precedence: Complete logical, equality, and relational operators respecting standard evaluation order.
Actions Ecosystem
- Local Action Runner: Native emulation for popular actions like
actions/checkout, actions/setup-python, actions/cache, and actions/upload-artifact/download-artifact.
- Composite Actions: Supports executing local or remote composite actions.
Infrastructure
- Service Containers: Runs background service containers (PostgreSQL, Redis, MySQL, etc.) linked over custom Docker bridge networks.
- Health Checking: Automatic container health inspection (
test, interval, timeout, retries) before step execution.
- Lifecycle & Cleanup: Reliable cleanup of created networks and containers upon workflow completion or interruption.
Security & UX
- Automatic Secrets Masking: Length-descending secret replacement engine preventing partial leakage in terminal logs.
- Rich Error Hints: Actionable troubleshooting suggestions for YAML syntax, missing context keys, or Docker errors.
- CI Exit Codes: Accurate process exit codes reflecting overall workflow execution results.
π¦ Installation
From Source
go install github.com/0n6k4v-Coder/github-action-ci-local-simulator/cmd/gacils@latest
From Binary Release
Download the pre-compiled binary for your operating system and architecture from the Releases page and place it in your PATH.
Prerequisites
π§ WSL2 + Docker Desktop Support
gacils v1.3.1+ fully supports WSL2 with Docker Desktop integration.
Installation on WSL2
# Install Go (if not already installed)
sudo apt-get update
sudo apt-get install -y golang-go
# Install gacils
go install github.com/0n6k4v-Coder/github-action-ci-local-simulator/cmd/gacils@latest
# Verify installation
gacils --version
Running on WSL2
gacils automatically detects the correct Docker socket path on WSL2.
No manual configuration required:
cd /path/to/your/repo
gacils run -W .github/workflows/ci.yml
How It Works
gacils uses Docker SDK's FromEnv pattern which:
- Reads
DOCKER_HOST environment variable if set
- Falls back to Docker context inspection
- Automatically detects WSL2 socket paths:
~/.docker/desktop/docker.sock
/mnt/wsl/docker-desktop/docker.sock
- Also works with Linux native Docker (
/var/run/docker.sock)
Troubleshooting
If you encounter Docker connection issues on WSL2:
- Verify Docker Desktop is running and WSL2 integration is enabled
- Check Docker context:
docker context ls
- Verify socket exists:
ls -la ~/.docker/desktop/docker.sock
- If needed, manually set DOCKER_HOST:
export DOCKER_HOST="unix://$(docker context inspect --format '{{.Endpoints.docker.Host}}' | sed 's|unix://||')"
| Platform |
Status |
Notes |
| Linux (native Docker) |
β
Full support |
Default socket: /var/run/docker.sock |
| WSL2 + Docker Desktop |
β
Full support |
Auto-detects WSL2 socket paths |
| macOS + Docker Desktop |
β οΈ Untested |
Should work with /var/run/docker.sock |
| Windows (native) |
β Not supported |
Requires WSL2 |
π― Quick Start
-
Navigate to your repository:
cd /path/to/your/repo
-
Verify your workflow file:
Ensure you have a workflow defined at .github/workflows/ci.yml.
-
Run gacils:
gacils run
π Usage
gacils [command] [flags]
Commands:
run Run GitHub Actions workflows locally
Flags:
-w, --workflow string Path to target workflow file (default ".github/workflows")
-j, --job string Run specific job by ID
-s, --secret string Provide secret in KEY=VAL format (can be specified multiple times)
--env string Provide environment variable in KEY=VAL format
--dry-run Validate and print execution plan without running containers
-h, --help Help for gacils
CLI Flags
| Flag |
Short |
Description |
Default |
--workflow |
-W |
Path to workflow file or directory |
.github/workflows/ |
--job |
-j |
Run only the specified job |
(all jobs) |
--dry-run |
|
Print execution plan without running |
false |
--offline |
|
Skip image pulls, use local images only |
false |
--parallel |
-p |
Max concurrent jobs (0 = unlimited) |
0 |
--platform |
|
Docker platform for image pulls |
(host platform) |
--crlf |
|
Line ending handling: convert, preserve, error |
convert |
Examples
Run default workflows:
gacils run
Run a specific job with secrets:
gacils run -j test -s DB_PASSWORD=supersecret -s API_KEY=xyz123
Dry-run validation:
gacils run --dry-run
π¬ Example Workflows
1. Matrix Build with Parallel Jobs
name: CI Matrix Build
on: [push]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ['1.21', '1.22']
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
- name: Run Tests
run: go test -v ./...
2. Service Containers with Secrets Masking
name: Integration Tests
on: [push]
jobs:
integration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: ${{ secrets.DB_PASS }}
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Run Database Migration
env:
DB_PASS: ${{ secrets.DB_PASS }}
run: |
echo "Connecting to DB with secret key: $DB_PASS"
go run ./cmd/migrate
β οΈ Limitations
- JavaScript Actions Execution: Only NodeJS runtime actions are emulated or executed inside containers; complex JS actions relying on GitHub API tokens may require local overrides.
- GitHub Hosted Runner Architecture: macOS and Windows native host execution are not supported; jobs run inside Linux Docker containers.
- GitHub API Context: Contexts requiring remote GitHub API calls (e.g.
github.event.pull_request.labels) are simulated using mock or local git metadata.
πΊοΈ Roadmap
- Complete GitHub Event Payload Generator
- Interactive UI / Terminal Dashboard (
tui)
- Support for reusable workflows (
jobs.<job_id>.uses)
- Pre-built runner image caching engine
π€ Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature)
- Commit your changes (
git commit -m 'feat: add amazing feature')
- Push to the branch (
git push origin feature/amazing-feature)
- Open a Pull Request
π License
Distributed under the MIT License. See LICENSE for more information.
π Acknowledgments