diff --git a/README.md b/README.md index 39c15f4..11f6f8b 100644 --- a/README.md +++ b/README.md @@ -139,25 +139,25 @@ This action can be configured to authenticate with GitHub App Installation or Pe #### Other Configuration Options -| field | required | default | description | -| ----------------------------- | -------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `GH_ENTERPRISE_URL` | False | `""` | URL of GitHub Enterprise instance to use for auth instead of github.com | -| `HIDE_AUTHOR` | False | False | If set to `true`, the author will not be displayed in the generated Markdown file. | -| `HIDE_ITEMS_CLOSED_COUNT` | False | False | If set to `true`, the number of items closed metric will not be displayed in the generated Markdown file. | -| `HIDE_LABEL_METRICS` | False | False | If set to `true`, the time in label metrics will not be displayed in the generated Markdown file. | -| `HIDE_TIME_TO_ANSWER` | False | False | If set to `true`, the time to answer a discussion will not be displayed in the generated Markdown file. | -| `HIDE_TIME_TO_CLOSE` | False | False | If set to `true`, the time to close will not be displayed in the generated Markdown file. | -| `HIDE_TIME_TO_FIRST_RESPONSE` | False | False | If set to `true`, the time to first response will not be displayed in the generated Markdown file. | -| `IGNORE_USERS` | False | False | A comma separated list of users to ignore when calculating metrics. (ie. `IGNORE_USERS: 'user1,user2'`). To ignore bots, append `[bot]` to the user (ie. `IGNORE_USERS: 'github-actions[bot]'`) | -| `ENABLE_MENTOR_COUNT` | False | False | If set to 'TRUE' count number of comments users left on discussions, issues and PRs and display number of active mentors | -| `MIN_MENTOR_COMMENTS` | False | 10 | Minimum number of comments to count as a mentor | -| `MAX_COMMENTS_EVAL` | False | 20 | Maximum number of comments per thread to evaluate for mentor stats | -| `HEAVILY_INVOLVED_CUTOFF` | False | 3 | Cutoff after which a mentor's comments in one issue are no longer counted against their total score | -| `LABELS_TO_MEASURE` | False | `""` | A comma separated list of labels to measure how much time the label is applied. If not provided, no labels durations will be measured. Not compatible with discussions at this time. | -| `NON_MENTIONING_LINKS` | False | False | If set to `true`, will use non-mentioning GitHub links to avoid linking to the generated issue from the source repository. Links of the form `https://www.github.com` will be used. | -| `OUTPUT_FILE` | False | `issue_metrics.md` or `issue_metrics.json` | Output filename. | -| `REPORT_TITLE` | False | `"Issue Metrics"` | Title to have on the report issue. | -| `SEARCH_QUERY` | True | `""` | The query by which you can filter issues/PRs which must contain a `repo:`, `org:`, `owner:`, or a `user:` entry. For discussions, include `type:discussions` in the query. | +| field | required | default | description | +| ----------------------------- | -------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `GH_ENTERPRISE_URL` | False | `""` | URL of GitHub Enterprise instance to use for auth instead of github.com | +| `HIDE_AUTHOR` | False | False | If set to `true`, the author will not be displayed in the generated Markdown file. | +| `HIDE_ITEMS_CLOSED_COUNT` | False | False | If set to `true`, the number of items closed metric will not be displayed in the generated Markdown file. | +| `HIDE_LABEL_METRICS` | False | False | If set to `true`, the time in label metrics will not be displayed in the generated Markdown file. | +| `HIDE_TIME_TO_ANSWER` | False | False | If set to `true`, the time to answer a discussion will not be displayed in the generated Markdown file. | +| `HIDE_TIME_TO_CLOSE` | False | False | If set to `true`, the time to close will not be displayed in the generated Markdown file. | +| `HIDE_TIME_TO_FIRST_RESPONSE` | False | False | If set to `true`, the time to first response will not be displayed in the generated Markdown file. | +| `IGNORE_USERS` | False | False | A comma separated list of users to ignore when calculating metrics. (ie. `IGNORE_USERS: 'user1,user2'`). To ignore bots, append `[bot]` to the user (ie. `IGNORE_USERS: 'github-actions[bot]'`) Users in this list will also have their authored issues and pull requests removed from the Markdown table. | +| `ENABLE_MENTOR_COUNT` | False | False | If set to 'TRUE' count number of comments users left on discussions, issues and PRs and display number of active mentors | +| `MIN_MENTOR_COMMENTS` | False | 10 | Minimum number of comments to count as a mentor | +| `MAX_COMMENTS_EVAL` | False | 20 | Maximum number of comments per thread to evaluate for mentor stats | +| `HEAVILY_INVOLVED_CUTOFF` | False | 3 | Cutoff after which a mentor's comments in one issue are no longer counted against their total score | +| `LABELS_TO_MEASURE` | False | `""` | A comma separated list of labels to measure how much time the label is applied. If not provided, no labels durations will be measured. Not compatible with discussions at this time. | +| `NON_MENTIONING_LINKS` | False | False | If set to `true`, will use non-mentioning GitHub links to avoid linking to the generated issue from the source repository. Links of the form `https://www.github.com` will be used. | +| `OUTPUT_FILE` | False | `issue_metrics.md` or `issue_metrics.json` | Output filename. | +| `REPORT_TITLE` | False | `"Issue Metrics"` | Title to have on the report issue. | +| `SEARCH_QUERY` | True | `""` | The query by which you can filter issues/PRs which must contain a `repo:`, `org:`, `owner:`, or a `user:` entry. For discussions, include `type:discussions` in the query. | ## Further Documentation diff --git a/issue_metrics.py b/issue_metrics.py index e6b84f8..3d176cf 100644 --- a/issue_metrics.py +++ b/issue_metrics.py @@ -202,6 +202,9 @@ def get_per_issue_metrics( else: num_issues_open += 1 else: + if ignore_users and issue.user["login"] in ignore_users: # type: ignore + continue + issue_with_metrics = IssueWithMetrics( issue.title, # type: ignore issue.html_url, # type: ignore diff --git a/test_issue_metrics.py b/test_issue_metrics.py index 5059a88..40e1244 100644 --- a/test_issue_metrics.py +++ b/test_issue_metrics.py @@ -195,7 +195,7 @@ def test_get_per_issue_metrics_with_hide_envs(self): mock_issue1 = MagicMock( title="Issue 1", html_url="https://github.com/user/repo/issues/1", - author="alice", + user={"login": "alice"}, state="open", comments=1, created_at="2023-01-01T00:00:00Z", @@ -209,7 +209,7 @@ def test_get_per_issue_metrics_with_hide_envs(self): mock_issue2 = MagicMock( title="Issue 2", html_url="https://github.com/user/repo/issues/2", - author="bob", + user={"login": "bob"}, state="closed", comments=1, created_at="2023-01-01T00:00:00Z", @@ -304,7 +304,7 @@ def test_get_per_issue_metrics_without_hide_envs(self): mock_issue1 = MagicMock( title="Issue 1", html_url="https://github.com/user/repo/issues/1", - author="alice", + user={"login": "alice"}, state="open", comments=1, created_at="2023-01-01T00:00:00Z", @@ -318,7 +318,7 @@ def test_get_per_issue_metrics_without_hide_envs(self): mock_issue2 = MagicMock( title="Issue 2", html_url="https://github.com/user/repo/issues/2", - author="bob", + user={"login": "bob"}, state="closed", comments=1, created_at="2023-01-01T00:00:00Z", @@ -391,6 +391,94 @@ def test_get_per_issue_metrics_without_hide_envs(self): expected_issues_with_metrics[1].time_to_close, ) + @patch.dict( + os.environ, + { + "GH_TOKEN": "test_token", + "SEARCH_QUERY": "is:issue is:open repo:user/repo", + "IGNORE_USERS": "alice", + }, + ) + def test_get_per_issue_metrics_with_ignore_users(self): + """ + Test that the function correctly filters out issues with authors in the IGNORE_USERS variable + """ + + # Create mock data + mock_issue1 = MagicMock( + title="Issue 1", + html_url="https://github.com/user/repo/issues/1", + user={"login": "alice"}, + state="open", + comments=1, + created_at="2023-01-01T00:00:00Z", + ) + + mock_comment1 = MagicMock() + mock_comment1.created_at = datetime.fromisoformat("2023-01-02T00:00:00Z") + mock_issue1.issue.comments.return_value = [mock_comment1] + mock_issue1.issue.pull_request_urls = None + + mock_issue2 = MagicMock( + title="Issue 2", + html_url="https://github.com/user/repo/issues/2", + user={"login": "bob"}, + state="closed", + comments=1, + created_at="2023-01-01T00:00:00Z", + closed_at="2023-01-04T00:00:00Z", + ) + + mock_comment2 = MagicMock() + mock_comment2.created_at = datetime.fromisoformat("2023-01-03T00:00:00Z") + mock_issue2.issue.comments.return_value = [mock_comment2] + mock_issue2.issue.pull_request_urls = None + + issues = [ + mock_issue1, + mock_issue2, + ] + + # Call the function and check the result + with unittest.mock.patch( # type:ignore + "issue_metrics.measure_time_to_first_response", + measure_time_to_first_response, + ), unittest.mock.patch( # type:ignore + "issue_metrics.measure_time_to_close", measure_time_to_close + ): + ( + result_issues_with_metrics, + result_num_issues_open, + result_num_issues_closed, + ) = get_per_issue_metrics( + issues, + env_vars=get_env_vars(test=True), + ignore_users=["alice"], + ) + expected_issues_with_metrics = [ + IssueWithMetrics( + "Issue 2", + "https://github.com/user/repo/issues/2", + "bob", + timedelta(days=2), + timedelta(days=3), + None, + None, + ), + ] + expected_num_issues_open = 0 + expected_num_issues_closed = 1 + self.assertEqual(result_num_issues_open, expected_num_issues_open) + self.assertEqual(result_num_issues_closed, expected_num_issues_closed) + self.assertEqual( + result_issues_with_metrics[0].time_to_first_response, + expected_issues_with_metrics[0].time_to_first_response, + ) + self.assertEqual( + result_issues_with_metrics[0].time_to_close, + expected_issues_with_metrics[0].time_to_close, + ) + class TestDiscussionMetrics(unittest.TestCase): """Test suite for the discussion_metrics function."""