码巢引擎2026年开发文档
00-开发规范
后端规范
README
后端开发手册
前端规范
README
TypeScript最佳实践
前端布局规范
前端页面模板
前端颜色与组件规范
核心规范
组件配置手册
问题排查指南
页面模板
最佳实践
README
bp-20260223-m7ps
图片上传优化总结
BUG自动记录系统使用指南
README
TYPE_SAFETY_GUIDE
常见BUG知识库
常见BUG知识库
开发前检查清单
开发安全规范
开发规范-完整版-含FutureBirdAadminAi部署
数据模型字典
文档分类规范
文档标准化规范
文档模板-基础版
文档模板-技术版
类型安全快速参考卡
类型安全规范体系
规范更新指南
过期文档清理机制
错误处理规范
错误预防指南
常见BUG知识库
常见BUG知识库
01-快速开始
Gitee快速开始
README
协作快速开始
快速开始
质量保证快速开始
02-部署指南
Docker更新指南
Docker部署
FutureBirdAadminAi部署指南
FutureBirdAadminAi部署问题分析
README
发布指南
宝塔Docker部署教程
宝塔PM2部署教程
宝塔图形化部署教程
快速发布指南
数据库和依赖变更处理指南
构建和发布
构建标准
构建检查清单
生产部署快速开始
生产部署方案
生产部署标准
生产部署检查清单
程序备份性能
自动修复和发布指南
自动化发布命令使用指南
部署快速开始
部署指南
项目更新部署指南
03-开发指南
Git凭据配置
Git推送规则
Git自动配置
README
全局样式
协作设置
定时任务
开发指南
开发流程
开发环境标准
技术改进
贡献指南
项目目录树
项目目录结构
04-API文档
API接口文档
README
hr-api
企业API
05-数据库
DATABASE_SCHEMA
README
分区指南
数据库字典
数据持久化
数据模型统一
数据迁移
06-架构设计
RBAC-PERMISSIONS
README
SaaS客户引导流程设计
companyId统一规范
employee-permission-system-design
enterprise-data-linkage
仓库实现总结
仓库模式
企业管理端员工权限系统分析
前端架构
前端重构总结
员工权限系统评估报告
员工管理菜单重构方案
权限系统混乱问题分析
架构优化计划
架构使用指南
架构结构
架构结构
状态管理
用户身份管理体系
系统架构
面试管理模块重构规划
项目技术栈
07-测试质量
README
测试修复标准
测试报告
质量保证系统
08-版本管理
CHANGELOG
README
VERSION_RULES
09-配置指南
README
SMTP配置指南
主题切换指南
渠道配置指南
环境变量指南
环境隔离
12-项目记忆
README
知识库导入指南
记忆系统指南
13-迁移指南
README
备份迁移指南
管理员迁移指南
迁移快速开始
17-其他
README
压缩摘要
18-开放平台
01-架构设计
02-API接口设计
03-安全机制
04-前端设计
05-数据库设计
开放平台API指南
开放平台API说明
19-智能进化
AI执行规则
AI进化机制
README
自动化实现总览
黄金规则
40-操作教程
README
微信公众号域名配置指南
微信本地开发调试指南
44-技能文件
alipay-payment-integration
references
checklist
SKILL
audio
python
README
typescript
README
SKILL
database
python
README
typescript
README
SKILL
design-style-thinking
SKILL
doctor
references
sql-patterns
SKILL
document-generation
python
README
SKILL
email
SKILL
embedding
python
README
typescript
README
SKILL
expo-advanced
references
audio-record-play
file-upload
masonry-layout
save-to-gallery
top-tab-navigation
SKILL
feishu-base
SKILL
feishu-message
SKILL
fetch-url
python
README
typescript
README
SKILL
frontend-design
LICENSE
SKILL
FutureBird-coding-web-performance-best-practice
SKILL
general-dev-preview
references
web-preview
SKILL
image-generation
python
README
typescript
README
SKILL
knowledge
references
python
README
typescript
README
cli
SKILL
llm
python
README
typescript
README
SKILL
miniapp-upload-asr
SKILL
pptx-generation
python
README
SKILL
project-memory-loader
scripts
project_memory_loader
SKILL
repair
scripts
merge-commit-map
SKILL
shadcn-web-base-theme
assets
colors
amber
artistic-green
bento-blue
blue
cyan
emerald
fuchsia
gray
green
indigo
lime
low-pink
neutral
orange
purple
red
retro-brown
rose
sky
supbase-green
teal
tech-purple
vintage-grey
violet
yellow
fonts
business
classic
playful
radius
2xl
2xs
lg
md
none
sm
xl
xs
shadow
artistic
bento
cool
retro
superbase
tech
tool
vintage
default
references
colors
fonts
quick
radius
shadows
scripts
theme
SKILL
package
skill-creator-coze
scripts
init_skill
quick_validate
SKILL
storage
python
README
typescript
README
SKILL
supabase
assets
supabase-client
supabase-client
references
_future
asset-supabase-browser
asset-supabase-config-inject
asset-supabase-config-route
python-auth
python-realtime
python-storage
typescript-auth
typescript-realtime
typescript-storage
typescript-supabase-browser
typescript-supabase-config-inject
typescript-supabase-config-route
python
README
database
edge-functions
orm-model-guide
supabase_client
typescript
README
database
drizzle-schema-guide
edge-functions
supabase-client
cli
rls
SKILL
supabase-auth
references
typescript
supabase-browser
supabase-config-inject
supabase-config-route
auth-config
verify-session
SKILL
ui-design-ref
reference
3D黏土风
克莱因蓝高定风
暗黑科技风
杂志风
极光柔和
柔和卡片
玻璃拟态
纯白极简风
自然有机
SKILL
ui-ux-pro-max
scripts
core
design_system
search
SKILL
vercel-composition-patterns
rules
architecture-avoid-boolean-props
architecture-compound-components
patterns-children-over-render-props
patterns-explicit-variants
react19-no-forwardref
state-context-interface
state-decouple-implementation
state-lift-state
AGENTS
SKILL
vercel-react-best-practices
rules
advanced-event-handler-refs
advanced-init-once
advanced-use-latest
async-api-routes
async-defer-await
async-dependencies
async-parallel
async-suspense-boundaries
bundle-barrel-imports
bundle-conditional
bundle-defer-third-party
bundle-dynamic-imports
bundle-preload
client-event-listeners
client-localstorage-schema
client-passive-event-listeners
client-swr-dedup
js-batch-dom-css
js-cache-function-results
js-cache-property-access
js-cache-storage
js-combine-iterations
js-early-exit
js-hoist-regexp
js-index-maps
js-length-check-first
js-min-max-loop
js-set-map-lookups
js-tosorted-immutable
rendering-activity
rendering-animate-svg-wrapper
rendering-conditional-render
rendering-content-visibility
rendering-hoist-jsx
rendering-hydration-no-flicker
rendering-hydration-suppress-warning
rendering-svg-precision
rendering-usetransition-loading
rerender-defer-reads
rerender-dependencies
rerender-derived-state-no-effect
rerender-derived-state
rerender-functional-setstate
rerender-lazy-state-init
rerender-memo-with-default-value
rerender-memo
rerender-move-effect-to-event
rerender-simple-expression-in-memo
rerender-transitions
rerender-use-ref-transient-values
server-auth-actions
server-cache-lru
server-cache-react
server-dedup-props
server-parallel-fetching
server-serialization
AGENTS
SKILL
video-edit
python
README
typescript
README
SKILL
video-generation
python
README
typescript
README
SKILL
volcano-ark
SKILL
web-design-guidelines
SKILL
web-search
python
README
typescript
README
SKILL
webrtc-best-practice
SKILL
websocket-guide
references
nextjs
nodejs
SKILL
wechat-bot
SKILL
wechat-official-account
SKILL
README
README
未来鸟:企业数字化转型奔腾的力量!
-
+
首页
质量保证系统
> **文档版本**: v1.0.0 > **创建日期**: 2026-02-12 > **最后更新**: 2026-02-12 > **维护人**: 未来鸟FutureBird码巢企业服务引擎开发组 > **状态**: [最新] --- # 代码质量保障体系 本文档定义了企业管理数字化中台的代码质量保障流程和规范,旨在从源头减少 BUG 出现的概率,避免陷入"修一个出一个"的死循环。 --- ## 🎯 核心原则 ### 1. 左移测试(Shift Left) - 在代码编写阶段就进行质量检查 - 提前发现问题,降低修复成本 ### 2. 多层防护 - Lint → 类型检查 → 单元测试 → 集成测试 → E2E 测试 - 每一层都能捕获不同类型的 BUG ### 3. 自动化优先 - 尽可能自动化质量检查 - 减少人为疏忽 ### 4. 渐进式改进 - 不要求一次性完美 - 逐步完善质量保障体系 --- ## 📊 质量保障金字塔 ``` ┌─────────────┐ │ E2E Tests │ 关键用户流程(10%) │ (少量) │ └─────────────┘ ┌───────────────┐ │ Integration │ API 和数据库交互(20%) │ Tests │ └───────────────┘ ┌─────────────────┐ │ Unit Tests │ 核心业务逻辑(50%) │ (核心) │ └─────────────────┘ ┌───────────────────┐ │ TypeScript & │ 类型安全(100%) │ Lint │ └───────────────────┘ ┌─────────────────────┐ │ Pre-commit Hooks │ 提交前检查(100%) └─────────────────────┘ ``` --- ## 🛡️ 防御体系详解 ### 第一层:Pre-commit Hooks(提交前检查) **目标**: 阻止有问题的代码提交到仓库 **工具**: Husky + lint-staged **检查项**: ```bash ✅ ESLint 检查 ✅ Prettier 格式化 ✅ TypeScript 类型检查 ✅ 单元测试通过 ``` **配置文件**: `.husky/pre-commit` ```bash #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" # 运行 lint-staged pnpm lint-staged # 类型检查 pnpm type-check # 运行单元测试 pnpm test:unit ``` **配置文件**: `lint-staged.config.js` ```javascript module.exports = { '*.{js,jsx,ts,tsx}': [ 'eslint --fix', 'prettier --write', () => 'pnpm type-check --noEmit' ], '*.{json,md,yml,yaml}': [ 'prettier --write' ] }; ``` --- ### 第二层:Lint 和 TypeScript(静态分析) **目标**: 在编译前发现语法和类型错误 #### ESLint 配置 **规则优先级**: 1. **错误级别(Error)** - 必须修复,代码无法提交 - 未使用的变量 - 重复的变量声明 - 必需的属性缺失 - 类型不匹配 2. **警告级别(Warning)** - 强烈建议修复 - 未使用的参数 - 潜在的空值引用 - 性能问题 **配置文件**: `.eslintrc.js` ```javascript module.exports = { extends: [ 'next/core-web-vitals', 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/stylistic', 'prettier' ], rules: { // 错误级别 '@typescript-eslint/no-unused-vars': 'error', '@typescript-eslint/no-explicit-any': 'error', '@typescript-eslint/explicit-function-return-type': 'warn', '@typescript-eslint/no-non-null-assertion': 'error', // React 相关 'react/no-unescaped-entities': 'off', 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn', // 代码风格 'no-console': ['warn', { allow: ['warn', 'error'] }], 'prefer-const': 'error', 'no-var': 'error' } }; ``` #### TypeScript 配置 **严格模式**: 启用所有严格检查 **配置文件**: `tsconfig.json` ```json { "compilerOptions": { "strict": true, "noUncheckedIndexedAccess": true, "noImplicitOverride": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noImplicitReturns": true, "skipLibCheck": true } } ``` --- ### 第三层:单元测试(核心业务逻辑) **目标**: 验证函数和组件的正确性 **测试框架**: Jest + React Testing Library **覆盖率目标**: - 核心业务逻辑: ≥ 80% - API 路由: ≥ 70% - 工具函数: ≥ 90% **测试策略**: #### 1. 工具函数测试 **示例**: `src/lib/utils.test.ts` ```typescript import { formatDate, calculateSalary } from './utils'; describe('formatDate', () => { it('应该正确格式化日期', () => { const date = new Date('2024-01-15'); expect(formatDate(date)).toBe('2024-01-15'); }); it('应该处理空值', () => { expect(formatDate(null)).toBe('-'); }); }); describe('calculateSalary', () => { it('应该正确计算基本工资', () => { const result = calculateSalary({ baseSalary: 10000, overtimeHours: 0, overtimeRate: 1.5 }); expect(result).toBe(10000); }); it('应该正确计算加班费', () => { const result = calculateSalary({ baseSalary: 10000, overtimeHours: 10, overtimeRate: 1.5, hourlyRate: 50 }); expect(result).toBe(10750); }); }); ``` #### 2. 组件测试 **示例**: `src/components/EmployeeForm.test.tsx` ```typescript import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import EmployeeForm from './EmployeeForm'; describe('EmployeeForm', () => { it('应该渲染表单字段', () => { render(<EmployeeForm />); expect(screen.getByLabelText('姓名')).toBeInTheDocument(); expect(screen.getByLabelText('部门')).toBeInTheDocument(); }); it('应该验证必填字段', async () => { render(<EmployeeForm />); const submitButton = screen.getByText('提交'); fireEvent.click(submitButton); await waitFor(() => { expect(screen.getByText('姓名不能为空')).toBeInTheDocument(); }); }); it('应该成功提交表单', async () => { const onSubmit = jest.fn(); render(<EmployeeForm onSubmit={onSubmit} />); fireEvent.change(screen.getByLabelText('姓名'), { target: { value: '张三' } }); fireEvent.click(screen.getByText('提交')); await waitFor(() => { expect(onSubmit).toHaveBeenCalledWith({ name: '张三' }); }); }); }); ``` #### 3. API 路由测试 **示例**: `src/app/api/v1/employees/route.test.ts` ```typescript import { POST } from './route'; import { NextRequest } from 'next/server'; describe('POST /api/v1/employees', () => { it('应该创建新员工', async () => { const request = new NextRequest('http://localhost:5000/api/v1/employees', { method: 'POST', body: JSON.stringify({ name: '张三', department: '技术部', salary: 10000 }) }); const response = await POST(request); const data = await response.json(); expect(response.status).toBe(201); expect(data.success).toBe(true); expect(data.data.name).toBe('张三'); }); it('应该验证必填字段', async () => { const request = new NextRequest('http://localhost:5000/api/v1/employees', { method: 'POST', body: JSON.stringify({ name: '' // 名称为空 }) }); const response = await POST(request); const data = await response.json(); expect(response.status).toBe(400); expect(data.success).toBe(false); expect(data.error).toContain('姓名不能为空'); }); }); ``` **测试命令**: ```bash # 运行所有测试 pnpm test # 运行单元测试 pnpm test:unit # 运行测试并生成覆盖率报告 pnpm test:coverage # 监听模式(开发时使用) pnpm test:watch ``` --- ### 第四层:集成测试(API 和数据库) **目标**: 验证 API 和数据库的交互是否正确 **工具**: Jest + Supertest + Test Database **测试策略**: #### 1. API 集成测试 **示例**: `src/app/api/v1/email/send-test/route.integration.test.ts` ```typescript import { POST } from './route'; import { NextRequest } from 'next/server'; // 使用测试数据库 const TEST_DATABASE_URL = process.env.TEST_DATABASE_URL; describe('POST /api/v1/email/send-test', () => { beforeAll(async () => { // 初始化测试数据库 await initializeTestDatabase(); }); afterAll(async () => { // 清理测试数据库 await cleanupTestDatabase(); }); it('应该成功发送测试邮件', async () => { const request = new NextRequest('http://localhost:5000/api/v1/email/send-test', { method: 'POST', body: JSON.stringify({ to: 'test@example.com', subject: '测试邮件', smtpConfig: { host: 'smtp.example.com', port: 587, secure: false, user: 'test@example.com', password: 'test-password' } }) }); const response = await POST(request); const data = await response.json(); expect(response.status).toBe(200); expect(data.success).toBe(true); expect(data.message).toContain('邮件发送成功'); }); it('应该处理连接失败', async () => { const request = new NextRequest('http://localhost:5000/api/v1/email/send-test', { method: 'POST', body: JSON.stringify({ to: 'test@example.com', smtpConfig: { host: 'invalid-host', port: 587, secure: false, user: 'test@example.com', password: 'test-password' } }) }); const response = await POST(request); const data = await response.json(); expect(response.status).toBe(500); expect(data.success).toBe(false); expect(data.code).toBe('CONNECTION_ERROR'); }); it('应该验证 SMTP 配置', async () => { const request = new NextRequest('http://localhost:5000/api/v1/email/send-test', { method: 'POST', body: JSON.stringify({ to: 'test@example.com', smtpConfig: { host: '', // 缺少必需字段 port: 587 } }) }); const response = await POST(request); const data = await response.json(); expect(response.status).toBe(400); expect(data.success).toBe(false); expect(data.code).toBe('VALIDATION_ERROR'); }); }); ``` **测试命令**: ```bash # 运行集成测试 pnpm test:integration # 使用测试数据库 TEST_DATABASE_URL="postgresql://test:test@localhost:5432/test_db" pnpm test:integration ``` --- ### 第五层:E2E 测试(端到端测试) **目标**: 验证关键用户流程的完整性 **工具**: Playwright **测试场景**: 1. **用户登录流程** 2. **创建员工流程** 3. **创建工资表流程** 4. **发送工资条流程** 5. **配置邮件服务流程** **示例**: `tests/e2e/email-config.spec.ts` ```typescript import { test, expect } from '@playwright/test'; test.describe('邮件配置功能', () => { test.beforeEach(async ({ page }) => { // 登录 await page.goto('/login'); await page.fill('input[name="username"]', 'admin'); await page.fill('input[name="password"]', 'admin123'); await page.click('button[type="submit"]'); await page.waitForURL('/admin/dashboard'); }); test('应该成功配置 SMTP 服务', async ({ page }) => { // 导航到邮件配置页面 await page.goto('/admin/settings/integrations/email'); // 填写表单 await page.fill('input[name="host"]', 'smtp.163.com'); await page.fill('input[name="port"]', '465'); await page.fill('input[name="user"]', 'test@163.com'); await page.fill('input[name="password"]', 'test-password'); // 保存配置 await page.click('button:has-text("保存配置")'); // 验证保存成功 await expect(page.locator('.ant-message-success')).toBeVisible(); // 验证配置已保存 const host = await page.inputValue('input[name="host"]'); expect(host).toBe('smtp.163.com'); }); test('应该成功发送测试邮件', async ({ page }) => { await page.goto('/admin/settings/integrations/email'); // 配置 SMTP await page.fill('input[name="host"]', 'smtp.163.com'); await page.fill('input[name="port"]', '465'); await page.fill('input[name="user"]', 'test@163.com'); await page.click('button:has-text("保存配置")'); // 打开测试邮件弹窗 await page.click('button:has-text("发送测试邮件")'); // 等待弹窗打开 await expect(page.locator('.ant-modal')).toBeVisible(); // 填写测试邮件表单 await page.fill('input[name="to"]', 'test@example.com'); await page.fill('input[name="password"]', 'test-password'); // 发送测试邮件 await page.click('button:has-text("发送")'); // 验证发送成功 await expect(page.locator('.ant-message-success')).toBeVisible(); await expect(page.locator('text=邮件发送成功')).toBeVisible(); }); }); ``` **测试命令**: ```bash # 运行 E2E 测试 pnpm test:e2e # 运行 E2E 测试(可视化模式) pnpm test:e2e:ui # 运行 E2E 测试(调试模式) pnpm test:e2e:debug ``` --- ## 🚀 构建流程 ### 开发构建(开发环境) ```bash # 步骤 1: 代码检查 pnpm lint # 步骤 2: 类型检查 pnpm type-check # 步骤 3: 运行测试(快速) pnpm test:unit # 步骤 4: 启动开发服务器 pnpm dev ``` ### 生产构建(正式环境) ```bash # 步骤 1: 清理构建缓存 rm -rf .next node_modules/.cache # 步骤 2: 代码检查 pnpm lint # 步骤 3: 类型检查(严格) pnpm type-check # 步骤 4: 运行所有测试 pnpm test # 步骤 5: 生成测试覆盖率报告 pnpm test:coverage # 步骤 6: 检查覆盖率是否达标 pnpm test:coverage:check # 步骤 7: 构建生产版本 pnpm build # 步骤 8: 验证构建产物 pnpm build:verify # 步骤 9: 启动生产服务器 pnpm start ``` **构建验证脚本**: `scripts/build-verify.sh` ```bash #!/bin/bash set -e echo "🔍 验证构建产物..." # 检查构建目录 if [ ! -d ".next" ]; then echo "❌ 构建目录不存在" exit 1 fi # 检查关键文件 if [ ! -f ".next/BUILD_ID" ]; then echo "❌ BUILD_ID 不存在" exit 1 fi # 检查静态资源 if [ ! -d ".next/static" ]; then echo "❌ 静态资源目录不存在" exit 1 fi echo "✅ 构建验证通过" ``` --- ## 📦 发布流程 ### 分支管理策略 ``` main (生产分支) ↑ develop (开发分支) ↑ feature/xxx (功能分支) ↑ bugfix/xxx (修复分支) ``` **分支规则**: 1. **main 分支** - 只接受来自 develop 的合并 - 只能通过 Pull Request 合并 - 必须通过所有检查 2. **develop 分支** - 开发主分支 - 每个功能完成后合并到这里 - 每天自动运行测试 3. **feature 分支** - 从 develop 分支创建 - 命名格式: `feature/功能名称` - 完成后合并回 develop 4. **bugfix 分支** - 从 develop 或 main 分支创建 - 命名格式: `bugfix/问题描述` - 完成后合并回对应的分支 ### Pull Request 流程 **PR 检查项**: ```yaml ✅ 代码审查(至少 1 人批准) ✅ CI 检查通过 ✅ 所有测试通过 ✅ 测试覆盖率不降低 ✅ 无安全漏洞 ✅ 文档已更新(如需要) ✅ CHANGELOG 已更新 ``` **PR 模板**: `.github/pull_request_template.md` ```markdown ## 变更描述 <!-- 简要描述本次变更的内容和目的 --> ## 变更类型 - [ ] 新功能 (feature) - [ ] Bug 修复 (bugfix) - [ ] 性能优化 (performance) - [ ] 重构 (refactor) - [ ] 文档更新 (docs) - [ ] 测试更新 (tests) - [ ] 其他 (other) ## 测试情况 - [ ] 单元测试已添加/更新 - [ ] 集成测试已添加/更新 - [ ] E2E 测试已添加/更新 - [ ] 手动测试已通过 ## 影响范围 <!-- 描述本次变更可能影响的功能模块 --> ## 截图/录屏 <!-- 如有 UI 变更,请提供截图或录屏 --> ## 检查清单 - [ ] 代码符合团队规范 - [ ] 已通过 ESLint 检查 - [ ] 已通过 TypeScript 类型检查 - [ ] 已运行所有测试 - [ ] 已更新相关文档 - [ ] 已更新 CHANGELOG ``` ### CI/CD 流程 **GitHub Actions 配置**: `.github/workflows/ci.yml` ```yaml name: CI on: pull_request: branches: [main, develop] push: branches: [main, develop] jobs: lint: name: 代码检查 runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: 设置 Node.js uses: actions/setup-node@v3 with: node-version: 20 cache: 'pnpm' - name: 安装依赖 run: pnpm install --frozen-lockfile - name: ESLint 检查 run: pnpm lint - name: 类型检查 run: pnpm type-check test: name: 运行测试 runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: 设置 Node.js uses: actions/setup-node@v3 with: node-version: 20 cache: 'pnpm' - name: 安装依赖 run: pnpm install --frozen-lockfile - name: 设置测试数据库 run: pnpm test:db:setup - name: 运行单元测试 run: pnpm test:unit - name: 运行集成测试 run: pnpm test:integration env: TEST_DATABASE_URL: postgresql://test:test@localhost:5432/test_db - name: 上传覆盖率报告 uses: codecov/codecov-action@v3 build: name: 构建项目 runs-on: ubuntu-latest needs: [lint, test] steps: - uses: actions/checkout@v3 - name: 设置 Node.js uses: actions/setup-node@v3 with: node-version: 20 cache: 'pnpm' - name: 安装依赖 run: pnpm install --frozen-lockfile - name: 构建项目 run: pnpm build - name: 验证构建产物 run: pnpm build:verify e2e: name: E2E 测试 runs-on: ubuntu-latest needs: [build] steps: - uses: actions/checkout@v3 - name: 设置 Node.js uses: actions/setup-node@v3 with: node-version: 20 cache: 'pnpm' - name: 安装依赖 run: pnpm install --frozen-lockfile - name: 安装 Playwright run: pnpm exec playwright install --with-deps - name: 运行 E2E 测试 run: pnpm test:e2e - name: 上传测试报告 uses: actions/upload-artifact@v3 if: always() with: name: playwright-report path: playwright-report/ ``` --- ## 🔄 环境隔离 ### 环境配置 ``` ┌─────────────────┐ │ 本地开发 │ .env.local │ Development │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 开发环境 │ .env.development │ Dev Server │ dev.example.com └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 测试环境 │ .env.test │ Test Server │ test.example.com └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 预发布环境 │ .env.staging │ Staging │ staging.example.com └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 生产环境 │ .env.production │ Production │ example.com └─────────────────┘ ``` **环境变量配置**: ```bash # 本地开发(.env.local) DATABASE_URL=postgresql://dev:dev@localhost:5432/payroll_dev NEXT_PUBLIC_APP_URL=http://localhost:5000 NODE_ENV=development # 开发环境(.env.development) DATABASE_URL=postgresql://dev:dev@dev-db.example.com:5432/payroll_dev NEXT_PUBLIC_APP_URL=https://dev.example.com NODE_ENV=development # 测试环境(.env.test) DATABASE_URL=postgresql://test:test@test-db.example.com:5432/payroll_test NEXT_PUBLIC_APP_URL=https://test.example.com NODE_ENV=test # 预发布环境(.env.staging) DATABASE_URL=postgresql://staging:staging@staging-db.example.com:5432/payroll_staging NEXT_PUBLIC_APP_URL=https://staging.example.com NODE_ENV=staging # 生产环境(.env.production) DATABASE_URL=postgresql://prod:prod@prod-db.example.com:5432/payroll?sslmode=require NEXT_PUBLIC_APP_URL=https://example.com NODE_ENV=production ``` --- ## 🎨 灰度发布 ### 发布策略 **1. 金丝雀发布(Canary Release)** 逐步将新版本发布给一小部分用户,监控反馈后再全量发布。 **步骤**: ```bash # 1. 发布到 5% 用户 kubectl rollout deployment payroll --replicas=1 --namespace=canary # 2. 观察 24 小时 # 检查错误日志、用户反馈、性能指标 # 3. 如果正常,扩大到 20% kubectl rollout deployment payroll --replicas=2 --namespace=canary # 4. 继续观察,逐步扩大到 50%、100% # 5. 全量发布 kubectl rollout deployment payroll --replicas=5 --namespace=production ``` **2. 蓝绿部署(Blue-Green Deployment)** 准备两个相同的生产环境,新版本部署到绿环境,验证通过后切换流量。 **步骤**: ```bash # 1. 部署新版本到绿环境 kubectl apply -f deployment-green.yaml # 2. 验证绿环境 curl https://green.example.com/health # 3. 切换流量到绿环境 kubectl patch service payroll -p '{"spec":{"selector":{"version":"green"}}}' # 4. 观察绿环境运行情况 # 5. 如果正常,保留绿环境,删除蓝环境 # 如果有问题,快速切回蓝环境 ``` --- ## 🔄 回滚机制 ### 快速回滚 **1. Git 回滚** ```bash # 回滚到上一个版本 git revert HEAD git push origin main # 回滚到指定版本 git revert <commit-hash> git push origin main ``` **2. Docker 回滚** ```bash # 回滚到上一个镜像 kubectl rollout undo deployment payroll # 回滚到指定版本 kubectl rollout undo deployment payroll --to-revision=3 ``` **3. 数据库回滚** ```bash # 回滚最后一个迁移 pnpm db:migrate:rollback # 回滚到指定版本 pnpm db:migrate:rollback --to=<migration-name> ``` --- ## 📊 监控和告警 ### 监控指标 **应用指标**: - 错误率 - 响应时间 - QPS (每秒查询数) - 内存使用率 - CPU 使用率 **业务指标**: - 用户活跃度 - 功能使用率 - 转化率 ### 告警规则 ```yaml # 错误率超过 1% - alert: HighErrorRate expr: error_rate > 0.01 for: 5m annotations: summary: "错误率过高" # 响应时间超过 1 秒 - alert: HighResponseTime expr: response_time > 1000 for: 5m annotations: summary: "响应时间过长" # 内存使用率超过 80% - alert: HighMemoryUsage expr: memory_usage > 0.8 for: 10m annotations: summary: "内存使用率过高" ``` --- ## 📝 开发规范 ### 代码编写规范 1. **类型安全** ```typescript // ✅ 好 interface User { id: string; name: string; email: string; } function getUser(id: string): Promise<User> { // ... } // ❌ 不好 function getUser(id: any): any { // ... } ``` 2. **错误处理** ```typescript // ✅ 好 try { const result = await fetchData(); return { success: true, data: result }; } catch (error) { console.error('获取数据失败:', error); return { success: false, error: '获取数据失败' }; } // ❌ 不好 const result = await fetchData(); return result; ``` 3. **参数验证** ```typescript // ✅ 好 function sendEmail(to: string, subject: string, content: string) { if (!to || !subject || !content) { throw new Error('缺少必需参数'); } // 发送邮件 } // ❌ 不好 function sendEmail(to: string, subject: string, content: string) { // 直接发送,不验证 } ``` 4. **防御性编程** ```typescript // ✅ 好 function getValue(obj: Record<string, unknown>, key: string): string { const value = obj[key]; return typeof value === 'string' ? value : ''; } // ❌ 不好 function getValue(obj: Record<string, unknown>, key: string): string { return obj[key] as string; // 可能是 undefined } ``` ### Git 提交规范 **提交消息格式**: ``` <type>(<scope>): <subject> <body> <footer> ``` **类型 (type)**: - `feat`: 新功能 - `fix`: Bug 修复 - `docs`: 文档更新 - `style`: 代码格式调整(不影响功能) - `refactor`: 重构 - `perf`: 性能优化 - `test`: 测试相关 - `chore`: 构建/工具相关 - `ci`: CI/CD 相关 **示例**: ```bash # 新功能 git commit -m "feat(email): 添加测试邮件发送功能" # Bug 修复 git commit -m "fix(email): 修复弹窗闪退问题" # 文档更新 git commit -m "docs(readme): 更新部署文档" # 性能优化 git commit -m "perf(salary): 优化工资表计算性能" ``` --- ## 🎯 快速检查清单 ### 提交代码前检查 - [ ] 代码已通过 ESLint 检查 - [ ] 代码已通过 TypeScript 类型检查 - [ ] 代码已通过 Prettier 格式化 - [ ] 单元测试已添加/更新 - [ ] 所有测试通过 - [ ] 无 console.log 调试代码 - [ ] 无 TODO 或 FIXME(除非有必要) - [ ] 提交消息符合规范 ### 发布前检查 - [ ] 所有测试通过 - [ ] 测试覆盖率达标 - [ ] 已在测试环境验证 - [ ] 已在预发布环境验证 - [ ] CHANGELOG 已更新 - [ ] 文档已更新 - [ ] 回滚方案已准备 - [ ] 监控已配置 --- ## 📚 参考资源 - [Next.js 测试最佳实践](https://nextjs.org/docs/testing) - [Jest 官方文档](https://jestjs.io/) - [React Testing Library](https://testing-library.com/react) - [Playwright 官方文档](https://playwright.dev/) - [GitHub Actions 文档](https://docs.github.com/en/actions) --- ## 🎉 总结 通过这套质量保障体系,你可以: 1. **从源头减少 BUG**: Lint + TypeScript + Pre-commit Hooks 2. **提前发现问题**: 单元测试 + 集成测试 3. **验证用户流程**: E2E 测试 4. **保证发布质量**: CI/CD + 代码审查 5. **快速发现问题**: 监控告警 6. **快速恢复服务**: 回滚机制 记住:**质量不是测试出来的,而是设计和构建出来的**。
未来鸟
2026年7月27日 10:39
转发
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
分享
链接
类型
密码
更新密码
有效期
Markdown文件
Word文件
PDF文档(打印)
AI