Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add issue open and close counts #11

Merged
merged 2 commits into from
Jun 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
REPOSITORY_URL: https://github.com/owner/repo
ISSUE_SEARCH_QUERY: "is:issue closed:2023-05-01..2023-05-31 reason:completed"
ISSUE_SEARCH_QUERY: 'is:issue created:2023-05-01..2023-05-31 -reason:"not planned"'

- name: Create issue
uses: peter-evans/create-issue-from-file@v4
Expand All @@ -60,7 +60,9 @@ jobs:
# Issue Metrics

Average time to first response: 2 days, 3:30:00
Number of issues: 2
Number of issues that remain open: 0
Number of issues closed: 2
Total number of issues created: 2

| Title | URL | TTFR |
| --- | --- | ---: |
Expand Down
72 changes: 66 additions & 6 deletions issue_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,49 @@ def get_average_time_to_first_response(issues):
return timedelta(seconds=average_seconds_to_first_response)


def write_to_markdown(issues_with_metrics, average_time_to_first_response, file=None):
def get_number_of_issues_open(issues):
"""Get the number of issues that were opened.

Args:
issues (list of github3.Issue): A list of GitHub issues.

Returns:
int: The number of issues that were opened.

"""
num_issues_opened = 0
for issue in issues:
if issue.state == "open":
num_issues_opened += 1

return num_issues_opened


def get_number_of_issues_closed(issues):
"""Get the number of issues that were closed.

Args:
issues (list of github3.Issue): A list of GitHub issues.

Returns:
int: The number of issues that were closed.

"""
num_issues_closed = 0
for issue in issues:
if issue.state == "closed":
num_issues_closed += 1

return num_issues_closed


def write_to_markdown(
issues_with_metrics,
average_time_to_first_response,
num_issues_opened,
num_issues_closed,
file=None,
):
"""Write the issues with metrics to a markdown file.

Args:
Expand All @@ -156,12 +198,19 @@ def write_to_markdown(issues_with_metrics, average_time_to_first_response, file=
response for the issues.
file (file object, optional): The file object to write to. If not provided,
a file named "issue_metrics.md" will be created.
num_issues_opened (int): The number of issues that remain opened.
num_issues_closed (int): The number of issues that were closed.

Returns:
None.

"""
if not issues_with_metrics and not average_time_to_first_response:
if (
not issues_with_metrics
and not average_time_to_first_response
and not num_issues_opened
and not num_issues_closed
):
with file or open("issue_metrics.md", "w", encoding="utf-8") as file:
file.write("no issues found for the given search criteria\n\n")
else:
Expand All @@ -171,7 +220,11 @@ def write_to_markdown(issues_with_metrics, average_time_to_first_response, file=
file.write(
f"Average time to first response: {average_time_to_first_response}\n"
)
file.write(f"Number of issues: {len(issues_with_metrics)}\n\n")
file.write(f"Number of issues that remain open: {num_issues_opened}\n")
file.write(f"Number of issues closed: {num_issues_closed}\n")
file.write(
f"Total number of issues created: {len(issues_with_metrics)}\n\n"
)
file.write("| Title | URL | TTFR |\n")
file.write("| --- | --- | ---: |\n")
for title, url, ttfr in issues_with_metrics:
Expand Down Expand Up @@ -214,17 +267,24 @@ def main():
issues = search_issues(repo_url, issue_search_query, github_connection)
if len(issues.items) <= 0:
print("No issues found")
write_to_markdown(None, None)
write_to_markdown(None, None, None, None)

return
# Find the time to first response
# Find the time to first response, average, open, and closed issues
issues_with_ttfr = measure_time_to_first_response(issues)
average_time_to_first_response = get_average_time_to_first_response(
issues_with_ttfr
)
num_issues_open = get_number_of_issues_open(issues)
num_issues_closed = get_number_of_issues_closed(issues)

# Write the results to a markdown file
write_to_markdown(issues_with_ttfr, average_time_to_first_response)
write_to_markdown(
issues_with_ttfr,
average_time_to_first_response,
num_issues_open,
num_issues_closed,
)


if __name__ == "__main__":
Expand Down
61 changes: 58 additions & 3 deletions test_issue_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,52 @@ def test_get_average_time_to_first_response(self):
)


class TestGetNumberOfIssuesOpened(unittest.TestCase):
"""Test case class for the get_number_of_issues_opened function in the issue_metrics module.

This class contains test cases for the get_number_of_issues_opened function,
which calculates the number of open issues in a list of GitHub issues.

"""

def test_get_number_of_issues_opened(self):
"""Test that get_number_of_issues_opened returns the correct number of open issues."""
# Set up the mock issues
mock_issues = [
MagicMock(state="open"),
MagicMock(state="closed"),
MagicMock(state="open"),
]

# Call get_number_of_issues_opened and check that it returns the
# correct number of open issues
num_issues_opened = issue_metrics.get_number_of_issues_open(mock_issues)
self.assertEqual(num_issues_opened, 2)


class TestGetNumberOfIssuesClosed(unittest.TestCase):
"""Test case class for the get_number_of_issues_closeded function in the issue_metrics module.

This class contains test cases for the get_number_of_issues_closed function,
which calculates the number of open issues in a list of GitHub issues.

"""

def test_get_number_of_issues_closed(self):
"""Test that get_number_of_issues_closed returns the correct number of closed issues."""
# Set up the mock issues
mock_issues = [
MagicMock(state="open"),
MagicMock(state="closed"),
MagicMock(state="open"),
]

# Call get_number_of_issues_opened and check that it returns the
# correct number of open issues
num_issues_closed = issue_metrics.get_number_of_issues_closed(mock_issues)
self.assertEqual(num_issues_closed, 1)


class TestWriteToMarkdown(unittest.TestCase):
"""Test the write_to_markdown function."""

Expand Down Expand Up @@ -192,8 +238,15 @@ def test_write_to_markdown(self):

# Call write_to_markdown with the list of issues and the average time to first response
average_time_to_first_response = timedelta(days=1, hours=3, minutes=10)
num_issues_open = 1
num_issues_closed = 2

write_to_markdown(
issues_with_metrics, average_time_to_first_response, file=None
issues_with_metrics,
average_time_to_first_response,
num_issues_open,
num_issues_closed,
file=None,
)

# Check that the function writes the correct markdown file
Expand All @@ -202,7 +255,9 @@ def test_write_to_markdown(self):
expected_content = (
"# Issue Metrics\n\n"
"Average time to first response: 1 day, 3:10:00\n"
"Number of issues: 3\n\n"
"Number of issues that remain open: 1\n"
"Number of issues closed: 2\n"
"Total number of issues created: 3\n\n"
"| Title | URL | TTFR |\n"
"| --- | --- | ---: |\n"
"| Issue 3 | https://github.com/user/repo/issues/3 | 0:30:00 |\n"
Expand Down Expand Up @@ -314,7 +369,7 @@ def test_main_no_issues_found(

# Call main and check that it writes 'No issues found'
issue_metrics.main()
mock_write_to_markdown.assert_called_once_with(None, None)
mock_write_to_markdown.assert_called_once_with(None, None, None, None)


if __name__ == "__main__":
Expand Down