name: CI on: push: pull_request: permissions: contents: read jobs: # ========================================================================== # 后端测试(与前端并行运行) # ========================================================================== backend-test: runs-on: ubuntu-latest services: postgres: image: postgres:16-alpine env: POSTGRES_USER: test POSTGRES_PASSWORD: test POSTGRES_DB: sub2api_test ports: - 5432:5432 options: >- --health-cmd "pg_isready -U test" --health-interval 10s --health-timeout 5s --health-retries 5 redis: image: redis:7-alpine ports: - 6379:6379 options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: backend/go.mod check-latest: false cache: true - name: 验证 Go 版本 run: go version | grep -q 'go1.25.7' - name: 单元测试 working-directory: backend run: make test-unit - name: 集成测试 working-directory: backend env: DATABASE_URL: postgres://test:test@localhost:5432/sub2api_test?sslmode=disable REDIS_URL: redis://localhost:6379/0 run: make test-integration - name: Race 检测 working-directory: backend run: go test -tags=unit -race -count=1 ./... - name: 覆盖率收集 working-directory: backend run: | go test -tags=unit -coverprofile=coverage.out -count=1 ./... echo "## 后端测试覆盖率" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY go tool cover -func=coverage.out | tail -1 >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY - name: 覆盖率门禁(≥8%) working-directory: backend run: | COVERAGE=$(go tool cover -func=coverage.out | tail -1 | awk '{print $3}' | sed 's/%//') echo "当前覆盖率: ${COVERAGE}%" if [ "$(echo "$COVERAGE < 8" | bc -l)" -eq 1 ]; then echo "::error::后端覆盖率 ${COVERAGE}% 低于门禁值 8%" exit 1 fi # ========================================================================== # 后端代码检查 # ========================================================================== golangci-lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: backend/go.mod check-latest: false cache: true - name: 验证 Go 版本 run: go version | grep -q 'go1.25.7' - name: golangci-lint uses: golangci/golangci-lint-action@v9 with: version: v2.7 args: --timeout=5m working-directory: backend # ========================================================================== # 前端测试(与后端并行运行) # ========================================================================== frontend-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 安装 pnpm uses: pnpm/action-setup@v4 with: version: 9 - name: 安装 Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm' cache-dependency-path: frontend/pnpm-lock.yaml - name: 安装依赖 working-directory: frontend run: pnpm install --frozen-lockfile - name: 类型检查 working-directory: frontend run: pnpm run typecheck - name: Lint 检查 working-directory: frontend run: pnpm run lint:check - name: 单元测试 working-directory: frontend run: pnpm run test:run - name: 覆盖率收集 working-directory: frontend run: | pnpm run test:coverage -- --exclude '**/integration/**' || true echo "## 前端测试覆盖率" >> $GITHUB_STEP_SUMMARY if [ -f coverage/coverage-final.json ]; then echo "覆盖率报告已生成" >> $GITHUB_STEP_SUMMARY fi - name: 覆盖率门禁(≥20%) working-directory: frontend run: | if [ ! -f coverage/coverage-final.json ]; then echo "::warning::覆盖率报告未生成,跳过门禁检查" exit 0 fi # 使用 node 解析覆盖率 JSON COVERAGE=$(node -e " const data = require('./coverage/coverage-final.json'); let totalStatements = 0, coveredStatements = 0; for (const file of Object.values(data)) { const stmts = file.s; totalStatements += Object.keys(stmts).length; coveredStatements += Object.values(stmts).filter(v => v > 0).length; } const pct = totalStatements > 0 ? (coveredStatements / totalStatements * 100) : 0; console.log(pct.toFixed(1)); ") echo "当前前端覆盖率: ${COVERAGE}%" if [ "$(echo "$COVERAGE < 20" | bc -l 2>/dev/null || node -e "console.log($COVERAGE < 20 ? 1 : 0)")" = "1" ]; then echo "::warning::前端覆盖率 ${COVERAGE}% 低于门禁值 20%(当前为警告,不阻塞)" fi # ========================================================================== # Docker 构建验证 # ========================================================================== docker-build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Docker 构建验证 run: docker build -t aicodex2api:ci-test .