Files
novalon-website/docs/plans/2026-03-09-production-readiness-plan.md
T
张翔 6d92024b63 feat: 修复测试套件问题并添加Woodpecker CI配置
- 修复API测试认证问题:创建全局认证设置,更新Playwright配置
- 优化回归测试稳定性:增加超时时间到15秒,修复定位器
- 创建Woodpecker CI工作流:CI、部署和质量门禁配置
- 添加Jest配置和测试脚本
- 移除登录页面的默认账号密码显示(安全问题修复)
2026-03-09 10:26:02 +08:00

25 KiB
Raw Blame History

生产就绪度修复与迭代计划

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

目标: 补齐生产就绪度和自动化体系,确保网站具备上线条件

架构: Next.js 16 + SQLite + Drizzle ORM + NextAuth.js + Playwright + Woodpecker CI + Sentry

技术栈: Next.js, React, TypeScript, SQLite, Drizzle ORM, NextAuth.js, Playwright, Woodpecker CI, Sentry, Prometheus

关键配置:

  • CI/CD: Forgejo + Woodpecker CI
  • 监控: Sentry (错误追踪) + Prometheus (性能监控)
  • 测试: Playwright + Jest
  • 质量门禁: ESLint + Prettier + 测试覆盖率

前置准备

环境要求

  • Node.js 18+
  • npm
  • Git
  • Forgejo账号(用于代码托管)
  • Woodpecker CI实例(用于CI/CD
  • Sentry账号(用于错误监控)

相关文档

  • 测试评估报告:见知识图谱
  • 上线条件评估:见知识图谱

阶段一:修复测试套件问题(预计 2 天)

Task 1: 修复API测试认证问题

文件:

  • 修改: e2e/src/tests/api/admin.api.spec.ts
  • 创建: e2e/global-setup.ts
  • 修改: e2e/playwright.config.ts

步骤 1: 创建全局认证设置

创建文件 e2e/global-setup.ts

import { chromium, FullConfig } from '@playwright/test';

async function globalSetup(config: FullConfig) {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  
  // 登录并保存认证状态
  await page.goto('http://localhost:3000/admin/login');
  await page.fill('#email', 'admin@novalon.cn');
  await page.fill('#password', 'admin123456');
  await page.click('button[type="submit"]');
  
  // 等待登录成功
  await page.waitForURL(/\/admin(?!\/login)/);
  
  // 保存认证状态
  await page.context().storageState({ path: 'e2e/.auth/admin.json' });
  
  await browser.close();
}

export default globalSetup;

步骤 2: 更新Playwright配置

修改 e2e/playwright.config.ts

export default defineConfig({
  globalSetup: require.resolve('./global-setup'),
  
  use: {
    storageState: '.auth/admin.json', // 使用保存的认证状态
  },
  
  // ... 其他配置
});

步骤 3: 更新API测试

修改 e2e/src/tests/api/admin.api.spec.ts

import { test, expect } from '../../fixtures/base.fixture';

test.describe('管理后台API测试', () => {
  // 移除 beforeAll 中的手动认证逻辑
  // 使用全局设置的认证状态

  test.describe('内容管理API', () => {
    test('应该能够获取内容列表', async ({ request }) => {
      const response = await request.get('/api/admin/content');

      expect(response.status()).toBe(200);
      
      const data = await response.json();
      expect(data).toHaveProperty('items');
      expect(Array.isArray(data.items)).toBe(true);
    });

    test('应该能够创建新内容', async ({ request }) => {
      const response = await request.post('/api/admin/content', {
        data: {
          type: 'news',
          title: '测试新闻',
          slug: `test-news-${Date.now()}`,
          content: '这是测试内容',
          status: 'draft',
        },
      });

      expect([200, 201]).toContain(response.status());
      
      const data = await response.json();
      expect(data).toHaveProperty('id');
      expect(data.title).toBe('测试新闻');
    });
  });
});

步骤 4: 运行测试验证

运行命令:

cd e2e
npm test -- tests/api/admin.api.spec.ts --project=chromium

预期结果:所有API测试通过,无跳过

步骤 5: 提交更改

git add e2e/global-setup.ts e2e/playwright.config.ts e2e/src/tests/api/admin.api.spec.ts
git commit -m "fix: 修复API测试认证问题,使用全局认证状态"

Task 2: 优化回归测试稳定性

文件:

  • 修改: e2e/src/tests/regression/admin.regression.spec.ts

步骤 1: 增加超时时间

修改 e2e/src/tests/regression/admin.regression.spec.ts

test.beforeEach(async ({ page }) => {
  loginPage = new AdminLoginPage(page);
  contentPage = new AdminContentPage(page);
  
  await loginPage.goto();
  await loginPage.login('admin@novalon.cn', 'admin123456');
  
  try {
    // 增加超时时间到15秒
    await page.waitForURL(/\/admin/, { timeout: 15000 });
  } catch (error) {
    console.error('登录超时,跳过测试:', error);
    test.skip();
  }
});

步骤 2: 修复列表页面定位器

修改 e2e/src/pages/AdminPage.ts

export class AdminContentPage extends BasePage {
  readonly createButton: Locator;
  readonly contentList: Locator;
  readonly searchInput: Locator;
  readonly typeFilter: Locator;

  constructor(page: Page) {
    super(page);
    this.createButton = page.getByRole('button', { name: /创建|新建|create/i });
    // 使用更精确的定位器
    this.contentList = page.locator('table tbody tr').or(page.locator('[data-testid="content-item"]'));
    this.searchInput = page.locator('input[type="search"], input[placeholder*="搜索"]');
    this.typeFilter = page.locator('select[name="type"], select[data-testid="type-filter"]');
  }
}

步骤 3: 运行测试验证

运行命令:

cd e2e
npm test -- tests/regression/admin.regression.spec.ts --project=chromium

预期结果:回归测试通过率提升到90%+

步骤 4: 提交更改

git add e2e/src/tests/regression/admin.regression.spec.ts e2e/src/pages/AdminPage.ts
git commit -m "fix: 优化回归测试稳定性,增加超时时间,修复定位器"

阶段二:搭建CI/CD流水线(预计 3 天)

Task 3: 创建Woodpecker CI工作流

文件:

  • 创建: .woodpecker/ci.yml
  • 创建: .woodpecker/deploy.yml

步骤 1: 创建CI工作流

创建文件 .woodpecker/ci.yml

when:
  branch: [main, develop]
  event: [push, pull_request]

steps:
  lint:
    image: node:18-alpine
    commands:
      - npm ci
      - npm run lint
      - npm run type-check

  test:
    image: node:18-alpine
    commands:
      - npm ci
      - npm run db:push
      - npm run test:unit
      - npx playwright install --with-deps
      - npm run test:e2e

  build:
    image: node:18-alpine
    commands:
      - npm ci
      - npm run build
    when:
      status: [success]

步骤 2: 创建部署工作流

创建文件 .woodpecker/deploy.yml

when:
  branch: [main]
  event: [push]

steps:
  deploy:
    image: node:18-alpine
    commands:
      - npm ci
      - npm run build
      - echo "Deploying to production..."
    secrets: [deploy_key]

步骤 3: 更新package.json脚本

修改 package.json

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "type-check": "tsc --noEmit",
    "test:unit": "jest",
    "test:e2e": "cd e2e && npm test",
    "db:push": "drizzle-kit push:sqlite",
    "db:migrate": "drizzle-kit generate:sqlite && drizzle-kit migrate"
  }
}

