Offical documentation
GitHub Actions
Caching
name: Caching with npm
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Cache node modules
id: cache-npm
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
name: List the state of node modules
continue-on-error: true
run: npm list
- name: Install dependencies
run: npm install
- name: Build
run: npm run build
- name: Test
run: npm test
Debugging Pipelines
Debugging Tools for GitHub Actions
GitHub Actions provides several built-in debugging capabilities to help investigate failures quickly.
1. Enable Debug Logging
When to use: You need more verbose output to understand what’s happening between steps, or want to see hidden commands and environment setup.
How to enable:
Add these secrets to your repository (Settings → Secrets and variables → Actions):
ACTIONS_STEP_DEBUG=true- Shows detailed step-by-step execution logsACTIONS_RUNNER_DEBUG=true- Shows runner diagnostic information
What you get:
- Detailed logs showing environment variable setup
- Hidden commands executed by actions
- Step-by-step execution trace
- Runner diagnostic information
Example output difference:
Without debug logging:
Run actions/checkout@v4
With debug logging:
##[debug]Evaluating condition for step: 'Checkout code'
##[debug]Evaluating: success()
##[debug]Evaluating success:
##[debug]=> true
##[debug]Result: true
##[debug]Starting: Checkout code
Run actions/checkout@v4
##[debug]Getting Git version info
##[debug]Working directory is '/home/runner/work/repo'
##[debug]Running command: git --version
2. Re-run Jobs with SSH Access
When to use: You need to inspect the CI environment interactively, debug environment-specific issues, or investigate complex failures hands-on.
How to use:
Add the tmate action to your workflow (triggers on failure):
- name: Setup tmate session
uses: mxschmitt/action-tmate@v3
if: failure()
timeout-minutes: 30
Or add it temporarily to debug a specific step:
- name: Debug with tmate
uses: mxschmitt/action-tmate@v3
if: always() # Run even if previous steps succeed
What you get:
- SSH access to the runner environment
- Connection string displayed in logs
- Ability to run commands interactively
- Inspect files, environment variables, installed tools
Usage tips:
- Remove or comment out before merging to production
- Use
timeout-minutesto prevent hanging - Set repository secret
ACTIONS_STEP_DEBUGto see connection info sooner
3. Download and Inspect Artifacts
When to use: You need to examine build outputs, test reports, logs, or coverage data after the run completes.
How to access:
- Go to Actions tab in your repository
- Click on the workflow run
- Scroll to bottom to see Artifacts section
- Click to download zip file
Upload debugging artifacts:
- name: Upload test results
uses: actions/upload-artifact@v4
if: always() # Upload even if tests fail
with:
name: test-results
path: |
test-results/
coverage/
**/*.log
retention-days: 7
Common artifacts to upload for debugging:
- Test results and reports (
test-results/,junit.xml) - Code coverage reports (
coverage/,htmlcov/) - Build logs (
*.log,build.log) - Screenshots from E2E tests (
screenshots/,cypress/screenshots/) - Application bundles or builds (
dist/,build/)
Tips:
- Use
if: always()to upload even when steps fail - Set reasonable
retention-daysto save storage costs - Use descriptive artifact names for multiple uploads
- Combine related files in single artifact to reduce clutter
Local Validation
Local Validation with act
act runs GitHub Actions workflows locally using Docker, giving you instant feedback without pushing to GitHub.
Installation
brew install act
curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
# Chocolatey
choco install act-cli
# Scoop
scoop install act
Requirements: Docker must be installed and running.
Essential Commands
Run workflows:
act # Run all push event workflows
act pull_request # Simulate PR event
act -j job-name # Run specific job
act -l # List all jobs
Working with secrets:
# Inline
act -s API_KEY=value -s TOKEN=abc123
# From file (recommended)
echo "API_KEY=value" >> .secrets
echo ".secrets" >> .gitignore
act
Debugging:
act -n # Dry run (show what would execute)
act --verbose # Verbose output
act -j build --rm=false # Keep container for inspection
Common Issues
“Error: Cannot connect to Docker daemon”
- Solution: Ensure Docker is running
- Check with:
docker ps
“No workflows found”
- Solution: Ensure you’re in a repo with
.github/workflows/directory - Verify with:
ls .github/workflows/
“Action not found”
- Some marketplace actions only work on GitHub
- Check action documentation for local support
- Consider using alternative actions or mocking
Slow first run:
- act downloads Docker images on first run
- Subsequent runs use cached images and are fast
- Choose “Medium” image size for best balance
What Works Locally
✅ Runs successfully:
- Checkout code
- Install dependencies
- Run tests
- Build artifacts
- Run scripts
- Use most marketplace actions
- Job dependencies and ordering
❌ Won’t work locally:
- Upload artifacts to GitHub
- Create releases
- Comment on PRs/issues
- OIDC token authentication (AWS, Azure, GCP)
- GitHub API write operations
- Some GitHub-specific actions
Workflow Integration
Pre-push validation:
# Add to your workflow
git add .
act
git commit -m "Add feature"
git push
Git hook automation:
Create .git/hooks/pre-push:
#!/bin/bash
echo "Validating workflows with act..."
act -q
Make it executable:
chmod +x .git/hooks/pre-push
Now workflows validate automatically before every push.
Tips
- Start small: Test individual jobs with
act -jbefore running full workflows - Use .secrets file: Avoid typing secrets repeatedly
- Check logs carefully: act output differs slightly from GitHub’s UI
- Keep Docker images updated:
docker pullthe images act uses periodically - Skip slow jobs locally: Use
if: github.event_name != 'workflow_dispatch'to skip jobs in local runs
Parallelisation
Offical documentation
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
Workload Identity
Offical documentation