|
|
@@ -3,40 +3,47 @@
|
|
|
# -----------------------------------------------------------------------------
|
|
|
# 落地:2026-11-06(最小 CI 管线搭建)
|
|
|
# 追加:2026-11-07(EVD-6 持续回归:契约 JUnit / langgraph pytest / Playwright e2e / tests jest)
|
|
|
+# 重设计:2026-11-07(B-40 修复——CI 软门禁升级为「两级硬门禁」)
|
|
|
# 前置:remote = http://git.iwintrue.com/liaoxg/cfc(GitLab 系自托管)
|
|
|
-# 本机实测(2026-11-06~07,processor JDK8+Maven3.9.9/node22):
|
|
|
-# - 后端 G0 编译 : mvn test-compile -DskipTests=false → BUILD SUCCESS (2046+231 源)
|
|
|
-# - 后端契约/单测 : mvn test -DskipTests=false -Dtest='!**/integration/**' → 1794 例实测跑通
|
|
|
-# - cfc-frontend jest : 14 suites / 296 例全绿
|
|
|
-# - cfc-web jest : 12 suites / 90 例全绿
|
|
|
-# - langgraph pytest : tests/ 11 文件 / 47 方法可拉起(24 pass / 19 fail 为既有 schema 漂移)
|
|
|
-# - Playwright e2e : 74 spec 文件 / 2418 用例收集成功;ci-smoke.spec.js headless 冒烟 1 passed
|
|
|
+#
|
|
|
+# ███ B-40 两级门禁设计(2026-11-07 落地,替代原 4 个 allow_failure 软门禁)███
|
|
|
+# - test-blocking(全绿子集):必须过。任一 blocking job 红 → 流水线红。
|
|
|
+# 含 backend-g0-compile / frontend-jest / web-jest / backend-blocking-junit
|
|
|
+# / langgraph-blocking-pytest。
|
|
|
+# - test-observed(已知红 / 环境依赖):allow_failure: true,失败不拦截,
|
|
|
+# 但始终产出 junit 趋势(artifacts when: always),供测试侧逐轮跟踪。
|
|
|
+# 含 backend-observed-junit / e2e-playwright-observed / tests-jest-observed。
|
|
|
+# - 「integration 包按类白名单逐批转入 blocking」机制:
|
|
|
+# * 后端 blocking 用 `-Dtest='!${BACKEND_OBSERVED_CLASSES}'` 排除「已知红类」,
|
|
|
+# 其余全跑——即所有**当前全绿**的 integration 类已自动进入 blocking(首批);
|
|
|
+# * 每修好一个红类,就从 BACKEND_OBSERVED_CLASSES 移除该类 → 下轮自动转入
|
|
|
+# blocking(逐批增量);blocking 覆盖例数随之上升,直至 observed 清空。
|
|
|
+# - 覆盖口径:blocking 覆盖 = 全量 − observed(已知红)≥ 当前全量 80%
|
|
|
+# (当前红类 33 类 / 红例 115 例 [failures+errors,第 69 轮干净 HEAD 实测],
|
|
|
+# blocking 覆盖例数 ≥92%,满足 B-40 闭环条件)。
|
|
|
#
|
|
|
# 🔴 关键坑(必须保留):cfc-backend/pom.xml 第 28 行 <skipTests>true</skipTests>,
|
|
|
# 直接 `mvn test` 会**静默跳过全部测试(假绿)**。因此后端 job 必须显式
|
|
|
-# `-DskipTests=false`,否则 CI 绿灯是假的。
|
|
|
+# `-DskipTests=false`,并加「0 XML 即失败」守卫(B-39)。
|
|
|
#
|
|
|
# 🔴 启用前置(本机实测,runner 侧待平台核实):
|
|
|
# 1) runner 需 JDK8 + Maven + node18/20/22 + npm + Python3.11+ + 可拉依赖网络
|
|
|
-# 2) 本文件默认 when: manual(首次先手动触发跑通);确认 runner 能力后
|
|
|
-# 将各 job 的 `when: manual` 改为 `when: on_success`(或删除该行走默认自动)
|
|
|
+# 2) blocking job 已改 `when: on_success`(自动触发,硬门禁);首次跑通前若
|
|
|
+# runner 能力未备,可临时将 blocking job 改回 `when: manual` 人工验证一次,
|
|
|
+# 但「红即拦」语义不变(blocking 均未设 allow_failure)。
|
|
|
# 3) 若 runner .m2 已预热且无外网,可在 mvn 命令加 `-o`(离线)
|
|
|
-# 4) e2e-playwright 需 runner 具备 chromium 系统依赖(或 root 跑
|
|
|
+# 4) e2e-playwright-observed 需 runner 具备 chromium 系统依赖(或 root 跑
|
|
|
# `npx playwright install --with-deps chromium`)
|
|
|
-# 5) tests-jest 依赖 npm>=10 解析 "npm:@vue/babel-plugin-jsx@^1.1.1"(node22 自带 npm10)
|
|
|
+# 5) tests-jest-observed 依赖 npm>=10 解析 "npm:@vue/babel-plugin-jsx@^1.1.1"(node22 自带 npm10)
|
|
|
# -----------------------------------------------------------------------------
|
|
|
# 设计说明(G0/G1 分层基线):
|
|
|
# - G0 编译门禁(backend-g0-compile,必绿,最快信号)
|
|
|
-# - G1 各套件分层回归:
|
|
|
-# * backend-contract-junit:契约/单测(排除需 DB 的 integration 包);
|
|
|
-# 存在既有契约漂移红(如 StatsControllerTest 500 vs 5001),
|
|
|
-# allow_failure 兜底,拍板后移除
|
|
|
-# * langgraph-pytest:schema 漂移既有 19 红(respondent_name 等),allow_failure 兜底
|
|
|
-# * e2e-playwright:**CI 安全模式**——只做 `--list` 收集校验 + headless 冒烟;
|
|
|
-# 真实 UI e2e 依赖部署环境 + DB(globalSetup 会重置 192.168.16.251 测试库,
|
|
|
-# **严禁**在 CI 开启 playwright.config.js 默认 globalSetup)
|
|
|
-# * tests-jest:依赖 cfc-frontend(vue)依赖,npm10 才能装
|
|
|
-# - 前端/管理端用 jest --ci(已验证全绿,无外部依赖)
|
|
|
+# - G1 两级回归(B-40):
|
|
|
+# * test-blocking:全绿子集(前端 jest / 管理端 jest / 后端非红类 / langgraph pytest)
|
|
|
+# * test-observed:已知红或环境依赖(后端红类 / e2e CI 安全模式 / tests jest)
|
|
|
+# - e2e-playwright-observed:**CI 安全模式**——只做 `--list` 收集校验 + headless 冒烟;
|
|
|
+# 真实 UI e2e 依赖部署环境 + DB(globalSetup 会重置 192.168.16.251 测试库,
|
|
|
+# **严禁**在 CI 开启 playwright.config.js 默认 globalSetup)
|
|
|
# =============================================================================
|
|
|
|
|
|
stages:
|
|
|
@@ -45,6 +52,13 @@ stages:
|
|
|
|
|
|
variables:
|
|
|
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"
|
|
|
+ # ---------------------------------------------------------------------------
|
|
|
+ # 后端「已知红类」(test-observed 白名单,逗号分隔的简单类名)。
|
|
|
+ # 依据:第 69 轮全量实跑(干净 HEAD)红类快照(33 类,surefire-reports 提取)+ B-38 归因;
|
|
|
+ # 修好一个类就从下方列表移除一个 → 该类下轮自动转入 test-blocking(逐批增量)。
|
|
|
+ # 说明:`-Dtest='!${BACKEND_OBSERVED_CLASSES}'` 只排除这些类,其余全跑(含全绿 integration 类)。
|
|
|
+ # ---------------------------------------------------------------------------
|
|
|
+ BACKEND_OBSERVED_CLASSES: "AdminFamilyOverviewControllerTest,ArticleControllerTest,ArticleWorkflowTest,AuthControllerTest,CfCommissionServiceSettleTest,DailyCheckinStreakFlowTest,DimensionRegistryMapContractTest,DimensionScoreServiceImplTest,EnergySystemFlowTest,FamilyAdminOverviewServiceTest,FamilyControllerTest,FamilyJoinRequestServiceReferrerBindTest,FortuneServiceTest,GrowthRecordSyncFlowTest,GuideFamilyTaskControllerTest,GuideModuleIntegrationTest,GuideOrderControllerTest,GuideRolePermissionTest,GuideTeamControllerTest,MembershipPaySwitchTest,MindFortuneControllerTest,OrchestrationEngineTest,OrchestrationIntegrationTest,PaymentControllerTest,PaymentServiceORDRoutingTest,PlannerBindInviteFlowTest,ProductControllerTest,ProductOrderControllerTest,ProductOrderServiceFulfillmentMultiModeTest,ProductOrderServiceUpdateExpressFieldTest,StatsControllerTest,UserServiceFamilyNameLinkTest,WishControllerTest"
|
|
|
|
|
|
cache:
|
|
|
key: "$CI_COMMIT_REF_SLUG"
|
|
|
@@ -55,11 +69,11 @@ cache:
|
|
|
- tests/node_modules/
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-# Job 1 — 后端 G0 编译门禁
|
|
|
+# Job 1 — 后端 G0 编译门禁(test-blocking)
|
|
|
# ---------------------------------------------------------------------------
|
|
|
backend-g0-compile:
|
|
|
stage: build
|
|
|
- when: manual # 首次手动;确认 runner 能力后改 on_success
|
|
|
+ when: on_success # B-40:硬门禁自动触发(红即拦)
|
|
|
cache:
|
|
|
key: "$CI_COMMIT_REF_SLUG"
|
|
|
paths:
|
|
|
@@ -73,14 +87,13 @@ backend-g0-compile:
|
|
|
expire_in: 7 days
|
|
|
paths:
|
|
|
- cfc-backend/target/classes/
|
|
|
- # 注:契约/单测复验(G1)暂由本地轮次承担(P-2 3 红未拍板,见 CI_READINESS)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-# Job 2 — 小程序前端(cfc-frontend)jest 单测
|
|
|
+# Job 2 — 小程序前端(cfc-frontend)jest 单测(test-blocking)
|
|
|
# ---------------------------------------------------------------------------
|
|
|
frontend-jest:
|
|
|
stage: test
|
|
|
- when: manual # 首次手动;确认 runner 能力后改 on_success
|
|
|
+ when: on_success # B-40:硬门禁自动触发(红即拦)
|
|
|
cache:
|
|
|
key: "$CI_COMMIT_REF_SLUG"
|
|
|
paths:
|
|
|
@@ -99,11 +112,11 @@ frontend-jest:
|
|
|
- cfc-frontend/coverage/
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-# Job 3 — 管理端(cfc-web)jest 单测
|
|
|
+# Job 3 — 管理端(cfc-web)jest 单测(test-blocking)
|
|
|
# ---------------------------------------------------------------------------
|
|
|
web-jest:
|
|
|
stage: test
|
|
|
- when: manual # 首次手动;确认 runner 能力后改 on_success
|
|
|
+ when: on_success # B-40:硬门禁自动触发(红即拦)
|
|
|
cache:
|
|
|
key: "$CI_COMMIT_REF_SLUG"
|
|
|
paths:
|
|
|
@@ -122,26 +135,55 @@ web-jest:
|
|
|
- cfc-web/coverage/
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-# Job 4 — 后端契约/单测 JUnit(G1,G0 编译门禁的测试侧补充)
|
|
|
+# Job 4 — 后端契约/单测 JUnit · test-blocking(全绿子集,必须过)
|
|
|
# ---------------------------------------------------------------------------
|
|
|
# - 必须 -DskipTests=false 覆盖 pom:28 假绿(否则 mvn test 静默跳测 = 假绿)
|
|
|
-# - 排除 **/integration/**(46 个 @SpringBootTest 中需内网 MySQL 的类在 CI 无法跑)
|
|
|
-# - 既有失败:契约漂移(expected 500 vs 5001 等)为 P-2 已知红,allow_failure 兜底
|
|
|
+# - 仅排除 BACKEND_OBSERVED_CLASSES(已知红类);其余全跑,**含全绿 integration 类**,
|
|
|
+# 即「integration 按类白名单逐批转入 blocking」的首批。
|
|
|
+# - B-39 守卫:surefire 0 个 XML 视为假绿,直接失败(红即拦)。
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
+backend-blocking-junit:
|
|
|
+ stage: test
|
|
|
+ when: on_success # B-40:硬门禁自动触发(红即拦)
|
|
|
+ cache:
|
|
|
+ key: "$CI_COMMIT_REF_SLUG"
|
|
|
+ paths:
|
|
|
+ - .m2/repository
|
|
|
+ script:
|
|
|
+ - cd cfc-backend
|
|
|
+ # 必须 -DskipTests=false(pom.xml:28 默认 true = 假绿);只排除已知红类,其余全跑
|
|
|
+ - mvn -B test -DskipTests=false "-Dtest=!${BACKEND_OBSERVED_CLASSES}"
|
|
|
+ # B-39 守卫:0 个 surefire XML = 零执行假绿 → 失败
|
|
|
+ - test "$(find target/surefire-reports -name 'TEST-*.xml' | wc -l)" -gt 0 || (echo "B-39 假绿守卫:surefire 未产出任何 TEST-*.xml" && exit 1)
|
|
|
+ artifacts:
|
|
|
+ when: always
|
|
|
+ expire_in: 7 days
|
|
|
+ reports:
|
|
|
+ junit:
|
|
|
+ - cfc-backend/target/surefire-reports/TEST-*.xml
|
|
|
+ paths:
|
|
|
+ - cfc-backend/target/surefire-reports/
|
|
|
+
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
+# Job 4b — 后端「已知红类」JUnit · test-observed(allow_failure,产出趋势)
|
|
|
+# ---------------------------------------------------------------------------
|
|
|
+# - 只跑 BACKEND_OBSERVED_CLASSES(红类),allow_failure 不拦截;
|
|
|
+# 每轮产生 junit 供测试侧看红例数是否下降(趋势)。
|
|
|
+# - 修好一个类 → 从 BACKEND_OBSERVED_CLASSES 移除 → 下轮自动转入 blocking。
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-backend-contract-junit:
|
|
|
+backend-observed-junit:
|
|
|
stage: test
|
|
|
- when: manual # 首次手动;确认 runner 能力后改 on_success
|
|
|
- allow_failure: true # 既有契约漂移红(StatsControllerTest 500 vs 5001 等)未拍板
|
|
|
+ when: on_success
|
|
|
+ allow_failure: true # 已知红,失败不拦截,仅产出趋势
|
|
|
cache:
|
|
|
key: "$CI_COMMIT_REF_SLUG"
|
|
|
paths:
|
|
|
- .m2/repository
|
|
|
script:
|
|
|
- cd cfc-backend
|
|
|
- # 必须 -DskipTests=false(pom.xml:28 默认 true = 假绿);排除需 DB 的 integration 包
|
|
|
- - mvn -B test -DskipTests=false -Dtest='!**/integration/**'
|
|
|
+ - mvn -B test -DskipTests=false "-Dtest=${BACKEND_OBSERVED_CLASSES}"
|
|
|
after_script:
|
|
|
- - echo "契约/单测结果见 surefire-reports" || true
|
|
|
+ - echo "observed 红类趋势见 surefire-reports(红例数应逐轮下降)" || true
|
|
|
artifacts:
|
|
|
when: always
|
|
|
expire_in: 7 days
|
|
|
@@ -152,17 +194,17 @@ backend-contract-junit:
|
|
|
- cfc-backend/target/surefire-reports/
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-# Job 5 — cfc-langgraph pytest(G1,AI 服务侧)
|
|
|
+# Job 5 — cfc-langgraph pytest · test-blocking(B-34 闭环后全绿,硬门禁)
|
|
|
# ---------------------------------------------------------------------------
|
|
|
# - conftest 自动 import app.main(需全量依赖,requirements_frozen.txt 锁版本)
|
|
|
# - --ignore=tests/qna(test_graph.py 引用不存在的 src.qna → collection error)
|
|
|
-# - 既有失败 19 红(schema 漂移:respondent_name/member_name、MemoryManager 签名等)
|
|
|
-# allow_failure 兜底,待测试侧修复后移除
|
|
|
+# - B-34/B-35/B-37 修复后 67 轮起实测 51 passed / 12 skipped / 0 failed → 转硬门禁。
|
|
|
+# - 注意:tests_contract/ 下的 B-41 flaky(TestGrowthReportInterpretB04)不在本 job
|
|
|
+# 的 `tests/` 范围内,不影响门禁;该 flaky 由测试侧单独跟踪(B-41)。
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-langgraph-pytest:
|
|
|
+langgraph-blocking-pytest:
|
|
|
stage: test
|
|
|
- when: manual
|
|
|
- allow_failure: true # 既有 schema 漂移 19 红(respondent_name 等)待修复
|
|
|
+ when: on_success # B-40:硬门禁自动触发(红即拦)
|
|
|
cache:
|
|
|
key: "$CI_COMMIT_REF_SLUG"
|
|
|
paths:
|
|
|
@@ -183,17 +225,20 @@ langgraph-pytest:
|
|
|
- cfc-langgraph/junit.xml
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-# Job 6 — Playwright e2e(G1,前端侧,CI 安全模式)
|
|
|
+# Job 6 — Playwright e2e(CI 安全模式)· test-observed(allow_failure,产出趋势)
|
|
|
# ---------------------------------------------------------------------------
|
|
|
# ⚠️ 严禁在 CI 使用 tests/playwright.config.js(其 globalSetup 会重置远程
|
|
|
# 192.168.16.251 测试库)。CI 采用安全模式:
|
|
|
# 1) `npx playwright test --list` — 校验 74 spec / 2418 用例可收集
|
|
|
# 2) `-c playwright.config.smoke.js ci-smoke` — headless chromium 真实拉起冒烟
|
|
|
# 真实 UI e2e 依赖部署环境 + DB(cfc.iwintrue.com),由测试负责人手动跑。
|
|
|
+# B-40:真实 e2e 未授权/环境依赖 → 归 test-observed(allow_failure),
|
|
|
+# 但 test-results 每轮归档供趋势跟踪。
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-e2e-playwright:
|
|
|
+e2e-playwright-observed:
|
|
|
stage: test
|
|
|
- when: manual # 首次手动;确认 runner 能力后改 on_success
|
|
|
+ when: on_success
|
|
|
+ allow_failure: true # 环境依赖(部署环境+DB),失败不拦截,仅产出趋势
|
|
|
cache:
|
|
|
key: "$CI_COMMIT_REF_SLUG"
|
|
|
paths:
|
|
|
@@ -212,17 +257,18 @@ e2e-playwright:
|
|
|
- tests/test-results/
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-# Job 7 — tests/ 目录 jest(unit + integration,G1 补充)
|
|
|
+# Job 7 — tests/ 目录 jest(unit + integration)· test-observed(allow_failure)
|
|
|
# ---------------------------------------------------------------------------
|
|
|
# - tests/jest.config.js 依赖 cfc-frontend/__tests__/setup.js(vue),
|
|
|
# 需先装 cfc-frontend 依赖;npm>=10 才能解析 "npm:@vue/babel-plugin-jsx@^1.1.1"
|
|
|
# 本机 npm9.2.0 验证失败(node22 自带 npm10 可装)
|
|
|
-# - integration 部分需后端 API(localhost:9082)在 CI 无后端时仅跑能跑的
|
|
|
+# - integration 部分需后端 API(localhost:9082)在 CI 无后端时仅跑能跑的;
|
|
|
+# 当前 B-36 下根级黑盒 23 例全 skip → 归 test-observed(allow_failure)。
|
|
|
# ---------------------------------------------------------------------------
|
|
|
-tests-jest:
|
|
|
+tests-jest-observed:
|
|
|
stage: test
|
|
|
- when: manual
|
|
|
- allow_failure: true # 需 npm10 + cfc-frontend(vue) 依赖;integration 需后端
|
|
|
+ when: on_success
|
|
|
+ allow_failure: true # 需 npm10 + cfc-frontend(vue) 依赖;integration 需后端;B-36 全 skip
|
|
|
cache:
|
|
|
key: "$CI_COMMIT_REF_SLUG"
|
|
|
paths:
|