AgentSkillsCN

devops-deployment

为 Buzz Stack 在 Vercel 上的部署策略、CI/CD 管道、环境管理与可观测性提供解决方案。

SKILL.md
--- frontmatter
name: devops-deployment
description: Deployment strategies, CI/CD pipelines, environment management, and observability for Buzz Stack on Vercel.
argument-hint: Describe the deployment need - environment setup, pipeline, monitoring, scaling, etc.

DevOps & Deployment

Overview

Deployment and observability ensure applications run reliably in production. This skill covers deployment strategies, CI/CD automation, environment management, and monitoring.

Why it matters:

  • Fast, reliable deploys enable shipping features safely
  • Monitoring catches issues before users notice
  • Environment consistency prevents "works on my machine" bugs
  • Automated pipelines reduce human error

Core Concepts

1. Deployment Environments

typescript
// Define environment-specific configurations
interface EnvironmentConfig {
  name: "development" | "staging" | "production";
  apiUrl: string;
  debugLogging: boolean;
  errorTracking: boolean;
  cacheEnabled: boolean;
}

// Environment-specific values
const environments: Record<string, EnvironmentConfig> = {
  development: {
    name: "development",
    apiUrl: "http://localhost:3001",
    debugLogging: true,
    errorTracking: false,
    cacheEnabled: false,
  },
  staging: {
    name: "staging",
    apiUrl: "https://staging-api.example.com",
    debugLogging: true,
    errorTracking: true,
    cacheEnabled: true,
  },
  production: {
    name: "production",
    apiUrl: "https://api.example.com",
    debugLogging: false,
    errorTracking: true,
    cacheEnabled: true,
  },
};

// Load environment at runtime
const config = environments[process.env.NODE_ENV || "development"];

// Use in code
const apiUrl = config.apiUrl;

2. Environment Variables

bash
# .env.local (NEVER COMMIT)
DATABASE_URL=postgresql://user:pass@localhost/db
API_KEY_SECRET=sk_test_abc123
JWT_SECRET=your-super-secret-key
DEBUG=true

# .env.production (for Vercel, use their UI instead)
# In Vercel: Settings → Environment Variables
typescript
// In code
const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY_SECRET;

// For client-side (must be prefixed with NEXT_PUBLIC_)
const PUBLIC_API_URL = process.env.NEXT_PUBLIC_API_URL;

3. CI/CD Pipeline (GitHub Actions Example)

yaml
# .github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  test_and_build:
    runs-on: ubuntu-latest
    steps:
      # Check out code
      - uses: actions/checkout@v3

      # Setup Node
      - uses: actions/setup-node@v3
        with:
          node-version: "18"
          cache: "pnpm"

      # Install dependencies
      - run: pnpm install

      # Run tests
      - run: pnpm test
      - run: pnpm lint
      - run: pnpm build

      # Deploy to Vercel
      - name: Deploy to Vercel
        uses: vercel/action@main
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}

4. Zero-Downtime Deployments

typescript
// Strategy: Blue-Green Deployment
// 1. Keep current version running (Blue)
// 2. Deploy new version to separate instance (Green)
// 3. Test new version thoroughly
// 4. Switch traffic from Blue → Green

// Vercel does this automatically:
// - New deployment gets unique preview URL
// - Test thoroughly (staging environment)
// - Promote to production (instant switch)

// Implementation: Graceful shutdown
async function shutdown(signal: string) {
  console.log(`Received ${signal}, shutting down gracefully...`);

  // Stop accepting new requests
  server.close(() => {
    console.log("Server closed");
    process.exit(0);
  });

  // Wait up to 30 seconds for existing requests to finish
  setTimeout(() => {
    console.log("Force closing outstanding connections");
    process.exit(1);
  }, 30000);
}

process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));

Deep Patterns

Pattern 1: Database Migrations (Prisma)

typescript
// Generate migration when schema changes
// Command: pnpm prisma migrate dev --name add_user_email

// Migration files are version-controlled
// migrations/
//   ├── 20240213100000_initial/
//   │   └── migration.sql
//   └── 20240213120000_add_user_email/
//       └── migration.sql

// In CI/CD before deploy:
// pnpm prisma migrate deploy
// Applies all pending migrations to production database

// Workflow for schema changes:
// 1. Update schema.prisma
// 2. Run: pnpm prisma migrate dev --name describe_change
// 3. Review migration file
// 4. Commit migration (version controlled)
// 5. CI/CD applies on deploy

Pattern 2: Secrets Management

typescript
// ❌ WRONG: Store secrets in git
DATABASE_PASSWORD = "super_secret_123"  # In .env file

// ✅ RIGHT: Use Vercel's secret management
// 1. In Vercel dashboard: Settings → Environment Variables
// 2. Add SECRET_NAME: "value"
// 3. In code: process.env.SECRET_NAME

// ✅ BETTER: Use external secret manager (Vercel + GitHub)
// 1. Generate on production service
// 2. Only accessible to authorized applications
// 3. Rotated regularly
// 4. Never logged or exposed

