[sysadmin-bin] Add script for generating GitLab activity report
- From: Bartłomiej Piotrowski <bpiotrowski src gnome org>
- To: gnome-sysadmin gnome org,commits-list gnome org
- Subject: [sysadmin-bin] Add script for generating GitLab activity report
- Date: Fri, 15 May 2020 20:02:26 +0000 (UTC)
commit f3fd7723082fcd5070319685f33c11b05b38f974
Author: Bartłomiej Piotrowski <bpiotrowski gnome org>
Date: Fri May 15 21:54:40 2020 +0200
Add script for generating GitLab activity report
gitlab/activity-report | 188 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 188 insertions(+)
---
diff --git a/gitlab/activity-report b/gitlab/activity-report
new file mode 100644
index 0000000..7c45afe
--- /dev/null
+++ b/gitlab/activity-report
@@ -0,0 +1,188 @@
+#!/usr/bin/python3
+
+import argparse
+import json
+import os
+from collections import defaultdict
+from datetime import datetime
+
+import gitlab # type: ignore
+
+
+def get_stats(gl, args):
+ group = gl.groups.get(8, with_projects=False, lazy=True)
+ projects = [
+ gl.projects.get(prj.id) for prj in group.projects.list(all=True, lazy=True)
+ ]
+
+ users = defaultdict(lambda: defaultdict(int))
+ since_dt = datetime.strptime(args.since, "%Y-%m-%d")
+ until_dt = datetime.strptime(args.until, "%Y-%m-%d")
+
+ projects_len = len(projects)
+ for count, proj in enumerate(projects):
+ print(f"=> Processing project {proj.id} ({count}/{projects_len})")
+
+ issues_enabled = proj.attributes["issues_enabled"]
+ mrs_enabled = proj.attributes["merge_requests_enabled"]
+
+ if issues_enabled:
+ created_issues = set(
+ proj.issues.list(
+ created_after=args.since, created_before=args.until, all=True
+ )
+ )
+
+ updated_issues = (
+ set(
+ proj.issues.list(
+ updated_after=args.since,
+ updated_before=args.until,
+ state="closed",
+ all=True,
+ )
+ )
+ - created_issues
+ )
+
+ for issue in created_issues | updated_issues:
+ print(f":: issue {issue.id}")
+ created_at = issue.attributes["created_at"]
+ created_at_dt = datetime.strptime(created_at[0:10], "%Y-%m-%d")
+
+ closed_at = issue.attributes["closed_at"]
+ if closed_at:
+ closed_at_dt = datetime.strptime(closed_at[0:10], "%Y-%m-%d")
+
+ if not (until_dt >= closed_at_dt >= since_dt):
+ continue
+
+ if until_dt >= created_at_dt >= since_dt:
+ author = issue.attributes["author"]
+ author_id = author["id"]
+ users[author_id]["opened_issues"] += 1
+
+ closed_by = issue.attributes["closed_by"]
+ if closed_by:
+ closed_by_id = closed_by["id"]
+ users[closed_by_id]["closed_issues"] += 1
+
+ if mrs_enabled:
+ created_mrs = set(
+ proj.mergerequests.list(
+ created_after=args.since, created_before=args.until, all=True
+ )
+ )
+
+ updated_mrs = (
+ set(
+ proj.mergerequests.list(
+ updated_after=args.since,
+ updated_before=args.until,
+ state="merged",
+ all=True,
+ )
+ )
+ - created_mrs
+ )
+
+ for mr in created_mrs | updated_mrs:
+ print(f":: merge request {mr.id}")
+
+ created_at = mr.attributes["created_at"]
+ created_at_dt = datetime.strptime(created_at[0:10], "%Y-%m-%d")
+
+ merged_at = mr.attributes["merged_at"]
+ if merged_at:
+ merged_at_dt = datetime.strptime(merged_at[0:10], "%Y-%m-%d")
+
+ if not (until_dt >= merged_at_dt >= since_dt):
+ continue
+
+ if until_dt >= created_at_dt >= since_dt:
+ author = mr.attributes["author"]
+ author_id = author["id"]
+ users[author_id]["opened_mr"] += 1
+
+ # Comments are saved internally as "notes"
+ notes = mr.notes.list(all=True)
+
+ if merged_at:
+ merged_by = mr.attributes["merged_by"]
+ if merged_by:
+ merged_by_id = merged_by["id"]
+ else:
+ # GitLab returns "None" for some MRs, so fetch the info form
+ # notes
+ for note in notes:
+ attrs = note.attributes
+ if attrs["system"] and attrs["body"] == "merged":
+ merged_by_id = attrs["author"]["id"]
+ break
+
+ users[merged_by_id]["merged_mrs"] += 1
+
+ for note in notes:
+ if note.attributes["system"]:
+ continue
+
+ attrs = note.attributes
+ note_created_at = attrs["created_at"]
+ note_created_at_dt = datetime.strptime(
+ note_created_at[0:10], "%Y-%m-%d"
+ )
+
+ if until_dt >= note_created_at_dt >= since_dt:
+ comment_author_id = attrs["author"]["id"]
+ users[comment_author_id]["mr_comments"] += 1
+
+ return users
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description="Generate GitLab usage statistics")
+ parser.add_argument("--since", type=str, required=True)
+ parser.add_argument("--until", type=str, required=True)
+ parser.add_argument("--token", type=str)
+ args = parser.parse_args()
+
+ gl = gitlab.Gitlab(
+ "https://gitlab.gnome.org", private_token=args.token, per_page=100
+ )
+ gl.auth()
+
+ filename = f"gitlabstats-{args.since}_{args.until}.json"
+ if os.path.exists(filename):
+ with open(filename) as f:
+ stats = json.load(f)
+ else:
+ stats = get_stats(gl, args)
+ with open(filename, "w") as f:
+ json.dump(stats, f)
+
+ users_ids = list(stats.keys())
+ group = gl.groups.get(8, with_projects=False, lazy=True)
+ members_ids = [user.id for user in group.members.list(all=True, lazy=True)]
+
+ metrics = [
+ "opened_issues",
+ "closed_issues",
+ "opened_mr",
+ "merged_mrs",
+ "mr_comments",
+ ]
+
+ for metric in metrics:
+ total = sum(stats[x].get(metric, 0) for x in stats)
+ top = sorted(users_ids, key=lambda x: stats[x].get(metric, 0), reverse=True)[
+ 0:10
+ ]
+
+ print(f"=> {metric}_total: {total}")
+ for user_id in top:
+ user = gl.users.get(user_id)
+ name = user.attributes["name"]
+ is_gnome_member = "*" if user.id not in members_ids else ""
+
+ print(f"{stats[user_id][metric]} {name}{is_gnome_member}")
+ print("")
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]