GitCodeStatic - Git仓库统计与缓存系统
一个用Go实现的高性能Git仓库代码统计与缓存系统,支持批量仓库管理、异步任务处理、智能缓存、多种统计维度,提供 Swagger API 文档和 Web 管理界面。
功能特性
核心功能
- ✅ 批量仓库管理:支持批量添加、更新、切换分支、重置仓库
- ✅ 异步任务处理:基于队列的Worker池,支持并发控制和任务去重
- ✅ 代码统计:按分支、贡献者维度统计代码变更(新增/删除/修改/净增加)
- ✅ 智能缓存:基于文件+数据库的双层缓存,自动失效机制
- ✅ 灵活约束:支持日期范围或提交次数限制(互斥校验)
- ✅ 辅助查询:查询指定日期到当前的提交次数
- ✅ 凭据管理:支持私有仓库(用户名/密码/Token)
- ✅ Git双引擎:优先使用git命令,可fallback到go-git
技术特性
- 📊 可观测:结构化日志(zerolog)、基础指标收集
- 🔒 安全:凭据加密存储、URL脱敏、命令注入防护
- 🧪 可测试:关键逻辑提供单元测试示例
- 🎯 RESTful API:统一响应格式、完善错误码
- 📚 Swagger 文档:完整的 API 文档和交互式测试界面
- 🖥️ Web UI:基于 Vue 3 + Element Plus 的管理界面,支持离线部署
- 🗄️ 存储灵活:默认SQLite,可扩展PostgreSQL
- ⚡ 高性能:任务去重、缓存命中、并发控制
快速体验
启动服务
# 构建
make build
# 运行
./bin/gitcodestatic
# 或直接运行
go run cmd/server/main.go
服务启动后,可以通过以下方式访问:
- Web UI: http://localhost:8080/
- Swagger API 文档: http://localhost:8080/swagger/index.html
- Health Check: http://localhost:8080/health cp configs/config.yaml configs/config.local.yaml
主要配置项:
```yaml
server:
port: 8080
workspace:
cache_dir: ./workspace/cache # 仓库本地缓存
stats_dir: ./workspace/stats # 统计结果存储
worker:
clone_workers: 2 # 克隆并发数
stats_workers: 2 # 统计并发数
cache:
max_total_size: 10737418240 # 10GB
retention_days: 30
git:
command_path: "" # 空表示使用PATH中的git
fallback_to_gogit: true
运行
# 开发模式
go run cmd/server/main.go
# 编译
go build -o gitcodestatic cmd/server/main.go
# 运行
./gitcodestatic
服务启动后访问:
- API:
http://localhost:8080/api/v1 - Health:
http://localhost:8080/health
Web UI 使用
启动服务后访问 http://localhost:8080/ 进入 Web 管理界面。
主要功能
-
仓库管理
- 批量添加仓库(支持多行输入)
- 查看仓库列表和状态
- 切换分支、更新、重置、删除操作
-
统计管理
- 触发统计计算(支持日期范围和提交数限制)
- 查询统计结果(可视化展示)
- 查看贡献者详情
-
API 文档
- 快速访问 Swagger 文档
- API 使用示例
详细使用说明请参考 WEBUI_GUIDE.md
API 使用示例
1. 批量添加仓库
curl -X POST http://localhost:8080/api/v1/repos/batch \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://github.com/golang/go.git",
"https://github.com/kubernetes/kubernetes.git"
]
}'
响应:
{
"code": 0,
"message": "success",
"data": {
"total": 2,
"succeeded": [
{
"repo_id": 1,
"url": "https://github.com/golang/go.git",
"task_id": 101
}
],
"failed": []
}
}
2. 查询仓库列表
curl http://localhost:8080/api/v1/repos?status=ready&page=1&page_size=20
3. 触发代码统计
按日期范围统计:
curl -X POST http://localhost:8080/api/v1/stats/calculate \
-H "Content-Type: application/json" \
-d '{
"repo_id": 1,
"branch": "main",
"constraint": {
"type": "date_range",
"from": "2024-01-01",
"to": "2024-12-31"
}
}'
按提交次数统计:
curl -X POST http://localhost:8080/api/v1/stats/calculate \
-H "Content-Type: application/json" \
-d '{
"repo_id": 1,
"branch": "main",
"constraint": {
"type": "commit_limit",
"limit": 100
}
}'
4. 查询统计结果
curl "http://localhost:8080/api/v1/stats/result?repo_id=1&branch=main&constraint_type=date_range&from=2024-01-01&to=2024-12-31"
响应:
{
"code": 0,
"message": "success",
"data": {
"cache_hit": true,
"cached_at": "2024-12-31T10:00:00Z",
"commit_hash": "abc123...",
"statistics": {
"summary": {
"total_commits": 150,
"total_contributors": 5,
"date_range": {
"from": "2024-01-01",
"to": "2024-12-31"
}
},
"by_contributor": [
{
"author": "Alice",
"email": "alice@example.com",
"commits": 50,
"additions": 1000,
"deletions": 200,
"modifications": 200,
"net_additions": 800
}
]
}
}
}
5. 辅助查询:统计提交次数
curl "http://localhost:8080/api/v1/stats/commit-count?repo_id=1&branch=main&from=2024-01-01"
响应:
{
"code": 0,
"message": "success",
"data": {
"repo_id": 1,
"branch": "main",
"from": "2024-01-01",
"to": "HEAD",
"commit_count": 150
}
}
6. 其他操作
切换分支:
curl -X POST http://localhost:8080/api/v1/repos/1/switch-branch \
-H "Content-Type: application/json" \
-d '{"branch": "develop"}'
更新仓库:
curl -X POST http://localhost:8080/api/v1/repos/1/update
重置仓库:
curl -X POST http://localhost:8080/api/v1/repos/1/reset
数据模型
统计指标说明
| 字段 | 说明 | 计算方式 |
|---|---|---|
additions |
新增行数 | git log --numstat 的additions |
deletions |
删除行数 | git log --numstat 的deletions |
modifications |
修改行数 | min(additions, deletions) |
net_additions |
净增加行数 | additions - deletions |
修改行数定义:一行代码被替换时,同时计入additions和deletions,modifications取两者最小值表示真正被修改的行数。
约束类型互斥
date_range 和 commit_limit 互斥使用:
- ✅
{"type": "date_range", "from": "2024-01-01", "to": "2024-12-31"} - ✅
{"type": "commit_limit", "limit": 100} - ❌
{"type": "date_range", "from": "2024-01-01", "to": "2024-12-31", "limit": 100}- 错误
缓存策略
缓存Key生成
SHA256(repo_id | branch | constraint_type | constraint_value | commit_hash)
缓存失效时机
- 仓库更新(pull):commit_hash变化,旧缓存自然失效
- 切换分支:branch变化,缓存key不同
- 重置仓库:主动删除该仓库所有缓存
存储位置
- 元数据:SQLite
stats_cache表 - 结果数据:文件系统
workspace/stats/{cache_key}.json.gz(gzip压缩)
任务系统
任务类型
clone: 克隆仓库pull: 拉取更新switch: 切换分支reset: 重置仓库stats: 统计代码
任务状态
pending: 等待处理running: 执行中completed: 完成failed: 失败cancelled: 已取消
去重机制
相同仓库+相同任务类型+相同参数的待处理任务只会存在一个,重复提交返回已有任务ID。
测试
运行单元测试
# 运行所有测试
go test ./...
# 运行特定测试
go test ./test/unit -v
# 测试覆盖率
go test ./... -cover
测试示例
见 test/unit/ 目录:
service_test.go- 参数校验测试cache_test.go- 缓存key生成测试
开发指南
添加新的 API 端点
- 在
internal/api/handlers/创建handler方法 - 添加 Swagger 注释
- 在
internal/api/router.go注册路由 - 重新生成 Swagger 文档:
swag init -g cmd/server/main.go -o docs
添加新的任务类型
- 在
internal/models/task.go定义任务类型常量 - 在
internal/worker/handlers.go实现TaskHandler接口 - 在
cmd/server/main.go注册handler
扩展存储层
实现 internal/storage/interface.go 中的接口即可,参考 sqlite/ 实现。
扩展 Web UI
- 修改
web/index.html添加新的页面组件 - 在
web/static/app.js添加相应的方法和数据 - 参考 WEBUI_GUIDE.md 了解详细开发流程
错误码
| Code | 说明 |
|---|---|
| 0 | 成功 |
| 40001 | 参数校验失败 |
| 40002 | 操作不允许 |
| 40400 | 资源未找到 |
| 40900 | 资源冲突 |
| 50000 | 内部错误 |
| 50001 | 数据库错误 |
| 50002 | Git操作失败 |
文档
- 架构设计 - 系统架构和技术选型
- 快速开始 - 快速上手指南
- Web UI 使用指南 - 前端和 Swagger 文档使用
- 项目总结 - 项目完整总结
性能优化建议
- Git命令模式:确保安装git命令,性能比go-git快10-100倍
- 并发调优:根据CPU核心数和IO性能调整worker数量
- 缓存预热:对常用仓库/分支提前触发统计
- 定期清理:配置缓存保留天数和总大小限制
已知限制
- 单机部署,不支持分布式(可扩展)
- go-git模式性能较差,仅作为fallback
- 大仓库(>5GB)统计可能耗时较长
- SSH认证暂未完整实现(仅支持https)
技术栈
- 后端: Go 1.21+, Chi Router, zerolog
- 存储: SQLite (可扩展 PostgreSQL)
- Git: git CLI + go-git fallback
- 文档: Swagger 2.0 (swaggo/swag)
- 前端: Vue 3, Element Plus, Axios
- 特性: 完全离线部署支持
贡献
欢迎提Issue和PR!
License
MIT License
作者
Created by Senior Backend/Full-stack Engineer (Go专家)
Description
Languages
Go
53%
HTML
16.4%
JavaScript
13.1%
Shell
9.6%
Batchfile
4.2%
Other
3.7%