步骤 4: 提交更改

git add .woodpecker/ package.json
git commit -m "feat: 添加Woodpecker CI流水线配置"

Task 4: 配置质量门禁

文件:

  • 创建: .github/workflows/quality-gate.yml
  • 创建: jest.config.js
  • 修改: package.json

步骤 1: 创建Jest配置

创建文件 jest.config.js

module.exports = {
  testEnvironment: 'node',
  collectCoverage: true,
  coverageThreshold: {
    global: {
      branches: 70,
      functions: 70,
      lines: 70,
      statements: 70
    }
  },
  testMatch: ['**/__tests__/**/*.test.ts', '**/*.test.ts'],
  moduleFileExtensions: ['ts', 'js', 'json'],
  transform: {
    '^.+\\.ts$': 'ts-jest'
  }
};

步骤 2: 创建质量门禁工作流

创建文件 .woodpecker/quality-gate.yml

when:
  event: [pull_request]
  branch: [main, develop]

steps:
  quality-check:
    image: node:18-alpine
    commands:
      - npm ci
      - npm run lint
      - npm run type-check
      - npm run test:unit -- --coverage
      - |
        COVERAGE=$(cat coverage/coverage-summary.json | grep -o '"lines":{"pct":[0-9.]*' | grep -o '[0-9.]*$')
        if [ $(echo "$COVERAGE < 70" | bc -l) -eq 1 ]; then
          echo "Coverage $COVERAGE% is below threshold 70%"
          exit 1
        fi

