CI/CD & Automation

Continuous integration, deployment pipelines, and automation workflows for Smart Shelf.

CI/CD & Automation

This section covers the continuous integration and deployment pipelines, automated workflows, and DevOps practices for Smart Shelf.

CI/CD Pipeline Overview

Smart Shelf uses GitHub Actions for comprehensive CI/CD automation, ensuring code quality, security, and reliable deployments.

Pipeline Architecture

graph TD
    A[Code Push] --> B[GitHub Actions]
    B --> C[Test & Lint]
    B --> D[Security Scan]
    B --> E[Build Application]
    
    C --> F{Branch Check}
    D --> F
    E --> F
    
    F -->|develop| G[Deploy to Staging]
    F -->|main| H[Deploy to Production]
    F -->|feature| I[Preview Deployment]
    
    G --> J[Run Integration Tests]
    H --> K[Run E2E Tests]
    H --> L[Health Check]
    
    style A fill:#e1f5fe
    style G fill:#fff3e0
    style H fill:#e8f5e8
    style I fill:#fce4ec

GitHub Actions Workflows

Main Deployment Workflow

# .github/workflows/deploy.yml
name: Deploy Smart Shelf

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

env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

jobs:
  test:
    name: Test & Lint
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'pnpm'
          
      - name: Install pnpm
        uses: pnpm/action-setup@v2
        with:
          version: 8
          
      - name: Install dependencies
        run: pnpm install --frozen-lockfile
        
      - name: Type check
        run: pnpm type-check
        
      - name: Lint
        run: pnpm lint
        
      - name: Run tests
        run: pnpm test:ci
        
      - name: Build application
        run: pnpm build
        env:
          NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
          NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}

  security:
    name: Security Scan
    runs-on: ubuntu-latest
    needs: test
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Run Snyk to check for vulnerabilities
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high
          
      - name: Upload result to GitHub Code Scanning
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: snyk.sarif

  deploy-staging:
    name: Deploy to Staging
    runs-on: ubuntu-latest
    needs: [test, security]
    if: github.ref == 'refs/heads/develop'
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Install Vercel CLI
        run: npm install --global vercel@latest
        
      - name: Pull Vercel Environment Information
        run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
        
      - name: Build Project Artifacts
        run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
        
      - name: Deploy Project Artifacts to Vercel
        run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }}

  deploy-production:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: [test, security]
    if: github.ref == 'refs/heads/main'
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Install Vercel CLI
        run: npm install --global vercel@latest
        
      - name: Pull Vercel Environment Information
        run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
        
      - name: Build Project Artifacts
        run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
        
      - name: Deploy Project Artifacts to Vercel
        run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
        
      - name: Run E2E Tests
        run: |
          pnpm install --frozen-lockfile
          pnpm test:e2e:prod
        env:
          BASE_URL: https://smart-shelf.vercel.app
          
      - name: Notify Deployment
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          channel: '#deployments'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Database Migration Workflow

# .github/workflows/migrate.yml
name: Database Migration

on:
  push:
    branches: [main]
    paths: ['supabase/migrations/**']

jobs:
  migrate:
    name: Run Database Migrations
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Setup Supabase CLI
        uses: supabase/setup-cli@v1
        
      - name: Run migrations on staging
        run: |
          supabase db push --db-url ${{ secrets.STAGING_DATABASE_URL }}
          
      - name: Run migrations on production
        run: |
          supabase db push --db-url ${{ secrets.PRODUCTION_DATABASE_URL }}
        if: success()

Code Quality Workflow

# .github/workflows/code-quality.yml
name: Code Quality

on:
  pull_request:
    branches: [main, develop]

jobs:
  quality:
    name: Code Quality Checks
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'pnpm'
          
      - name: Install dependencies
        run: pnpm install --frozen-lockfile
        
      - name: Run ESLint
        run: pnpm lint:check
        
      - name: Run Prettier
        run: pnpm format:check
        
      - name: Run TypeScript check
        run: pnpm type-check
        
      - name: Run tests with coverage
        run: pnpm test:coverage
        
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info
          flags: unittests
          name: codecov-umbrella

Automated Testing

Test Pipeline Configuration

// jest.config.js
const nextJest = require('next/jest');

const createJestConfig = nextJest({
  dir: './',
});

const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testEnvironment: 'jest-environment-jsdom',
  testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
  collectCoverageFrom: [
    'app/**/*.{js,jsx,ts,tsx}',
    'components/**/*.{js,jsx,ts,tsx}',
    'lib/**/*.{js,jsx,ts,tsx}',
    '!**/*.d.ts',
    '!**/node_modules/**',
  ],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80,
    },
  },
  moduleNameMapping: {
    '^@/(.*)$': '<rootDir>/$1',
  },
};

module.exports = createJestConfig(customJestConfig);

E2E Testing Setup

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests/e2e',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
    trace: 'on-first-retry',
  },
  
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
    {
      name: 'Mobile Chrome',
      use: { ...devices['Pixel 5'] },
    },
  ],
  
  webServer: {
    command: 'pnpm dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
});

Deployment Automation

Vercel Integration

