December 15, 2025ยท2 min read

Building Production-Ready CI/CD Pipelines with GitHub Actions

Introduction

A well-designed CI/CD pipeline is the backbone of modern software delivery. In this post, I'll walk through building production-grade pipelines with GitHub Actions.

Pipeline Architecture

A typical pipeline follows this flow:

  1. Lint & Format โ€” catch style issues early
  2. Test โ€” unit, integration, and e2e tests
  3. Build โ€” compile and package artifacts
  4. Deploy โ€” push to staging, then production

Basic Workflow

name: CI/CD Pipeline
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
 
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      - run: npm ci
      - run: npm test

Matrix Builds

Matrix builds let you test across multiple configurations simultaneously. This is critical for libraries that need to support multiple runtimes:

strategy:
  matrix:
    os: [ubuntu-latest, macos-latest]
    python-version: ['3.10', '3.11', '3.12']
    exclude:
      - os: macos-latest
        python-version: '3.10'

Reusable Workflows

Stop copying YAML between repos. Create reusable workflows:

# .github/workflows/deploy.yml
name: Deploy
on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
    secrets:
      AWS_ACCESS_KEY_ID:
        required: true
      AWS_SECRET_ACCESS_KEY:
        required: true
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ inputs.environment }}
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to ${{ inputs.environment }}
        run: |
          aws ecs update-service \
            --cluster my-cluster \
            --service my-service \
            --force-new-deployment

Docker Build & Push

- name: Build and push Docker image
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: |
      ghcr.io/${{ github.repository }}:latest
      ghcr.io/${{ github.repository }}:${{ github.sha }}
    cache-from: type=gha
    cache-to: type=gha,mode=max

Security Scanning

Always include security checks in your pipeline:

# Run Trivy for container scanning
trivy image --severity HIGH,CRITICAL myapp:latest
 
# Check for secrets
gitleaks detect --source . --verbose

Conclusion

GitHub Actions provides a powerful, flexible platform for CI/CD. Start with simple workflows and iterate โ€” add caching, matrix builds, and reusable workflows as your needs grow.

What I learned

Github action is really good for automating your deployment workflow

powered by Gemini 2.5 Flash