步骤 3: 提交更改

git add .woodpecker/quality-gate.yml jest.config.js package.json
git commit -m "feat: 添加质量门禁配置"

阶段三:建立监控告警体系(预计 3 天)

Task 5: 集成Sentry错误监控

文件:

  • 修改: package.json
  • 创建: src/lib/sentry.ts
  • 修改: src/app/layout.tsx

步骤 1: 安装Sentry依赖

运行命令:

npm install @sentry/nextjs

步骤 2: 创建Sentry配置

创建文件 src/lib/sentry.ts

import * as Sentry from '@sentry/nextjs';

export function initSentry() {
  if (process.env.NODE_ENV === 'production') {
    Sentry.init({
      dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
      environment: process.env.NODE_ENV,
      tracesSampleRate: 0.1,
      replaysSessionSampleRate: 0.1,
      replaysOnErrorSampleRate: 1.0,
    });
  }
}

步骤 3: 在应用中初始化Sentry

修改 src/app/layout.tsx

import { initSentry } from '@/lib/sentry';

// 在文件顶部初始化
initSentry();

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="zh-CN">
      <body>{children}</body>
    </html>
  );
}

步骤 4: 创建Sentry配置文件

创建文件 sentry.client.config.ts

import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: 0.1,
});

创建文件 sentry.server.config.ts

import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: 0.1,
});

步骤 5: 更新环境变量

修改 .env.example

# Sentry
NEXT_PUBLIC_SENTRY_DSN=https://xxx@xxx.ingest.sentry.io/xxx

步骤 6: 提交更改

git add src/lib/sentry.ts src/app/layout.tsx sentry.client.config.ts sentry.server.config.ts .env.example package.json
git commit -m "feat: 集成Sentry错误监控"

Task 6: 配置性能监控

文件:

  • 创建: src/lib/monitoring.ts
  • 创建: src/app/api/health/route.ts

步骤 1: 创建监控工具

创建文件 src/lib/monitoring.ts

export class PerformanceMonitor {
  private static instance: PerformanceMonitor;
  private metrics: Map<string, number[]> = new Map();

  static getInstance(): PerformanceMonitor {
    if (!PerformanceMonitor.instance) {
      PerformanceMonitor.instance = new PerformanceMonitor();
    }
    return PerformanceMonitor.instance;
  }

  recordMetric(name: string, value: number) {
    if (!this.metrics.has(name)) {
      this.metrics.set(name, []);
    }
    this.metrics.get(name)!.push(value);
  }

  getAverage(name: string): number {
    const values = this.metrics.get(name) || [];
    if (values.length === 0) return 0;
    return values.reduce((a, b) => a + b, 0) / values.length;
  }

  getPercentile(name: string, percentile: number): number {
    const values = this.metrics.get(name) || [];
    if (values.length === 0) return 0;
    
    const sorted = [...values].sort((a, b) => a - b);
    const index = Math.ceil((percentile / 100) * sorted.length) - 1;
    return sorted[index];
  }
}

export const monitor = PerformanceMonitor.getInstance();

步骤 2: 创建健康检查API

创建文件 src/app/api/health/route.ts

import { NextResponse } from 'next/server';
import { monitor } from '@/lib/monitoring';

export async function GET() {
  const health = {
    status: 'ok',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    memory: process.memoryUsage(),
    metrics: {
      avgResponseTime: monitor.getAverage('response_time'),
      p95ResponseTime: monitor.getPercentile('response_time', 95),
    }
  };

  return NextResponse.json(health);
}

步骤 3: 提交更改

git add src/lib/monitoring.ts src/app/api/health/route.ts
git commit -m "feat: 添加性能监控和健康检查API"

阶段四:配置生产环境(预计 2 天)

Task 7: 创建生产环境配置

文件:

  • 创建: .env.production.example
  • 创建: docker-compose.prod.yml
  • 创建: Dockerfile

步骤 1: 创建生产环境变量模板

创建文件 .env.production.example

# Database
DATABASE_URL=file:./data/prod.db

# NextAuth
NEXTAUTH_URL=https://novalon.cn
NEXTAUTH_SECRET=your-production-secret-here

# Admin User
ADMIN_EMAIL=admin@novalon.cn
ADMIN_PASSWORD=your-secure-password

