Skip to content

CI/CD Pipeline

Last Updated: 2025-01-22

Automated Continuous Integration and Continuous Deployment pipeline for AccessALI using GitHub Actions.


Overview

The CI/CD pipeline automates:

  • Code quality - Linting and type checking
  • Testing - Unit, integration, and E2E tests
  • Building - Docker image creation
  • Deployment - Automated deployment to environments

Workflow

graph LR
    Push[Push to GitHub] --> Lint[Lint & Type Check]
    Lint --> Test[Run Tests]
    Test --> Build[Build Docker Image]
    Build --> Deploy[Deploy to Environment]

GitHub Actions Workflow

Main Workflow

# .github/workflows/ci.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

env:
  NODE_VERSION: '20'

jobs:
  lint:
    name: Lint and Type Check
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'

      - name: Install dependencies
        run: |
          corepack enable
          pnpm install

      - name: Run type check
        run: cd src && pnpm type-check

      - name: Run linter
        run: cd src && pnpm lint

  test:
    name: Run Tests
    runs-on: ubuntu-latest
    needs: lint

    services:
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_USER: accessali
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: accessali_test
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'pnpm'

      - name: Install dependencies
        run: |
          corepack enable
          pnpm install

      - name: Run migrations
        run: cd src && pnpm db:migrate
        env:
          DATABASE_URL: postgresql://accessali:postgres@localhost:5432/accessali_test

      - name: Run unit tests
        run: cd src && pnpm test
        env:
          DATABASE_URL: postgresql://accessali:postgres@localhost:5432/accessali_test

      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info

  build:
    name: Build Docker Image
    runs-on: ubuntu-latest
    needs: test
    if: github.event_name == 'push'

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

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

  deploy-staging:
    name: Deploy to Staging
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/develop'
    environment:
      name: staging
      url: https://staging.accessali.example.com

    steps:
      - name: Deploy to staging
        run: |
          # Deploy using kubectl, helm, or deployment script
          echo "Deploying to staging environment"

  deploy-production:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/main'
    environment:
      name: production
      url: https://accessali.example.com

    steps:
      - name: Deploy to production
        run: |
          # Deploy to production
          echo "Deploying to production environment"

E2E Testing

# .github/workflows/e2e.yml
name: E2E Tests

on:
  pull_request:
    branches: [main, develop]

jobs:
  e2e:
    name: Playwright E2E Tests
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'pnpm'

      - name: Install dependencies
        run: |
          corepack enable
          pnpm install
          pnpm exec playwright install --with-deps

      - name: Run E2E tests
        run: cd src && pnpm test:e2e

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: src/playwright-report/

Deployment Strategies

# .github/workflows/vercel.yml
name: Deploy to Vercel

on:
  push:
    branches: [main, develop]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Vercel
        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: ${{ github.ref == 'refs/heads/main' && '--prod' || '' }}

2. Docker Registry + Kubernetes

# Build and push
docker build -t registry.example.com/accessali:$VERSION .
docker push registry.example.com/accessali:$VERSION

# Deploy to Kubernetes
kubectl set image deployment/accessali-app \
  app=registry.example.com/accessali:$VERSION \
  -n accessali

3. AWS ECS

# .github/workflows/ecs.yml
- name: Deploy to Amazon ECS
  uses: aws-actions/amazon-ecs-deploy-task-definition@v1
  with:
    task-definition: task-definition.json
    service: accessali-service
    cluster: accessali-cluster

Environment Secrets

Configure in GitHub repository settings:

Required Secrets

# Docker
DOCKER_USERNAME=your-username
DOCKER_PASSWORD=your-password

# Vercel (if using Vercel)
VERCEL_TOKEN=your-vercel-token
VERCEL_ORG_ID=your-org-id
VERCEL_PROJECT_ID=your-project-id

# Database
DATABASE_URL=postgresql://...

# NextAuth
NEXTAUTH_SECRET=production-secret

# OAuth (if using)
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...

Branch Strategy

graph LR
    Feature[feature/*] -->|PR| Develop[develop]
    Develop -->|PR| Main[main]

    Feature -->|CI: Lint, Test| CI1[CI Checks]
    Develop -->|Deploy| Staging[Staging Environment]
    Main -->|Deploy| Production[Production Environment]

Environments

  • feature/* - Local development only
  • develop - Auto-deploy to staging
  • main - Auto-deploy to production (with approval)

Best Practices

  • Run CI on all pull requests
  • Require passing CI before merge
  • Use branch protection rules
  • Implement environment-specific deployments
  • Store secrets in GitHub Secrets or vault
  • Tag releases with semantic versioning
  • Implement rollback procedures
  • Monitor deployment success
  • Use deployment approvals for production
  • Keep workflows DRY with reusable workflows


Next Steps

  1. Configure GitHub Actions workflows
  2. Set up environment secrets
  3. Configure deployment environments
  4. Review Production Checklist