From f8f4ee0ce8f0ea34ca137823dfb76a3f1254a865 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Thu, 25 Jun 2026 21:19:34 +0800 Subject: [PATCH] =?UTF-8?q?test(ci):=20=E7=AC=AC6=E5=88=80=20=E2=80=94=20C?= =?UTF-8?q?I=20gate=20=E8=A1=A5=E5=85=A8(=E8=A6=86=E7=9B=96=E7=8E=87?= =?UTF-8?q?=E9=97=B8=20A1=20+=20=E9=9B=86=E6=88=90=E6=B5=8B=E8=AF=95=20job?= =?UTF-8?q?=20A2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A 类「闸的完整性」: - A1 覆盖率闸(防断崖,非追高): · go-server job 加 -coverprofile,host 侧解析 total,< 30% 失败(当前 34.9%)。 · flutter-client job 加 --coverage,host 侧 awk 解析 lcov,< 28% 失败(当前 32.7%)。 阈值留 ~5% 缓冲,只拦回归断崖,不卡日常波动。 - A2 集成测试进 CI(新 go-integration job,Job 10): 真 mysql:8/redis 经 testcontainers 跑 -tags integration(跨库可移植/按租户 记账/配额/兑换/节点生命周期/migrate·时区——sqlite 单测覆盖不到的真库行为)。 · 在 host-mode runner 宿主机直接跑 go(不套 golang 容器):testcontainers 要真 docker,DooD 在 Docker Desktop(mac)上网络不通;依赖宿主 go + docker。 · -p 1 串行:一次只起一个 mysql 容器,避免并发压垮 Docker Desktop。 covers/ 覆盖率产物入 .gitignore。 Co-Authored-By: Claude Opus 4.8 --- .gitea/workflows/ci.yml | 37 ++++++++++++++++++++++++++++++++----- .gitignore | 5 +++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 9fbf63f..a115ca2 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -74,12 +74,16 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: flutter analyze + test (unit/widget) + - name: flutter analyze + test + coverage run: | docker run --rm \ -v "$PWD/client:/app" -w /app \ ghcr.io/cirruslabs/flutter:stable \ - bash -c "flutter pub get && flutter analyze --no-fatal-infos && flutter test test/unit test/widget test/contract" + bash -c "flutter pub get && flutter analyze --no-fatal-infos && flutter test --coverage test/unit test/widget test/contract" + # 覆盖率闸(host 侧解析 lcov):防断崖,低于阈值即失败。 + COV=$(awk -F: '/^LF:/{f+=$2} /^LH:/{h+=$2} END{if(f>0)printf "%.1f",h/f*100}' client/coverage/lcov.info) + echo "flutter 行覆盖 ${COV}%" + awk -v c="$COV" 'BEGIN{ if(c+0 < 28){ print "❌ flutter 覆盖率 "c"% < 阈值 28%"; exit 1 } print "✅ flutter 覆盖率 "c"% ≥ 28%" }' # ── Job 5: Portable SQL Scan (支柱 3:双库可移植)───────────────────────── # server Go 运行时查询不得含 MySQL 专属构造(同一份 SQL 要跑 mysql 与 sqlite)。 @@ -113,7 +117,7 @@ jobs: # ── Job 7: Go 服务端(build + test:含契约快照 + sqlite 真库,跳过 integration)── # 此前 server 测试未进 CI;契约快照(支柱 2)等需在此守门。integration 测试走 - # -tags integration(需 docker 起 mysql/redis),不在本 job,由 run_mysql_test.sh 手动跑。 + # -tags integration(需 docker 起 mysql/redis),见 go-integration job。 go-server: name: Go — build + test runs-on: nas @@ -121,12 +125,16 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: go build + vet + test (non-integration) + - name: go build + vet + test + coverage run: | docker run --rm \ -v "$PWD/server:/app" -w /app \ golang:1.25 \ - bash -c "go build ./... && go vet ./... && go test ./..." + bash -c "go build ./... && go vet ./... && go test -coverprofile=cover.out ./... && go tool cover -func=cover.out > coverage.txt" + tail -1 server/coverage.txt + # 覆盖率闸(host 侧解析,避开容器引号转义):防断崖,低于阈值即失败。 + COV=$(grep '^total:' server/coverage.txt | grep -oE '[0-9]+\.[0-9]+') + awk -v c="$COV" 'BEGIN{ if(c+0 < 30){ print "❌ Go 覆盖率 "c"% < 阈值 30%"; exit 1 } print "✅ Go 覆盖率 "c"% ≥ 30%" }' # ── Job 8: E2E Smoke (L4 进程级端到端,含 gRPC 全链路)─────────────────── # 真起打包的 server 二进制(sqlite 临时库 + 内嵌 miniredis,无需 docker-in-docker) @@ -146,6 +154,25 @@ jobs: golang:1.25 \ bash -c "apt-get update -qq && apt-get install -y -qq openssl curl python3 >/dev/null 2>&1 && bash scripts/e2e-smoke.sh" + # ── Job 10: Go 集成测试 (L2:真 mysql8/redis 经 testcontainers)────────── + # 跨库可移植(支柱 3)+ 按租户流量记账(usage)+ 配额(devices)+ 兑换(codes)+ + # 节点生命周期(nodes)+ migrate/时区(store)的真库行为,sqlite 单测覆盖不到。 + # 走 -tags integration,testcontainers 自起 mysql:8/redis 容器。 + # · 在 host-mode runner 的宿主机直接跑 go(不套 golang 容器):testcontainers 要真 + # docker,DooD 套在容器里在 Docker Desktop(mac)上网络不通。依赖宿主 go + docker。 + # · -p 1 串行:一次只起一个 mysql 容器,避免并发把 Docker Desktop 压垮/端口资源争用。 + go-integration: + name: Go — integration (mysql/redis testcontainers) + runs-on: nas + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: go test -tags integration (宿主 docker + testcontainers) + run: | + cd server + go test -tags integration -count=1 -p 1 ./... + # ── Job 9: Golden 视觉回归 (L3 子集:components + auth)────────────────── # Linux 权威基线(scripts/update-goldens.sh 生成;mac 渲染不一致故钉死 Linux 容器)。 # tablet/desktop-stats golden 与 stats-overhaul 工作区耦合,待其合并后并入本 job。 diff --git a/.gitignore b/.gitignore index 78b3184..7a3dc7b 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,8 @@ client/test/golden/failures/ # Inno Setup 编译产物(安装包,本地生成不入库) client/windows/installer/Output/ + +# 覆盖率产物(CI 覆盖率闸生成,临时不入库) +/server/cover.out +/server/coverage.txt +/client/coverage/