# Sentry
NEXT_PUBLIC_SENTRY_DSN=https://xxx@xxx.ingest.sentry.io/xxx

# Email (Resend)
RESEND_API_KEY=re_icMNpBzS_DL9GirDmhG5PbNU6PLRWvUtY

# File Upload
UPLOAD_DIR=./uploads
MAX_FILE_SIZE=10485760

步骤 2: 创建Docker配置

创建文件 Dockerfile

FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN npm run build

# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app

ENV NODE_ENV production

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT 3000
ENV HOSTNAME "0.0.0.0"

CMD ["node", "server.js"]

步骤 3: 创建Docker Compose配置

创建文件 docker-compose.prod.yml

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
    env_file:
      - .env.production
    volumes:
      - ./data:/app/data
      - ./uploads:/app/uploads
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
      interval: 30s
      timeout: 10s
      retries: 3

步骤 4: 提交更改

git add .env.production.example docker-compose.prod.yml Dockerfile
git commit -m "feat: 添加生产环境配置"

Task 8: 创建备份脚本

文件:

  • 创建: scripts/backup.sh
  • 创建: scripts/restore.sh

步骤 1: 创建备份脚本

创建文件 scripts/backup.sh

#!/bin/bash

# 备份脚本
BACKUP_DIR="./backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="backup_$DATE"

# 创建备份目录
mkdir -p $BACKUP_DIR/$BACKUP_NAME

# 备份数据库
echo "Backing up database..."
cp ./data/prod.db $BACKUP_DIR/$BACKUP_NAME/database.db

# 备份上传文件
echo "Backing up uploads..."
cp -r ./uploads $BACKUP_DIR/$BACKUP_NAME/uploads

# 备份配置
echo "Backing up config..."
cp .env.production $BACKUP_DIR/$BACKUP_NAME/.env.production

# 压缩备份
echo "Compressing backup..."
tar -czf $BACKUP_DIR/$BACKUP_NAME.tar.gz -C $BACKUP_DIR $BACKUP_NAME

# 删除临时目录
rm -rf $BACKUP_DIR/$BACKUP_NAME

# 保留最近7天的备份
find $BACKUP_DIR -name "backup_*.tar.gz" -mtime +7 -delete

echo "Backup completed: $BACKUP_DIR/$BACKUP_NAME.tar.gz"

步骤 2: 创建恢复脚本

创建文件 scripts/restore.sh

#!/bin/bash

# 恢复脚本
if [ -z "$1" ]; then
  echo "Usage: ./restore.sh <backup_file.tar.gz>"
  exit 1
fi

BACKUP_FILE=$1

if [ ! -f $BACKUP_FILE ]; then
  echo "Backup file not found: $BACKUP_FILE"
  exit 1
fi

# 解压备份
echo "Extracting backup..."
tar -xzf $BACKUP_FILE -C ./temp_restore

# 恢复数据库
echo "Restoring database..."
cp ./temp_restore/backup_*/database.db ./data/prod.db

# 恢复上传文件
echo "Restoring uploads..."
cp -r ./temp_restore/backup_*/uploads ./uploads

# 清理临时文件
rm -rf ./temp_restore

echo "Restore completed"

步骤 3: 设置定时备份

创建文件 scripts/cron-backup.sh

#!/bin/bash

# 添加到crontab: 0 2 * * * /path/to/scripts/cron-backup.sh

cd /path/to/novalon-website
./scripts/backup.sh >> ./logs/backup.log 2>&1

步骤 4: 提交更改

git add scripts/
git commit -m "feat: 添加备份和恢复脚本"

阶段五:性能和安全测试(预计 2 天)

Task 9: 创建性能测试脚本

文件:

  • 创建: tests/performance/load-test.js
  • 创建: tests/performance/stress-test.js

步骤 1: 安装性能测试工具

运行命令:

npm install -D k6

步骤 2: 创建负载测试

创建文件 tests/performance/load-test.js

import http from 'k6/http';
import { check, sleep } from 'k6';

export let options = {
  stages: [
    { duration: '2m', target: 100 },  // 2分钟内增加到100用户
    { duration: '5m', target: 100 },  // 保持100用户5分钟
    { duration: '2m', target: 0 },    // 2分钟内降到0用户
  ],
  thresholds: {
    http_req_duration: ['p(95)<500'], // 95%的请求响应时间小于500ms
    http_req_failed: ['rate<0.01'],   // 错误率小于1%
  },
};

