From 8ea3263a12a957624a7a31824a6ee4b2ce22ead8 Mon Sep 17 00:00:00 2001 From: CI Bot Date: Wed, 22 Jul 2026 21:16:16 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(ci):=20=E9=9B=86=E6=88=90=E6=B5=8B?= =?UTF-8?q?=E8=AF=95xdist=20worker=E6=95=B0=E6=8C=89=E5=86=85=E5=AD=98?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=AE=A1=E7=AE=97=EF=BC=8C=E9=98=B2=E6=AD=A2?= =?UTF-8?q?OOM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 之前 -n auto 用满所有CPU核,CI runner内存不足导致worker crash 和ffmpeg子进程被SIGKILL。改为根据可用内存动态计算worker数, 预留1GB给系统和ffmpeg等子进程,限制2-8个worker。 同时 maxfail 从1调到3,容忍偶发不稳定。 --- scripts/ci/run_integration_tests.sh | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/scripts/ci/run_integration_tests.sh b/scripts/ci/run_integration_tests.sh index 1fca1158f..0e13d585f 100755 --- a/scripts/ci/run_integration_tests.sh +++ b/scripts/ci/run_integration_tests.sh @@ -252,14 +252,29 @@ echo "" echo "=== 运行集成测试(pytest-xdist 并行模式) ===" echo "CPU 核数: $(nproc 2>/dev/null || echo 'unknown')" +# 根据可用内存动态计算 worker 数,防止 OOM +# 每个 worker 约占 200-300MB(含 DB 连接 + FastAPI test client) +# 预留 1GB 给系统 + ffmpeg 等子进程 +AVAIL_MEM_MB=$(($(grep MemAvailable /proc/meminfo 2>/dev/null | awk '{print $2}' || echo 2097152) / 1024)) +RESERVED_MB=1024 +PER_WORKER_MB=256 +MAX_WORKERS=$(( (AVAIL_MEM_MB - RESERVED_MB) / PER_WORKER_MB )) +# 下限 2,上限 8,CPU 核数也作为上限 +CPU_CORES=$(nproc 2>/dev/null || echo 4) +XDIST_WORKERS=$MAX_WORKERS +[ $XDIST_WORKERS -lt 2 ] && XDIST_WORKERS=2 +[ $XDIST_WORKERS -gt 8 ] && XDIST_WORKERS=8 +[ $XDIST_WORKERS -gt $CPU_CORES ] && XDIST_WORKERS=$CPU_CORES +echo "可用内存: ${AVAIL_MEM_MB}MB, CPU核数: ${CPU_CORES}, xdist workers: ${XDIST_WORKERS}" + # 集成测试使用 pytest-xdist 并行加速(coverage 由单元测试负责,并行模式下 coverage 不稳定) -# -n auto: 自动使用 CPU 核数 +# -n N: 并行 worker 数 # --dist loadfile: 同一测试文件分配到同一 worker(共享 fixture 更高效) -# --maxfail=1: 遇到失败停止调度新测试(并行模式下等价于 -x) +# --maxfail=3: 容忍少量失败(避免偶发 OOM 导致全挂) PYTHONPATH="$PWD/apps/api:$PWD" python3 -m pytest tests/integration \ - -q --timeout=60 --maxfail=1 --reruns 2 --reruns-delay 1 \ + -q --timeout=60 --maxfail=3 --reruns 2 --reruns-delay 1 \ -m "not performance" \ - -n auto --dist loadfile \ + -n $XDIST_WORKERS --dist loadfile \ -p no:cacheprovider echo "✅ 集成测试通过" -- 2.54.0 From 0fccfcd181b2265d1cfcac2642bacacf817916bb Mon Sep 17 00:00:00 2001 From: CI Bot Date: Wed, 22 Jul 2026 20:58:49 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix(test):=20=E4=BF=AE=E5=A4=8Dtest=5Fverif?= =?UTF-8?q?y=5Ftoken=5Ftampered=5Fsignature=E5=81=B6=E5=8F=91=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原测试仅篡改token最后一个字符,在某些PyJWT/环境下可能因 base64填充位或签名末尾字节对齐问题导致验证仍通过。 改为篡改payload内容(修改sub字段),确保签名必然不匹配。 --- tests/unit/test_auth_service.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_auth_service.py b/tests/unit/test_auth_service.py index 42d1c64bc..b0ffa5477 100755 --- a/tests/unit/test_auth_service.py +++ b/tests/unit/test_auth_service.py @@ -456,10 +456,25 @@ class TestJWTService: service.verify_token(token) def test_verify_token_tampered_signature(self, service): - """篡改签名的token无法验证""" + """篡改payload的token无法验证(签名不匹配)""" + import base64 + import json + token = service.create_access_token(user_id="user_123") - # 篡改最后一个字符 - tampered = token[:-1] + ("A" if token[-1] != "A" else "B") + parts = token.split(".") + assert len(parts) == 3 + # 篡改 payload 部分(改用户ID),会导致签名不匹配 + payload_b64 = parts[1] + # 补 padding 以便解码 + padding = 4 - len(payload_b64) % 4 + if padding != 4: + payload_b64 += "=" * padding + payload_bytes = base64.urlsafe_b64decode(payload_b64) + payload = json.loads(payload_bytes) + payload["sub"] = "hacked_user" + new_payload_bytes = json.dumps(payload).encode() + new_payload_b64 = base64.urlsafe_b64encode(new_payload_bytes).rstrip(b"=").decode() + tampered = f"{parts[0]}.{new_payload_b64}.{parts[2]}" with pytest.raises(InvalidTokenError): service.verify_token(tampered) -- 2.54.0