github-actions
GitHub Actions CI/CD
Complete guide for building CI/CD pipelines with GitHub Actions.
Quick Reference
| File Location | Purpose |
|---|---|
.github/workflows/*.yml |
Workflow definitions |
workflow_dispatch |
Manual trigger |
push / pull_request |
Automatic triggers |
schedule |
Cron-based triggers |
1. Basic Workflow Structure
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
2. Triggers (Events)
Push and Pull Request
on:
push:
branches:
- main
- 'releases/**'
tags:
- 'v*'
paths:
- 'src/**'
- '!src/**/*.md'
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
Schedule (Cron)
on:
schedule:
# Every day at midnight UTC
- cron: '0 0 * * *'
# Every Monday at 9am UTC
- cron: '0 9 * * 1'
Manual Trigger
on:
workflow_dispatch:
inputs:
environment:
description: 'Deployment environment'
required: true
default: 'staging'
type: choice
options:
- staging
- production
debug:
description: 'Enable debug logging'
required: false
type: boolean
default: false
Multiple Triggers
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
release:
types: [published]
3. Jobs and Steps
Basic Job
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: npm test
working-directory: ./app
env:
NODE_ENV: test
Job Dependencies
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: npm run build
test:
needs: build
runs-on: ubuntu-latest
steps:
- run: npm test
deploy:
needs: [build, test]
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
Conditional Jobs
jobs:
deploy:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
notify:
if: always() # Runs even if previous jobs fail
needs: [deploy]
runs-on: ubuntu-latest
steps:
- run: ./notify.sh
4. Matrix Builds
Basic Matrix
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm test
Matrix with Include/Exclude
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [18, 20]
include:
- os: ubuntu-latest
node: 22
experimental: true
exclude:
- os: windows-latest
node: 18
fail-fast: false # Don't cancel all jobs if one fails
max-parallel: 4
5. Caching
Node.js Caching
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
# Or manual caching
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
Python Caching
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
Custom Caching
- uses: actions/cache@v4
id: cache-build
with:
path: |
./build
./node_modules
key: ${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('src/**') }}
restore-keys: |
${{ runner.os }}-build-${{ hashFiles('**/package-lock.json') }}-
${{ runner.os }}-build-
- name: Build
if: steps.cache-build.outputs.cache-hit != 'true'
run: npm run build
6. Secrets and Variables
Using Secrets
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: ./deploy.sh
Environment Variables
env:
NODE_ENV: production
jobs:
build:
runs-on: ubuntu-latest
env:
CI: true
steps:
- name: Build
env:
BUILD_NUMBER: ${{ github.run_number }}
run: npm run build
GitHub Context Variables
steps:
- run: |
echo "Repository: ${{ github.repository }}"
echo "Branch: ${{ github.ref_name }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
echo "Run ID: ${{ github.run_id }}"
echo "Event: ${{ github.event_name }}"
7. Artifacts
Upload Artifacts
- name: Build
run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
Download Artifacts
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: build
path: dist/
- run: ./deploy.sh
8. Environments and Deployments
Environment Protection
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- run: ./deploy.sh staging
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://myapp.com
steps:
- run: ./deploy.sh production
9. Reusable Workflows
Define Reusable Workflow
# .github/workflows/deploy.yml
name: Deploy
on:
workflow_call:
inputs:
environment:
required: true
type: string
secrets:
DEPLOY_KEY:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh ${{ inputs.environment }}
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
Call Reusable Workflow
# .github/workflows/ci.yml
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: npm run build
deploy:
needs: build
uses: ./.github/workflows/deploy.yml
with:
environment: production
secrets:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
10. Common Workflows
Node.js CI
name: Node.js CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
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 build
- run: npm test -- --coverage
- uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
Python CI
name: Python CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- run: pip install -r requirements.txt
- run: pytest --cov=src --cov-report=xml
- uses: codecov/codecov-action@v3
Docker Build and Push
name: Docker
on:
push:
branches: [main]
tags: ['v*']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=sha
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
Release on Tag
name: Release
on:
push:
tags: ['v*']
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: |
dist/*
generate_release_notes: true
11. Services and Containers
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7
ports:
- 6379:6379
steps:
- uses: actions/checkout@v4
- run: npm test
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
REDIS_URL: redis://localhost:6379
12. Composite Actions
# .github/actions/setup-node/action.yml
name: Setup Node.js
description: Setup Node.js with caching
inputs:
node-version:
description: Node.js version
default: '20'
runs:
using: composite
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- run: npm ci
shell: bash
# Usage
- uses: ./.github/actions/setup-node
with:
node-version: '20'
Best Practices
- Pin action versions - Use
@v4not@main - Use caching - Speed up workflows significantly
- Matrix for compatibility - Test multiple versions
- Fail fast -
fail-fast: falsefor complete matrix results - Use environments - Protect production deployments
- Minimize secrets scope - Use job-level env vars
- Reuse workflows - DRY with
workflow_call - Use GITHUB_TOKEN - Built-in, auto-rotated
- Conditional steps -
if:for efficiency - Artifacts for debugging - Upload logs and reports
More from housegarofalo/claude-code-base
react-typescript
Build modern React applications with TypeScript. Covers React 18+ patterns, hooks, component architecture, state management (Zustand, Redux Toolkit), server components, and best practices. Use for React development, TypeScript integration, component design, and frontend architecture.
5power-automate
Expert guidance for Power Automate development including cloud flows, desktop flows, Dataverse connector, expression functions, custom connectors, error handling, and child flow patterns. Use when building automated workflows, writing flow expressions, creating custom connectors from OpenAPI, or implementing error handling patterns.
5mobile-pwa
Build Progressive Web Apps with offline support, push notifications, and native-like experiences. Covers service workers, Web App Manifest, caching strategies, IndexedDB, background sync, and installability. Use for mobile-first web apps, offline-capable applications, and app-like experiences.
5svelte-kit
Expert guidance for SvelteKit 2 with Svelte 5 runes, server-side rendering, and modern patterns. Covers $state, $derived, $effect, form actions, load functions, and API routes. Use for SvelteKit applications, Svelte 5 runes, and full-stack Svelte development.
5matter-thread
>
5vitest
Fast Vite-native unit testing framework for JavaScript/TypeScript. ESM-first, Jest-compatible API, with instant HMR. Use for modern frontend testing, Vue/React/Svelte testing, or fast test execution. Triggers on vitest, vite test, vue test, svelte test.
5