// vercel.json
{
  "framework": "nextjs",
  "buildCommand": "pnpm build",
  "devCommand": "pnpm dev",
  "installCommand": "pnpm install --frozen-lockfile",
  "outputDirectory": ".next",
  
  "functions": {
    "app/api/*/route.ts": {
      "maxDuration": 30
    }
  },
  
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "X-Frame-Options",
          "value": "DENY"
        },
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        }
      ]
    }
  ],
  
  "rewrites": [
    {
      "source": "/api/webhooks/:path*",
      "destination": "/api/webhooks/:path*"
    }
  ]
}

Automated Rollback

# .github/workflows/rollback.yml
name: Emergency Rollback

on:
  workflow_dispatch:
    inputs:
      deployment_id:
        description: 'Deployment ID to rollback to'
        required: true
        type: string

jobs:
  rollback:
    name: Rollback Deployment
    runs-on: ubuntu-latest
    
    steps:
      - name: Install Vercel CLI
        run: npm install --global vercel@latest
        
      - name: Rollback to specified deployment
        run: |
          vercel rollback ${{ github.event.inputs.deployment_id }} --token=${{ secrets.VERCEL_TOKEN }}
          
      - name: Verify rollback
        run: |
          sleep 30
          curl -f ${{ vars.PRODUCTION_URL }}/api/health || exit 1
          
      - name: Notify team
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          channel: '#alerts'
          text: 'Emergency rollback completed to deployment ${{ github.event.inputs.deployment_id }}'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Package Management Automation

Dependency Updates

# .github/workflows/dependency-update.yml
name: Update Dependencies

on:
  schedule:
    - cron: '0 0 * * 1' # Weekly on Monday
  workflow_dispatch:

jobs:
  update:
    name: Update Dependencies
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'pnpm'
          
      - name: Install pnpm
        uses: pnpm/action-setup@v2
        with:
          version: 8
          
      - name: Update dependencies
        run: |
          pnpm update --latest
          pnpm audit --fix
          
      - name: Run tests
        run: |
          pnpm install
          pnpm test
          pnpm build
          
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v5
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          commit-message: 'chore: update dependencies'
          title: 'chore: weekly dependency updates'
          body: |
            This PR contains automated dependency updates.
            
            Please review the changes and ensure all tests pass before merging.
          branch: chore/dependency-updates

Environment Management

Environment Synchronization

// scripts/sync-env.ts
import { createServiceRoleClient } from '@/lib/supabase/server';

async function syncEnvironmentVariables() {
  const environments = ['staging', 'production'];
  
  for (const env of environments) {
    console.log(`Syncing environment: ${env}`);
    
    try {
      // Sync environment-specific configurations
      const supabase = createServiceRoleClient();
      
      // Update feature flags
      await supabase
        .from('feature_flags')
        .upsert({
          environment: env,
          flags: getEnvironmentFlags(env),
          updated_at: new Date().toISOString(),
        });
      
      console.log(`${env} environment synced successfully`);
      
    } catch (error) {
      console.error(`❌ Failed to sync ${env}:`, error);
      process.exit(1);
    }
  }
}

function getEnvironmentFlags(env: string) {
  const baseFlags = {
    ENABLE_ANALYTICS: true,
    ENABLE_REAL_TIME: true,
    MAINTENANCE_MODE: false,
  };
  
  if (env === 'staging') {
    return {
      ...baseFlags,
      ENABLE_DEBUG_MODE: true,
      ENABLE_TEST_DATA: true,
    };
  }
  
  return baseFlags;
}

// Run synchronization
if (require.main === module) {
  syncEnvironmentVariables();
}

Monitoring and Alerts

Build Notifications

# .github/workflows/notify.yml
name: Build Notifications

on:
  workflow_run:
    workflows: ["Deploy Smart Shelf"]
    types: [completed]

jobs:
  notify:
    name: Send Notifications
    runs-on: ubuntu-latest
    
    steps:
      - name: Deployment Success
        if: ${{ github.event.workflow_run.conclusion == 'success' }}
        uses: 8398a7/action-slack@v3
        with:
          status: 'success'
          channel: '#deployments'
          text: '✅ Smart Shelf deployed successfully'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}
          
      - name: Deployment Failure
        if: ${{ github.event.workflow_run.conclusion == 'failure' }}
        uses: 8398a7/action-slack@v3
        with:
          status: 'failure'
          channel: '#alerts'
          text: '❌ Smart Shelf deployment failed'
          webhook_url: ${{ secrets.SLACK_WEBHOOK }}

Best Practices

CI/CD Guidelines

  • Fast Feedback: Keep pipelines under 10 minutes
  • Fail Fast: Stop on first failure for quick feedback
  • Parallel Execution: Run independent jobs in parallel
  • Caching: Cache dependencies and build artifacts
  • Security: Scan for vulnerabilities before deployment

Automation Principles

  • Idempotent Operations: Scripts should be safe to run multiple times
  • Rollback Capability: Always have a way to rollback changes
  • Monitoring Integration: Include health checks and alerts
  • Documentation: Document all automated processes
  • Testing: Test automation scripts thoroughly

This CI/CD system ensures reliable, automated deployments with comprehensive quality checks and monitoring for Smart Shelf.