diff --git a/.gitea/workflows/ci-cd.yml b/.gitea/workflows/ci-cd.yml index 2b7373ebb..222b27587 100755 --- a/.gitea/workflows/ci-cd.yml +++ b/.gitea/workflows/ci-cd.yml @@ -164,7 +164,8 @@ jobs: USE_IN_MEMORY_DB: "true" run: | set -eu - PYTHONPATH="$PWD/apps/api:$PWD" python3 -m pytest tests/unit -q + PYTHONPATH="$PWD/apps/api:$PWD" python3 -m pytest tests/unit -q \ + --cov=apps --cov-report=term --cov-report=xml - name: Start PostgreSQL for integration tests shell: sh @@ -209,7 +210,8 @@ jobs: run: | set -eu pip install -q pytest-rerunfailures - PYTHONPATH="$PWD/apps/api:$PWD" python3 -m pytest tests/integration -q --timeout=60 -x --reruns 2 --reruns-delay 1 -m "not performance" + PYTHONPATH="$PWD/apps/api:$PWD" python3 -m pytest tests/integration -q --timeout=60 -x --reruns 2 --reruns-delay 1 -m "not performance" \ + --cov=apps --cov-append --cov-report=term --cov-report=xml --cov-fail-under=50 - name: Run API performance baseline tests shell: sh diff --git a/docs/ci-env-vars.md b/docs/ci-env-vars.md new file mode 100644 index 000000000..5def67aea --- /dev/null +++ b/docs/ci-env-vars.md @@ -0,0 +1,235 @@ +# CI 必需环境变量清单 + +> 本文档整理小虾 SaaS 项目中所有从环境变量读取的配置项,明确哪些是 CI 测试必须的、哪些是可选的。 +> 最后更新:2026-07-09 + +## 目录 + +- [一、配置来源说明](#一配置来源说明) +- [二、CI 必需环境变量(P0)](#二ci-必需环境变量p0) +- [三、可选环境变量(有默认值)](#三可选环境变量有默认值) +- [四、测试专用环境变量](#四测试专用环境变量) +- [五、Worker 服务环境变量](#五worker-服务环境变量) +- [六、当前 CI 配置对照](#六当前-ci-配置对照) + +--- + +## 一、配置来源说明 + +项目的环境变量配置主要来自以下几处: + +| 来源 | 文件路径 | 说明 | +|------|---------|------| +| API 主配置 | `apps/api/app/config.py` | pydantic `Settings` 类,API 服务核心配置 | +| Worker 配置 | `apps/worker/worker_app/core/config.py` | pydantic `WorkerSettings` 类,Worker 服务配置 | +| 共享配置 | `packages/shared/config.py` | pydantic `SharedSettings` 类,API + Worker 共享配置 | +| 直接读取 | 各模块中 `os.environ` / `os.getenv` | 散落在各业务模块中的直接读取 | + +> **注意**:pydantic-settings 配置默认 `case_sensitive=False`,即环境变量名不区分大小写,但习惯上使用大写。 + +--- + +## 二、CI 必需环境变量(P0) + +以下变量是 CI 运行测试**必须配置**的,缺失会导致测试启动失败或核心功能异常。 + +| 变量名 | 用途说明 | 默认值 | 影响范围 | +|--------|---------|--------|---------| +| `DATABASE_URL` | 数据库连接字符串 | `postgresql+psycopg://postgres:postgres@localhost:5432/xiaoxia_saas` | 集成测试、 Alembic 迁移验证 | +| `USE_IN_MEMORY_DB` | 是否使用内存数据库(SQLite) | `false` | 单元测试(设为 `true` 可跳过 PostgreSQL 依赖) | +| `JWT_SECRET_KEY` | JWT 签名密钥,**无安全默认值**,必须显式设置 | `None`(启动校验失败) | 所有涉及认证的 API 测试 | + +> **说明**: +> - 单元测试通过 `USE_IN_MEMORY_DB=true` 使用 SQLite 内存数据库,无需 PostgreSQL +> - 集成测试需要真实 PostgreSQL,需设置 `DATABASE_URL` +> - `JWT_SECRET_KEY` 在测试文件中通过 `os.environ.setdefault()` 设置了测试用默认值,CI 中可不额外配置,但生产环境必须配置 + +--- + +## 三、可选环境变量(有默认值) + +以下变量都有合理的默认值,CI 中可以不配置,使用默认值即可。 + +### 3.1 应用基础配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `APP_NAME` | 应用名称 | `xiaoxia-saas` | +| `APP_VERSION` | 应用版本号 | `0.1.61` / `unknown` | +| `ENVIRONMENT` | 运行环境标识 | `development` | +| `DEBUG` | 是否开启调试模式 | `true` | +| `APP_BASE_URL` | 应用基础 URL(用于生成邮件链接等) | `http://localhost:3000` | +| `API_HOST` | API 服务绑定地址 | `0.0.0.0` | +| `API_PORT` | API 服务端口 | `8000` | +| `API_PREFIX` | API 路由前缀 | `/api/v1` | +| `APP_ENV` | 环境标识(用于加载 .env.{env} 文件) | `development` | +| `LOG_LEVEL` | 日志级别 | `INFO` | + +### 3.2 数据库连接池配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `DATABASE_POOL_SIZE` | 连接池大小 | `20` | +| `DATABASE_MAX_OVERFLOW` | 最大溢出连接数 | `10` (API) / `40` (Worker) | +| `DATABASE_POOL_TIMEOUT` | 获取连接超时时间(秒) | `30` | +| `DATABASE_POOL_RECYLE` / `DATABASE_POOL_RECYCLE` | 连接回收时间(秒) | `3600` | +| `AUTO_CREATE_SCHEMA` | 是否自动创建表结构 | `false` | + +### 3.3 Redis / Celery 配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `REDIS_URL` | Redis 连接地址 | `redis://localhost:6379/0` | +| `REDIS_MAX_CONNECTION` | Redis 最大连接数 | `50` | +| `ENABLE_REDIS_SESSIONS` | 是否启用 Redis 会话存储 | `false` | +| `CELERY_BROKER_URL` / `BROKER_URL` | Celery Broker 地址 | `redis://localhost:6379/0` | +| `CELERY_RESULT_BACKEND` / `RESULT_BACKEND` | Celery 结果后端 | `redis://localhost:6379/1` | + +### 3.4 JWT 配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `JWT_ALGORITHM` | JWT 签名算法 | `HS256`(隐式默认) | +| `JWT_ACCESS_TOKEN_EXPIRE_MINUTES` | Access Token 过期时间(分钟) | `30`(隐式默认) | +| `JWT_REFRESH_TOKEN_EXPIRE_DAYS` | Refresh Token 过期时间(天) | `30`(隐式默认) | +| `JWT_SECRET_KEY_OLD` | 旧 JWT 密钥(用于密钥轮换) | `None` | +| `SECRET_ROTATION_DAYS` | 密钥轮换建议天数 | `90` | + +### 3.5 邮件配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `ENABLE_EMAIL_DELIVERY` | 是否启用邮件发送 | `false` | +| `SMTP_HOST` | SMTP 服务器地址 | `smtp.gmail.com` | +| `SMTP_PORT` | SMTP 端口 | `587` | +| `SMTP_USER` | SMTP 用户名 | `""`(空) | +| `SMTP_PASSWORD` | SMTP 密码 | `""`(空) | +| `SMTP_FROM_EMAIL` | 发件人邮箱 | `""`(空) | +| `SMTP_FROM_NAME` | 发件人名称 | `小虾 SaaS` | +| `SMTP_USE_TLS` | 是否使用 TLS | `true` | + +### 3.6 OSS 阿里云存储配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `OSS_ENDPOINT` | OSS Endpoint | `oss-cn-hangzhou.aliiyuncs.com` | +| `OSS_ACCESS_KEY_ID` | OSS Access Key ID | `""`(空) | +| `OSS_ACCESS_KEY_SECRET` | OSS Access Key Secret | `""`(空) | +| `OSS_BUCKET_NAME` | OSS Bucket 名称 | `xiaoxia-autocut` | +| `OSS_DIRECT_UPLOAD_MAX_MB` / `MAX_UPLOAD_SIZE_MB` | 直传最大文件大小(MB) | `2000` | +| `OSS_DIRECT_UPLOAD_EXPIRE_SECONDS` | 直传签名过期时间(秒) | `900` | + +### 3.7 CosyVoice 语音合成配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `COSYVOICE_API_KEY` | CosyVoice API Key | `""`(空) | +| `COSYVOICE_BASE_URL` | CosyVoice API 地址 | `https://dashscope.aliyuncs.com/api/v1/services/aigc/text2audio` | +| `COSYVOICE_MODEL` | CosyVoice 模型 | `cosyvoice-v1` | +| `COSYVOICE_VOICE` | 默认音色 | `longxiaochun` | +| `COSYVOICE_SAMPLE_RATE` | 采样率 | `22050` | +| `COSYVOICE_FORMAT` | 输出格式 | `mp3` | + +### 3.8 CORS 配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `CORS_ORIGINS_RAW` | CORS 允许的源(逗号分隔) | `http://localhost:3000,http://localhost:5173,http://localhost:8000` | + +### 3.9 文件存储 / 生成文件配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `GENERATED_FILES_DIR` | 生成文件本地存储目录 | `/app/generated` | +| `GENERATED_FILES_URL_PREFIX` | 生成文件访问 URL 前缀 | `/generated-files` | +| `VIDEO_OUTPUT_DIR` | 视频输出目录 | `{tempdir}/video_output` | +| `PUBLIC_API_BASE_URL` | 公开 API 基础 URL | `https://api.xiaoxiajianji.com` | + +### 3.10 监控 / 指标配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `METRICS_AUTH_TOKEN` | Prometheus 指标接口认证 Token | `""`(空,不启用认证) | + +### 3.11 内部 API 配置 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `INTERNAL_API_KEYS` | 内部 API 调用密钥列表(逗号分隔) | `""`(空) | + +--- + +## 四、测试专用环境变量 + +以下变量仅在测试或冒烟测试脚本中使用。 + +| 变量名 | 用途说明 | 默认值 | 使用位置 | +|--------|---------|--------|---------| +| `SMOKE_TEST_PASSWORD` | 冒烟测试用的测试账号密码 | `changeme` | `scripts/smoke_*.py` | +| `MIGRATION_SINCE_REVISION` | 迁移安全检查的起始版本 | `None` | `scripts/check_migration_safety.py` | +| `MIGRATION_DIFF_AGAINST` | 迁移 diff 对比的目标分支/版本 | `None` | `scripts/check_migration_safety.py` | + +--- + +## 五、Worker 服务环境变量 + +以下变量主要用于 Worker(Celery)服务,CI 的单元/集成测试通常不涉及。 + +| 变量名 | 用途说明 | 默认值 | +|--------|---------|--------| +| `WORKER_NAME` | Worker 名称 | `xiaoxia-saas-worker` | +| `WORKER_CONCURRENCY` | Worker 并发数 | `4` | +| `WORKER_MAX_TASKS_PER_CHILD` | 每个子进程最大任务数 | `1000` | + +--- + +## 六、当前 CI 配置对照 + +当前 `.gitea/workflows/ci-cd.yml` 中 `validate` job 配置的环境变量: + +| 变量名 | CI 配置值 | 是否必需 | 备注 | +|--------|----------|---------|------| +| `DATABASE_URL` | `postgresql+psycopg://postgres:postgres@127.0.0.1:5432/xiaoxia_saas` | ✅ 是 | Job 级别配置 | +| `USE_IN_MEMORY_DB` | `"false"`(Job 级) / `"true"`(单元测试 step 级) | ✅ 是 | 单元测试 step 覆盖为 `true` | +| `JWT_SECRET_KEY` | (未配置) | ⚠️ 测试内置 | 测试文件中通过 `setdefault` 设置了测试密钥 | + +### 6.1 CI 环境变量现状评估 + +- ✅ **数据库配置完备**:DATABASE_URL + USE_IN_MEMORY_DB 已正确配置 +- ✅ **JWT 密钥**:测试代码内置默认值,CI 可正常运行 +- ⚠️ **缺少 Redis 配置**:但当前测试不依赖 Redis,使用默认值即可 +- ⚠️ **缺少邮件/OSS/语音配置**:均为可选,CI 中使用空默认值不影响核心测试 + +### 6.2 建议后续补充 + +如果未来测试覆盖到以下功能,需要在 CI 中补充对应配置: + +1. **Redis 相关测试** → 配置 `REDIS_URL` +2. **邮件发送测试** → 配置 `ENABLE_EMAIL_DELIVERY` 及 SMTP 相关变量 +3. **OSS 上传测试** → 配置 OSS 相关变量(或使用 mock) +4. **语音合成测试** → 配置 CosyVoice 相关变量(或使用 mock) + +--- + +## 附录:环境变量读取位置索引 + +### pydantic Settings 类 +- `apps/api/app/config.py` → `Settings` 类(API 主配置) +- `apps/worker/worker_app/core/config.py` → `WorkerSettings` 类(Worker 配置) +- `packages/shared/config.py` → `SharedSettings` 类(共享配置) + +### 直接 os.environ / os.getenv 读取 +| 变量名 | 文件位置 | +|--------|---------| +| `VIDEO_OUTPUT_DIR` | `apps/worker/video_processing/video_compose_service.py`、`apps/worker/worker_app/tasks/compose_video.py` | +| `INTERNAL_API_KEYS` | `apps/api/app/api/routes/auth.py` | +| `APP_ENV` / `ENV` | `apps/api/app/api/routes/auth.py`、各 config.py 的 `get_settings()` | +| `GENERATED_FILES_DIR` | `apps/worker/worker_app/tasks/generation.py`、`apps/api/main.py`、`scripts/cleanup_generated_files.py` | +| `GENERATED_FILES_URL_PREFIX` | `apps/worker/worker_app/tasks/generation.py`、`apps/api/main.py`、`apps/api/app/core/storage.py` | +| `PUBLIC_API_BASE_URL` | `apps/worker/worker_app/tasks/generation.py` | +| `METRICS_AUTH_TOKEN` | `apps/api/app/middleware/prometheus_metrics.py` | +| `APP_VERSION` | `apps/api/app/middleware/prometheus_metrics.py` | +| `SMOKE_TEST_PASSWORD` | `scripts/smoke_*.py` | +| `MIGRATION_SINCE_REVISION` | `scripts/check_migration_safety.py` | +| `MIGRATION_DIFF_AGAINST` | `scripts/check_migration_safety.py` | +| `DATABASE_URL` | `alembic/env.py` | diff --git a/pytest.ini b/pytest.ini index 8befdf898..06ff5b0f9 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,8 @@ [pytest] pythonpath = . apps/api apps/worker testpaths = tests + +# ===== 覆盖率配置 ===== +# 覆盖率统计范围(供 --cov 使用时的默认源) +# 注意:addopts 不默认开启 --cov,避免影响本地开发调试 +# CI 中通过命令行参数显式开启:--cov=apps --cov-report=term --cov-report=xml --cov-fail-under=50