Skip to content

Commit dbb38d4

Browse files
committed
Another script to calculate github workflow stats
1 parent 26e9166 commit dbb38d4

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

workflow_stats.py

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from collections import defaultdict
2+
import matplotlib.pyplot as plt
3+
from github import Github
4+
from matplotlib.ticker import MultipleLocator, FuncFormatter
5+
6+
GITHUB_TOKEN = "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"
7+
g = Github(GITHUB_TOKEN)
8+
9+
ORGANIZATION = "ivelum"
10+
REPOSITORY = "teamplify"
11+
START_WORKFLOW = "test.yaml"
12+
END_WORKFLOW = "deploy.yaml"
13+
LAST_N_RUNS = 50
14+
15+
16+
def get_time_series():
17+
repo = g.get_organization(ORGANIZATION).get_repo(REPOSITORY)
18+
19+
runs_by_sha = defaultdict(lambda: dict(workflow_names=[], start=None, end=None))
20+
for workflow_name in [START_WORKFLOW, END_WORKFLOW]:
21+
workflow = repo.get_workflow(workflow_name)
22+
23+
all_runs = iter(workflow.get_runs(status="completed"))
24+
25+
for _ in range(LAST_N_RUNS):
26+
workflow_run = next(all_runs)
27+
28+
if workflow_run.status != "completed":
29+
continue
30+
31+
if workflow_run.conclusion != "success":
32+
continue
33+
34+
stats = runs_by_sha[workflow_run.head_sha]
35+
36+
stats["workflow_names"].append(workflow_name)
37+
38+
if not stats["start"] or stats["start"] > workflow_run.created_at:
39+
stats["start"] = workflow_run.created_at
40+
41+
if not stats["end"] or stats["end"] < workflow_run.updated_at:
42+
stats["end"] = workflow_run.updated_at
43+
44+
with_start_and_end = [
45+
stats
46+
for stats in runs_by_sha.values()
47+
if set(stats["workflow_names"]) == {START_WORKFLOW, END_WORKFLOW}
48+
]
49+
by_start = sorted(with_start_and_end, key=lambda stats: stats["start"])
50+
51+
starts = []
52+
durations = []
53+
for stats in by_start:
54+
starts.append(stats["start"].strftime("%-dth\n%H:%M"))
55+
duration = stats["end"] - stats["start"]
56+
durations.append(duration.seconds)
57+
58+
return starts, durations
59+
60+
61+
def format_seconds(total_seconds, position=None):
62+
minutes = total_seconds // 60
63+
seconds = total_seconds % 60
64+
return f"{minutes:.0f}:{seconds:02.0f}"
65+
66+
67+
if __name__ == "__main__":
68+
plt.style.use("seaborn-v0_8")
69+
70+
starts, durations = get_time_series()
71+
72+
ax = plt.subplot()
73+
bars = ax.bar(starts, durations)
74+
ax.bar_label(bars, labels=[format_seconds(duration) for duration in durations])
75+
ax.yaxis.set_major_locator(MultipleLocator(base=60))
76+
ax.yaxis.set_major_formatter(FuncFormatter(format_seconds))
77+
ax.set_ylim(bottom=0)
78+
plt.show()

0 commit comments

Comments
 (0)