GitHub Actions handles everything from running tests to deploying to production. Once you move beyond basic workflows, these patterns keep your CI/CD fast and maintainable.
Matrix Builds
Test across multiple versions and platforms in parallel:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
node: [18, 20, 22]
exclude:
- os: macos-latest
node: 18
include:
- os: ubuntu-latest
node: 22
coverage: true
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
- if: matrix.coverage
run: npm run test:coverageCaching
Speed up builds by caching dependencies:
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'npm' # Built-in caching
# Or manual caching for more control
- uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-Docker Layer Caching
- uses: docker/build-push-action@v6
with:
push: true
tags: my-app:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=maxReusable Workflows
Define once, use everywhere:
# .github/workflows/reusable-test.yml
name: Reusable Test
on:
workflow_call:
inputs:
node-version:
type: string
default: '22'
secrets:
NPM_TOKEN:
required: false
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
- run: npm testCall from another workflow:
# .github/workflows/ci.yml
jobs:
test:
uses: ./.github/workflows/reusable-test.yml
with:
node-version: '22'
secrets: inheritEnvironment Protection
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- run: echo "Deploying to staging"
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://myapp.com
steps:
- run: echo "Deploying to production"Configure in GitHub Settings → Environments:
- Required reviewers: Approval before deploy
- Wait timer: Delay (e.g., 30 minutes)
- Branch protection: Only main can deploy to production
- Environment secrets: Production-only API keys
Master this topic with hands-on labs
Go beyond reading — build real projects in sandboxed environments with expert video guidance.
Browse Courses →Artifacts
Share data between jobs:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
- run: npx vercel deploy dist/ --prodConditional Jobs
jobs:
lint:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- run: npm run lint
deploy:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
release:
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- run: ./release.shConcurrency Control
Prevent duplicate deployments:
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: true # Cancel previous run for same branchComposite Actions
Package multiple steps into a reusable action:
# .github/actions/setup-project/action.yml
name: Setup Project
description: Install dependencies and build
inputs:
node-version:
default: '22'
runs:
using: composite
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: npm
- run: npm ci
shell: bash
- run: npm run build
shell: bashUse it:
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
with:
node-version: '22'
- run: npm testGet weekly IT automation tips
Docker, Ansible, Terraform, MLOps — curated insights delivered to your inbox. No spam.
Subscribe Free →Path Filtering
Only run when relevant files change:
on:
push:
paths:
- 'apps/web/**'
- 'packages/shared/**'
- 'package.json'
paths-ignore:
- '**.md'
- '.github/ISSUE_TEMPLATE/**'Self-Hosted Runners
jobs:
build:
runs-on: [self-hosted, linux, x64, gpu]
steps:
- uses: actions/checkout@v4
- run: nvidia-smi # GPU available!
- run: python train.pyComplete Production Workflow
name: CI/CD
on:
push:
branches: [main]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- run: npm run lint
- run: npm run typecheck
test:
needs: lint
uses: ./.github/workflows/reusable-test.yml
secrets: inherit
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-project
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build
path: dist/
deploy:
if: github.ref == 'refs/heads/main'
needs: build
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/download-artifact@v4
with:
name: build
- run: ./deploy.shWhat's Next?
Our Docker Fundamentals course covers CI/CD with containers. Terraform for Beginners teaches infrastructure automation with GitHub Actions. First lessons are free. -e ---
Ready to go deeper? Explore our hands-on DevOps courses — practical labs covering Docker, Ansible, Terraform, and more.
Ready to learn by doing?
Stop reading tutorials — start building. Expert video courses with hands-on labs in real sandboxed environments.
Related Articles
CI/CD Pipeline Tutorial from Scratch
Build a complete CI/CD pipeline from scratch with GitHub Actions. Lint, test, build, and deploy your application — fully automated on every push to your.
Quality vs Cost in DevOps
The quality-cost tradeoff in DevOps is real but misunderstood. Learn why cutting quality to reduce cost usually increases total cost, and how to find.
GitHub Actions CI/CD for Terraform
Automate Terraform with GitHub Actions. Plan on PR, apply on merge, remote state locking, and secure secrets for IaC pipelines.
GitOps with ArgoCD Beginner Guide
Get started with GitOps using ArgoCD on Kubernetes. Install ArgoCD, create applications, configure sync, and automate deployments.
Golden Paths in Platform Engineering
Golden paths give developers a paved road through infrastructure complexity. Learn how to design golden paths for your internal developer platform.
Grafana Alloy OpenTelemetry Collector
Grafana Alloy is a programmable OpenTelemetry collector that replaces Prometheus Agent, Grafana Agent, and OTel Collector. Learn how to collect metrics, logs.
Explore topics
Browse more articles on the topics covered here.