| name | github-actions |
| description | GitHub Actions CI/CD workflow configuration. Use when setting up automated testing, deployment, or continuous integration for GitHub repositories. |
Purpose
Automate build, test, and deployment workflows directly from GitHub repositories.
When to Use
- Setting up CI/CD pipelines
- Automating tests on push/PR
- Deploying to production
- Running scheduled jobs
- Automating code quality checks
Workflow Basics
Workflow File Location
.github/
└── workflows/
├── ci.yml
├── deploy.yml
└── scheduled.yml
Basic Workflow Structure
name: Workflow Name
on: [push, pull_request]
jobs:
job-name:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "Hello World"
Common Triggers
Push and Pull Request
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
Manual Trigger
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy'
required: true
default: 'staging'
Scheduled (Cron)
on:
schedule:
- cron: '0 0 * * *'
Path Filters
on:
push:
paths:
- 'src/**'
- 'package.json'
Common Jobs
Install and Test (Node.js)
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: '20'
cache: 'npm'
- run: npm ci
- run: npm test
- run: npm run build
Install and Test (Python)
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- run: pip install -r requirements.txt
- run: pytest
Lint and Format
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run format:check
Build Docker Image
name: Docker Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:latest
Deploy to Vercel
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod'
Deploy to AWS
name: Deploy to AWS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- run: npm ci
- run: npm run build
- run: aws s3 sync ./dist s3://my-bucket
Multi-Stage Workflows
Test Then Deploy
name: CI/CD
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run build
- run: echo "Deploying..."
Matrix Testing
name: Test Matrix
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 21]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
Caching
Cache npm Dependencies
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
Custom Cache
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
Cache Build Artifacts
- uses: actions/cache@v4
with:
path: |
~/.npm
dist
key: ${{ runner.os }}-build-${{ github.sha }}
restore-keys: |
${{ runner.os }}-build-
Secrets Management
Using Secrets
- run: |
echo "API_KEY=${{ secrets.API_KEY }}" >> .env
npm run build
Required Secrets
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Check secrets
run: |
if [ -z "${{ secrets.API_KEY }}" ]; then
echo "API_KEY secret is required"
exit 1
fi
Environment Variables
Setting Environment Variables
jobs:
build:
runs-on: ubuntu-latest
env:
NODE_ENV: production
API_URL: https://api.example.com
steps:
- run: echo $NODE_ENV
From Job Output
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- id: version
run: echo "version=1.0.0" >> $GITHUB_OUTPUT
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Version ${{ needs.build.outputs.version }}"
Artifacts
Upload Build Output
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
Download Artifact
- uses: actions/download-artifact@v4
with:
name: build-output
path: ./dist
Common Actions
Checkout
- uses: actions/checkout@v4
with:
fetch-depth: 0
Setup Node.js
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
Setup Python
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
Setup Docker
- uses: docker/setup-buildx-action@v3
Setup AWS Credentials
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
Conditional Execution
Run on Specific Branch
jobs:
deploy:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- run: echo "Deploying main branch"
Run on Tag
jobs:
release:
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- run: echo "Creating release"
Skip on Draft PR
jobs:
test:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- run: echo "Testing PR"
Status Badges
Workflow Status Badge

Custom Badge

Best Practices
Workflow Design
- Keep workflows simple and focused
- Use matrix for testing multiple configurations
- Cache dependencies to speed up builds
- Use secrets for sensitive data
- Set appropriate timeouts
- Use specific action versions (not @latest)
Performance
- Use caching for dependencies
- Parallelize independent jobs
- Use self-hosted runners for large projects
- Minimize artifact sizes
- Use conditional execution
Security
- Pin action versions
- Use OIDC for cloud authentication
- Limit permissions with permissions field
- Review third-party actions
- Keep secrets encrypted
- Use environment protection rules
Common Patterns
Monorepo
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
package: [frontend, backend, shared]
steps:
- uses: actions/checkout@v4
- working-directory: ./packages/${{ matrix.package }}
run: npm ci && npm test
Release Workflow
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: softprops/action-gh-release@v1
with:
files: dist/*
Dependency Update
name: Dependency Update
on:
schedule:
- cron: '0 0 * * 0'
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npx npm-check-updates -u
- run: npm install
- run: npm test
- uses: peter-evans/create-pull-request@v6
with:
title: 'Update dependencies'
body: 'Automated dependency update'
Troubleshooting
View Workflow Logs
- Go to Actions tab in repository
- Click on workflow run
- Expand job to see logs
Debug Failed Workflows
- name: Debug
run: |
echo "Runner OS: ${{ runner.os }}"
echo "Event: ${{ github.event_name }}"
echo "Ref: ${{ github.ref }}"
Re-run Workflow
- Click on failed workflow
- Click "Re-run jobs" button
Enable Debug Logging
Add secret ACTIONS_STEP_DEBUG with value true
Scripts
.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: '20'
cache: 'npm'
- run: npm ci
- run: npm test
- run: npm run lint
- run: npm run build
.github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- run: echo "Deploying to production"