|
24519
|
18239
|
6
|
5
|
62f424f94b745efdce16bde3aa2c73e3839a9264
|
0
|
📊 生成综合报告
|
0
|
name: Test Report
"on":
workflow_run:
name: Test Report
"on":
workflow_run:
workflows:
- 'Test Suite'
- 'E2E Tests'
- 'Performance Tests'
types:
- completed
env:
NODE_VERSION: "18"
jobs:
generate-report:
name: "\U0001F4CA 生成综合报告"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 检出代码"
uses: actions/checkout@v4
- name: "\U0001F7E2 设置 Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E5 下载触发工作流的 artifacts"
uses: dawidd6/action-download-artifact@v3
with:
path: downloaded-artifacts
run_id: ${{ github.event.workflow_run.id }}
workflow: ${{ github.event.workflow_run.workflow_id }}
continue-on-error: true
- name: "\U0001F4CA 生成综合测试报告"
run: "echo \"# \U0001F4CA 测试报告\" > test-report.md\necho \"\" >> test-report.md\necho \"**生成时间**: $(date)\" >> test-report.md\necho \"**触发工作流**: ${{ github.event.workflow_run.name }}\" >> test-report.md\necho \"**运行 ID**: ${{ github.event.workflow_run.id }}\" >> test-report.md\necho \"**分支**: ${{ github.event.workflow_run.head_branch }}\" >> test-report.md\necho \"**结果**: ${{ github.event.workflow_run.conclusion }}\" >> test-report.md\necho \"\" >> test-report.md\n\necho \"## \U0001F4C1 测试结果\" >> test-report.md\necho \"\" >> test-report.md\n\n# 遍历下载的 artifacts\nif [ -d \"downloaded-artifacts\" ]; then\n echo \"### 已下载的测试结果\" >> test-report.md\n echo \"\" >> test-report.md\n\n for dir in downloaded-artifacts/*; do\n if [ -d \"$dir\" ]; then\n name=$(basename \"$dir\")\n echo \"- **$name**\" >> test-report.md\n\n # 检查是否有 JSON 结果文件\n for json in \"$dir\"/*.json; do\n if [ -f \"$json\" ]; then\n echo \" - $(basename \"$json\")\" >> test-report.md\n fi\n done\n fi\n done\nelse\n echo \"暂无测试结果下载\" >> test-report.md\nfi\n\necho \"\" >> test-report.md\necho \"---\" >> test-report.md\necho \"*此报告由 CI/CD 自动生成*\" >> test-report.md\n"
- name: "\U0001F4DD 生成 GitHub Summary"
run: "echo \"## \U0001F4CA 测试报告汇总\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\necho \"| 项目 | 值 |\" >> $GITHUB_STEP_SUMMARY\necho \"|------|------|\" >> $GITHUB_STEP_SUMMARY\necho \"| 触发工作流 | ${{ github.event.workflow_run.name }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 运行 ID | ${{ github.event.workflow_run.id }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 分支 | ${{ github.event.workflow_run.head_branch }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 结果 | ${{ github.event.workflow_run.conclusion }} |\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\n\nif [ \"${{ github.event.workflow_run.conclusion }}\" == \"success\" ]; then\n echo \"### ✅ 测试通过\" >> $GITHUB_STEP_SUMMARY\nelse\n echo \"### ❌ 测试失败\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"请查看 [运行详情](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) 了解更多信息。\" >> $GITHUB_STEP_SUMMARY\nfi\n"
- name: "\U0001F4E4 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: test-report-${{ github.event.workflow_run.id }}
path: test-report.md
retention-days: "30"
...
|
generate-report
|
["collect-results"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777340589
|
1777340614
|
|
1
|
|
0
|
Edit
Delete
|
|
24567
|
18265
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
Unit Tests
|
0
|
name: CI
"on":
push:
branches: name: CI
"on":
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: "20"
PNPM_VERSION: "9"
jobs:
test:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- run: pnpm install --frozen-lockfile
- name: Generate Prisma Client
run: pnpm -C backend exec prisma generate
- name: Build shared package
run: pnpm -C shared run build
- name: Run unit tests
run: pnpm -C backend run test:unit
permissions:
contents: read
...
|
test
|
["frontend-typecheck","lint-and-typech ["frontend-typecheck","lint-and-typecheck"]...
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347376
|
1777347413
|
|
1
|
|
0
|
Edit
Delete
|
|
24568
|
18265
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
Governance Audit (HIGH=0 gate)
|
0
|
name: CI
"on":
push:
branches: name: CI
"on":
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: "20"
PNPM_VERSION: "9"
jobs:
governance-audit:
name: Governance Audit (HIGH=0 gate)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- run: pnpm install --frozen-lockfile
- name: Generate Prisma Client
run: pnpm -C backend exec prisma generate
- name: Build shared package
run: pnpm -C shared run build
- name: Audit Prisma↔Zod 契约
run: pnpm -C backend run audit:prisma-zod-contract
continue-on-error: true
- name: Audit FormRules↔Zod
run: pnpm run audit:formrules-zod
continue-on-error: true
- name: Audit Response Columns
run: pnpm run audit:response-columns
continue-on-error: true
- name: Audit Field Payload
run: pnpm run audit:field-payload
continue-on-error: true
- name: Audit Enum Consistency
run: pnpm run audit:enum-consistency
continue-on-error: true
- name: Audit useListPage ↔ Router
run: pnpm run audit:list-page-routes
continue-on-error: true
- name: Audit Page AI Assist Coverage
run: pnpm run audit:ai-assist-coverage
continue-on-error: true
- name: Audit Page AI Assist Skill Binding
run: pnpm run audit:ai-assist-skill-binding
continue-on-error: true
- name: Audit Page AI Assist Context Providers
run: pnpm run audit:context-provider-redact
continue-on-error: true
- name: Harness Report 聚合
run: pnpm harness report
continue-on-error: true
- if: always()
name: Upload audit reports
uses: actions/upload-artifact@v4
with:
name: governance-audit-reports
path: |
reports/prisma-zod-contract-audit.latest.json
reports/formrules-zod-audit.latest.json
reports/response-columns-audit.latest.json
reports/field-payload-audit.latest.json
reports/enum-consistency-audit.latest.json
reports/list-page-routes-audit.latest.json
reports/ai-assist-coverage.latest.json
reports/ai-assist-skill-binding.latest.json
reports/ai-assist-context-providers.latest.json
reports/harness-dashboard.latest.json
reports/module-grades.latest.json
retention-days: "14"
- if: always()
name: 输出 governance summary
run: |
if [ -f reports/harness-dashboard.latest.json ]; then
node -e "
const d = require('./reports/harness-dashboard.latest.json');
const s = d.summary || {};
const lines = [
'## Governance Audit Summary',
'',
'| Severity | Count |',
'|---|---|',
\`| CRITICAL | \${s.critical ?? 0} |\`,
\`| HIGH | \${s.high ?? 0} |\`,
\`| MEDIUM | \${s.medium ?? 0} |\`,
\`| LOW | \${s.low ?? 0} |\`,
\`| INFO | \${s.info ?? 0} |\`,
'',
\`- 总 finding: \${s.total ?? 0}\`,
\`- 涉及模块: \${s.modulesAffected ?? 0}\`,
\`- 审计执行: \${s.auditsRun ?? 0}\`,
'',
'**HIGH+CRITICAL 必须为 0;任何新增高危 finding 阻塞 PR 合并。**',
];
require('fs').appendFileSync(process.env.GITHUB_STEP_SUMMARY, lines.join('\n') + '\n');
"
else
echo '⚠️ harness-dashboard.latest.json 未生成,治理门禁判定失败' >> $GITHUB_STEP_SUMMARY
fi
- name: 校验 HIGH+CRITICAL 必须为 0
run: |
if [ ! -f reports/harness-dashboard.latest.json ]; then
echo "::error::治理门禁失败:harness-dashboard 未生成"
exit 1
fi
node -e "
const d = require('./reports/harness-dashboard.latest.json');
const s = d.summary || {};
const blocking = (s.high || 0) + (s.critical || 0);
if (blocking > 0) {
console.error('::error::治理门禁失败:HIGH+CRITICAL = ' + blocking + ',必须为 0');
console.error('详见 governance-audit-reports artifact 中的 harness-dashboard.latest.json');
process.exit(1);
}
console.log('治理门禁通过:HIGH+CRITICAL = 0');
"
permissions:
contents: read
...
|
governance-audit
|
["lint-and-typecheck"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347376
|
1777347413
|
|
1
|
|
0
|
Edit
Delete
|
|
24583
|
18267
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
后端单元测试 (1/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (1/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 1
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347378
|
1777347619
|
|
1
|
|
0
|
Edit
Delete
|
|
24584
|
18267
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
后端单元测试 (2/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (2/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 2
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347378
|
1777347619
|
|
1
|
|
0
|
Edit
Delete
|
|
24585
|
18267
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
后端单元测试 (3/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (3/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 3
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347378
|
1777347619
|
|
1
|
|
0
|
Edit
Delete
|
|
24586
|
18267
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
后端单元测试 (4/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (4/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 4
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347378
|
1777347619
|
|
1
|
|
0
|
Edit
Delete
|
|
24587
|
18267
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
前端单元测试
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
frontend-unit-test:
name: 前端单元测试
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 运行前端单元测试
run: pnpm --filter juhi-frontend run test:coverage
- name: 上传覆盖率
uses: actions/upload-artifact@v4
with:
name: frontend-coverage
path: frontend/coverage/lcov.info
retention-days: "7"
...
|
frontend-unit-test
|
["frontend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347378
|
1777347624
|
|
1
|
|
0
|
Edit
Delete
|
|
24588
|
18267
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
状态机测试
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
state-machine-test:
name: 状态机测试
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行状态机测试
run: cd backend && npx vitest run src/shared/state-machines --reporter=verbose --passWithNoTests
...
|
state-machine-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347378
|
1777347619
|
|
1
|
|
0
|
Edit
Delete
|
|
24592
|
18267
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
后端构建验证
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-build:
name: 后端构建验证
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 构建
run: pnpm --filter juhi-api run build
- name: 验证构建产物
run: |
if [ ! -d "backend/dist" ]; then
echo "后端构建产物不存在"
exit 1
fi
...
|
backend-build
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347378
|
1777347620
|
|
1
|
|
0
|
Edit
Delete
|
|
24593
|
18267
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
前端构建验证
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
frontend-build:
name: 前端构建验证
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 构建
run: pnpm --filter juhi-frontend run build
- name: 验证构建产物
run: |
if [ ! -d "frontend/dist" ]; then
echo "前端构建产物不存在"
exit 1
fi
- name: 上传构建产物
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: frontend/dist
retention-days: "7"
...
|
frontend-build
|
["frontend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347378
|
1777347624
|
|
1
|
|
0
|
Edit
Delete
|
|
24598
|
18267
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
治理基线采集
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
governance-baseline:
name: 治理基线采集
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: "0"
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 审计门禁基线采集
run: pnpm --filter juhi-api run audit:baseline:capture -- --label pipeline-${{ github.run_id }}
continue-on-error: true
- if: always()
name: 生成治理摘要
run: |
mkdir -p reports/audit-baseline/latest
if [ -f reports/audit-baseline/latest/summary.json ]; then
pnpm --filter juhi-api run governance:summary -- \
--module workspace-baseline \
--stage Pipeline \
--scope workspace \
--classification workspace-baseline \
--summary-json reports/audit-baseline/latest/summary.json \
--output reports/audit-baseline/latest/governance-summary.md
fi
- if: always()
name: 写入审计摘要
run: |
if [ -f reports/audit-baseline/latest/summary.md ]; then
cat reports/audit-baseline/latest/summary.md >> $GITHUB_STEP_SUMMARY
fi
if [ -f reports/audit-baseline/latest/governance-summary.md ]; then
echo "" >> $GITHUB_STEP_SUMMARY
cat reports/audit-baseline/latest/governance-summary.md >> $GITHUB_STEP_SUMMARY
fi
- if: always()
name: 上传审计基线
uses: actions/upload-artifact@v4
with:
name: governance-baseline
path: reports/audit-baseline/latest
retention-days: "30"
...
|
governance-baseline
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347378
|
1777347621
|
|
1
|
|
0
|
Edit
Delete
|
|
24602
|
18268
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
📊 生成综合报告
|
0
|
name: Test Report
"on":
workflow_run:
name: Test Report
"on":
workflow_run:
workflows:
- 'Test Suite'
- 'E2E Tests'
- 'Performance Tests'
types:
- completed
env:
NODE_VERSION: "18"
jobs:
generate-report:
name: "\U0001F4CA 生成综合报告"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 检出代码"
uses: actions/checkout@v4
- name: "\U0001F7E2 设置 Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E5 下载触发工作流的 artifacts"
uses: dawidd6/action-download-artifact@v3
with:
path: downloaded-artifacts
run_id: ${{ github.event.workflow_run.id }}
workflow: ${{ github.event.workflow_run.workflow_id }}
continue-on-error: true
- name: "\U0001F4CA 生成综合测试报告"
run: "echo \"# \U0001F4CA 测试报告\" > test-report.md\necho \"\" >> test-report.md\necho \"**生成时间**: $(date)\" >> test-report.md\necho \"**触发工作流**: ${{ github.event.workflow_run.name }}\" >> test-report.md\necho \"**运行 ID**: ${{ github.event.workflow_run.id }}\" >> test-report.md\necho \"**分支**: ${{ github.event.workflow_run.head_branch }}\" >> test-report.md\necho \"**结果**: ${{ github.event.workflow_run.conclusion }}\" >> test-report.md\necho \"\" >> test-report.md\n\necho \"## \U0001F4C1 测试结果\" >> test-report.md\necho \"\" >> test-report.md\n\n# 遍历下载的 artifacts\nif [ -d \"downloaded-artifacts\" ]; then\n echo \"### 已下载的测试结果\" >> test-report.md\n echo \"\" >> test-report.md\n\n for dir in downloaded-artifacts/*; do\n if [ -d \"$dir\" ]; then\n name=$(basename \"$dir\")\n echo \"- **$name**\" >> test-report.md\n\n # 检查是否有 JSON 结果文件\n for json in \"$dir\"/*.json; do\n if [ -f \"$json\" ]; then\n echo \" - $(basename \"$json\")\" >> test-report.md\n fi\n done\n fi\n done\nelse\n echo \"暂无测试结果下载\" >> test-report.md\nfi\n\necho \"\" >> test-report.md\necho \"---\" >> test-report.md\necho \"*此报告由 CI/CD 自动生成*\" >> test-report.md\n"
- name: "\U0001F4DD 生成 GitHub Summary"
run: "echo \"## \U0001F4CA 测试报告汇总\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\necho \"| 项目 | 值 |\" >> $GITHUB_STEP_SUMMARY\necho \"|------|------|\" >> $GITHUB_STEP_SUMMARY\necho \"| 触发工作流 | ${{ github.event.workflow_run.name }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 运行 ID | ${{ github.event.workflow_run.id }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 分支 | ${{ github.event.workflow_run.head_branch }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 结果 | ${{ github.event.workflow_run.conclusion }} |\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\n\nif [ \"${{ github.event.workflow_run.conclusion }}\" == \"success\" ]; then\n echo \"### ✅ 测试通过\" >> $GITHUB_STEP_SUMMARY\nelse\n echo \"### ❌ 测试失败\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"请查看 [运行详情](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) 了解更多信息。\" >> $GITHUB_STEP_SUMMARY\nfi\n"
- name: "\U0001F4E4 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: test-report-${{ github.event.workflow_run.id }}
path: test-report.md
retention-days: "30"
...
|
generate-report
|
["collect-results"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347559
|
1777347613
|
|
1
|
|
0
|
Edit
Delete
|
|
24616
|
18270
|
6
|
5
|
3fa41aea52e84435c16a79dd19c6775f93236a33
|
0
|
📊 生成综合报告
|
0
|
name: Test Report
"on":
workflow_run:
name: Test Report
"on":
workflow_run:
workflows:
- 'Test Suite'
- 'E2E Tests'
- 'Performance Tests'
types:
- completed
env:
NODE_VERSION: "18"
jobs:
generate-report:
name: "\U0001F4CA 生成综合报告"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 检出代码"
uses: actions/checkout@v4
- name: "\U0001F7E2 设置 Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E5 下载触发工作流的 artifacts"
uses: dawidd6/action-download-artifact@v3
with:
path: downloaded-artifacts
run_id: ${{ github.event.workflow_run.id }}
workflow: ${{ github.event.workflow_run.workflow_id }}
continue-on-error: true
- name: "\U0001F4CA 生成综合测试报告"
run: "echo \"# \U0001F4CA 测试报告\" > test-report.md\necho \"\" >> test-report.md\necho \"**生成时间**: $(date)\" >> test-report.md\necho \"**触发工作流**: ${{ github.event.workflow_run.name }}\" >> test-report.md\necho \"**运行 ID**: ${{ github.event.workflow_run.id }}\" >> test-report.md\necho \"**分支**: ${{ github.event.workflow_run.head_branch }}\" >> test-report.md\necho \"**结果**: ${{ github.event.workflow_run.conclusion }}\" >> test-report.md\necho \"\" >> test-report.md\n\necho \"## \U0001F4C1 测试结果\" >> test-report.md\necho \"\" >> test-report.md\n\n# 遍历下载的 artifacts\nif [ -d \"downloaded-artifacts\" ]; then\n echo \"### 已下载的测试结果\" >> test-report.md\n echo \"\" >> test-report.md\n\n for dir in downloaded-artifacts/*; do\n if [ -d \"$dir\" ]; then\n name=$(basename \"$dir\")\n echo \"- **$name**\" >> test-report.md\n\n # 检查是否有 JSON 结果文件\n for json in \"$dir\"/*.json; do\n if [ -f \"$json\" ]; then\n echo \" - $(basename \"$json\")\" >> test-report.md\n fi\n done\n fi\n done\nelse\n echo \"暂无测试结果下载\" >> test-report.md\nfi\n\necho \"\" >> test-report.md\necho \"---\" >> test-report.md\necho \"*此报告由 CI/CD 自动生成*\" >> test-report.md\n"
- name: "\U0001F4DD 生成 GitHub Summary"
run: "echo \"## \U0001F4CA 测试报告汇总\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\necho \"| 项目 | 值 |\" >> $GITHUB_STEP_SUMMARY\necho \"|------|------|\" >> $GITHUB_STEP_SUMMARY\necho \"| 触发工作流 | ${{ github.event.workflow_run.name }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 运行 ID | ${{ github.event.workflow_run.id }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 分支 | ${{ github.event.workflow_run.head_branch }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 结果 | ${{ github.event.workflow_run.conclusion }} |\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\n\nif [ \"${{ github.event.workflow_run.conclusion }}\" == \"success\" ]; then\n echo \"### ✅ 测试通过\" >> $GITHUB_STEP_SUMMARY\nelse\n echo \"### ❌ 测试失败\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"请查看 [运行详情](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) 了解更多信息。\" >> $GITHUB_STEP_SUMMARY\nfi\n"
- name: "\U0001F4E4 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: test-report-${{ github.event.workflow_run.id }}
path: test-report.md
retention-days: "30"
...
|
generate-report
|
["collect-results"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777347606
|
1777347632
|
|
1
|
|
0
|
Edit
Delete
|
|
24684
|
18316
|
6
|
5
|
e9258713d6944a1e296ddd7017cf9755186b54d8
|
0
|
Unit Tests
|
0
|
name: CI
"on":
push:
branches: name: CI
"on":
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: "20"
PNPM_VERSION: "9"
jobs:
test:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- run: pnpm install --frozen-lockfile
- name: Generate Prisma Client
run: pnpm -C backend exec prisma generate
- name: Build shared package
run: pnpm -C shared run build
- name: Run unit tests
run: pnpm -C backend run test:unit
permissions:
contents: read
...
|
test
|
["frontend-typecheck","lint-and-typech ["frontend-typecheck","lint-and-typecheck"]...
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360414
|
1777360454
|
|
1
|
|
0
|
Edit
Delete
|
|
24685
|
18316
|
6
|
5
|
e9258713d6944a1e296ddd7017cf9755186b54d8
|
0
|
Governance Audit (HIGH=0 gate)
|
0
|
name: CI
"on":
push:
branches: name: CI
"on":
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: "20"
PNPM_VERSION: "9"
jobs:
governance-audit:
name: Governance Audit (HIGH=0 gate)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- run: pnpm install --frozen-lockfile
- name: Generate Prisma Client
run: pnpm -C backend exec prisma generate
- name: Build shared package
run: pnpm -C shared run build
- name: Audit Prisma↔Zod 契约
run: pnpm -C backend run audit:prisma-zod-contract
continue-on-error: true
- name: Audit FormRules↔Zod
run: pnpm run audit:formrules-zod
continue-on-error: true
- name: Audit Response Columns
run: pnpm run audit:response-columns
continue-on-error: true
- name: Audit Field Payload
run: pnpm run audit:field-payload
continue-on-error: true
- name: Audit Enum Consistency
run: pnpm run audit:enum-consistency
continue-on-error: true
- name: Audit useListPage ↔ Router
run: pnpm run audit:list-page-routes
continue-on-error: true
- name: Audit Page AI Assist Coverage
run: pnpm run audit:ai-assist-coverage
continue-on-error: true
- name: Audit Page AI Assist Skill Binding
run: pnpm run audit:ai-assist-skill-binding
continue-on-error: true
- name: Audit Page AI Assist Context Providers
run: pnpm run audit:context-provider-redact
continue-on-error: true
- name: Harness Report 聚合
run: pnpm harness report
continue-on-error: true
- if: always()
name: Upload audit reports
uses: actions/upload-artifact@v4
with:
name: governance-audit-reports
path: |
reports/prisma-zod-contract-audit.latest.json
reports/formrules-zod-audit.latest.json
reports/response-columns-audit.latest.json
reports/field-payload-audit.latest.json
reports/enum-consistency-audit.latest.json
reports/list-page-routes-audit.latest.json
reports/ai-assist-coverage.latest.json
reports/ai-assist-skill-binding.latest.json
reports/ai-assist-context-providers.latest.json
reports/harness-dashboard.latest.json
reports/module-grades.latest.json
retention-days: "14"
- if: always()
name: 输出 governance summary
run: |
if [ -f reports/harness-dashboard.latest.json ]; then
node -e "
const d = require('./reports/harness-dashboard.latest.json');
const s = d.summary || {};
const lines = [
'## Governance Audit Summary',
'',
'| Severity | Count |',
'|---|---|',
\`| CRITICAL | \${s.critical ?? 0} |\`,
\`| HIGH | \${s.high ?? 0} |\`,
\`| MEDIUM | \${s.medium ?? 0} |\`,
\`| LOW | \${s.low ?? 0} |\`,
\`| INFO | \${s.info ?? 0} |\`,
'',
\`- 总 finding: \${s.total ?? 0}\`,
\`- 涉及模块: \${s.modulesAffected ?? 0}\`,
\`- 审计执行: \${s.auditsRun ?? 0}\`,
'',
'**HIGH+CRITICAL 必须为 0;任何新增高危 finding 阻塞 PR 合并。**',
];
require('fs').appendFileSync(process.env.GITHUB_STEP_SUMMARY, lines.join('\n') + '\n');
"
else
echo '⚠️ harness-dashboard.latest.json 未生成,治理门禁判定失败' >> $GITHUB_STEP_SUMMARY
fi
- name: 校验 HIGH+CRITICAL 必须为 0
run: |
if [ ! -f reports/harness-dashboard.latest.json ]; then
echo "::error::治理门禁失败:harness-dashboard 未生成"
exit 1
fi
node -e "
const d = require('./reports/harness-dashboard.latest.json');
const s = d.summary || {};
const blocking = (s.high || 0) + (s.critical || 0);
if (blocking > 0) {
console.error('::error::治理门禁失败:HIGH+CRITICAL = ' + blocking + ',必须为 0');
console.error('详见 governance-audit-reports artifact 中的 harness-dashboard.latest.json');
process.exit(1);
}
console.log('治理门禁通过:HIGH+CRITICAL = 0');
"
permissions:
contents: read
...
|
governance-audit
|
["lint-and-typecheck"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360414
|
1777360454
|
|
1
|
|
0
|
Edit
Delete
|
|
24720
|
18319
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
Unit Tests
|
0
|
name: CI
"on":
push:
branches: name: CI
"on":
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: "20"
PNPM_VERSION: "9"
jobs:
test:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- run: pnpm install --frozen-lockfile
- name: Generate Prisma Client
run: pnpm -C backend exec prisma generate
- name: Build shared package
run: pnpm -C shared run build
- name: Run unit tests
run: pnpm -C backend run test:unit
permissions:
contents: read
...
|
test
|
["frontend-typecheck","lint-and-typech ["frontend-typecheck","lint-and-typecheck"]...
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360555
|
1777360644
|
|
1
|
|
0
|
Edit
Delete
|
|
24721
|
18319
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
Governance Audit (HIGH=0 gate)
|
0
|
name: CI
"on":
push:
branches: name: CI
"on":
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: "20"
PNPM_VERSION: "9"
jobs:
governance-audit:
name: Governance Audit (HIGH=0 gate)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- run: pnpm install --frozen-lockfile
- name: Generate Prisma Client
run: pnpm -C backend exec prisma generate
- name: Build shared package
run: pnpm -C shared run build
- name: Audit Prisma↔Zod 契约
run: pnpm -C backend run audit:prisma-zod-contract
continue-on-error: true
- name: Audit FormRules↔Zod
run: pnpm run audit:formrules-zod
continue-on-error: true
- name: Audit Response Columns
run: pnpm run audit:response-columns
continue-on-error: true
- name: Audit Field Payload
run: pnpm run audit:field-payload
continue-on-error: true
- name: Audit Enum Consistency
run: pnpm run audit:enum-consistency
continue-on-error: true
- name: Audit useListPage ↔ Router
run: pnpm run audit:list-page-routes
continue-on-error: true
- name: Audit Page AI Assist Coverage
run: pnpm run audit:ai-assist-coverage
continue-on-error: true
- name: Audit Page AI Assist Skill Binding
run: pnpm run audit:ai-assist-skill-binding
continue-on-error: true
- name: Audit Page AI Assist Context Providers
run: pnpm run audit:context-provider-redact
continue-on-error: true
- name: Harness Report 聚合
run: pnpm harness report
continue-on-error: true
- if: always()
name: Upload audit reports
uses: actions/upload-artifact@v4
with:
name: governance-audit-reports
path: |
reports/prisma-zod-contract-audit.latest.json
reports/formrules-zod-audit.latest.json
reports/response-columns-audit.latest.json
reports/field-payload-audit.latest.json
reports/enum-consistency-audit.latest.json
reports/list-page-routes-audit.latest.json
reports/ai-assist-coverage.latest.json
reports/ai-assist-skill-binding.latest.json
reports/ai-assist-context-providers.latest.json
reports/harness-dashboard.latest.json
reports/module-grades.latest.json
retention-days: "14"
- if: always()
name: 输出 governance summary
run: |
if [ -f reports/harness-dashboard.latest.json ]; then
node -e "
const d = require('./reports/harness-dashboard.latest.json');
const s = d.summary || {};
const lines = [
'## Governance Audit Summary',
'',
'| Severity | Count |',
'|---|---|',
\`| CRITICAL | \${s.critical ?? 0} |\`,
\`| HIGH | \${s.high ?? 0} |\`,
\`| MEDIUM | \${s.medium ?? 0} |\`,
\`| LOW | \${s.low ?? 0} |\`,
\`| INFO | \${s.info ?? 0} |\`,
'',
\`- 总 finding: \${s.total ?? 0}\`,
\`- 涉及模块: \${s.modulesAffected ?? 0}\`,
\`- 审计执行: \${s.auditsRun ?? 0}\`,
'',
'**HIGH+CRITICAL 必须为 0;任何新增高危 finding 阻塞 PR 合并。**',
];
require('fs').appendFileSync(process.env.GITHUB_STEP_SUMMARY, lines.join('\n') + '\n');
"
else
echo '⚠️ harness-dashboard.latest.json 未生成,治理门禁判定失败' >> $GITHUB_STEP_SUMMARY
fi
- name: 校验 HIGH+CRITICAL 必须为 0
run: |
if [ ! -f reports/harness-dashboard.latest.json ]; then
echo "::error::治理门禁失败:harness-dashboard 未生成"
exit 1
fi
node -e "
const d = require('./reports/harness-dashboard.latest.json');
const s = d.summary || {};
const blocking = (s.high || 0) + (s.critical || 0);
if (blocking > 0) {
console.error('::error::治理门禁失败:HIGH+CRITICAL = ' + blocking + ',必须为 0');
console.error('详见 governance-audit-reports artifact 中的 harness-dashboard.latest.json');
process.exit(1);
}
console.log('治理门禁通过:HIGH+CRITICAL = 0');
"
permissions:
contents: read
...
|
governance-audit
|
["lint-and-typecheck"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360555
|
1777360644
|
|
1
|
|
0
|
Edit
Delete
|
|
24746
|
18322
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
后端单元测试 (1/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (1/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 1
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360565
|
1777361889
|
|
1
|
|
0
|
Edit
Delete
|
|
24747
|
18322
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
后端单元测试 (2/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (2/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 2
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360565
|
1777361889
|
|
1
|
|
0
|
Edit
Delete
|
|
24748
|
18322
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
后端单元测试 (3/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (3/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 3
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360565
|
1777361889
|
|
1
|
|
0
|
Edit
Delete
|
|
24749
|
18322
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
后端单元测试 (4/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (4/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 4
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360565
|
1777361889
|
|
1
|
|
0
|
Edit
Delete
|
|
24750
|
18322
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
前端单元测试
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
frontend-unit-test:
name: 前端单元测试
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 运行前端单元测试
run: pnpm --filter juhi-frontend run test:coverage
- name: 上传覆盖率
uses: actions/upload-artifact@v4
with:
name: frontend-coverage
path: frontend/coverage/lcov.info
retention-days: "7"
...
|
frontend-unit-test
|
["frontend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360565
|
1777361889
|
|
1
|
|
0
|
Edit
Delete
|
|
24751
|
18322
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
状态机测试
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
state-machine-test:
name: 状态机测试
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行状态机测试
run: cd backend && npx vitest run src/shared/state-machines --reporter=verbose --passWithNoTests
...
|
state-machine-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360565
|
1777361890
|
|
1
|
|
0
|
Edit
Delete
|
|
24755
|
18322
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
后端构建验证
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-build:
name: 后端构建验证
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 构建
run: pnpm --filter juhi-api run build
- name: 验证构建产物
run: |
if [ ! -d "backend/dist" ]; then
echo "后端构建产物不存在"
exit 1
fi
...
|
backend-build
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360565
|
1777361890
|
|
1
|
|
0
|
Edit
Delete
|
|
24756
|
18322
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
前端构建验证
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
frontend-build:
name: 前端构建验证
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 构建
run: pnpm --filter juhi-frontend run build
- name: 验证构建产物
run: |
if [ ! -d "frontend/dist" ]; then
echo "前端构建产物不存在"
exit 1
fi
- name: 上传构建产物
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: frontend/dist
retention-days: "7"
...
|
frontend-build
|
["frontend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360565
|
1777361890
|
|
1
|
|
0
|
Edit
Delete
|
|
24761
|
18322
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
治理基线采集
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
governance-baseline:
name: 治理基线采集
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: "0"
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 审计门禁基线采集
run: pnpm --filter juhi-api run audit:baseline:capture -- --label pipeline-${{ github.run_id }}
continue-on-error: true
- if: always()
name: 生成治理摘要
run: |
mkdir -p reports/audit-baseline/latest
if [ -f reports/audit-baseline/latest/summary.json ]; then
pnpm --filter juhi-api run governance:summary -- \
--module workspace-baseline \
--stage Pipeline \
--scope workspace \
--classification workspace-baseline \
--summary-json reports/audit-baseline/latest/summary.json \
--output reports/audit-baseline/latest/governance-summary.md
fi
- if: always()
name: 写入审计摘要
run: |
if [ -f reports/audit-baseline/latest/summary.md ]; then
cat reports/audit-baseline/latest/summary.md >> $GITHUB_STEP_SUMMARY
fi
if [ -f reports/audit-baseline/latest/governance-summary.md ]; then
echo "" >> $GITHUB_STEP_SUMMARY
cat reports/audit-baseline/latest/governance-summary.md >> $GITHUB_STEP_SUMMARY
fi
- if: always()
name: 上传审计基线
uses: actions/upload-artifact@v4
with:
name: governance-baseline
path: reports/audit-baseline/latest
retention-days: "30"
...
|
governance-baseline
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360565
|
1777361891
|
|
1
|
|
0
|
Edit
Delete
|
|
24765
|
18323
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
📊 生成综合报告
|
0
|
name: Test Report
"on":
workflow_run:
name: Test Report
"on":
workflow_run:
workflows:
- 'Test Suite'
- 'E2E Tests'
- 'Performance Tests'
types:
- completed
env:
NODE_VERSION: "18"
jobs:
generate-report:
name: "\U0001F4CA 生成综合报告"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 检出代码"
uses: actions/checkout@v4
- name: "\U0001F7E2 设置 Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E5 下载触发工作流的 artifacts"
uses: dawidd6/action-download-artifact@v3
with:
path: downloaded-artifacts
run_id: ${{ github.event.workflow_run.id }}
workflow: ${{ github.event.workflow_run.workflow_id }}
continue-on-error: true
- name: "\U0001F4CA 生成综合测试报告"
run: "echo \"# \U0001F4CA 测试报告\" > test-report.md\necho \"\" >> test-report.md\necho \"**生成时间**: $(date)\" >> test-report.md\necho \"**触发工作流**: ${{ github.event.workflow_run.name }}\" >> test-report.md\necho \"**运行 ID**: ${{ github.event.workflow_run.id }}\" >> test-report.md\necho \"**分支**: ${{ github.event.workflow_run.head_branch }}\" >> test-report.md\necho \"**结果**: ${{ github.event.workflow_run.conclusion }}\" >> test-report.md\necho \"\" >> test-report.md\n\necho \"## \U0001F4C1 测试结果\" >> test-report.md\necho \"\" >> test-report.md\n\n# 遍历下载的 artifacts\nif [ -d \"downloaded-artifacts\" ]; then\n echo \"### 已下载的测试结果\" >> test-report.md\n echo \"\" >> test-report.md\n\n for dir in downloaded-artifacts/*; do\n if [ -d \"$dir\" ]; then\n name=$(basename \"$dir\")\n echo \"- **$name**\" >> test-report.md\n\n # 检查是否有 JSON 结果文件\n for json in \"$dir\"/*.json; do\n if [ -f \"$json\" ]; then\n echo \" - $(basename \"$json\")\" >> test-report.md\n fi\n done\n fi\n done\nelse\n echo \"暂无测试结果下载\" >> test-report.md\nfi\n\necho \"\" >> test-report.md\necho \"---\" >> test-report.md\necho \"*此报告由 CI/CD 自动生成*\" >> test-report.md\n"
- name: "\U0001F4DD 生成 GitHub Summary"
run: "echo \"## \U0001F4CA 测试报告汇总\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\necho \"| 项目 | 值 |\" >> $GITHUB_STEP_SUMMARY\necho \"|------|------|\" >> $GITHUB_STEP_SUMMARY\necho \"| 触发工作流 | ${{ github.event.workflow_run.name }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 运行 ID | ${{ github.event.workflow_run.id }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 分支 | ${{ github.event.workflow_run.head_branch }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 结果 | ${{ github.event.workflow_run.conclusion }} |\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\n\nif [ \"${{ github.event.workflow_run.conclusion }}\" == \"success\" ]; then\n echo \"### ✅ 测试通过\" >> $GITHUB_STEP_SUMMARY\nelse\n echo \"### ❌ 测试失败\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"请查看 [运行详情](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) 了解更多信息。\" >> $GITHUB_STEP_SUMMARY\nfi\n"
- name: "\U0001F4E4 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: test-report-${{ github.event.workflow_run.id }}
path: test-report.md
retention-days: "30"
...
|
generate-report
|
["collect-results"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360604
|
1777361865
|
|
1
|
|
0
|
Edit
Delete
|
|
24769
|
18324
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
📊 生成综合报告
|
0
|
name: Test Report
"on":
workflow_run:
name: Test Report
"on":
workflow_run:
workflows:
- 'Test Suite'
- 'E2E Tests'
- 'Performance Tests'
types:
- completed
env:
NODE_VERSION: "18"
jobs:
generate-report:
name: "\U0001F4CA 生成综合报告"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 检出代码"
uses: actions/checkout@v4
- name: "\U0001F7E2 设置 Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E5 下载触发工作流的 artifacts"
uses: dawidd6/action-download-artifact@v3
with:
path: downloaded-artifacts
run_id: ${{ github.event.workflow_run.id }}
workflow: ${{ github.event.workflow_run.workflow_id }}
continue-on-error: true
- name: "\U0001F4CA 生成综合测试报告"
run: "echo \"# \U0001F4CA 测试报告\" > test-report.md\necho \"\" >> test-report.md\necho \"**生成时间**: $(date)\" >> test-report.md\necho \"**触发工作流**: ${{ github.event.workflow_run.name }}\" >> test-report.md\necho \"**运行 ID**: ${{ github.event.workflow_run.id }}\" >> test-report.md\necho \"**分支**: ${{ github.event.workflow_run.head_branch }}\" >> test-report.md\necho \"**结果**: ${{ github.event.workflow_run.conclusion }}\" >> test-report.md\necho \"\" >> test-report.md\n\necho \"## \U0001F4C1 测试结果\" >> test-report.md\necho \"\" >> test-report.md\n\n# 遍历下载的 artifacts\nif [ -d \"downloaded-artifacts\" ]; then\n echo \"### 已下载的测试结果\" >> test-report.md\n echo \"\" >> test-report.md\n\n for dir in downloaded-artifacts/*; do\n if [ -d \"$dir\" ]; then\n name=$(basename \"$dir\")\n echo \"- **$name**\" >> test-report.md\n\n # 检查是否有 JSON 结果文件\n for json in \"$dir\"/*.json; do\n if [ -f \"$json\" ]; then\n echo \" - $(basename \"$json\")\" >> test-report.md\n fi\n done\n fi\n done\nelse\n echo \"暂无测试结果下载\" >> test-report.md\nfi\n\necho \"\" >> test-report.md\necho \"---\" >> test-report.md\necho \"*此报告由 CI/CD 自动生成*\" >> test-report.md\n"
- name: "\U0001F4DD 生成 GitHub Summary"
run: "echo \"## \U0001F4CA 测试报告汇总\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\necho \"| 项目 | 值 |\" >> $GITHUB_STEP_SUMMARY\necho \"|------|------|\" >> $GITHUB_STEP_SUMMARY\necho \"| 触发工作流 | ${{ github.event.workflow_run.name }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 运行 ID | ${{ github.event.workflow_run.id }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 分支 | ${{ github.event.workflow_run.head_branch }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 结果 | ${{ github.event.workflow_run.conclusion }} |\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\n\nif [ \"${{ github.event.workflow_run.conclusion }}\" == \"success\" ]; then\n echo \"### ✅ 测试通过\" >> $GITHUB_STEP_SUMMARY\nelse\n echo \"### ❌ 测试失败\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"请查看 [运行详情](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) 了解更多信息。\" >> $GITHUB_STEP_SUMMARY\nfi\n"
- name: "\U0001F4E4 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: test-report-${{ github.event.workflow_run.id }}
path: test-report.md
retention-days: "30"
...
|
generate-report
|
["collect-results"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777360788
|
1777361875
|
|
1
|
|
0
|
Edit
Delete
|
|
24787
|
18330
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
📊 生成综合报告
|
0
|
name: Test Report
"on":
workflow_run:
name: Test Report
"on":
workflow_run:
workflows:
- 'Test Suite'
- 'E2E Tests'
- 'Performance Tests'
types:
- completed
env:
NODE_VERSION: "18"
jobs:
generate-report:
name: "\U0001F4CA 生成综合报告"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 检出代码"
uses: actions/checkout@v4
- name: "\U0001F7E2 设置 Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E5 下载触发工作流的 artifacts"
uses: dawidd6/action-download-artifact@v3
with:
path: downloaded-artifacts
run_id: ${{ github.event.workflow_run.id }}
workflow: ${{ github.event.workflow_run.workflow_id }}
continue-on-error: true
- name: "\U0001F4CA 生成综合测试报告"
run: "echo \"# \U0001F4CA 测试报告\" > test-report.md\necho \"\" >> test-report.md\necho \"**生成时间**: $(date)\" >> test-report.md\necho \"**触发工作流**: ${{ github.event.workflow_run.name }}\" >> test-report.md\necho \"**运行 ID**: ${{ github.event.workflow_run.id }}\" >> test-report.md\necho \"**分支**: ${{ github.event.workflow_run.head_branch }}\" >> test-report.md\necho \"**结果**: ${{ github.event.workflow_run.conclusion }}\" >> test-report.md\necho \"\" >> test-report.md\n\necho \"## \U0001F4C1 测试结果\" >> test-report.md\necho \"\" >> test-report.md\n\n# 遍历下载的 artifacts\nif [ -d \"downloaded-artifacts\" ]; then\n echo \"### 已下载的测试结果\" >> test-report.md\n echo \"\" >> test-report.md\n\n for dir in downloaded-artifacts/*; do\n if [ -d \"$dir\" ]; then\n name=$(basename \"$dir\")\n echo \"- **$name**\" >> test-report.md\n\n # 检查是否有 JSON 结果文件\n for json in \"$dir\"/*.json; do\n if [ -f \"$json\" ]; then\n echo \" - $(basename \"$json\")\" >> test-report.md\n fi\n done\n fi\n done\nelse\n echo \"暂无测试结果下载\" >> test-report.md\nfi\n\necho \"\" >> test-report.md\necho \"---\" >> test-report.md\necho \"*此报告由 CI/CD 自动生成*\" >> test-report.md\n"
- name: "\U0001F4DD 生成 GitHub Summary"
run: "echo \"## \U0001F4CA 测试报告汇总\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\necho \"| 项目 | 值 |\" >> $GITHUB_STEP_SUMMARY\necho \"|------|------|\" >> $GITHUB_STEP_SUMMARY\necho \"| 触发工作流 | ${{ github.event.workflow_run.name }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 运行 ID | ${{ github.event.workflow_run.id }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 分支 | ${{ github.event.workflow_run.head_branch }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 结果 | ${{ github.event.workflow_run.conclusion }} |\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\n\nif [ \"${{ github.event.workflow_run.conclusion }}\" == \"success\" ]; then\n echo \"### ✅ 测试通过\" >> $GITHUB_STEP_SUMMARY\nelse\n echo \"### ❌ 测试失败\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"请查看 [运行详情](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) 了解更多信息。\" >> $GITHUB_STEP_SUMMARY\nfi\n"
- name: "\U0001F4E4 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: test-report-${{ github.event.workflow_run.id }}
path: test-report.md
retention-days: "30"
...
|
generate-report
|
["collect-results"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777361858
|
1777361900
|
|
1
|
|
0
|
Edit
Delete
|
|
24791
|
18331
|
6
|
5
|
6086495033147939cdd979bd15fd97d71f6c1ac3
|
0
|
📊 生成综合报告
|
0
|
name: Test Report
"on":
workflow_run:
name: Test Report
"on":
workflow_run:
workflows:
- 'Test Suite'
- 'E2E Tests'
- 'Performance Tests'
types:
- completed
env:
NODE_VERSION: "18"
jobs:
generate-report:
name: "\U0001F4CA 生成综合报告"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 检出代码"
uses: actions/checkout@v4
- name: "\U0001F7E2 设置 Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E5 下载触发工作流的 artifacts"
uses: dawidd6/action-download-artifact@v3
with:
path: downloaded-artifacts
run_id: ${{ github.event.workflow_run.id }}
workflow: ${{ github.event.workflow_run.workflow_id }}
continue-on-error: true
- name: "\U0001F4CA 生成综合测试报告"
run: "echo \"# \U0001F4CA 测试报告\" > test-report.md\necho \"\" >> test-report.md\necho \"**生成时间**: $(date)\" >> test-report.md\necho \"**触发工作流**: ${{ github.event.workflow_run.name }}\" >> test-report.md\necho \"**运行 ID**: ${{ github.event.workflow_run.id }}\" >> test-report.md\necho \"**分支**: ${{ github.event.workflow_run.head_branch }}\" >> test-report.md\necho \"**结果**: ${{ github.event.workflow_run.conclusion }}\" >> test-report.md\necho \"\" >> test-report.md\n\necho \"## \U0001F4C1 测试结果\" >> test-report.md\necho \"\" >> test-report.md\n\n# 遍历下载的 artifacts\nif [ -d \"downloaded-artifacts\" ]; then\n echo \"### 已下载的测试结果\" >> test-report.md\n echo \"\" >> test-report.md\n\n for dir in downloaded-artifacts/*; do\n if [ -d \"$dir\" ]; then\n name=$(basename \"$dir\")\n echo \"- **$name**\" >> test-report.md\n\n # 检查是否有 JSON 结果文件\n for json in \"$dir\"/*.json; do\n if [ -f \"$json\" ]; then\n echo \" - $(basename \"$json\")\" >> test-report.md\n fi\n done\n fi\n done\nelse\n echo \"暂无测试结果下载\" >> test-report.md\nfi\n\necho \"\" >> test-report.md\necho \"---\" >> test-report.md\necho \"*此报告由 CI/CD 自动生成*\" >> test-report.md\n"
- name: "\U0001F4DD 生成 GitHub Summary"
run: "echo \"## \U0001F4CA 测试报告汇总\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\necho \"| 项目 | 值 |\" >> $GITHUB_STEP_SUMMARY\necho \"|------|------|\" >> $GITHUB_STEP_SUMMARY\necho \"| 触发工作流 | ${{ github.event.workflow_run.name }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 运行 ID | ${{ github.event.workflow_run.id }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 分支 | ${{ github.event.workflow_run.head_branch }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 结果 | ${{ github.event.workflow_run.conclusion }} |\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\n\nif [ \"${{ github.event.workflow_run.conclusion }}\" == \"success\" ]; then\n echo \"### ✅ 测试通过\" >> $GITHUB_STEP_SUMMARY\nelse\n echo \"### ❌ 测试失败\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"请查看 [运行详情](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) 了解更多信息。\" >> $GITHUB_STEP_SUMMARY\nfi\n"
- name: "\U0001F4E4 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: test-report-${{ github.event.workflow_run.id }}
path: test-report.md
retention-days: "30"
...
|
generate-report
|
["collect-results"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777361869
|
1777361910
|
|
1
|
|
0
|
Edit
Delete
|
|
24819
|
18337
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
Unit Tests
|
0
|
name: CI
"on":
push:
branches: name: CI
"on":
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: "20"
PNPM_VERSION: "9"
jobs:
test:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- run: pnpm install --frozen-lockfile
- name: Generate Prisma Client
run: pnpm -C backend exec prisma generate
- name: Build shared package
run: pnpm -C shared run build
- name: Run unit tests
run: pnpm -C backend run test:unit
permissions:
contents: read
...
|
test
|
["frontend-typecheck","lint-and-typech ["frontend-typecheck","lint-and-typecheck"]...
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362869
|
1777363053
|
|
1
|
|
0
|
Edit
Delete
|
|
24820
|
18337
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
Governance Audit (HIGH=0 gate)
|
0
|
name: CI
"on":
push:
branches: name: CI
"on":
push:
branches: [main]
pull_request:
branches: [main]
env:
NODE_VERSION: "20"
PNPM_VERSION: "9"
jobs:
governance-audit:
name: Governance Audit (HIGH=0 gate)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- run: pnpm install --frozen-lockfile
- name: Generate Prisma Client
run: pnpm -C backend exec prisma generate
- name: Build shared package
run: pnpm -C shared run build
- name: Audit Prisma↔Zod 契约
run: pnpm -C backend run audit:prisma-zod-contract
continue-on-error: true
- name: Audit FormRules↔Zod
run: pnpm run audit:formrules-zod
continue-on-error: true
- name: Audit Response Columns
run: pnpm run audit:response-columns
continue-on-error: true
- name: Audit Field Payload
run: pnpm run audit:field-payload
continue-on-error: true
- name: Audit Enum Consistency
run: pnpm run audit:enum-consistency
continue-on-error: true
- name: Audit useListPage ↔ Router
run: pnpm run audit:list-page-routes
continue-on-error: true
- name: Audit Page AI Assist Coverage
run: pnpm run audit:ai-assist-coverage
continue-on-error: true
- name: Audit Page AI Assist Skill Binding
run: pnpm run audit:ai-assist-skill-binding
continue-on-error: true
- name: Audit Page AI Assist Context Providers
run: pnpm run audit:context-provider-redact
continue-on-error: true
- name: Harness Report 聚合
run: pnpm harness report
continue-on-error: true
- if: always()
name: Upload audit reports
uses: actions/upload-artifact@v4
with:
name: governance-audit-reports
path: |
reports/prisma-zod-contract-audit.latest.json
reports/formrules-zod-audit.latest.json
reports/response-columns-audit.latest.json
reports/field-payload-audit.latest.json
reports/enum-consistency-audit.latest.json
reports/list-page-routes-audit.latest.json
reports/ai-assist-coverage.latest.json
reports/ai-assist-skill-binding.latest.json
reports/ai-assist-context-providers.latest.json
reports/harness-dashboard.latest.json
reports/module-grades.latest.json
retention-days: "14"
- if: always()
name: 输出 governance summary
run: |
if [ -f reports/harness-dashboard.latest.json ]; then
node -e "
const d = require('./reports/harness-dashboard.latest.json');
const s = d.summary || {};
const lines = [
'## Governance Audit Summary',
'',
'| Severity | Count |',
'|---|---|',
\`| CRITICAL | \${s.critical ?? 0} |\`,
\`| HIGH | \${s.high ?? 0} |\`,
\`| MEDIUM | \${s.medium ?? 0} |\`,
\`| LOW | \${s.low ?? 0} |\`,
\`| INFO | \${s.info ?? 0} |\`,
'',
\`- 总 finding: \${s.total ?? 0}\`,
\`- 涉及模块: \${s.modulesAffected ?? 0}\`,
\`- 审计执行: \${s.auditsRun ?? 0}\`,
'',
'**HIGH+CRITICAL 必须为 0;任何新增高危 finding 阻塞 PR 合并。**',
];
require('fs').appendFileSync(process.env.GITHUB_STEP_SUMMARY, lines.join('\n') + '\n');
"
else
echo '⚠️ harness-dashboard.latest.json 未生成,治理门禁判定失败' >> $GITHUB_STEP_SUMMARY
fi
- name: 校验 HIGH+CRITICAL 必须为 0
run: |
if [ ! -f reports/harness-dashboard.latest.json ]; then
echo "::error::治理门禁失败:harness-dashboard 未生成"
exit 1
fi
node -e "
const d = require('./reports/harness-dashboard.latest.json');
const s = d.summary || {};
const blocking = (s.high || 0) + (s.critical || 0);
if (blocking > 0) {
console.error('::error::治理门禁失败:HIGH+CRITICAL = ' + blocking + ',必须为 0');
console.error('详见 governance-audit-reports artifact 中的 harness-dashboard.latest.json');
process.exit(1);
}
console.log('治理门禁通过:HIGH+CRITICAL = 0');
"
permissions:
contents: read
...
|
governance-audit
|
["lint-and-typecheck"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362869
|
1777363053
|
|
1
|
|
0
|
Edit
Delete
|
|
24835
|
18339
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
后端单元测试 (1/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (1/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 1
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362871
|
1777363286
|
|
1
|
|
0
|
Edit
Delete
|
|
24836
|
18339
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
后端单元测试 (2/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (2/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 2
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362871
|
1777363286
|
|
1
|
|
0
|
Edit
Delete
|
|
24837
|
18339
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
后端单元测试 (3/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (3/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 3
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362871
|
1777363286
|
|
1
|
|
0
|
Edit
Delete
|
|
24838
|
18339
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
后端单元测试 (4/4)
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-unit-test:
name: 后端单元测试 (4/4)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行单元测试(分片 ${{ matrix.shard }}/4)
run: pnpm --filter juhi-api run test:ci -- --shard=${{ matrix.shard }}/4
env:
DATABASE_URL: postgresql://test:test@localhost:5432/juhi_test
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
JWT_REFRESH_SECRET: test-jwt-refresh-secret
NODE_ENV: test
- name: 上传覆盖率
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: "false"
files: backend/coverage/lcov.info
flags: backend-shard-${{ matrix.shard }}
- if: always()
name: 上传测试结果
uses: actions/upload-artifact@v4
with:
name: backend-unit-shard-${{ matrix.shard }}
path: backend/test-results/
retention-days: "7"
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: juhi_test
POSTGRES_PASSWORD: test
POSTGRES_USER: test
ports:
- 5432:5432
options: --health-cmd pg_isready --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
strategy:
fail-fast: "false"
matrix:
shard:
- 4
...
|
backend-unit-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362871
|
1777363286
|
|
1
|
|
0
|
Edit
Delete
|
|
24839
|
18339
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
前端单元测试
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
frontend-unit-test:
name: 前端单元测试
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 运行前端单元测试
run: pnpm --filter juhi-frontend run test:coverage
- name: 上传覆盖率
uses: actions/upload-artifact@v4
with:
name: frontend-coverage
path: frontend/coverage/lcov.info
retention-days: "7"
...
|
frontend-unit-test
|
["frontend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362871
|
1777363292
|
|
1
|
|
0
|
Edit
Delete
|
|
24840
|
18339
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
状态机测试
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
state-machine-test:
name: 状态机测试
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 运行状态机测试
run: cd backend && npx vitest run src/shared/state-machines --reporter=verbose --passWithNoTests
...
|
state-machine-test
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362871
|
1777363286
|
|
1
|
|
0
|
Edit
Delete
|
|
24844
|
18339
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
后端构建验证
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
backend-build:
name: 后端构建验证
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 构建
run: pnpm --filter juhi-api run build
- name: 验证构建产物
run: |
if [ ! -d "backend/dist" ]; then
echo "后端构建产物不存在"
exit 1
fi
...
|
backend-build
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362871
|
1777363287
|
|
1
|
|
0
|
Edit
Delete
|
|
24845
|
18339
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
前端构建验证
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
frontend-build:
name: 前端构建验证
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 构建
run: pnpm --filter juhi-frontend run build
- name: 验证构建产物
run: |
if [ ! -d "frontend/dist" ]; then
echo "前端构建产物不存在"
exit 1
fi
- name: 上传构建产物
uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: frontend/dist
retention-days: "7"
...
|
frontend-build
|
["frontend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362871
|
1777363292
|
|
1
|
|
0
|
Edit
Delete
|
|
24850
|
18339
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
治理基线采集
|
0
|
name: Test Pipeline
"on":
push:
name: Test Pipeline
"on":
push:
branches: [main, develop, 'feature/**', 'claude/**']
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
coverage_threshold:
description: '覆盖率阈值 (%)'
required: false
default: '80'
run_ai_tests:
description: '运行 AI 模块测试'
required: false
default: 'true'
type: boolean
run_api_tests:
description: '运行 API 集成测试'
required: false
default: 'true'
type: boolean
run_security_audit:
description: '运行安全审计'
required: false
default: 'true'
type: boolean
env:
COVERAGE_THRESHOLD: ${{ github.event.inputs.coverage_threshold || '80' }}
NODE_VERSION: "20"
PNPM_VERSION: "8"
jobs:
governance-baseline:
name: 治理基线采集
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: "0"
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 恢复依赖缓存
uses: actions/cache/restore@v4
with:
key: pipeline-deps-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
path: |
node_modules
backend/node_modules
frontend/node_modules
shared/node_modules
shared/dist
e2e/node_modules
- name: 生成 Prisma Client
run: pnpm --filter juhi-api run db:generate
- name: 审计门禁基线采集
run: pnpm --filter juhi-api run audit:baseline:capture -- --label pipeline-${{ github.run_id }}
continue-on-error: true
- if: always()
name: 生成治理摘要
run: |
mkdir -p reports/audit-baseline/latest
if [ -f reports/audit-baseline/latest/summary.json ]; then
pnpm --filter juhi-api run governance:summary -- \
--module workspace-baseline \
--stage Pipeline \
--scope workspace \
--classification workspace-baseline \
--summary-json reports/audit-baseline/latest/summary.json \
--output reports/audit-baseline/latest/governance-summary.md
fi
- if: always()
name: 写入审计摘要
run: |
if [ -f reports/audit-baseline/latest/summary.md ]; then
cat reports/audit-baseline/latest/summary.md >> $GITHUB_STEP_SUMMARY
fi
if [ -f reports/audit-baseline/latest/governance-summary.md ]; then
echo "" >> $GITHUB_STEP_SUMMARY
cat reports/audit-baseline/latest/governance-summary.md >> $GITHUB_STEP_SUMMARY
fi
- if: always()
name: 上传审计基线
uses: actions/upload-artifact@v4
with:
name: governance-baseline
path: reports/audit-baseline/latest
retention-days: "30"
...
|
governance-baseline
|
["backend-lint"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777362871
|
1777363288
|
|
1
|
|
0
|
Edit
Delete
|
|
24855
|
18341
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
📊 生成综合报告
|
0
|
name: Test Report
"on":
workflow_run:
name: Test Report
"on":
workflow_run:
workflows:
- 'Test Suite'
- 'E2E Tests'
- 'Performance Tests'
types:
- completed
env:
NODE_VERSION: "18"
jobs:
generate-report:
name: "\U0001F4CA 生成综合报告"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 检出代码"
uses: actions/checkout@v4
- name: "\U0001F7E2 设置 Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E5 下载触发工作流的 artifacts"
uses: dawidd6/action-download-artifact@v3
with:
path: downloaded-artifacts
run_id: ${{ github.event.workflow_run.id }}
workflow: ${{ github.event.workflow_run.workflow_id }}
continue-on-error: true
- name: "\U0001F4CA 生成综合测试报告"
run: "echo \"# \U0001F4CA 测试报告\" > test-report.md\necho \"\" >> test-report.md\necho \"**生成时间**: $(date)\" >> test-report.md\necho \"**触发工作流**: ${{ github.event.workflow_run.name }}\" >> test-report.md\necho \"**运行 ID**: ${{ github.event.workflow_run.id }}\" >> test-report.md\necho \"**分支**: ${{ github.event.workflow_run.head_branch }}\" >> test-report.md\necho \"**结果**: ${{ github.event.workflow_run.conclusion }}\" >> test-report.md\necho \"\" >> test-report.md\n\necho \"## \U0001F4C1 测试结果\" >> test-report.md\necho \"\" >> test-report.md\n\n# 遍历下载的 artifacts\nif [ -d \"downloaded-artifacts\" ]; then\n echo \"### 已下载的测试结果\" >> test-report.md\n echo \"\" >> test-report.md\n\n for dir in downloaded-artifacts/*; do\n if [ -d \"$dir\" ]; then\n name=$(basename \"$dir\")\n echo \"- **$name**\" >> test-report.md\n\n # 检查是否有 JSON 结果文件\n for json in \"$dir\"/*.json; do\n if [ -f \"$json\" ]; then\n echo \" - $(basename \"$json\")\" >> test-report.md\n fi\n done\n fi\n done\nelse\n echo \"暂无测试结果下载\" >> test-report.md\nfi\n\necho \"\" >> test-report.md\necho \"---\" >> test-report.md\necho \"*此报告由 CI/CD 自动生成*\" >> test-report.md\n"
- name: "\U0001F4DD 生成 GitHub Summary"
run: "echo \"## \U0001F4CA 测试报告汇总\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\necho \"| 项目 | 值 |\" >> $GITHUB_STEP_SUMMARY\necho \"|------|------|\" >> $GITHUB_STEP_SUMMARY\necho \"| 触发工作流 | ${{ github.event.workflow_run.name }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 运行 ID | ${{ github.event.workflow_run.id }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 分支 | ${{ github.event.workflow_run.head_branch }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 结果 | ${{ github.event.workflow_run.conclusion }} |\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\n\nif [ \"${{ github.event.workflow_run.conclusion }}\" == \"success\" ]; then\n echo \"### ✅ 测试通过\" >> $GITHUB_STEP_SUMMARY\nelse\n echo \"### ❌ 测试失败\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"请查看 [运行详情](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) 了解更多信息。\" >> $GITHUB_STEP_SUMMARY\nfi\n"
- name: "\U0001F4E4 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: test-report-${{ github.event.workflow_run.id }}
path: test-report.md
retention-days: "30"
...
|
generate-report
|
["collect-results"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777363223
|
1777363280
|
|
1
|
|
0
|
Edit
Delete
|
|
24870
|
18344
|
6
|
5
|
106c45ddee8406e0190ccbba4c3dcf6703cc6117
|
0
|
📊 生成综合报告
|
0
|
name: Test Report
"on":
workflow_run:
name: Test Report
"on":
workflow_run:
workflows:
- 'Test Suite'
- 'E2E Tests'
- 'Performance Tests'
types:
- completed
env:
NODE_VERSION: "18"
jobs:
generate-report:
name: "\U0001F4CA 生成综合报告"
runs-on: ubuntu-latest
steps:
- name: "\U0001F4E5 检出代码"
uses: actions/checkout@v4
- name: "\U0001F7E2 设置 Node.js"
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: "\U0001F4E5 下载触发工作流的 artifacts"
uses: dawidd6/action-download-artifact@v3
with:
path: downloaded-artifacts
run_id: ${{ github.event.workflow_run.id }}
workflow: ${{ github.event.workflow_run.workflow_id }}
continue-on-error: true
- name: "\U0001F4CA 生成综合测试报告"
run: "echo \"# \U0001F4CA 测试报告\" > test-report.md\necho \"\" >> test-report.md\necho \"**生成时间**: $(date)\" >> test-report.md\necho \"**触发工作流**: ${{ github.event.workflow_run.name }}\" >> test-report.md\necho \"**运行 ID**: ${{ github.event.workflow_run.id }}\" >> test-report.md\necho \"**分支**: ${{ github.event.workflow_run.head_branch }}\" >> test-report.md\necho \"**结果**: ${{ github.event.workflow_run.conclusion }}\" >> test-report.md\necho \"\" >> test-report.md\n\necho \"## \U0001F4C1 测试结果\" >> test-report.md\necho \"\" >> test-report.md\n\n# 遍历下载的 artifacts\nif [ -d \"downloaded-artifacts\" ]; then\n echo \"### 已下载的测试结果\" >> test-report.md\n echo \"\" >> test-report.md\n\n for dir in downloaded-artifacts/*; do\n if [ -d \"$dir\" ]; then\n name=$(basename \"$dir\")\n echo \"- **$name**\" >> test-report.md\n\n # 检查是否有 JSON 结果文件\n for json in \"$dir\"/*.json; do\n if [ -f \"$json\" ]; then\n echo \" - $(basename \"$json\")\" >> test-report.md\n fi\n done\n fi\n done\nelse\n echo \"暂无测试结果下载\" >> test-report.md\nfi\n\necho \"\" >> test-report.md\necho \"---\" >> test-report.md\necho \"*此报告由 CI/CD 自动生成*\" >> test-report.md\n"
- name: "\U0001F4DD 生成 GitHub Summary"
run: "echo \"## \U0001F4CA 测试报告汇总\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\necho \"| 项目 | 值 |\" >> $GITHUB_STEP_SUMMARY\necho \"|------|------|\" >> $GITHUB_STEP_SUMMARY\necho \"| 触发工作流 | ${{ github.event.workflow_run.name }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 运行 ID | ${{ github.event.workflow_run.id }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 分支 | ${{ github.event.workflow_run.head_branch }} |\" >> $GITHUB_STEP_SUMMARY\necho \"| 结果 | ${{ github.event.workflow_run.conclusion }} |\" >> $GITHUB_STEP_SUMMARY\necho \"\" >> $GITHUB_STEP_SUMMARY\n\nif [ \"${{ github.event.workflow_run.conclusion }}\" == \"success\" ]; then\n echo \"### ✅ 测试通过\" >> $GITHUB_STEP_SUMMARY\nelse\n echo \"### ❌ 测试失败\" >> $GITHUB_STEP_SUMMARY\n echo \"\" >> $GITHUB_STEP_SUMMARY\n echo \"请查看 [运行详情](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) 了解更多信息。\" >> $GITHUB_STEP_SUMMARY\nfi\n"
- name: "\U0001F4E4 上传综合报告"
uses: actions/upload-artifact@v4
with:
name: test-report-${{ github.event.workflow_run.id }}
path: test-report.md
retention-days: "30"
...
|
generate-report
|
["collect-results"]
|
["ubuntu-latest"]
|
0
|
4
|
0
|
0
|
1777363272
|
1777363300
|
|
1
|
|
0
|
Edit
Delete
|