# CI/CD 细则(团队开发版) > 本文档规定 NotesAgent 在 Gitea 上的持续集成、构建产物、发布和回滚要求。当前仓库尚未提交 Gitea Actions 工作流,因此本文首先作为落地流水线时的统一规范;流水线启用前,Pull Request 仍须人工执行同等检查。 > 更新日期:2026-09-01。当前阶段的 CD 指“生成可验证的候选构建与发布产物”,不包含把后端自动部署到公网环境。 ## 1. 目标与原则 CI/CD 用于尽早发现依赖锁文件失效、类型错误、测试回归、前后端契约不一致和生产构建失败。流水线应遵守以下原则: - 以 Gitea 为唯一远程和流水线入口; - `main` 始终保持可安装、可测试、可构建; - 安装依赖时使用锁文件,避免流水线与开发机解析出不同版本; - 未通过必需检查的提交不得合入 `main`; - 外部模型、真实 API Key 和用户本地数据不得成为基础 CI 的前置条件; - 缓存只用于加速,不得影响构建结果;删除缓存后流水线仍应成功; - 测试、构建和发布步骤使用最小权限,敏感信息不得写入日志或产物。 ## 2. 运行环境基线 | 组件 | CI 要求 | 说明 | | --- | --- | --- | | Python | 3.12 | 项目最低支持 3.11,CI 使用团队推荐版本 | | uv | 当前稳定版,并在日志中输出版本 | 按 `backend/uv.lock` 安装后端依赖 | | Node.js | 22 LTS | 满足前端环境要求并保持 Runner 兼容性 | | pnpm | 10 | 按 `frontend/pnpm-lock.yaml` 安装前端依赖 | | 操作系统 | Linux Runner 为基础门禁 | 桌面端启用后再增加 Windows、macOS 构建矩阵 | Runner 镜像或 Action 的大版本必须固定。升级 Python、Node.js、uv、pnpm 或基础 Action 时,应使用独立的 `chore/` 分支,并完整运行前后端检查。 ## 3. 触发规则 | 事件 | 必须执行 | 用途 | | --- | --- | --- | | Pull Request 指向 `main` | 文档检查、后端测试、前端测试、类型检查、生产构建 | 合并门禁 | | 推送到 `main` | 全量检查、集成冒烟、保存候选构建 | 验证合并结果 | | 推送功能分支 | 至少执行受影响模块的检查 | 尽早反馈;不得替代 PR 全量门禁 | | 推送 `v*` 标签 | 全量检查、构建、校验和、发布候选产物 | 正式发布入口 | | 手动触发 | 可选择全量回归或重新生成候选产物 | 发布前复核和故障恢复 | 纯文档变更可以跳过前后端耗时任务,但必须执行文档链接检查和 `git diff --check`。只有可靠的路径检测结果才能判定为纯文档变更;锁文件、工作流、构建配置和接口契约变更一律按代码变更处理。 ## 4. Pull Request 必需检查 建议将以下 Job 名称固定为 Gitea 分支保护所要求的状态检查: | Job | 必需命令或行为 | 通过标准 | | --- | --- | --- | | `docs-check` | `git diff --check`,检查仓库内 Markdown 相对链接 | 无空白错误、无失效本地链接 | | `backend-test` | `uv sync --frozen`、编译检查、`uv run pytest` | 依赖锁有效且测试全部通过 | | `frontend-test` | `pnpm install --frozen-lockfile`、`pnpm test` | 依赖锁有效且测试全部通过 | | `frontend-typecheck` | `pnpm type-check` | 无 TypeScript/Vue 类型错误 | | `frontend-build` | `pnpm build` | Vite 生产构建成功 | | `integration-smoke` | 启动 FastAPI,验证健康检查和关键本地链路 | 服务可启动,响应与契约符合预期 | 后端 Job 的基准命令: ```bash cd backend uv sync --frozen uv run python -m compileall -q app uv run pytest ``` 前端 Job 的基准命令: ```bash cd frontend pnpm install --frozen-lockfile pnpm test pnpm type-check pnpm build ``` `integration-smoke` 应使用 Mock Provider、临时数据库和临时附件目录,不访问 OpenAI、DeepSeek 或其他外部服务。测试结束后必须关闭服务并清理临时数据。 ## 5. 路径与模块检查规则 - 修改 `backend/**`、`backend/uv.lock` 或后端配置时,必须运行 `backend-test` 和 `integration-smoke`。 - 修改 `frontend/**`、`frontend/pnpm-lock.yaml` 或前端配置时,必须运行全部前端 Job。 - 修改 `docs/contracts/**`、FastAPI 路由、DTO、SSE 事件或前端 Service 类型时,必须同时运行前后端全量检查。 - 修改 `.gitea/**`、根目录工程配置或依赖版本时,必须运行所有 Job。 - 修改 `docs/**` 以外且无法明确归类的文件时,默认运行所有 Job。 路径过滤只用于减少无关重复任务,不得造成关键检查缺失。若无法可靠判断影响范围,应执行全量流水线。 ## 6. 凭据与敏感信息 - 基础 CI 不配置真实模型 API Key,Provider 相关测试统一使用 Mock 或请求桩。 - 确需发布签名或访问受保护服务时,凭据只保存在 Gitea Actions Secrets 中,不写入仓库、工作流参数、缓存或构建产物。 - 来自外部分支或不受信任 Pull Request 的任务不得读取发布凭据。 - Secret 名称表达用途和环境,例如 `RELEASE_SIGNING_KEY`;禁止使用含义模糊的 `KEY1`、`TOKEN2`。 - 日志中禁止输出请求头、完整 Token、API Key、用户笔记内容和本地凭据存储内容。 - 生产凭据与测试凭据分离,并遵循最小权限、定期轮换和可撤销原则。 前端构建时注入的变量会进入静态资源,不能用于保存秘密。只有明确可公开的配置才允许使用 Vite 客户端环境变量。 ## 7. 缓存与产物 可以缓存 uv 下载缓存和 pnpm Store,缓存键至少包含操作系统、运行时版本和对应锁文件哈希。不得缓存: - `backend/.venv/`; - `frontend/node_modules/`; - `backend/data/`、测试数据库和用户附件; - `.env`、API Key、本地凭据库或签名材料。 普通 PR 不上传可执行发布包,只保留必要的测试报告和前端构建日志。`main` 或版本标签的候选产物应记录提交 SHA,生成 SHA-256 校验和,并设置明确的保留期限;非正式候选产物建议保留 14 天。 ## 8. 分支保护与合并门禁 Gitea 中的 `main` 应启用以下保护: - 禁止普通成员直接推送和强制推送; - 要求 Pull Request 审阅通过; - 要求第 4 节列出的适用状态检查成功; - Head 更新后使旧审阅和旧检查失效,必须针对最新提交重新检查; - 对话和审阅意见处理完成后才允许合并; - 优先使用 squash 或 rebase 保持主线清晰,具体方式遵循 [Git 使用细则](Git使用细则-团队开发版.md)。 临时绕过门禁只允许用于明确的仓库级故障。绕过者需要记录原因、影响、补验计划,并在恢复后立即补跑全部检查。 ## 9. 发布流程 当前阶段按以下顺序生成发布候选: 1. 从已通过全部检查的 `main` 提交确定发布 SHA; 2. 更新版本号、变更说明和必要文档; 3. 创建形如 `v0.2.0` 的语义化版本标签; 4. 标签流水线重新执行全部测试和生产构建; 5. 对产物执行本地启动或安装冒烟测试; 6. 生成校验和,并把版本、提交 SHA、构建环境和已知限制写入发布说明; 7. 人工确认后在 Gitea 发布页面公开产物。 Tauri 桌面端接入后,发布流水线再增加 Windows、macOS 和 Linux 构建矩阵、平台签名及安装包验证。在签名、更新通道和回滚方案准备完成前,不启用面向用户的自动更新。 ## 10. 回滚与热修复 - 尚未公开的候选产物直接标记为失败,不覆盖同一版本的已有产物;修复后递增预发布编号或版本号。 - 已发布版本出现问题时,优先停止分发并回退到最近一个已验证版本。 - 代码修复从 `main` 创建 `hotfix/<模块>-<问题>` 分支,通过完整门禁后合并并发布补丁版本。 - 禁止重写已公开版本标签或用新文件替换旧版本同名产物。 - 回滚或热修复完成后,在 `docs/retrospectives/` 记录原因、影响、处置过程和防复发措施。 ## 11. 流水线失败处理 1. 先确认失败是否可在本地使用相同锁文件和命令复现; 2. 判断是代码、测试、依赖、Runner 还是外部基础设施问题; 3. 代码或测试问题由当前 PR 修复,不通过重跑掩盖不稳定测试; 4. Runner 或 Gitea 故障应记录日志和时间,恢复后针对同一 Head 重新执行; 5. 连续出现的偶发失败必须作为缺陷处理,明确负责人并增加稳定性修复; 6. 修复流水线本身时,不得顺便降低测试范围或绕过既有门禁。 ## 12. 落地清单 首次创建 `.gitea/workflows/` 时,应逐项确认: - [ ] 工作流只使用 Gitea Runner 支持且来源可信的 Action; - [ ] Python、Node.js、uv 和 pnpm 版本符合本规范; - [ ] 后端和前端依赖均以 frozen 模式安装; - [ ] 必需 Job 名称与 `main` 分支保护一致; - [ ] Mock 测试不依赖外部模型服务和真实凭据; - [ ] 缓存键包含锁文件哈希,缓存内容不含用户数据或秘密; - [ ] PR、`main`、版本标签和手动触发行为分别验证; - [ ] 失败任务能返回非零退出码,后续发布步骤不会继续; - [ ] 候选产物包含提交 SHA、校验和和保留期限; - [ ] 团队成员能够按本文档在本地复现全部门禁。