Run your GitHub Actions locally!
GHA enables you to execute GitHub Actions workflows on your local machine using Docker containers. This provides fast feedback during development and allows you to use GitHub Actions as a local task runner, eliminating the need to commit and push changes just to test your workflows.
- Fast Feedback - Test workflow changes locally without committing to GitHub
- Local Development - Debug actions and workflows in your development environment
- Task Runner - Use GitHub Actions workflows as a replacement for Makefiles
- Consistent Environment - Run the same containers and environment variables as GitHub's hosted runners
- Offline Development - Work on workflows without internet connectivity
- Quick Start
- Installation
- Basic Usage
- Commands Reference
- Configuration
- Advanced Features
- Examples
- Troubleshooting
- Development
GHA reads your GitHub Actions workflows from .github/workflows/ and determines which actions need to run. It uses the Docker API to pull or build the necessary images as defined in your workflow files, then executes containers for each action. The environment variables and filesystem are configured to match what GitHub provides in their hosted runners.
- Prerequisites: Ensure Docker is installed and running on your system
- Install GHA: Download the latest binary or build from source (see Installation)
- Navigate to your repository:
cd your-repo-with-github-actions - Run a workflow:
gha push(or any event name from your workflows)
# Example: Run workflows triggered by push event
gha push
# Run a specific job
gha push -j build
# Run with secrets
gha push -s GITHUB_TOKEN=your_tokenCreate .github/workflows/ci.yml:
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '18'
- run: npm install
- run: npm test
build:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- run: echo "Building application..."
- run: echo "Build complete!"Then run it locally:
# Run all jobs for push event
gha push
# Run only the test job
gha push -j test
# Run with file watching (re-run on changes)
gha push --watchDownload the latest release from the releases page:
# Linux/macOS
curl -L https://github.com/Leapfrog-DevOps/gha/releases/latest/download/gha-linux-amd64 -o gha
chmod +x gha
sudo mv gha /usr/local/bin/Prerequisites:
- Go 1.24+ (installation guide)
- Git
- Docker
Build steps:
# Clone the repository
git clone https://github.com/Leapfrog-DevOps/gha.git
cd gha
# Run tests
make test
# Build and install
make installgha --versionGHA automatically detects workflows in .github/workflows/ and runs them based on event triggers:
# Run workflows triggered by 'push' event (default)
gha push
# Run workflows triggered by 'pull_request' event
gha pull_request
# If only one event exists, you can omit the event name
gha
# Auto-detect the first event type
gha --detect-eventUse the -j flag to run a specific job by ID:
# Run only the 'build' job
gha push -j build
# Run only the 'test' job from pull_request workflows
gha pull_request -j test# Pass secrets via command line
gha push -s GITHUB_TOKEN=ghp_xxxx -s API_KEY=secret123
# Load secrets from file (.secrets)
echo "GITHUB_TOKEN=ghp_xxxx" > .secrets
echo "API_KEY=secret123" >> .secrets
gha push --secret-file .secrets
# Prompt for secret value (secure input)
gha push -s GITHUB_TOKEN# Pass environment variables
gha push --env NODE_ENV=production --env DEBUG=true
# Load from .env file
echo "NODE_ENV=production" > .env
echo "DEBUG=true" >> .env
gha push --env-file .env# Pass variables (similar to GitHub repository variables)
gha push --var ENVIRONMENT=staging --var VERSION=1.0.0
# Load from .vars file
gha push --var-file .varsAutomatically re-run workflows when files change:
# Watch for file changes and re-run
gha push --watch
# Watch with specific job
gha push -j test --watch# Validate workflow syntax
gha --validate
# Strict validation (more rigorous checks)
gha --validate --strict# Run from different directory
gha push --directory /path/to/repo
# Use workflows from different path
gha push --workflows /path/to/workflows
# Disable recursive workflow search
gha push --no-recursegha [event name] [flags]
If no event name is provided, GHA defaults to "push" or uses the only available event if there's just one.
| Flag | Short | Description | Example |
|---|---|---|---|
--job |
-j |
Run specific job ID | gha push -j build |
--list |
-l |
List available workflows | gha --list |
--graph |
-g |
Show workflow dependency graph | gha --graph |
--watch |
-w |
Watch files and re-run on changes | gha push --watch |
--validate |
Validate workflow files | gha --validate |
|
--strict |
Use strict workflow validation | gha --validate --strict |
| Flag | Short | Description | Example |
|---|---|---|---|
--secret |
-s |
Set secret values | gha push -s TOKEN=abc123 |
--var |
Set variable values | gha push --var ENV=prod |
|
--env |
Set environment variables | gha push --env DEBUG=true |
|
--input |
Set action inputs | gha push --input version=1.0 |
|
--secret-file |
Load secrets from file | gha push --secret-file .secrets |
|
--var-file |
Load variables from file | gha push --var-file .vars |
|
--env-file |
Load environment from file | gha push --env-file .env |
|
--input-file |
Load inputs from file | gha push --input-file .input |
| Flag | Short | Description | Example |
|---|---|---|---|
--workflows |
-W |
Path to workflow files | gha push -W ./custom/workflows |
--directory |
-C |
Working directory | gha push -C /path/to/repo |
--no-recurse |
Don't search subdirectories for workflows | gha push --no-recurse |
|
--eventpath |
-e |
Path to event JSON file | gha push -e event.json |
| Flag | Short | Description | Example |
|---|---|---|---|
--platform |
-P |
Custom platform images | gha push -P ubuntu-20.04=custom:latest |
--pull |
-p |
Force pull Docker images (default: true) | gha push --pull |
--rebuild |
Force rebuild local actions (default: true) | gha push --rebuild |
|
--bind |
-b |
Bind working directory instead of copy | gha push --bind |
--reuse |
-r |
Reuse containers between runs | gha push --reuse |
--privileged |
Run containers in privileged mode | gha push --privileged |
|
--container-architecture |
Set container architecture | gha push --container-architecture linux/amd64 |
|
--container-options |
Custom container options | gha push --container-options "--memory=2g" |
| Flag | Short | Description | Example |
|---|---|---|---|
--verbose |
-v |
Verbose output | gha push --verbose |
--quiet |
-q |
Disable step output logging | gha push --quiet |
--json |
Output logs in JSON format | gha push --json |
|
--log-prefix-job-id |
Use job ID in log prefix | gha push --log-prefix-job-id |
|
--dryrun |
-n |
Validate without running containers | gha push --dryrun |
| Flag | Description | Example |
|---|---|---|
--actor |
User that triggered the event (default: "Leapfrog-DevOps/gha") | gha push --actor username |
--defaultbranch |
Name of the default branch | gha push --defaultbranch main |
--remote-name |
Git remote name for repo URL | gha push --remote-name upstream |
--github-instance |
GitHub instance URL (for Enterprise) | gha push --github-instance github.company.com |
--use-gitignore |
Respect .gitignore when copying files | gha push --use-gitignore |
--matrix |
Include specific matrix combinations | gha push --matrix os:ubuntu-20.04 |
--artifact-server-path |
Enable artifact server with storage path | gha push --artifact-server-path ./artifacts |
--network |
Docker network name | gha push --network custom-network |
The gha actions command provides GitHub API integration for managing workflows, runs, and logs.
# List all workflows in the repository
gha actions list
# List workflow runs
gha actions runs [workflow-id]
# Show jobs for a workflow run
gha actions jobs <run-id>
# Show logs for a workflow run
gha actions logs <run-id>
# Show detailed run information
gha actions show <run-id>
# Watch runs in real-time
gha actions watch [workflow-id]
# Rerun a workflow
gha actions rerun <run-id>
# Trigger a workflow manually
gha actions trigger <workflow-name># List workflows using flags
gha actions --list
# List runs using flags
gha actions --runs
gha actions --runs-for workflow-id
# Show run details using flags
gha actions --show run-id
gha actions --jobs run-id
gha actions --logs run-id
# Watch and manage using flags
gha actions --watch
gha actions --rerun run-id
gha actions --trigger workflow-name# Limit number of runs displayed
gha actions runs --limit 20
# Filter by status
gha actions runs --status completed
# Filter by branch
gha actions runs --branch main
# Show logs for specific job
gha actions logs run-id --job job-name
# Show raw logs without formatting
gha actions logs run-id --raw
# Rerun only failed jobs
gha actions rerun run-id --failed-only
# Trigger on specific branch
gha actions trigger workflow-name --ref feature-branchThe actions commands require GitHub authentication. Set your token via:
# Environment variable
export GITHUB_TOKEN=ghp_xxxxxxxxxxxx
# Or use gh CLI authentication
gh auth login
# Or pass token directly (not recommended for security)
gha actions list -s GITHUB_TOKEN=ghp_xxxxxxxxxxxxNote: For more authentication options, see the Configuration section.
GHA includes an OIDC (OpenID Connect) server for testing cloud provider integrations locally. This is particularly useful for testing AWS authentication in GitHub Actions.
# Start OIDC server with ngrok forwarding
gha oidc start
# Start with custom domain (command line)
gha oidc start --domain my-custom-domain.ngrok.io
# Or configure domain in .gharc for persistent use
echo "--domain my-custom-domain.ngrok.io" >> .gharc
gha oidc start
# Check server status
gha oidc status
# Stop OIDC server
gha oidc stop
# Restart server (keeps ngrok running)
gha oidc restart# Setup AWS OIDC identity provider and IAM role
gha oidc setup --provider aws --role-name gha-test-role
# This creates:
# - OIDC Identity Provider in AWS IAM
# - IAM Role with trust policy for your OIDC provider
# - Outputs role ARN for use in workflowsExample workflow using AWS OIDC:
name: Test AWS OIDC
on: push
jobs:
test-aws:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/gha-test-role
aws-region: us-east-1
- run: aws sts get-caller-identityNote: Currently only AWS provider is supported for OIDC setup. Azure and GCP support may be added in future versions.
# Remove AWS OIDC setup
gha oidc cleanup --provider aws --role-name gha-test-role
# This removes:
# - IAM Role
# - OIDC Identity ProviderWhen the OIDC server is running, GHA automatically sets these environment variables in your workflows:
ACTIONS_ID_TOKEN_REQUEST_URL- OIDC token endpointACTIONS_ID_TOKEN_REQUEST_TOKEN- Request token for authenticationGITHUB_ACTIONS=true- Indicates GitHub Actions environment
-
ngrok: Required for exposing local OIDC server to cloud providers
# Download from https://ngrok.com/download # Authenticate ngrok (free account required) ngrok authtoken YOUR_AUTHTOKEN
-
AWS CLI: Required for AWS OIDC setup commands
# AWS CLI aws configure
Tip: For troubleshooting OIDC issues, see the Troubleshooting section.
# List all available workflows and jobs
gha --list
# Show workflow dependency graph
gha --graph
# List workflows for specific event
gha pull_request --list
# Show graph for specific event
gha push --graphExample output of gha --list:
Job ID Job name Stage Workflow name Workflow file Events
build build 0 CI ci.yml push,pull_request
test test 1 CI ci.yml push,pull_request
deploy deploy 2 CI ci.yml push
# Basic validation
gha --validate
# Strict validation with enhanced checks
gha --validate --strict
# Validate specific workflow file
gha --validate --workflows ./custom/workflow.yml
# Dry run - validate without executing
gha push --dryrun# Generate bug report with system information
gha --bug-report
# Show version information
gha --version
# List all available command options in JSON format
gha --list-options
# Generate manual page
gha --man-pageExample bug report output includes:
- GHA version and build info
- Operating system details
- Docker configuration
- Available socket locations
- Configuration files in use
# Show main help
gha --help
# Show help for actions commands
gha actions --help
# Show help for OIDC commands
gha oidc --help
# Show help for specific subcommand
gha actions --helpGHA supports configuration files to avoid repeating command-line flags. Configuration files are searched in this order:
~/.config/gha/gharc(XDG config directory)~/.gharc(home directory)./.gharc(current directory)
Configuration files contain command-line flags, one per line:
# .gharc example
--platform ubuntu-20.04=custom:latest
--secret-file .secrets
--env-file .env
--verbose
--pull
--actor myusernameNote: Flags with spaces in values should be quoted or use separate lines for each flag and value.
Development Configuration:
# .gharc for development
--verbose
--bind
--reuse
--env-file .env.local
--secret-file .secrets.localCI/Production Configuration:
# .gharc for CI
--pull
--rebuild
--json
--quiet
--container-architecture linux/amd64Custom Platform Configuration:
# .gharc with custom images
--platform ubuntu-latest=myregistry/ubuntu:latest
--platform node:16=myregistry/node:16-custom
--platform python:3.9=myregistry/python:3.9-customOIDC Configuration:
# .gharc with custom ngrok domain for OIDC
--domain my-custom-domain.ngrok.io
--artifact-server-path ./artifacts| Variable | Description | Example |
|---|---|---|
DOCKER_HOST |
Docker daemon socket | unix:///var/run/docker.sock |
DOCKER_CERT_PATH |
Docker TLS certificate path | /path/to/certs |
DOCKER_TLS_VERIFY |
Enable Docker TLS verification | 1 |
| Variable | Description | Example |
|---|---|---|
GITHUB_TOKEN |
GitHub personal access token | ghp_xxxxxxxxxxxx |
GITHUB_REPOSITORY |
Repository name | owner/repo |
GITHUB_ACTOR |
GitHub username | username |
| Variable | Description | Default |
|---|---|---|
GHA_CACHE_DIR |
Action cache directory | ~/.cache/gha |
GHA_CONFIG_DIR |
Configuration directory | ~/.config/gha |
GHA_LOG_LEVEL |
Log level (debug, info, warn, error) | info |
# .secrets file format
GITHUB_TOKEN=ghp_xxxxxxxxxxxx
API_KEY=secret123
DATABASE_PASSWORD=supersecret# .vars file format
ENVIRONMENT=production
VERSION=1.0.0
REGION=us-east-1# .env file format
NODE_ENV=production
DEBUG=false
PORT=3000# .input file format (for action inputs)
version=1.0.0
environment=staging
deploy=trueGHA also supports YAML format for configuration files:
# .secrets.yml
GITHUB_TOKEN: ghp_xxxxxxxxxxxx
API_KEY: secret123
# .vars.yml
ENVIRONMENT: production
VERSION: 1.0.0
# .env.yml
NODE_ENV: production
DEBUG: falseOverride default runner images with custom ones:
# Use custom Ubuntu image
gha push --platform ubuntu-latest=myregistry/ubuntu:custom
# Use multiple custom platforms
gha push \
--platform ubuntu-20.04=myregistry/ubuntu:20.04 \
--platform node:16=myregistry/node:16-alpine \
--platform python:3.9=myregistry/python:3.9-slimConfiguration file example:
# .gharc
--platform ubuntu-latest=myregistry/ubuntu:latest
--platform node:16=myregistry/node:16-customRun specific matrix combinations:
# Run specific matrix combination
gha push --matrix os:ubuntu-20.04 --matrix node:16
# Run multiple matrix combinations
gha push --matrix os:ubuntu-20.04 --matrix os:macos-latestExample workflow with matrix:
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-22.04, macos-latest]
node: [14, 16, 18]# Use local repository instead of remote
gha push --local-repository actions/checkout@v4=/path/to/local/checkout
# Multiple local repositories
gha push \
--local-repository actions/checkout@v4=/path/to/checkout \
--local-repository actions/setup-node@v3=/path/to/setup-nodemy-action/
├── action.yml # Action metadata
├── Dockerfile # For Docker actions
├── index.js # For JavaScript actions
└── README.md
Example action.yml:
name: 'My Local Action'
description: 'A custom local action'
inputs:
message:
description: 'Message to display'
required: true
runs:
using: 'docker'
image: 'Dockerfile'# Custom container options
gha push --container-options "--memory=2g --cpus=2"
# Privileged mode (use with caution)
gha push --privileged
# Custom user namespace
gha push --userns host
# Add/drop kernel capabilities
gha push --container-cap-add SYS_PTRACE --container-cap-drop NET_RAW# Force specific architecture (useful for M1 Macs)
gha push --container-architecture linux/amd64
# Use ARM64 architecture
gha push --container-architecture linux/arm64# Use custom Docker network
gha push --network my-custom-network
# Use host networking
gha push --network host# Enable artifact server with storage path
gha push --artifact-server-path ./artifacts
# Custom artifact server address and port
gha push \
--artifact-server-path ./artifacts \
--artifact-server-addr 0.0.0.0 \
--artifact-server-port 8080# Enable cache server
gha push --cache-server-path ./cache
# Custom cache server configuration
gha push \
--cache-server-path ./cache \
--cache-server-addr 0.0.0.0 \
--cache-server-port 9000
# External cache server URL (behind proxy)
gha push --cache-server-external-url https://cache.example.com# Use GitHub Enterprise Server
gha push --github-instance github.company.com
# Replace GHE actions with GitHub.com actions
gha push \
--github-instance github.company.com \
--replace-ghe-action-with-github-com actions/checkout \
--replace-ghe-action-token-with-github-com ghp_token_for_github_com# Reuse containers between runs (faster subsequent runs)
gha push --reuse
# Bind working directory (faster file access)
gha push --bind# Limit concurrent jobs (default: number of CPUs)
gha push --concurrent-jobs 2
# Unlimited concurrent jobs
gha push --concurrent-jobs 0# Use new action cache system
gha push --use-new-action-cache
# Offline mode (don't fetch actions if cached)
gha push --action-offline-mode
# Custom action cache path
gha push --action-cache-path /custom/cache/path# Use custom event JSON file
gha push --eventpath event.jsonExample event.json:
{
"ref": "refs/heads/main",
"repository": {
"name": "my-repo",
"full_name": "owner/my-repo"
},
"pusher": {
"name": "username"
}
}# Set custom actor (user who triggered event)
gha push --actor myusername
# Set default branch name
gha push --defaultbranch main
# Set git remote name
gha push --remote-name upstream# .github/workflows/nodejs.yml
name: Node.js CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
env:
NODE_ENV: test
- name: Upload coverage
uses: actions/upload-artifact@v3
with:
name: coverage-${{ matrix.node-version }}
path: coverage/
build:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: dist
path: dist/Run locally:
# Run all jobs
gha push
# Run specific matrix combination
gha push --matrix node-version:18
# Run with custom environment
gha push --env NODE_ENV=development# .github/workflows/docker.yml
name: Docker Build
on:
push:
branches: [ main ]
tags: [ 'v*' ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: myapp/myimage
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}Run locally:
# Run with Docker secrets
gha push -s DOCKER_USERNAME=myuser -s DOCKER_PASSWORD=mypass
# Or use secrets file
echo "DOCKER_USERNAME=myuser" > .secrets
echo "DOCKER_PASSWORD=mypass" >> .secrets
gha push --secret-file .secrets# .github/workflows/multi-platform.yml
name: Multi-Platform
on: [push]
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: Build
run: go build -v ./...
- name: Test
run: go test -v ./...Run locally (Linux/macOS only):
# Run Ubuntu jobs only
gha push --matrix os:ubuntu-latest
# Use custom platform image
gha push --platform ubuntu-latest=ubuntu:22.04# Setup for development
echo "--bind" >> .gharc
echo "--reuse" >> .gharc
echo "--verbose" >> .gharc
# Run tests on file changes
gha push -j test --watch
# Quick validation
gha --validate --strict# Test full pipeline
gha push
# Test specific deployment job
gha push -j deploy --env ENVIRONMENT=staging
# Test with production secrets
gha push --secret-file .secrets.prod# Test local action
gha push --local-repository ./my-action@v1=./local-action
# Test with different inputs
gha push --input version=1.0.0 --input debug=true# Test all matrix combinations
gha push
# Test specific combinations
gha push --matrix os:ubuntu-20.04 --matrix node:16
gha push --matrix python-version:3.9# Verbose output with dry run
gha push --verbose --dryrun
# Debug with custom event
gha push --eventpath debug-event.json --verbose
# Test with minimal environment
gha push --env-file .env.minimalProblem: Cannot connect to the Docker daemon
Solutions:
# Check if Docker is running
docker ps
# Check Docker socket permissions (Linux)
sudo chmod 666 /var/run/docker.sock
# Use custom Docker socket
gha push --container-daemon-socket unix:///custom/docker.sock
# Check Docker host environment variable
echo $DOCKER_HOSTProblem: Permission denied while trying to connect to Docker
Solutions:
# Add user to docker group (Linux)
sudo usermod -aG docker $USER
# Then logout and login again
# Or run with sudo (not recommended)
sudo gha pushProblem: Architecture compatibility issues on Apple Silicon
Solutions:
# Force AMD64 architecture
gha push --container-architecture linux/amd64
# Add to .gharc for permanent fix
echo "--container-architecture linux/amd64" >> ~/.gharcProblem: Workflow file is invalid
Solutions:
# Validate workflow syntax
gha --validate
# Use strict validation for detailed errors
gha --validate --strict
# Check specific workflow file
gha --validate --workflows .github/workflows/problematic.ymlProblem: Action 'owner/action@version' not found
Solutions:
# Force pull latest actions
gha push --pull
# Rebuild local actions
gha push --rebuild
# Use offline mode if action is cached
gha push --action-offline-mode
# Check action reference in workflow file
# Ensure correct owner/repo@version formatProblem: Cannot pull Docker images or actions
Solutions:
# Check internet connectivity
ping github.com
# Use custom network
gha push --network host
# Configure Docker proxy (if behind corporate firewall)
# Edit ~/.docker/config.jsonProblem: Out of memory or disk space errors
Solutions:
# Limit concurrent jobs
gha push --concurrent-jobs 1
# Clean up Docker resources
docker system prune -a
# Use custom container options
gha push --container-options "--memory=1g --cpus=1"
# Check available disk space
df -hProblem: Permission denied accessing files in container
Solutions:
# Use bind mount instead of copy
gha push --bind
# Check file permissions
ls -la .github/workflows/
# Ensure files are readable
chmod +r .github/workflows/*# Generate comprehensive bug report
gha --bug-report
# Check GHA version
gha --version
# List configuration files in use
gha --bug-report | grep "Config files"# Enable verbose output
gha push --verbose
# JSON formatted logs (for parsing)
gha push --json
# Disable step output (quiet mode)
gha push --quiet
# Show job ID in logs instead of full name
gha push --log-prefix-job-id# Validate without running containers
gha push --dryrun
# Combine with verbose for detailed validation
gha push --dryrun --verbose# Check Docker system info
docker system info
# Check available Docker images
docker images
# Check running containers
docker ps
# Check Docker logs
docker logs <container_id># Check environment variables in workflow
gha push --env DEBUG=true
# Print all environment variables in step
# Add this step to your workflow:
- name: Debug Environment
run: env | sort- Operating System: Linux, macOS, or Windows with WSL2
- Docker: Version 20.10+
- Memory: 2GB RAM minimum, 4GB+ recommended
- Disk Space: 5GB+ for Docker images and action cache
- Network: Internet connection for pulling actions and images
- Linux: x86_64, ARM64
- macOS: Intel and Apple Silicon (M1/M2)
- Windows: WSL2 with Docker Desktop
Recommended Docker settings:
- Memory: 4GB+
- CPU: 2+ cores
- Disk: 20GB+ for images
Docker Desktop settings (macOS/Windows):
{
"memoryMiB": 4096,
"cpus": 2,
"diskSizeMiB": 20480
}-
Use Container Reuse:
gha push --reuse
-
Enable Bind Mounting:
gha push --bind
-
Limit Concurrent Jobs:
gha push --concurrent-jobs 2
-
Use Action Caching:
gha push --action-offline-mode
-
Custom Platform Images:
# Use smaller, optimized images gha push --platform ubuntu-latest=ubuntu:20.04
# Monitor Docker resource usage
docker stats
# Monitor system resources
top
htop
# Check disk usage
du -sh ~/.cache/gha
du -sh /var/lib/docker- GitHub Issues: Report bugs and request features
- Discussions: Ask questions and share tips
- Documentation: Official documentation
- Check existing issues: Search for similar problems
- Generate bug report: Run
gha --bug-report - Provide minimal reproduction: Include workflow file and command used
- Include system information: OS, Docker version, GHA version
# System information
gha --bug-report
# Docker information
docker version
docker system info
# Workflow validation
gha --validate --strict
# Verbose output
gha push --verbose --dryrun- Go: Version 1.24+ (installation guide)
- Docker: Version 20.10+ (installation guide)
- Git: For version control
- Make: For build automation (usually pre-installed on Linux/macOS)
# Clone the repository
git clone https://github.com/Leapfrog-DevOps/gha.git
cd gha
# Install dependencies
go mod tidy
# Verify setup
go version
docker --version
make --version# Run tests
make test
# Format code
make format
# Lint code
make lint
# Build binary
make build
# Install locally
make install
# Run all checks (format, lint, test)
make prgha/
├── cmd/ # Command implementations
│ ├── root.go # Main command and flags
│ ├── actions.go # GitHub Actions API commands
│ ├── oidc.go # OIDC server commands
│ ├── list.go # Workflow listing
│ └── graph.go # Workflow visualization
├── pkg/ # Core packages
│ ├── common/ # Shared utilities
│ ├── container/ # Docker integration
│ ├── model/ # Workflow models
│ ├── runner/ # Workflow execution
│ ├── gh/ # GitHub API client
│ └── artifacts/ # Artifact handling
├── main.go # Application entry point
├── Makefile # Build automation
├── go.mod # Go module definition
└── VERSION # Version information
Command Layer (cmd/):
root.go: Main CLI interface and flag definitionsactions.go: GitHub API integration for workflow managementoidc.go: OIDC server for cloud provider authentication
Core Logic (pkg/):
runner/: Workflow execution enginemodel/: Workflow parsing and planningcontainer/: Docker container managementcommon/: Shared utilities and helpers
# Enable debug logging
export GHA_LOG_LEVEL=debug
# Use custom cache directory
export GHA_CACHE_DIR=/tmp/gha-cache
# Use custom Docker socket
export DOCKER_HOST=unix:///custom/docker.sockVS Code (.vscode/settings.json):
{
"go.lintTool": "golangci-lint",
"go.formatTool": "goimports",
"go.testFlags": ["-v"],
"go.buildFlags": ["-v"]
}GoLand/IntelliJ:
- Enable Go modules support
- Configure golangci-lint as external tool
- Set up run configurations for tests### T esting
# Run all tests
make test
# Run tests with verbose output
go test -v ./...
# Run tests for specific package
go test -v ./pkg/runner
# Run tests with coverage
go test -cover ./...
# Generate coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.outpkg/runner/testdata/
├── basic/ # Basic workflow tests
├── matrix/ # Matrix build tests
├── secrets/ # Secret handling tests
├── local-action-js/ # JavaScript action tests
├── local-action-dockerfile/ # Docker action tests
└── uses-composite/ # Composite action tests
Unit Tests:
func TestWorkflowExecution(t *testing.T) {
// Test implementation
ctx := context.Background()
config := &runner.Config{
Workdir: "/tmp/test",
EventName: "push",
}
// Run test
err := runner.New(config).Run(ctx)
assert.NoError(t, err)
}Integration Tests:
func TestDockerIntegration(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test")
}
// Integration test implementation
}Test workflows are located in pkg/runner/testdata/. Each test case includes:
push.yml: Workflow file- Expected behavior documentation
- Any required local actions or files
- Fork the repository on GitHub
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes following the coding standards
- Add tests for new functionality
- Run the test suite:
make test - Format and lint:
make format && make lint - Commit your changes:
git commit -m "Add my feature" - Push to your fork:
git push origin feature/my-feature - Create a Pull Request on GitHub
Go Code Style:
# Format code
go fmt ./...
make format
# Lint code
golangci-lint run
make lint
# Check for common issues
go vet ./...Commit Message Format:
type(scope): description
feat(runner): add support for composite actions
fix(docker): resolve container cleanup issue
docs(readme): update installation instructions
test(runner): add matrix build test cases
Types: feat, fix, docs, test, refactor, chore
For Contributors:
- Keep PRs focused and small
- Include tests for new features
- Update documentation as needed
- Respond to review feedback promptly
For Reviewers:
- Check functionality and test coverage
- Verify documentation updates
- Ensure coding standards compliance
- Test changes locally when possible
Version Management:
# Check current version
cat VERSION
# Update version (maintainers only)
make promote
# Create snapshot build
make snapshotRelease Checklist:
- All tests pass
- Documentation updated
- Version bumped in VERSION file
- Release notes prepared
- Binaries built and tested
- Parse: Read and validate workflow files
- Plan: Determine execution order and dependencies
- Prepare: Pull/build required Docker images
- Execute: Run jobs in containers with proper environment
- Cleanup: Remove containers and temporary files
- Docker-first: All actions run in containers for consistency
- GitHub compatibility: Match GitHub Actions environment exactly
- Local development: Optimize for fast feedback loops
- Extensibility: Support custom platforms and local actions
New Command:
- Add command definition in
cmd/ - Implement business logic in
pkg/ - Add tests in appropriate test files
- Update documentation
New Flag:
- Add flag definition in
cmd/root.go - Add to
Inputstruct if needed - Implement functionality in relevant packages
- Add tests and documentation
- Container reuse: Minimize container creation overhead
- Image caching: Leverage Docker layer caching
- Parallel execution: Run independent jobs concurrently
- Resource limits: Respect system resource constraints
This project is licensed under the MIT License - see the LICENSE file for details.
- GitHub Actions team for the excellent CI/CD platform
- Docker community for containerization technology
- Go community for the robust programming language