-
Notifications
You must be signed in to change notification settings - Fork 55
/
time_to_first_response.py
120 lines (94 loc) · 4.16 KB
/
time_to_first_response.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""A module for measuring the time it takes to get the first response to a GitHub issue.
This module provides functions for measuring the time it takes to get the first response
to a GitHub issue, as well as calculating the average time to first response for a list
of issues.
Functions:
measure_time_to_first_response(
issue: Union[github3.issues.Issue, None],
discussion: Union[dict, None]
) -> Union[timedelta, None]:
Measure the time to first response for a single issue or a discussion.
get_average_time_to_first_response(
issues: List[IssueWithMetrics]
) -> Union[timedelta, None]:
Calculate the average time to first response for a list of issues with metrics.
"""
from datetime import datetime, timedelta
from typing import List, Union
import github3
from classes import IssueWithMetrics
def measure_time_to_first_response(
issue: Union[github3.issues.Issue, None], # type: ignore
discussion: Union[dict, None],
) -> Union[timedelta, None]:
"""Measure the time to first response for a single issue or a discussion.
Args:
issue (Union[github3.issues.Issue, None]): A GitHub issue.
discussion (Union[dict, None]): A GitHub discussion.
Returns:
Union[timedelta, None]: The time to first response for the issue/discussion.
"""
first_review_comment_time = None
first_comment_time = None
earliest_response = None
issue_time = None
# Get the first comment time
if issue:
comments = issue.issue.comments(
number=1, sort="created", direction="asc"
) # type: ignore
for comment in comments:
first_comment_time = comment.created_at
# Check if the issue is actually a pull request
# so we may also get the first review comment time
if issue.issue.pull_request_urls:
pull_request = issue.issue.pull_request()
review_comments = pull_request.reviews(number=1) # type: ignore
for review_comment in review_comments:
first_review_comment_time = review_comment.submitted_at
# Figure out the earliest response timestamp
if first_comment_time and first_review_comment_time:
earliest_response = min(first_comment_time, first_review_comment_time)
elif first_comment_time:
earliest_response = first_comment_time
elif first_review_comment_time:
earliest_response = first_review_comment_time
else:
return None
# Get the created_at time for the issue so we can calculate the time to first response
issue_time = datetime.fromisoformat(issue.created_at) # type: ignore
if discussion and len(discussion["comments"]["nodes"]) > 0:
earliest_response = datetime.fromisoformat(
discussion["comments"]["nodes"][0]["createdAt"]
)
issue_time = datetime.fromisoformat(discussion["createdAt"])
# Calculate the time between the issue and the first comment
if earliest_response and issue_time:
return earliest_response - issue_time
return None
def get_average_time_to_first_response(
issues: List[IssueWithMetrics],
) -> Union[timedelta, None]:
"""Calculate the average time to first response for a list of issues.
Args:
issues (List[IssueWithMetrics]): A list of GitHub issues with metrics attached.
Returns:
datetime.timedelta: The average time to first response for the issues in seconds.
"""
total_time_to_first_response = 0
none_count = 0
for issue in issues:
if issue.time_to_first_response:
total_time_to_first_response += issue.time_to_first_response.total_seconds()
else:
none_count += 1
if len(issues) - none_count <= 0:
return None
average_seconds_to_first_response = total_time_to_first_response / (
len(issues) - none_count
) # type: ignore
# Print the average time to first response converting seconds to a readable time format
print(
f"Average time to first response: {timedelta(seconds=average_seconds_to_first_response)}"
)
return timedelta(seconds=average_seconds_to_first_response)