// For local development:
// 1. Create .env.local (add to .gitignore)
// 2. Only you have these secrets
// 3. Never commit them

Pattern 3: Health Checks & Monitoring

typescript
// Health check endpoint
app.get("/health", (req, res) => {
  const health = {
    status: "ok",
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    environment: process.env.NODE_ENV,
    database: "checking...",
  };

  // Quick database check
  db.query("SELECT 1")
    .then(() => {
      health.database = "connected";
      res.status(200).json(health);
    })
    .catch(() => {
      health.database = "disconnected";
      res.status(503).json(health);
    });
});

// Vercel: Configure health checks in vercel.json
// {
//   "env": { "HEALTH_CHECK_PATH": "/health" }
// }

Pattern 4: Logging & Observability

typescript
// Structured logging (not console.log!)
class Logger {
  info(message: string, meta?: Record<string, unknown>) {
    console.log(
      JSON.stringify({
        level: "info",
        message,
        timestamp: new Date().toISOString(),
        ...meta,
      }),
    );
  }

  error(message: string, error?: Error, meta?: Record<string, unknown>) {
    console.error(
      JSON.stringify({
        level: "error",
        message,
        error: error?.message,
        stack: error?.stack,
        timestamp: new Date().toISOString(),
        ...meta,
      }),
    );
  }
}

// Usage
const logger = new Logger();
logger.info("User logged in", { userId: "123", loginMethod: "google" });
logger.error("Database connection failed", error, { retries: 3 });

// In production + observability tool (Sentry, Datadog, etc.):
// - Logs captured automatically
// - Can search and filter by any field
// - Alerts on error rates
// - Performance metrics tracked

Pattern 5: Feature Flags (Safe Rollouts)

typescript
// Deploy code that's not yet active
function isFeatureEnabled(feature: string, userId?: string): boolean {
  // Example: 10% of users see new feature
  if (feature === 'new-search') {
    if (userId) {
      return hashUserId(userId) % 100 < 10; // 10% of users
    }
    return false;
  }

  // Example: Feature only in staging
  if (feature === 'experimental-api') {
    return process.env.NODE_ENV === 'staging';
  }

  return false;
}

// Usage
export function SearchBox() {
  const useNewSearch = isFeatureEnabled('new-search');

  if (useNewSearch) {
    return <NewSearchComponent />;
  } else {
    return <LegacySearchComponent />;
  }
}

// Benefit: Deploy, test with 10%, expand to 50%, then 100%
// If issues arise, rollback instantly by disabling flag

Deployment Checklist

Before shipping to production:

  • All tests passing (pnpm test)
  • No lint errors (pnpm lint)
  • Build succeeds (pnpm build)
  • Environment variables configured in Vercel
  • Database migrations reviewed and tested
  • Feature flags tested in staging
  • Secrets not exposed anywhere
  • Health checks passing
  • Monitoring/alerting configured
  • Rollback plan documented

Vercel-Specific Best Practices

typescript
// vercel.json - Configure Vercel
{
  "buildCommand": "pnpm run build",
  "installCommand": "pnpm install",
  "env": {
    "NODE_ENV": "production"
  },
  "regions": ["sfo1"], // Deploy in specific region
  "functions": {
    "api/**": {
      "memory": 1024,
      "maxDuration": 60
    }
  }
}

// Preview deployments
// - Every push creates preview.example.com URL
// - Full production-like environment
// - Test before deploying to main domain
// - Share with team for review

// Production deployment
// - Automatic on merge to main branch
// - Instant propagation to CDN
// - Built-in analytics and monitoring

Anti-Patterns to Avoid

typescript
// ❌ Wrong: Storing secrets in code
const API_KEY = "sk_live_abc123"; // In source file

// ✅ Correct: Load from environment
const API_KEY = process.env.API_KEY;

// ❌ Wrong: No database backups before migration
// Schema change → data loss if migration fails

// ✅ Correct: Backups + test migrations first
// 1. Backup production database
// 2. Test migration on backup
// 3. Run migration on production

// ❌ Wrong: Deploy without tests
// Ship untested code → production bugs

// ✅ Correct: CI/CD runs tests before deploy
// Tests → Build → Deploy

// ❌ Wrong: No monitoring after deploy
// Bugs discovered by angry users

// ✅ Correct: Monitor errors, performance, uptime
// Alerts notify you in Slack

Monitoring & Alerting Strategy

MetricToolAlert Threshold
Error RateSentry> 1% errors
Response TimeVercel Analytics> 2s P95
UptimePingdom< 99.5%
Memory UsageVercel> 512MB
Login SuccessSentry< 95%

Key Questions

  1. How do I safely deploy changes? (CI/CD pipeline)
  2. What if something breaks in production? (Rollback plan)
  3. How do users get new features? (Feature flags, gradual rollout)
  4. What metrics matter? (Define SLOs)
  5. Are my secrets safe? (Environment variables, secret manager)

Resources