标题高大上,其实核心问题就是统计团队成员的提交次数和代码行数,以及最近提交的时间。
这个工作在之前有一个小工具,是运维团队里的一位小兄弟写的,我定期(每周)可以收到一封 HTML 格式的报告,看上去基本够用。年后计划在新的团队里用起来,把代码打开一看,发现要重新适配的东西还不少。
首先,就是环境的不同。这包括:
- 运行此工具的主机
- GitLab 所在主机
- 团队人员信息数据所在的数据库、表
- 供本工具使用的数据库、表
- 以上各系统的访问身份以及权限
原来的程序在结构上分为两个部分,各为一个 python 源文件,一个负责收集数据,一个负责对收集到的数据进行加工处理,生成报表。这两个程序的特点就是,把编程新手能犯的错几乎都犯了:1. 每个文件中一个函数,数百行;2. 所有可能发生变化的信息均为就地硬编码;3. 命名拙实,i、ii、iii、data、data1、data2 这样的;4. if 和 for 等语句组合起来导致缩进严重;5. 几乎没有考虑中间步骤出错的情况。在对这一团乱麻进行梳理的过程中,也着手开展了重构工作,最后形成了个看上去勉强算是差不多的项目。期间还在网络上搜索他人的解决方案,试图加以吸收优点。
可以找的 git 代码库统计程序,大致有:
- 基于 Gitlab 统计代码行——统计所有仓库、所有提交人的代码总行数(新增/删除);这个程序是用 shell 脚本写的,如果明确知晓在可预见的将来对程序的拓展性没有什么大要求,可以考虑,但对我来说不会首选,由于 shell 编程水平太菜,几乎每条复杂语句都需要较高的调试验证成本;
- 通过 gitlab 远程统计 git 代码量 以及 https://segmentfault.com/a/1190000020367913;记得这两篇都是利用 GitLab 的开放 API 来做统计的,偏巧昨天开始思否网站触了霉头,正在停服整顿,所以只好把 URL 留存;这种方式就是要学习 GitLab 开放 API 的设计了,然后请求数据,再解析 JSON;
- 使用其他第三方的工具/库:https://github.com/tomgi/git_stats(Ruby 实现,分析 git 命令行输出)、https://github.com/gitlab4j/gitlab4j-api(Java 实现,封装了 GitLab 的 RESTful API)、https://github.com/python-gitlab/python-gitlab(Python 实现,封装了 GitLab 的 API v4)。
在现有代码里,有对 GitLab 自己所用数据库的访问操作,但经过分析,发现其作用只是用于仓库同步等任务状态的判断,与代码提交统计无关。代码统计采用 ssh 远程登录到 GitLab 服务所在主机,调用 git 命令后分析其输出即可。这样就确定了着手的焦点。
通常情况下,GitLab 将所有仓库存储于 /var/opt/gitlab/git-data/repositories
目录下。GitLab 中的用户,以及创建的组,均会直接体现在此目录下,而其下才是各自拥有的代码仓库。需要注意,在 GitLab 里创建的仓库,通常会自动生成一个伴生的用于存放项目 Wiki 的仓库。假设项目存储在 project.git 目录的话,则会有 project.wiki.git 目录存在,这个目录的变更要不要纳入统计是要考虑的(我是将它们直接排除了)。再有就是 GitLab 支持子组,体现为一个不带 .git 后缀的普通目录,其下又可以存放仓库目录。之前的统计程序没有递归遍历,只是简单处理了 ls
命令的输出,是有遗漏项目的可能的,在改进时把枚举命令改成了 find
,直接就会得到更准确的目录集合。
原来的统计程序被设定为每周日自动执行,因此在写程序的时候,把统计截止时间到处默认为当前时间/日期,无论是在 Python 代码里,还是和数据库交互时的 SQL 里,在做重构时也进行了相应的修改,可以指定某一天为截止日,以该日期为基准统计此前一周的数据(当然,如果愿意,还可以把单位“周”也修改为可以设置为“月”或者“季”或“年”)。
ssh 访问库,用的是 paramiko,如果有强烈的洁癖,你甚至可以抽象一层 RemoteHost 的类,以达到可以替换此实现的目的。
顺便记录个 git 仓库从外网迁移至内网的步骤:
- 克隆代码(base 仓库):
git clone --base 外仓地址
; - 修改远程仓库地址:
git remote set-url orign 内仓地址
; - 推送代码:
git push --mirror 内仓地址
。