├── run.sh
├── template
├── 周统计模板.xlsx
└── 月统计模板.xlsx
├── requirements.txt
├── README.md
├── LICENSE
├── day.py
├── .gitignore
├── week.py
├── month.py
└── code_statistics.py
/run.sh:
--------------------------------------------------------------------------------
1 | #!bin/bash
2 | cd /root/GitLab
3 | python -u $1 >> run_info.log
4 |
--------------------------------------------------------------------------------
/template/周统计模板.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fog-forest/code-statistics/main/template/周统计模板.xlsx
--------------------------------------------------------------------------------
/template/月统计模板.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fog-forest/code-statistics/main/template/月统计模板.xlsx
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | certifi==2020.11.8
2 | chardet==3.0.4
3 | et-xmlfile==1.0.1
4 | idna==2.10
5 | jdcal==1.4.1
6 | openpyxl==3.0.5
7 | python-dateutil==2.8.1
8 | python-gitlab==2.5.0
9 | requests==2.25.0
10 | six==1.15.0
11 | urllib3==1.26.2
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GitLab 开发者代码提交量统计
2 | 统计 GitLab 所有开发者代码提交情况,按删除、新增、总计、次数四个维度展示,支持日、月、周三种时间范围,自动将统计结果推送钉钉群
3 |
4 |
5 | ### 使用说明
6 | 1. 安装需要的支持库
7 | `pip install -r requirements.txt`
8 |
9 | 2. 修改 `code_statistics.py` 文件 L13-L24 内容以及 `day.py、month.py、week.py` 三个文件的倒数第二行内容,最后运行即可,这三个文件分别对应 日、月、周三个统计时间范围,需要统计哪个时间就运行哪个脚本
10 |
11 |
12 | ### 自动运行
13 | Linux 设置 crontab 定时任务即可
14 |
15 | ```bash
16 | 50 20 * * 1-6 bash run.sh day.py
17 | 00 21 * * 7 bash run.sh week.py
18 | 30 10 2 1-12 * bash run.sh month.py
19 | ```
20 |
21 |
22 | ### 已知问题
23 | 1. 统计人数超过 25 人,Excel模板排版会有问题,因为数据直接由Excel处理的,所以需要拖下表格让他支持更多行
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Mario
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/day.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from code_statistics import *
4 |
5 | imgurl = "https://ae01.alicdn.com/kf/U56b2fb24ff7b4e5fa05c5acf7d3d0318r.jpg"
6 | file_name = "day.html"
7 |
8 | if __name__ == "__main__":
9 | print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " [日]")
10 | time1 = time.strftime("%Y-%m-%d 00:00:00") # 开始时间
11 | time2 = time.strftime("%Y-%m-%d 23:59:59") # 结束时间
12 |
13 | # header1
14 | content_save(
15 | "
GitLab代码提交量统计GitLab代码提交量统计(单位:行) 【日报】
注:统计将会剔除所有合并操作
上次更新时间:" + time.strftime(
16 | "%Y-%m-%d %H:%M:%S",
17 | time.localtime()) + "
群组仓库
master
| Git用户名 | 新增代码数 | 删除代码数 | 总计代码数 | 提交次数 |
",
18 | "w", file_name)
19 |
20 | gitlab_info(time1, time2, "group") # 群组仓库统计
21 | gitlab_statistics_data(1) # master
22 | gitlab_statistics_content(file_name)
23 | content_save(
24 | "
dev
| Git用户名 | 新增代码数 | 删除代码数 | 总计代码数 | 提交次数 |
",
25 | "a", file_name)
26 |
27 | gitlab_statistics_data(2) # dev
28 | gitlab_statistics_content(file_name)
29 |
30 | # 准备第二次统计前需要清空
31 | print("\n******************* switch *******************\n")
32 | info_master.clear()
33 | info_other.clear()
34 |
35 | # header2
36 | content_save(
37 | "
个人仓库
all
| Git用户名 | 新增代码数 | 删除代码数 | 总计代码数 | 提交次数 |
",
38 | "a", file_name)
39 |
40 | gitlab_info(time1, time2, "user") # 个人仓库统计
41 | gitlab_statistics_data(2) # 个人仓直接统计全部分支
42 | gitlab_statistics_content(file_name)
43 | # footer
44 | content_save("
", "a", file_name)
45 |
46 | dingding("http://localhost/" + file_name, imgurl, "[日报]") # 不需要推送可以注释掉
47 | print("http://localhost/" + file_name)
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
--------------------------------------------------------------------------------
/week.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # coding=utf8
3 | # GitLab 周代码提交详细统计
4 |
5 | import shutil
6 | import time
7 |
8 | from openpyxl import load_workbook
9 |
10 | from code_statistics import *
11 |
12 | imgurl = "https://ae01.alicdn.com/kf/U950a6ec6d17d4bd7b37afe16959d7cbdO.jpg"
13 | Template_Path = "template/周统计模板.xlsx" # 模板路径
14 | Save_Path = report_path + "/week-group.xlsx" # 保存路径
15 |
16 | date_list = [] # 日期列表
17 | name_list = [] # Git用户名列表
18 | daily_master_statistics = {} # 每日详情数据
19 | daily_dev_statistics = {}
20 |
21 |
22 | # 获取本周日期列表
23 | def get_week_list():
24 | global date_list
25 | # 获取当前日期
26 | today = datetime.date.today()
27 | # 本周第一天和最后一天
28 | this_week_start = today - datetime.timedelta(today.weekday())
29 | this_week_end = today + datetime.timedelta(6 - today.weekday())
30 |
31 | # 遍历上月每一天日期
32 | while this_week_start <= this_week_end:
33 | date_list.append(str(this_week_start))
34 | this_week_start += datetime.timedelta(1)
35 |
36 |
37 | # 获取Git用户名列表
38 | def get_user_list(date, dictionary):
39 | global name_list
40 | for name in dictionary[date].keys():
41 | if name in name_list:
42 | continue
43 | else:
44 | name_list.append(name)
45 |
46 |
47 | # 生成每日统计数据
48 | def get_gitlab_daily(start_time, end_time, date):
49 | global daily_dev_statistics, daily_master_statistics
50 | gitlab_info(start_time, end_time, "group") # 群组仓库统计
51 |
52 | # 收集数据
53 | daily_master_statistics[date] = gitlab_statistics_data(1).copy() # master
54 | print("master: ", daily_master_statistics)
55 |
56 | daily_dev_statistics[date] = gitlab_statistics_data(2).copy() # dev
57 | print("dev: ", daily_dev_statistics)
58 |
59 | # 清空数据,准备下一轮循环
60 | info_master.clear()
61 | info_other.clear()
62 |
63 | # 收集Git用户名
64 | get_user_list(date, daily_master_statistics)
65 | get_user_list(date, daily_dev_statistics)
66 |
67 |
68 | # 数据处理写入到excel文件(表面,项目分支名)
69 | def wirte_excel(sheet, branch_type):
70 | wb = load_workbook(Save_Path)
71 | ws_master = wb[sheet] # 访问指定工作表
72 |
73 | if branch_type == "master":
74 | temp = daily_master_statistics
75 | else:
76 | temp = daily_dev_statistics
77 |
78 | # 写入日期到表格
79 | i = 2 # 列
80 | for date in date_list:
81 | ws_master.cell(row=1, column=i, value=date + " (" + get_week_num(date) + ")")
82 | i += 4
83 |
84 | # 写入统计内容到表格
85 | j = 3 # 行
86 | for name in name_list:
87 | k = 2 # 列
88 | # 列写入姓名
89 | ws_master.cell(row=j, column=1, value=name)
90 | for date in date_list:
91 | # 如果有代码提交记录
92 | if name in temp[date].keys():
93 | ws_master.cell(row=j, column=k, value=temp[date][name][0])
94 | ws_master.cell(row=j, column=k + 1, value=temp[date][name][1])
95 | ws_master.cell(row=j, column=k + 2, value=temp[date][name][2])
96 | ws_master.cell(row=j, column=k + 3, value=temp[date][name][3])
97 | else:
98 | ws_master.cell(row=j, column=k, value=0)
99 | ws_master.cell(row=j, column=k + 1, value=0)
100 | ws_master.cell(row=j, column=k + 2, value=0)
101 | ws_master.cell(row=j, column=k + 3, value=0)
102 | # 下一列
103 | k += 4
104 | # 下一行
105 | j += 1
106 | wb.save(Save_Path)
107 |
108 |
109 | if __name__ == "__main__":
110 | print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " [周详细-群组仓]")
111 | get_week_list() # 生成本周日期列表
112 | print(date_list)
113 |
114 | # 获取数据中。。。
115 | for date in date_list:
116 | time1 = date + " 00:00:00" # 开始时间
117 | time2 = date + " 23:59:59" # 结束时间
118 | print("\n", time1, time2)
119 | get_gitlab_daily(time1, time2, date)
120 |
121 | shutil.copy(Template_Path, Save_Path) # 拷贝模板
122 |
123 | wirte_excel("master", "master") # master
124 | wirte_excel("dev", "dev") # dev
125 |
126 | dingding("http://localhost/week-group.xlsx", imgurl, "[周]详细统计仅群组仓 👉点击下载") # 不需要推送可以注释掉
127 |
--------------------------------------------------------------------------------
/month.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # coding=utf8
3 | # GitLab 月代码提交详细统计
4 |
5 | import shutil
6 | import time
7 |
8 | from openpyxl import load_workbook
9 |
10 | from code_statistics import *
11 |
12 | imgurl = "https://ae01.alicdn.com/kf/Uc321eb139bc944989428170e74e9e957W.jpg"
13 | Template_Path = "template/月统计模板.xlsx" # 模板路径
14 | Save_Path = report_path + "/month-group.xlsx" # 保存路径
15 |
16 | date_list = [] # 日期列表
17 | name_list = [] # Git用户名列表
18 | daily_master_statistics = {} # 每日详情数据
19 | daily_dev_statistics = {}
20 |
21 |
22 | # 获取上月日期列表
23 | def get_month_list():
24 | global date_list
25 | today = datetime.date.today() # 获取当前日期
26 | year = today.year
27 | month = today.month
28 |
29 | # 上月第一天和最后一天
30 | if month == 1:
31 | last_month_start = datetime.date(year - 1, 12, 1)
32 | else:
33 | last_month_start = datetime.date(year, month - 1, 1)
34 | last_month_end = datetime.date(year, month, 1) - datetime.timedelta(1)
35 |
36 | # 遍历上月每一天日期
37 | while last_month_start <= last_month_end:
38 | date_list.append(str(last_month_start))
39 | last_month_start += datetime.timedelta(1)
40 |
41 |
42 | # 获取Git用户名列表
43 | def get_user_list(date, dictionary):
44 | global name_list
45 | for name in dictionary[date].keys():
46 | if name in name_list:
47 | continue
48 | else:
49 | name_list.append(name)
50 |
51 |
52 | # 生成每日统计数据
53 | def get_gitlab_daily(start_time, end_time, date):
54 | global daily_dev_statistics, daily_master_statistics
55 | gitlab_info(start_time, end_time, "group") # 群组仓库统计
56 |
57 | # 收集数据
58 | daily_master_statistics[date] = gitlab_statistics_data(1).copy() # master
59 | print("master: ", daily_master_statistics)
60 |
61 | daily_dev_statistics[date] = gitlab_statistics_data(2).copy() # dev
62 | print("dev: ", daily_dev_statistics)
63 |
64 | # 清空数据,准备下一轮循环
65 | info_master.clear()
66 | info_other.clear()
67 |
68 | # 收集Git用户名
69 | get_user_list(date, daily_master_statistics)
70 | get_user_list(date, daily_dev_statistics)
71 |
72 |
73 | # 数据处理写入到excel文件(表面,项目分支名)
74 | def wirte_excel(sheet, branch_type):
75 | wb = load_workbook(Save_Path)
76 | ws_master = wb[sheet] # 访问指定工作表
77 |
78 | if branch_type == "master":
79 | temp = daily_master_statistics
80 | else:
81 | temp = daily_dev_statistics
82 |
83 | # 写入日期到表格
84 | i = 2 # 列
85 | for date in date_list:
86 | ws_master.cell(row=1, column=i, value=date + " (" + get_week_num(date) + ")")
87 | i += 4
88 |
89 | # 写入统计内容到表格
90 | j = 3 # 行
91 | for name in name_list:
92 | k = 2 # 列
93 | # 列写入姓名
94 | ws_master.cell(row=j, column=1, value=name)
95 | for date in date_list:
96 | # 如果有代码提交记录
97 | if name in temp[date].keys():
98 | ws_master.cell(row=j, column=k, value=temp[date][name][0])
99 | ws_master.cell(row=j, column=k + 1, value=temp[date][name][1])
100 | ws_master.cell(row=j, column=k + 2, value=temp[date][name][2])
101 | ws_master.cell(row=j, column=k + 3, value=temp[date][name][3])
102 | else:
103 | ws_master.cell(row=j, column=k, value=0)
104 | ws_master.cell(row=j, column=k + 1, value=0)
105 | ws_master.cell(row=j, column=k + 2, value=0)
106 | ws_master.cell(row=j, column=k + 3, value=0)
107 | # 下一列
108 | k += 4
109 | # 下一行
110 | j += 1
111 | wb.save(Save_Path)
112 |
113 |
114 | if __name__ == "__main__":
115 | print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " [月详细-群组仓]")
116 | get_month_list() # 生成上月日期列表
117 | print(date_list)
118 |
119 | # 获取数据中。。。
120 | for date in date_list:
121 | time1 = date + " 00:00:00" # 开始时间
122 | time2 = date + " 23:59:59" # 结束时间
123 | print("\n", time1, time2)
124 | get_gitlab_daily(time1, time2, date)
125 |
126 | shutil.copy(Template_Path, Save_Path) # 拷贝模板
127 |
128 | wirte_excel("master", "master") # master
129 | wirte_excel("dev", "dev") # dev
130 |
131 | dingding("http://localhost/month-group.xlsx", imgurl, "[月]详细统计仅群组仓 👉点击下载") # 不需要推送可以注释掉
132 |
--------------------------------------------------------------------------------
/code_statistics.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # coding=utf8
3 | # @Author: Mario
4 | # @Date : 2021/01/01
5 | # @Desc : GitLab 按时间查看各用户代码提交量官方API版(钉钉推送版)
6 |
7 | import datetime
8 | import json
9 |
10 | import requests
11 | from dateutil.parser import parse
12 |
13 | # 需修改如下四条信息
14 | gitlab_url = "" # GitLab 地址
15 | private_token = "" # GitLab Access Tokens(管理员权限)
16 | report_path = "/data/" # 生成的报告文件存放目录
17 | dingding_token = "" # 钉钉机器人token
18 |
19 | info_master = []
20 | info_other = []
21 | statistics = {}
22 |
23 | # 需要去除的统计的 Git 用户名
24 | exclude_names = ["Administrator",]
25 |
26 | headers = {
27 | 'Connection': 'close',
28 | }
29 |
30 |
31 | # UTC时间转时间戳
32 | def utc_time(time):
33 | dt = parse(time)
34 | return int(dt.timestamp())
35 |
36 |
37 | # 根据日期获取星期
38 | def get_week_num(date):
39 | week = datetime.datetime.strptime(date, "%Y-%m-%d").weekday() + 1
40 | if week == 1:
41 | return "周一"
42 | elif week == 2:
43 | return "周二"
44 | elif week == 3:
45 | return "周三"
46 | elif week == 4:
47 | return "周四"
48 | elif week == 5:
49 | return "周五"
50 | elif week == 6:
51 | return "周六"
52 | else:
53 | return "周日"
54 |
55 |
56 | # 获取 GitLab 上的所有项目
57 | def gitlab_projects(project_kind):
58 | project_ids = []
59 | page = 1
60 | while True:
61 | url = gitlab_url + "api/v4/projects/?private_token=" + private_token + "&page=" + str(page) + "&per_page=20"
62 | while True:
63 | try:
64 | res = requests.get(url, headers=headers, timeout=10)
65 | break
66 | except Exception as e:
67 | print(e)
68 | continue
69 | projects = json.loads(res.text)
70 | if len(projects) == 0:
71 | break
72 | else:
73 | for project in projects:
74 | if project["namespace"]["kind"] != project_kind or project["archived"]: # 统计哪种类型未归档的仓库 user、group
75 | continue
76 | else:
77 | # print(project["namespace"]["name"] + " ID:" + str(project["id"]) + " 描述:" + project["description"])
78 | project_ids.append(project["id"])
79 | page += 1
80 | print("共获取到 " + str(len(project_ids)) + " 个有效项目")
81 | return project_ids
82 |
83 |
84 | # 获取 GitLab 上的项目 id 中的分支
85 | def project_branches(project_id):
86 | branch_names = []
87 | page = 1
88 | while True:
89 | url = gitlab_url + "api/v4/projects/" + str(
90 | project_id) + "/repository/branches?private_token=" + private_token + "&page=" + str(page) + "&per_page=20"
91 | while True:
92 | try:
93 | res = requests.get(url, headers=headers, timeout=10)
94 | break
95 | except Exception as e:
96 | print(e)
97 | continue
98 | branches = json.loads(res.text)
99 | if len(branches) == 0:
100 | break
101 | else:
102 | for branch in branches:
103 | branch_names.append(branch["name"])
104 | page += 1
105 | return branch_names
106 |
107 |
108 | # 获取 GitLab 上的项目分支中的 commits,当 title 或 message 首单词为 Merge 时,表示合并操作,剔除此代码量
109 | def project_commits(project_id, branch, start_time, end_time):
110 | commit_ids = []
111 | page = 1
112 | while True:
113 | url = gitlab_url + "api/v4/projects/" + str(
114 | project_id) + "/repository/commits?ref_name=" + branch + "&private_token=" + private_token + "&page=" + str(
115 | page) + "&per_page=20"
116 | while True:
117 | try:
118 | res = requests.get(url, headers=headers, timeout=10)
119 | break
120 | except Exception as e:
121 | print(e)
122 | continue
123 | commits = json.loads(res.text)
124 | if len(commits) == 0:
125 | break
126 | else:
127 | for commit in commits:
128 | if "Merge" in commit["title"] or "Merge" in commit["message"] or "合并" in commit["title"] or "合并" in \
129 | commit["message"]: # 不统计合并操作
130 | continue
131 | elif utc_time(commit["authored_date"]) < utc_time(start_time) or utc_time(
132 | commit["authored_date"]) > utc_time(end_time): # 不满足时间区间
133 | continue
134 | else:
135 | commit_ids.append(commit["id"])
136 | page += 1
137 | return commit_ids
138 |
139 |
140 | # 根据 commits 的 id 获取代码量,type: 1 为主分支,2为其他分支
141 | def commit_code(project_id, commit_id, branch_type):
142 | global info_master, info_other
143 | url = gitlab_url + "api/v4/projects/" + str(
144 | project_id) + "/repository/commits/" + commit_id + "?private_token=" + private_token
145 | while True:
146 | try:
147 | res = requests.get(url, headers=headers, timeout=10)
148 | break
149 | except Exception as e:
150 | print(e)
151 | continue
152 | data = json.loads(res.text)
153 | obj = {"name": data["author_name"], "additions": data["stats"]["additions"],
154 | "deletions": data["stats"]["deletions"], "total": data["stats"]["total"]} # Git工具用户名,新增代码数,删除代码数,总计代码数
155 | if data["author_name"] not in exclude_names: # 去除不需要统计的Git用户名
156 | if branch_type == 1:
157 | info_master.append(obj)
158 | elif branch_type == 2:
159 | info_other.append(obj)
160 | # else:
161 | # do some things
162 |
163 |
164 | # GitLab 数据查询
165 | def gitlab_info(start_time, end_time, project_kind):
166 | for project_id in gitlab_projects(project_kind): # 遍历所有项目ID
167 | for branch_name in project_branches(project_id): # 遍历每个项目中的分支
168 | if branch_name == "master" and project_kind != "user": # 主分支(个人仓直接统计全部)
169 | for commit_id in project_commits(project_id, branch_name, start_time, end_time): # 遍历每个分支中的 commit id
170 | commit_code(project_id, commit_id, 1) # 获取代码提交量
171 | else: # 其他分支
172 | for commit_id in project_commits(project_id, branch_name, start_time, end_time):
173 | commit_code(project_id, commit_id, 2) # 获取代码提交量
174 |
175 |
176 | # 统计数据处理
177 | def gitlab_statistics_data(branch_type):
178 | global statistics
179 | statistics.clear()
180 |
181 | name = [] # Git工具用户名
182 | additions = [] # 新增代码数
183 | deletions = [] # 删除代码数
184 | total = [] # 总计代码数
185 | times = [] # 提交次数
186 |
187 | if branch_type == 1:
188 | info = info_master
189 | elif branch_type == 2:
190 | info = info_other
191 | # else
192 | # do some things
193 |
194 | for i in info:
195 | for key, value in i.items():
196 | if key == "name":
197 | name.append(value)
198 | if key == "additions":
199 | additions.append(value)
200 | if key == "deletions":
201 | deletions.append(value)
202 | if key == "total":
203 | total.append(value)
204 | times.append(1) # 提交次数
205 | array = list(zip(name, additions, deletions, total, times))
206 | # print(array)
207 |
208 | # 去重累加
209 | for j in array:
210 | name = j[0]
211 | additions = j[1]
212 | deletions = j[2]
213 | total = j[3]
214 | times = j[4]
215 | if name in statistics.keys():
216 | statistics[name][0] += additions
217 | statistics[name][1] += deletions
218 | statistics[name][2] += total
219 | statistics[name][3] += times
220 | else:
221 | statistics.update({name: [additions, deletions, total, times]})
222 | # else:
223 | # do some things
224 | return statistics
225 |
226 |
227 | # 代码统计内容列表处理
228 | def gitlab_statistics_content(file_name):
229 | for i in statistics.keys():
230 | content_save("| " + str(i) + " | " + str(statistics[i][0]) + " | " + str(
231 | statistics[i][1]) + " | " + str(statistics[i][2]) + " | " + str(
232 | statistics[i][3]) + " |
", "a", file_name)
233 |
234 |
235 | # 保存数据到文件
236 | def content_save(data, mode, file_name):
237 | file = open(report_path + "/" + file_name, mode, encoding='utf-8')
238 | file.write(data)
239 | file.close()
240 |
241 |
242 | # 钉钉通知
243 | def dingding(url, imgurl, mes):
244 | content = {
245 | "msgtype": "actionCard",
246 | "actionCard": {
247 | "title": "GitLab代码提交量统计[]",
248 | "text": "GitLab代码提交量统计" + mes,
249 | "hideAvatar": "0",
250 | "btnOrientation": "0",
251 | "singleTitle": "点击查看详情",
252 | "singleURL": url
253 | }
254 | }
255 | json_headers = {'Content-Type': 'application/json;charset=utf-8'}
256 | result = requests.post("https://oapi.dingtalk.com/robot/send?access_token=" + dingding_token, json.dumps(content),
257 | headers=json_headers).text
258 | print(result)
259 |
--------------------------------------------------------------------------------