# Gate3 误判修复 + test_api.py 生产适配

**日期**: 2026-05-26
**变更摘要**: 修复 Gate3 测试门控误判 BLOCK 问题；完善 test_api.py 适配生产环境

## 动机

1. Gate3 使用 `grep -qiE "FAIL|ERROR|failed|error"` 匹配测试输出，但测试摘要行 "0/25 failed" 也会被匹配，导致全部通过时仍被 BLOCK
2. test_api.py 在生产环境登录失败（默认密码 admin 不对），需从 .env 加载测试凭据
3. test_api.py 使用错误的状态码期望（POST 创建期望 200 应为 201，DELETE 期望 200 应为 204）

## 变更内容

### deploy/pre_deploy_check.sh — Gate3 修复
- 旧逻辑: `grep -qiE "FAIL|ERROR|failed|error"` — 匹配摘要行 "0/25 failed" 导致误判
- 新逻辑: 精确计数 `[FAIL]` 标记 + 检查 "N test(s) failed" 模式
- 修复 sed 替换丢失 `\s` 转义的问题（`^s+` → `^\s+\[FAIL\]`）

### tests/test_api.py — 生产适配
- 新增 `_load_credentials_from_env_file()` 从 .env 加载 NEXUS_TEST_ADMIN_USER / NEXUS_TEST_ADMIN_PASSWORD
- POST 创建操作 expect_code 从 200 改为 201（REST 标准）
- DELETE 操作 expect_code 从 200 改为 204（REST 标准）
- 修复 server_id 回退逻辑：`else 1` → `else None`（避免操作不存在的服务器）
- 新增测试前清理残留的 test-server-e2e（防止重复创建报错）
- 新增 204 No Content 空响应体处理（`json.loads("")` 会崩溃）
- Schedules 创建改用 `run_mode: "cron"` + `cron_expr`（避免 once 模式需要 fire_at）
- Schedules 的 `server_ids` 从数组改为字符串 `"all"`

## 涉及文件

- `deploy/pre_deploy_check.sh` — Gate3 检测逻辑修复
- `tests/test_api.py` — 生产适配 + REST 状态码修复

## 是否需迁移/重启

- 无需重启后端（test_api.py 是独立脚本）
- 需部署 pre_deploy_check.sh 到远程服务器

## 验证方式

1. 远程运行 `bash deploy/pre_deploy_check.sh` → Gate3 PASS（之前 BLOCK）
2. 远程运行 `python3 tests/test_api.py` → 25/25 passed
3. 全部 7/7 门控通过
