# Git Repo Manager - 设计文档 ## 概述 一个面向小团队(3-10人)的 Git 仓库本地同步管理工具。通过 Web 界面管理多个 Gitea 服务器,支持将远程仓库批量同步到本地,提供提交历史查看和定时自动同步功能。首版聚焦 Gitea 服务器支持。 ## 技术选型 | 层 | 技术 | 理由 | |----|------|------| | 后端 | Python FastAPI | 开发快速,异步支持好 | | 前端 | Vue 3 + Element Plus + Pinia | 中文生态完善,适合管理后台 | | 数据库 | SQLite + SQLAlchemy ORM | 零部署,适合小团队 | | 调度 | APScheduler | Python 生态成熟方案 | | SSH | paramiko | 纯 Python SSH 实现 | | HTTP 客户端 | Axios | 前端请求拦截器 | | 部署 | 单进程 uvicorn | 一个命令启动全部功能 | ## 架构设计 ### 整体架构 单体 FastAPI 应用,内嵌前端静态资源,单进程运行: ``` ┌─────────────────────────────────────────────┐ │ FastAPI 单进程 │ │ │ │ ┌─────────┐ ┌──────────┐ ┌────────────┐ │ │ │ REST API │ │ Scheduler │ │ Git Engine │ │ │ │ /api/v1 │ │ APSched │ │ git+SSH │ │ │ └────┬─────┘ └─────┬────┘ └─────┬──────┘ │ │ │ │ │ │ │ ┌────┴──────────────┴──────────────┴──────┐ │ │ │ Service Layer │ │ │ │ ServerService / RepoService / SyncSvc │ │ │ └────────────────┬────────────────────────┘ │ │ │ │ │ ┌────────────────┴────────────────────────┐ │ │ │ SQLAlchemy + SQLite (data + keys) │ │ │ └─────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ Vue 3 SPA (打包后静态托管) │ │ │ └─────────────────────────────────────────┘ │ └─────────────────────────────────────────────┘ ``` ### 项目目录结构 ``` git-manager/ ├── backend/ │ ├── app/ │ │ ├── main.py # FastAPI 入口,挂载路由和静态文件 │ │ ├── config.py # 配置管理,读取环境变量 │ │ ├── database.py # SQLite 连接,会话管理 │ │ ├── security.py # 加解密工具,API 认证 │ │ ├── models/ # SQLAlchemy 数据模型 │ │ │ ├── __init__.py │ │ │ ├── server.py # Server 模型 │ │ │ ├── repo.py # Repo 模型 │ │ │ ├── ssh_key.py # SshKey 模型 │ │ │ └── sync_log.py # SyncLog 模型 │ │ ├── schemas/ # Pydantic 请求/响应模型 │ │ │ ├── __init__.py │ │ │ ├── server.py │ │ │ ├── repo.py │ │ │ ├── ssh_key.py │ │ │ ├── sync_log.py │ │ │ └── common.py # 标准响应格式 │ │ ├── services/ # 业务逻辑层 │ │ │ ├── __init__.py │ │ │ ├── server_service.py │ │ │ ├── repo_service.py │ │ │ ├── sync_service.py │ │ │ └── ssh_key_service.py │ │ ├── api/ # API 路由 │ │ │ ├── __init__.py │ │ │ ├── deps.py # 依赖注入(DB 会话、认证) │ │ │ ├── servers.py │ │ │ ├── repos.py │ │ │ ├── ssh_keys.py │ │ │ ├── sync_logs.py │ │ │ ├── schedules.py │ │ │ └── status.py │ │ └── tasks/ # 定时任务 │ │ ├── __init__.py │ │ └── sync_task.py │ ├── init_db.py # 数据库初始化脚本 │ └── requirements.txt ├── frontend/ │ ├── src/ │ │ ├── App.vue │ │ ├── main.js │ │ ├── router/ │ │ │ └── index.js │ │ ├── views/ # 页面组件 │ │ │ ├── Dashboard.vue │ │ │ ├── Servers.vue │ │ │ ├── Repos.vue │ │ │ ├── SyncLogs.vue │ │ │ ├── SshKeys.vue │ │ │ └── Settings.vue │ │ ├── components/ # 通用组件 │ │ │ ├── ServerForm.vue │ │ │ ├── RepoSyncStatus.vue │ │ │ └── CommitHistory.vue │ │ ├── api/ # API 调用封装 │ │ │ ├── index.js # Axios 实例,拦截器 │ │ │ ├── servers.js │ │ │ ├── repos.js │ │ │ ├── sshKeys.js │ │ │ └── syncLogs.js │ │ └── stores/ # Pinia 状态管理 │ │ ├── servers.js │ │ ├── repos.js │ │ └── app.js │ ├── index.html │ ├── vite.config.js │ └── package.json └── data/ # 运行时数据目录 ├── git_manager.db # SQLite 数据库 ├── ssh_keys/ # SSH 密钥文件(加密存储) └── repos/ # 本地仓库镜像 └── {server_name}/ └── {repo_full_name}/ ``` ## API 设计 ### 设计原则 - 统一 `/api/v1/` 前缀,版本化管理 - 标准 JSON 响应格式:`{"code": 0, "data": {}, "message": "success"}` - Bearer Token 认证:`Authorization: Bearer ` - Swagger 文档自动生成(`/docs`) ### 接口列表 #### 服务器管理 | 方法 | 路径 | 说明 | |------|------|------| | POST | `/api/v1/servers` | 添加 Gitea 服务器 | | GET | `/api/v1/servers` | 服务器列表 | | GET | `/api/v1/servers/{id}` | 服务器详情 | | PUT | `/api/v1/servers/{id}` | 更新服务器配置 | | DELETE | `/api/v1/servers/{id}` | 删除服务器 | | POST | `/api/v1/servers/{id}/test` | 测试连接 + SSH 密钥有效性 | | POST | `/api/v1/servers/{id}/sync` | 触发该服务器所有仓库同步 | #### 仓库管理 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/v1/servers/{id}/repos` | 获取服务器仓库列表(调 Gitea API) | | GET | `/api/v1/repos` | 所有本地已同步的仓库 | | GET | `/api/v1/repos/{id}` | 仓库详情 | | POST | `/api/v1/repos/{id}/sync` | 手动同步单个仓库 | | GET | `/api/v1/repos/{id}/commits` | 仓库提交历史 | #### SSH 密钥管理 | 方法 | 路径 | 说明 | |------|------|------| | POST | `/api/v1/ssh-keys` | 上传私钥 | | GET | `/api/v1/ssh-keys` | 密钥列表 | | DELETE | `/api/v1/ssh-keys/{id}` | 删除密钥 | | POST | `/api/v1/ssh-keys/{id}/test` | 测试密钥有效性 | #### 同步记录 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/v1/sync-logs` | 同步日志列表(支持分页和状态筛选) | | GET | `/api/v1/sync-logs/{id}` | 同步详情 | #### 调度配置 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/v1/schedules` | 查看调度配置 | | PUT | `/api/v1/schedules` | 修改调度配置 | #### 系统状态 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/v1/status` | 系统运行状态、磁盘空间、仓库统计 | ## 数据模型 ### ER 关系 ``` ssh_keys 1 ──── N servers servers 1 ──── N repos repos 1 ──── N sync_logs ``` ### ssh_keys 表 | 字段 | 类型 | 说明 | |------|------|------| | id | INTEGER PK | 自增主键 | | name | VARCHAR(100) | 密钥名称 | | private_key | TEXT | AES-256 加密后的私钥内容 | | fingerprint | VARCHAR(64) | 密钥指纹(用于展示) | | created_at | DATETIME | 创建时间 | ### servers 表 | 字段 | 类型 | 说明 | |------|------|------| | id | INTEGER PK | 自增主键 | | name | VARCHAR(100) | 服务器名称 | | url | VARCHAR(500) | Gitea 服务器地址(如 https://gitea.example.com) | | api_token | TEXT | Gitea API Token(AES-256 加密存储) | | ssh_key_id | INTEGER FK | 关联 ssh_keys.id | | sync_enabled | BOOLEAN | 是否启用自动同步 | | schedule_cron | VARCHAR(50) | 定时表达式(如 `0 */2 * * *`) | | local_path | VARCHAR(500) | 本地仓库存储路径 | | status | VARCHAR(20) | 连接状态:connected / disconnected / untested | | created_at | DATETIME | 创建时间 | | updated_at | DATETIME | 更新时间 | ### repos 表 | 字段 | 类型 | 说明 | |------|------|------| | id | INTEGER PK | 自增主键 | | server_id | INTEGER FK | 关联 servers.id | | name | VARCHAR(200) | 仓库名称 | | full_name | VARCHAR(300) | 完整路径(owner/repo) | | clone_url | VARCHAR(500) | SSH 克隆地址 | | local_path | VARCHAR(500) | 本地镜像路径 | | last_sync_at | DATETIME | 最后同步时间 | | status | VARCHAR(20) | 状态:pending / syncing / synced / failed | | created_at | DATETIME | 创建时间 | ### sync_logs 表 | 字段 | 类型 | 说明 | |------|------|------| | id | INTEGER PK | 自增主键 | | repo_id | INTEGER FK | 关联 repos.id | | status | VARCHAR(20) | synced / failed | | started_at | DATETIME | 开始时间 | | finished_at | DATETIME | 结束时间 | | commits_count | INTEGER | 本次同步新增提交数 | | error_msg | TEXT | 失败时的错误信息 | | created_at | DATETIME | 创建时间 | ## 同步流程 ### 首次同步(clone) ``` 用户添加服务器 → 调 Gitea API 获取仓库列表 → 对每个仓库: 1. 生成 local_path: data/repos/{server_name}/{full_name} 2. 解密 SSH 私钥到内存 3. git clone --mirror 4. 记录 sync_log(状态 synced,提交数) 5. 更新 repo.status = synced ``` ### 增量同步(fetch) ``` 定时任务触发 / 手动触发 → 遍历该服务器下所有仓库: 1. repo.status = syncing 2. 解密 SSH 私钥到内存 3. git fetch --all 4. 对比 refs 变化,计算新增提交数 5. 记录 sync_log 6. repo.status = synced / failed ``` ## 前端页面 ### 页面布局 ``` ┌──────────────────────────────────────────────────┐ │ Git Manager [状态] [≡] │ ├────────┬─────────────────────────────────────────┤ │ 仪表盘 │ │ │ 服务器 │ 主内容区 │ │ 仓库 │ │ │ 同步记录 │ │ │ SSH密钥 │ │ │ 系统设置 │ │ ├────────┴─────────────────────────────────────────┤ │ 上次同步: 2026-03-30 14:00 | 下次: 16:00 | 共 42 仓库 │ └──────────────────────────────────────────────────┘ ``` ### 页面功能 **仪表盘:** 服务器数量、仓库总数、同步状态统计(synced/failed/syncing)、最近 5 条同步记录、磁盘占用。 **服务器管理:** 添加/编辑/删除 Gitea 服务器,配置 URL、API Token、关联 SSH 密钥、同步计划(Cron 表达式),"测试连接"按钮验证配置有效性。 **仓库列表:** 按服务器分组展示,显示同步状态(标签颜色区分)、最后同步时间。支持搜索过滤。每行有"手动同步"按钮。 **同步记录:** 时间线形式展示同步日志,支持按状态(成功/失败)筛选,展开查看新增提交数和错误详情。 **SSH 密钥:** 上传私钥文件或粘贴内容,显示密钥指纹和关联服务器数,删除时检查是否有关联服务器。 **系统设置:** API Token 管理、全局仓库存储根路径、调度全局开关(暂停/恢复所有定时任务)。 ## 安全设计 | 项 | 方案 | |----|------| | 私钥存储 | AES-256 加密后存入 SQLite,加密密钥从环境变量 `GM_ENCRYPT_KEY` 读取 | | Gitea Token | 同样 AES-256 加密存储 | | API 认证 | Bearer Token,配置在环境变量 `GM_API_TOKEN` | | SSH 连接 | paramiko 使用内存中的解密私钥,不写入磁盘临时文件 | | 输入校验 | Pydantic 模型自动校验所有 API 入参 | ## 环境变量 | 变量 | 必填 | 默认值 | 说明 | |------|------|--------|------| | GM_ENCRYPT_KEY | 是 | - | AES-256 加密密钥(32字节) | | GM_API_TOKEN | 是 | - | API 认证 Token | | GM_DATA_DIR | 否 | ./data | 数据存储根目录 | | GM_HOST | 否 | 0.0.0.0 | 监听地址 | | GM_PORT | 否 | 8000 | 监听端口 | ## 部署方式 ```bash # 安装后端依赖 pip install -r backend/requirements.txt # 构建前端 cd frontend && npm install && npm run build # 构建产物自动输出到 backend/app/static/ # 配置环境变量 export GM_ENCRYPT_KEY= export GM_API_TOKEN= # 初始化数据库 python -m backend.init_db # 启动服务 uvicorn backend.app.main:app --host 0.0.0.0 --port 8000 ``` ## MVP 交付范围 ### 包含 - 多 Gitea 服务器管理(增删改查) - SSH 密钥上传和管理 - 拉取服务器所有仓库列表 - 仓库 clone/fetch 同步 - 手动触发同步 - 定时自动同步(APScheduler + Cron) - 同步历史记录查看 - 提交历史查看 - REST API(版本化,供外部集成) - API Token 认证 - Vue 3 Web 管理界面 ### 不包含(后续迭代) - 多用户 / 权限系统 - Webhook 实时推送 - GitLab / GitHub 支持 - Docker 容器化部署 - 仓库内容浏览(文件树)