1.说明
统计公司所有项目的提交情况,可指定分支和时间段,返回每个人的提交新增数、删除数和总数。
2.API
文档地址:http://公司gitlab域名/help/api/README.md
- 项目列表查询
返回示例:
[
{
"id": 1, //项目ID
"http_url_to_repo": "http://git.xxx.com/a/saas-project-1.git",
"web_url": "http://git.xxx.com/a/saas-project-1",
"name": "saas-project-1", //项目名
"name_with_namespace": "a / saas-project-1",
"path": "saas-project-1",
"path_with_namespace": "a/saas-project-1"
}
]
- 提交记录查询
- 单次提交统计
3.PRIVATE-TOKEN
PRIVATE-TOKEN获取地址:http://公司gitlab域名/profile/account
查看Private token下面的值即可
4.代码
package com.visy.utils;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.tuple.Triple;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* @author visy.wang
*/
public class GitStatsUtil {
private static final String PRIVATE_TOKEN = "你自己的Private token";
private static final String BASE_URL = "http://公司gitlab域名/api/v4";
private static <T> T doGet(String url, Function<String,T> respHandler, Supplier<T> defaultResp){
HttpRequest request = HttpUtil.createGet(BASE_URL + url);
request.header("PRIVATE-TOKEN", PRIVATE_TOKEN);
HttpResponse response = request.execute();
if(response.getStatus() == 200){
return respHandler.apply(response.body());
}else{
return defaultResp.get();
}
}
private static List<Map<String,Object>> listProjects(){
int pageNo = 1, pageSize = 100;
List<Map<String,Object>> allList = new ArrayList<>();
boolean hasNext = true;
while (hasNext){
System.out.println("listProjects: pageNo=" + pageNo);
List<Map<String,Object>> list = listProjects(pageNo, pageSize);
allList.addAll(list);
pageNo ++;
hasNext = list.size() >= pageSize;
}
return allList;
}
private static List<Map<String,Object>> listProjects(int pageNo, int pageSize){
String url = "/projects?order_by=name&sort=asc&simple=true&archived=false&owned=false&page="+pageNo+"&per_page="+pageSize;
return doGet(url, body -> {
JSONArray array = JSONArray.parseArray(body);
return array.stream().map(item -> {
Map<String,Object> mp = new HashMap<>();
mp.put("id", ((JSONObject)item).getLong("id"));
mp.put("name", ((JSONObject)item).getString("name"));
return mp;
}).collect(Collectors.toList());
}, Collections::emptyList);
}
private static List<String> listCommitIds(Object projectId, String since, String until, String refName){
int pageNo = 1, pageSize = 100;
List<String> allList = new ArrayList<>();
boolean hasNext = true;
while (hasNext){
System.out.println("listCommitIds: pageNo=" + pageNo+", projectId="+projectId);
List<String> list = listCommitIds(projectId, since, until, refName, pageNo, pageSize);
allList.addAll(list);
pageNo ++;
hasNext = list.size() >= pageSize;
}
return allList;
}
private static List<String> listCommitIds(Object projectId, String since, String until, String refName, int pageNo, int pageSize){
String url = "/projects/" + projectId + "/repository/commits?ref_name=" + refName
+ "&page=" + pageNo + "&per_page=" + pageSize
+ "&since=" + since + "T00:00:00+08:00&until=" + until+"T23:59:59+08:00";
return doGet(url, body -> {
JSONArray array = JSONArray.parseArray(body);
return array.stream().map(item -> ((JSONObject)item).getString("id")).collect(Collectors.toList());
}, Collections::emptyList);
}
private static Map<String,Object> getCommitStats(Object projectId, Object commitId){
String url = "/projects/" + projectId + "/repository/commits/" + commitId;
return doGet(url, body -> {
JSONObject data = JSONObject.parseObject(body);
Map<String,Object> mp = new HashMap<>();
mp.put("authorName", data.getString("author_name"));
mp.put("authorEmail", data.getString("author_email"));
data = data.getJSONObject("stats");
mp.put("add", data.getInteger("additions"));
mp.put("delete", data.getInteger("deletions"));
mp.put("total", data.getInteger("total"));
return mp;
}, Collections::emptyMap);
}
public static void main(String[] args) {
//指定时间段和分支名
String since = "2024-01-01", until = "2024-01-31", branch = "branch1";
List<Map<String, Object>> projects = listProjects();
List<Map<String,Object>> allUserCommits = new ArrayList<>();
projects.forEach(project -> {
Object projectId = project.get("id");
List<String> commitIds = listCommitIds(projectId, since, until, branch);
commitIds.forEach(commitId -> allUserCommits.add(getCommitStats(projectId, commitId)));
});
Map<String, Triple<Integer,Integer,Integer>> userCommitsMap = new HashMap<>();
allUserCommits.forEach(item -> {
if(item==null || item.isEmpty()){
return;
}
String userName = item.get("authorName").toString();
Triple<Integer,Integer,Integer> triple = userCommitsMap.getOrDefault(userName, Triple.of(0,0,0));
Integer add = Integer.valueOf(item.get("add").toString());
Integer delete = Integer.valueOf(item.get("delete").toString());
Integer total = Integer.valueOf(item.get("total").toString());
triple = Triple.of(triple.getLeft()+add, triple.getMiddle()+delete, triple.getRight()+total);
userCommitsMap.put(userName, triple);
});
System.out.println("涉及项目("+projects.size()+"):");
projects.forEach(p -> System.out.println(p.get("name")+" [id="+p.get("id")+"]"));
System.out.println("----------------------------------------------------------");
System.out.println("分支:"+branch+", 统计周期: " + since+" ~ " + until);
System.out.println("----------------------------------------------------------");
AtomicInteger add = new AtomicInteger(0), delete = new AtomicInteger(0), total = new AtomicInteger(0);
userCommitsMap.forEach((userName, triple) -> {
add.getAndAdd(triple.getLeft());
delete.getAndAdd(triple.getMiddle());
total.getAndAdd(triple.getRight());
System.out.println(userName + ": 新增=" + triple.getLeft()+", 删除="+triple.getMiddle()+", 总数="+triple.getRight());
});
System.out.println("总计: 新增=" + add.get() + ", 删除=" + delete.get() + ", 总数=" + total.get());
}
}
5.输出示例:
涉及项目(3):
saas-project-1 [id=1]
saas-project-2 [id=2]
saas-project-3 [id=3]
----------------------------------------------------------
分支:branch1, 统计周期: 2024-01-01 ~ 2024-01-31
----------------------------------------------------------
张三: 新增=1, 删除=2, 总数=3
李四: 新增=4, 删除=5, 总数=9
王五: 新增=6, 删除=7, 总数=13
总计: 新增=11, 删除=14, 总数=25