Skip to content

Commit 4e16ea9

Browse files
authored
Merge pull request #585 from github/copilot/fix-584
fix: TypeError when processing pull requests with ghost users
2 parents 63da87a + cbda2ec commit 4e16ea9

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed

issue_metrics.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,18 @@ def get_per_issue_metrics(
139139
# Check if issue is actually a pull request
140140
pull_request, ready_for_review_at = None, None
141141
if issue.issue.pull_request_urls: # type: ignore
142-
pull_request = issue.issue.pull_request() # type: ignore
143-
ready_for_review_at = get_time_to_ready_for_review(issue, pull_request)
144-
if env_vars.draft_pr_tracking:
145-
issue_with_metrics.time_in_draft = measure_time_in_draft(
146-
issue=issue
142+
try:
143+
pull_request = issue.issue.pull_request() # type: ignore
144+
ready_for_review_at = get_time_to_ready_for_review(
145+
issue, pull_request
146+
)
147+
if env_vars.draft_pr_tracking:
148+
issue_with_metrics.time_in_draft = measure_time_in_draft(
149+
issue=issue
150+
)
151+
except TypeError as e:
152+
print(
153+
f"An error occurred processing review comments. Perhaps the review contains a ghost user. {e}"
147154
)
148155

149156
if env_vars.hide_time_to_first_response is False:

test_issue_metrics.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,71 @@ def test_get_per_issue_metrics_with_ignore_users(self):
365365
expected_issues_with_metrics[0].time_to_close,
366366
)
367367

368+
@patch.dict(
369+
os.environ,
370+
{
371+
"GH_TOKEN": "test_token",
372+
"SEARCH_QUERY": "is:pr is:open repo:user/repo",
373+
},
374+
)
375+
def test_get_per_issue_metrics_with_ghost_user_pull_request(self):
376+
"""
377+
Test that the function handles TypeError when a pull request
378+
contains a ghost user (deleted account) gracefully.
379+
"""
380+
# Create mock data for a pull request that will cause TypeError on pull_request()
381+
mock_issue = MagicMock(
382+
title="PR with Ghost User",
383+
html_url="https://github.com/user/repo/pull/1",
384+
user={"login": "existing_user"},
385+
state="open",
386+
comments=0,
387+
created_at="2023-01-01T00:00:00Z",
388+
closed_at=None,
389+
)
390+
391+
# Mock the issue to have pull_request_urls (indicating it's a PR)
392+
mock_issue.issue.pull_request_urls = [
393+
"https://api.github.com/repos/user/repo/pulls/1"
394+
]
395+
396+
# Make pull_request() raise TypeError (simulating ghost user scenario)
397+
mock_issue.issue.pull_request.side_effect = TypeError(
398+
"'NoneType' object is not subscriptable"
399+
)
400+
mock_issue.issue.comments.return_value = []
401+
mock_issue.issue.assignee = None
402+
mock_issue.issue.assignees = None
403+
404+
issues = [mock_issue]
405+
406+
# Mock the measure functions to avoid additional complexities
407+
with unittest.mock.patch( # type: ignore
408+
"issue_metrics.measure_time_to_first_response",
409+
return_value=timedelta(days=1),
410+
), unittest.mock.patch( # type: ignore
411+
"issue_metrics.measure_time_to_close", return_value=None
412+
):
413+
# Call the function and verify it doesn't crash
414+
(
415+
result_issues_with_metrics,
416+
result_num_issues_open,
417+
result_num_issues_closed,
418+
) = get_per_issue_metrics(
419+
issues,
420+
env_vars=get_env_vars(test=True),
421+
)
422+
423+
# Verify the function completed successfully despite the TypeError
424+
self.assertEqual(len(result_issues_with_metrics), 1)
425+
self.assertEqual(result_num_issues_open, 1)
426+
self.assertEqual(result_num_issues_closed, 0)
427+
428+
# Verify the issue was processed with pull_request as None
429+
issue_metric = result_issues_with_metrics[0]
430+
self.assertEqual(issue_metric.title, "PR with Ghost User")
431+
self.assertEqual(issue_metric.author, "existing_user")
432+
368433

369434
class TestDiscussionMetrics(unittest.TestCase):
370435
"""Test suite for the discussion_metrics function."""

0 commit comments

Comments
 (0)