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.