CI/CD 流水线集成
将 AI 辅助开发的项目接入 CI/CD 流水线,能够在代码进入生产环境前自动执行质量门控。这对于 AI 生成代码尤为重要,因为 AI 产出物需要经过多道自动化验证才能建立对其可靠性的信任。
流水线设计原则
针对 AI 开发项目的 CI/CD 流水线应遵循以下原则:
- 快速反馈:Lint 和单元测试在 3 分钟内完成,让开发者保持专注
- 质量门控不可绕过:任何质量门控失败都阻断合并,无例外
- 分层检测:静态分析 → 单元测试 → 集成测试 → 安全扫描 → 部署
- 环境隔离:staging 环境验证通过后方可推向 production
完整 GitHub Actions 工作流
yaml
# .github/workflows/ci.yml
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
NODE_VERSION: '20'
COVERAGE_THRESHOLD: 80
jobs:
# ── 第一阶段:静态检查(最快,先行) ──────────────────────────
lint:
name: 代码质量检查
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: 安装依赖
run: npm ci
- name: ESLint 检查
run: npm run lint -- --format=@microsoft/eslint-formatter-sarif \
--output-file eslint-results.sarif
continue-on-error: true
- name: 上传 ESLint 结果到 GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: eslint-results.sarif
- name: TypeScript 类型检查
run: npm run type-check
- name: Prettier 格式检查
run: npx prettier --check "src/**/*.{ts,tsx,json}"
# ── 第二阶段:测试与覆盖率 ──────────────────────────────────
test:
name: 单元测试与覆盖率
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- name: 运行单元测试
run: npm test -- --coverage --coverageReporters=json-summary
- name: 覆盖率门控检查
run: |
COVERAGE=$(node -e "
const s = require('./coverage/coverage-summary.json');
console.log(Math.floor(s.total.lines.pct));
")
echo "当前行覆盖率: ${COVERAGE}%"
if [ "$COVERAGE" -lt "${{ env.COVERAGE_THRESHOLD }}" ]; then
echo "覆盖率 ${COVERAGE}% 低于阈值 ${{ env.COVERAGE_THRESHOLD }}%"
exit 1
fi
- name: 上传覆盖率报告
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
# ── 第三阶段:安全扫描 ──────────────────────────────────────
security:
name: 安全扫描
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 完整历史,用于密钥扫描
- name: 依赖漏洞扫描
run: npm audit --audit-level=high
- name: 密钥泄漏扫描(git 历史)
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Semgrep 代码安全扫描
uses: semgrep/semgrep-action@v1
with:
config: >-
p/owasp-top-ten
p/javascript
p/typescript
# ── 第四阶段:构建产物 ──────────────────────────────────────
build:
name: 构建
runs-on: ubuntu-latest
needs: [test, security]
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- name: 设置 Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 登录容器仓库
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 提取镜像元数据
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=sha,prefix=sha-
type=ref,event=branch
- name: 构建并推送镜像
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ── 第五阶段:部署到 Staging ────────────────────────────────
deploy-staging:
name: 部署到预发布环境
runs-on: ubuntu-latest
needs: build
environment:
name: staging
url: https://staging.example.com
if: github.ref == 'refs/heads/develop'
steps:
- name: 部署到 Staging
run: |
curl -X POST "${{ secrets.DEPLOY_WEBHOOK_STAGING }}" \
-H "Authorization: Bearer ${{ secrets.DEPLOY_TOKEN }}" \
-d '{"image": "${{ needs.build.outputs.image-tag }}"}'
- name: 等待部署就绪
run: |
for i in {1..12}; do
STATUS=$(curl -s https://staging.example.com/health | jq -r '.status')
if [ "$STATUS" = "ok" ]; then
echo "Staging 部署成功"
exit 0
fi
echo "等待中... ($i/12)"
sleep 10
done
echo "Staging 部署超时"
exit 1
- name: 运行 E2E 冒烟测试
run: npm run test:e2e:staging
# ── 第六阶段:部署到 Production ─────────────────────────────
deploy-production:
name: 部署到生产环境
runs-on: ubuntu-latest
needs: deploy-staging
environment:
name: production
url: https://example.com
if: github.ref == 'refs/heads/main'
steps:
- name: 蓝绿部署
run: |
curl -X POST "${{ secrets.DEPLOY_WEBHOOK_PROD }}" \
-H "Authorization: Bearer ${{ secrets.DEPLOY_TOKEN }}" \
-d '{
"image": "${{ needs.build.outputs.image-tag }}",
"strategy": "blue-green"
}'
- name: 生产环境健康检查
run: |
sleep 30
curl --fail https://example.com/health质量门控配置详解
覆盖率阈值(Jest)
javascript
// jest.config.ts
export default {
coverageThreshold: {
global: {
branches: 75,
functions: 80,
lines: 80,
statements: 80,
},
// 核心业务模块要求更高覆盖率
'./src/core/**/*.ts': {
lines: 90,
},
},
};质量门控汇总
| 检查项 | 阈值 | 不通过后果 |
|---|---|---|
| ESLint error | 0 个 | 阻断 PR 合并 |
| TypeScript 类型错误 | 0 个 | 阻断 PR 合并 |
| 单元测试失败 | 0 个 | 阻断 PR 合并 |
| 代码行覆盖率 | ≥ 80% | 阻断 PR 合并 |
| npm audit 高危漏洞 | 0 个 | 阻断 PR 合并 |
| 密钥泄漏检测 | 0 条 | 阻断 PR 合并 |
| 构建产物大小增量 | ≤ 10% | 发出警告 |
部署策略
Staging → Production 流程
feature 分支
│
▼ PR 通过所有质量门控
develop 分支 ──► 自动部署 Staging ──► 人工验收测试
│
▼ Release PR
main 分支 ──► 蓝绿部署 Production ──► 监控 15 分钟 ──► 完成 / 回滚蓝绿部署说明
蓝绿部署维护两个相同的生产环境(蓝色=当前,绿色=新版本):
- 新版本部署到绿色环境,蓝色继续接收流量
- 健康检查通过后,负载均衡器将流量切换到绿色
- 观察 15 分钟,错误率和响应时间无异常则部署完成
- 如发现问题,将流量切回蓝色(秒级回滚)
回滚程序
自动回滚触发条件
yaml
# .github/workflows/rollback-monitor.yml
name: 生产监控与自动回滚
on:
workflow_dispatch:
inputs:
target-sha:
description: '回滚到的 commit SHA'
required: true
jobs:
rollback:
runs-on: ubuntu-latest
environment: production
steps:
- name: 执行回滚
run: |
echo "回滚到版本: ${{ inputs.target-sha }}"
curl -X POST "${{ secrets.DEPLOY_WEBHOOK_PROD }}" \
-H "Authorization: Bearer ${{ secrets.DEPLOY_TOKEN }}" \
-d '{"image": "ghcr.io/org/app:sha-${{ inputs.target-sha }}"}'
- name: 通知团队
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "生产环境已回滚到 ${{ inputs.target-sha }},原因:${{ inputs.reason }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}手动回滚命令(紧急情况)
bash
# 查看最近的成功部署镜像
gh run list --workflow=ci.yml --status=success --limit=5
# 触发回滚工作流
gh workflow run rollback-monitor.yml \
-f target-sha=<上一个稳定版本的SHA>本地开发与 CI 对齐
确保本地运行与 CI 结果一致,避免"在我机器上没问题":
json
// package.json
{
"scripts": {
"lint": "eslint src/",
"type-check": "tsc --noEmit",
"test": "jest",
"test:coverage": "jest --coverage",
"ci": "npm run lint && npm run type-check && npm run test:coverage",
"ci:security": "npm audit --audit-level=high"
}
}在提交 PR 前,开发者应在本地运行 npm run ci 确认所有检查通过,减少 CI 失败返工成本。