export default function () {
  let res = http.get('http://localhost:3000/');
  check(res, { 'status was 200': (r) => r.status == 200 });
  sleep(1);
}

步骤 3: 创建压力测试

创建文件 tests/performance/stress-test.js

import http from 'k6/http';
import { check } from 'k6';

export let options = {
  stages: [
    { duration: '2m', target: 200 },
    { duration: '5m', target: 200 },
    { duration: '2m', target: 400 },
    { duration: '5m', target: 400 },
    { duration: '2m', target: 600 },
    { duration: '5m', target: 600 },
    { duration: '2m', target: 0 },
  ],
  thresholds: {
    http_req_duration: ['p(95)<2000'],
    http_req_failed: ['rate<0.05'],
  },
};

export default function () {
  let res = http.get('http://localhost:3000/');
  check(res, { 'status was 200': (r) => r.status == 200 });
}

步骤 4: 提交更改

git add tests/performance/
git commit -m "feat: 添加性能测试脚本"

Task 10: 创建安全测试脚本

文件:

  • 创建: tests/security/sql-injection-test.ts
  • 创建: tests/security/xss-test.ts

步骤 1: 创建SQL注入测试

创建文件 tests/security/sql-injection-test.ts

import { test, expect } from '@playwright/test';

test.describe('SQL注入防护测试', () => {
  const sqlInjectionPayloads = [
    "' OR '1'='1",
    "'; DROP TABLE users; --",
    "' UNION SELECT * FROM users --",
    "1' OR '1' = '1",
  ];

  test('登录页面应该防护SQL注入', async ({ page }) => {
    await page.goto('/admin/login');

    for (const payload of sqlInjectionPayloads) {
      await page.fill('#email', payload);
      await page.fill('#password', payload);
      await page.click('button[type="submit"]');

      // 应该显示错误信息,而不是成功登录
      await expect(page.locator('.text-red-700')).toBeVisible();
      
      // 不应该跳转到管理页面
      expect(page.url()).toContain('/admin/login');
    }
  });

  test('搜索功能应该防护SQL注入', async ({ page }) => {
    await page.goto('/');
    
    for (const payload of sqlInjectionPayloads) {
      const searchInput = page.locator('input[type="search"]');
      if (await searchInput.isVisible()) {
        await searchInput.fill(payload);
        await page.keyboard.press('Enter');
        
        // 应该显示正常结果或错误信息,而不是崩溃
        await page.waitForLoadState('networkidle');
        expect(page.url()).not.toContain('error');
      }
    }
  });
});

步骤 2: 创建XSS测试

创建文件 tests/security/xss-test.ts

import { test, expect } from '@playwright/test';

test.describe('XSS防护测试', () => {
  const xssPayloads = [
    '<script>alert("XSS")</script>',
    '<img src=x onerror=alert("XSS")>',
    'javascript:alert("XSS")',
    '<svg onload=alert("XSS")>',
  ];

  test('表单应该防护XSS攻击', async ({ page }) => {
    await page.goto('/contact');

    for (const payload of xssPayloads) {
      await page.fill('#name', payload);
      await page.fill('#email', 'test@example.com');
      await page.fill('#subject', 'Test Subject');
      await page.fill('#message', 'Test Message');
      await page.click('button[type="submit"]');

      // 应该显示成功或错误信息,而不是执行脚本
      await page.waitForLoadState('networkidle');
      
      // 检查是否有alert弹窗(不应该有)
      page.on('dialog', async dialog => {
        expect(dialog.type()).not.toBe('alert');
      });
    }
  });
});

步骤 3: 提交更改

git add tests/security/
git commit -m "feat: 添加安全测试脚本"

阶段六:文档和培训(预计 1 天)

Task 11: 更新部署文档

文件:

  • 修改: README.md
  • 创建: docs/deployment-guide.md
  • 创建: docs/monitoring-guide.md

步骤 1: 更新README

修改 README.md,添加以下内容:

## 生产部署

### 环境要求
- Node.js 18+
- Docker & Docker Compose
- 域名和SSL证书

### 部署步骤

1. 克隆代码
\`\`\`bash
git clone https://github.com/your-org/novalon-website.git
cd novalon-website
\`\`\`

2. 配置环境变量
\`\`\`bash
cp .env.production.example .env.production
# 编辑 .env.production,填入实际配置
\`\`\`

3. 启动服务
\`\`\`bash
docker-compose -f docker-compose.prod.yml up -d
\`\`\`

4. 初始化数据库
\`\`\`bash
npm run db:push
\`\`\`

5. 访问应用
打开浏览器访问 https://novalon.cn

### 监控和告警

- 错误监控: Sentry Dashboard
- 性能监控: /api/health
- 日志查看: docker logs novalon-website-app-1

### 备份和恢复

- 自动备份: 每天凌晨2点自动备份
- 手动备份: ./scripts/backup.sh
- 恢复数据: ./scripts/restore.sh <backup_file>

### 故障排查

详见: docs/troubleshooting.md

步骤 2: 创建部署指南

创建文件 docs/deployment-guide.md

# 部署指南

## 1. 环境准备

### 1.1 服务器要求
- CPU: 2核+
- 内存: 4GB+
- 磁盘: 20GB+
- 操作系统: Ubuntu 20.04+

### 1.2 软件要求
- Docker 20.10+
- Docker Compose 2.0+
- Node.js 18+ (用于本地构建)

## 2. 部署流程

### 2.1 首次部署
...

### 2.2 更新部署
...

### 2.3 回滚操作
...

## 3. 域名和SSL配置

### 3.1 域名解析
...

### 3.2 SSL证书配置
...

## 4. 监控配置

### 4.1 Sentry配置
...

### 4.2 日志收集
...

步骤 3: 创建监控指南

创建文件 docs/monitoring-guide.md

# 监控指南

## 1. 监控指标

### 1.1 应用健康
- 健康检查: /api/health
- 响应时间: < 500ms (P95)
- 错误率: < 1%

### 1.2 系统资源
- CPU使用率: < 70%
- 内存使用率: < 80%
- 磁盘使用率: < 80%

## 2. 告警规则

### 2.1 严重告警
- 应用宕机
- 数据库连接失败
- 错误率 > 5%

### 2.2 警告告警
- 响应时间 > 1s
- CPU使用率 > 80%
- 内存使用率 > 85%

## 3. 日志查看

### 3.1 Docker日志
\`\`\`bash
docker logs novalon-website-app-1 -f
\`\`\`

### 3.2 应用日志
\`\`\`bash
tail -f logs/app.log
\`\`\`

步骤 4: 提交更改

git add README.md docs/
git commit -m "docs: 更新部署和监控文档"

验收标准

阶段一验收标准

  • API测试全部通过,无跳过
  • 回归测试通过率 > 90%
  • 测试覆盖率 > 70%

阶段二验收标准

  • CI流水线正常运行
  • 代码提交自动触发测试
  • 质量门禁生效

阶段三验收标准

  • Sentry正常收集错误
  • 健康检查API正常工作
  • 性能指标可监控

阶段四验收标准

  • 生产环境配置完整
  • 备份脚本可正常执行
  • 恢复脚本可正常执行

阶段五验收标准

  • 负载测试通过
  • 压力测试通过
  • 安全测试通过

阶段六验收标准

  • 文档完整清晰
  • 团队成员了解部署流程
  • 团队成员了解监控方式

时间估算

阶段 任务数 预计时间 累计时间
阶段一 2 2天 2天
阶段二 2 3天 5天
阶段三 2 3天 8天
阶段四 2 2天 10天
阶段五 2 2天 12天
阶段六 1 1天 13天

总计:13个工作日(约2-3周)


风险和依赖

风险

  1. Sentry配置问题 - 需要提前注册账号并获取DSN
  2. Docker部署问题 - 需要运维团队支持
  3. 性能测试环境 - 需要独立的测试环境

依赖

  1. 运维团队支持 - 服务器配置、域名解析、SSL证书
  2. Sentry账号 - 错误监控服务
  3. Forgejo + Woodpecker CI - 代码托管和CI/CD服务

执行建议

  1. 优先级执行:按照阶段顺序执行,优先完成P0任务
  2. 并行执行:阶段二和阶段三可以并行进行
  3. 持续验证:每个阶段完成后进行验收测试
  4. 文档同步:实施过程中及时更新文档

后续优化

完成本计划后,可以考虑以下优化:

  1. 自动化测试增强:增加更多边界情况测试
  2. 性能优化:数据库查询优化、缓存策略优化
  3. 安全加固:定期安全审计、渗透测试
  4. 监控完善:增加业务指标监控、用户行为分析
  5. 灾备方案:多地域部署、故障自动转移