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 author column #129

Merged
merged 9 commits into from
Sep 27, 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
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The metrics that are measured are:
| Time to answer | (Discussions only) The time between when a discussion is created and when it is answered. |
| Time in label | The time between when a label has a specific label applied to an issue/pull request/discussion and when it is removed. This requires the LABELS_TO_MEASURE env variable to be set. |

*For pull requests, these metrics exclude the time the PR was in draft mode.
*For pull requests, these metrics exclude the time the PR was in draft mode.
*For Issue and pull requests, issue/pull request author's own comments and comments by bots are excluded.

This action was developed by the GitHub OSPO for our own use and developed in a way that we could open source it that it might be useful to you as well! If you want to know more about how we use it, reach out in an issue in this repository.
Expand Down Expand Up @@ -51,6 +51,7 @@ Below are the allowed configuration options:
| `GH_TOKEN` | True | | The GitHub Token used to scan the repository. Must have read access to all repository you are interested in scanning. |
| `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. |
| `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. |
| `HIDE_AUTHOR` | False | | If set to any value, the author will not be displayed in the generated markdown file. |
| `HIDE_TIME_TO_FIRST_RESPONSE` | False | | If set to any value, the time to first response will not be displayed in the generated markdown file. |
| `HIDE_TIME_TO_CLOSE` | False | | If set to any value, the time to close will not be displayed in the generated markdown file. |
| `HIDE_TIME_TO_ANSWER` | False | | If set to any value, the time to answer a discussion will not be displayed in the generated markdown file. |
Expand Down Expand Up @@ -324,10 +325,10 @@ then the report will look like this:
| Number of items closed | 1 |
| Total number of items created | 3 |

| Title | URL | Time to first response | Time to close | Time to answer | Time spent in waiting-for-manager-approval | Time spent in waiting-for-security-review |
| --- | --- | --- | --- | --- | --- | --- |
| Pull Request Title 1 | https://github.com/user/repo/pulls/1 | 0:05:26 | None | None | None | None |
| Issue Title 2 | https://github.com/user/repo/issues/2 | 2:26:07 | None | None | 0:00:41 | 2 days, 4:25:03 |
| Title | URL | Author | Time to first response | Time to close | Time to answer | Time spent in waiting-for-manager-approval | Time spent in waiting-for-security-review |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Pull Request Title 1 | https://github.com/user/repo/pulls/1 | alice | 0:05:26 | None | None | None | None |
| Issue Title 2 | https://github.com/user/repo/issues/2 | bob | 2:26:07 | None | None | 0:00:41 | 2 days, 4:25:03 |

```

Expand All @@ -346,11 +347,11 @@ Here is the output with no hidden columns:
| Number of items closed | 1 |
| Total number of items created | 3 |

| Title | URL | Time to first response | Time to close | Time to answer |
| --- | --- | --- | --- | --- |
| Discussion Title 1 | https://github.com/user/repo/discussions/1 | 0:00:41 | 6 days, 7:08:52 | 1 day |
| Pull Request Title 2 | https://github.com/user/repo/pulls/2 | 0:05:26 | None | None |
| Issue Title 3 | https://github.com/user/repo/issues/3 | 2:26:07 | None | None |
| Title | URL | Author | Time to first response | Time to close | Time to answer |
| --- | --- | --- | --- | --- | --- |
| Discussion Title 1 | https://github.com/user/repo/discussions/1 | None | 0:00:41 | 6 days, 7:08:52 | 1 day |
| Pull Request Title 2 | https://github.com/user/repo/pulls/2 | bob | 0:05:26 | None | None |
| Issue Title 3 | https://github.com/user/repo/issues/3 | carol | 2:26:07 | None | None |

```

Expand All @@ -364,11 +365,11 @@ Here is the output with all hidable columns hidden:
| Number of items closed | 1 |
| Total number of items created | 3 |

| Title | URL |
| --- | --- |
| Discussion Title 1 | https://github.com/user/repo/discussions/1 |
| Pull Request Title 2 | https://github.com/user/repo/pulls/2 |
| Issue Title 3 | https://github.com/user/repo/issues/3 |
| Title | URL | Author |
| --- | --- | --- |
| Discussion Title 1 | https://github.com/user/repo/discussions/1 | None |
| Pull Request Title 2 | https://github.com/user/repo/pulls/2 | bob |
| Issue Title 3 | https://github.com/user/repo/issues/3 | carol |

```

Expand Down
3 changes: 3 additions & 0 deletions classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class IssueWithMetrics:
Attributes:
title (str): The title of the issue.
html_url (str): The URL of the issue on GitHub.
author (str): The author of the issue.
time_to_first_response (timedelta, optional): The time it took to
get the first response to the issue.
time_to_close (timedelta, optional): The time it took to close the issue.
Expand All @@ -25,13 +26,15 @@ def __init__(
self,
title,
html_url,
author,
time_to_first_response=None,
time_to_close=None,
time_to_answer=None,
labels_metrics=None,
):
self.title = title
self.html_url = html_url
self.author = author
self.time_to_first_response = time_to_first_response
self.time_to_close = time_to_close
self.time_to_answer = time_to_answer
Expand Down
2 changes: 2 additions & 0 deletions issue_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def get_per_issue_metrics(
None,
None,
None,
None,
)
issue_with_metrics.time_to_first_response = measure_time_to_first_response(
None, issue, ignore_users
Expand All @@ -190,6 +191,7 @@ def get_per_issue_metrics(
issue_with_metrics = IssueWithMetrics(
issue.title, # type: ignore
issue.html_url, # type: ignore
issue.user["login"], # type: ignore
None,
None,
None,
Expand Down
3 changes: 3 additions & 0 deletions json_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def write_to_json(
{
"title": "Issue 1",
"html_url": "https://github.com/owner/repo/issues/1",
"author": "author",
"time_to_first_response": "3 days, 0:00:00",
"time_to_close": "6 days, 0:00:00",
"time_to_answer": "None",
Expand All @@ -58,6 +59,7 @@ def write_to_json(
{
"title": "Issue 2",
"html_url": "https://github.com/owner/repo/issues/2",
"author": "author",
"time_to_first_response": "2 days, 0:00:00",
"time_to_close": "4 days, 0:00:00",
"time_to_answer": "1 day, 0:00:00",
Expand Down Expand Up @@ -100,6 +102,7 @@ def write_to_json(
{
"title": issue.title,
"html_url": issue.html_url,
"author": issue.author,
"time_to_first_response": str(issue.time_to_first_response),
"time_to_close": str(issue.time_to_close),
"time_to_answer": str(issue.time_to_answer),
Expand Down
6 changes: 6 additions & 0 deletions markdown_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def get_non_hidden_columns(labels) -> List[str]:
"""
columns = ["Title", "URL"]
# Find the number of columns and which are to be hidden
hide_author = os.getenv("HIDE_AUTHOR")
if not hide_author:
columns.append("Author")

hide_time_to_first_response = os.getenv("HIDE_TIME_TO_FIRST_RESPONSE")
if not hide_time_to_first_response:
columns.append("Time to first response")
Expand Down Expand Up @@ -142,6 +146,8 @@ def write_to_markdown(
issue.title = issue.title.strip()

file.write(f"| " f"{issue.title} | " f"{issue.html_url} |")
if "Author" in columns:
file.write(f" {issue.author} |")
if "Time to first response" in columns:
file.write(f" {issue.time_to_first_response} |")
if "Time to close" in columns:
Expand Down
12 changes: 12 additions & 0 deletions test_issue_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,13 @@ def test_main(
(
"Issue 1",
"https://github.com/user/repo/issues/1",
"alice",
timedelta(days=1, hours=2, minutes=30),
),
(
"Issue 2",
"https://github.com/user/repo/issues/2",
"bob",
timedelta(days=3, hours=4, minutes=30),
),
]
Expand Down Expand Up @@ -231,6 +233,7 @@ def test_get_per_issue_metrics(self):
mock_issue1 = MagicMock(
title="Issue 1",
html_url="https://github.com/user/repo/issues/1",
author="alice",
state="open",
comments=1,
created_at="2023-01-01T00:00:00Z",
Expand All @@ -244,6 +247,7 @@ def test_get_per_issue_metrics(self):
mock_issue2 = MagicMock(
title="Issue 2",
html_url="https://github.com/user/repo/issues/2",
author="bob",
state="closed",
comments=1,
created_at="2023-01-01T00:00:00Z",
Expand Down Expand Up @@ -276,6 +280,7 @@ def test_get_per_issue_metrics(self):
IssueWithMetrics(
"Issue 1",
"https://github.com/user/repo/issues/1",
"alice",
timedelta(days=1),
None,
None,
Expand All @@ -284,6 +289,7 @@ def test_get_per_issue_metrics(self):
IssueWithMetrics(
"Issue 2",
"https://github.com/user/repo/issues/2",
"bob",
timedelta(days=2),
timedelta(days=3),
None,
Expand Down Expand Up @@ -320,6 +326,9 @@ def setUp(self):
self.issue1 = {
"title": "Issue 1",
"url": "github.com/user/repo/issues/1",
"user": {
"login": "alice",
},
"createdAt": "2023-01-01T00:00:00Z",
"comments": {
"nodes": [
Expand All @@ -335,6 +344,9 @@ def setUp(self):
self.issue2 = {
"title": "Issue 2",
"url": "github.com/user/repo/issues/2",
"user": {
"login": "bob",
},
"createdAt": "2023-01-01T00:00:00Z",
"comments": {"nodes": [{"createdAt": "2023-01-03T00:00:00Z"}]},
"answerChosenAt": "2023-01-05T00:00:00Z",
Expand Down
4 changes: 4 additions & 0 deletions test_json_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def test_write_to_json(self):
IssueWithMetrics(
title="Issue 1",
html_url="https://github.com/owner/repo/issues/1",
author="alice",
time_to_first_response=timedelta(days=3),
time_to_close=timedelta(days=6),
time_to_answer=None,
Expand All @@ -26,6 +27,7 @@ def test_write_to_json(self):
IssueWithMetrics(
title="Issue 2",
html_url="https://github.com/owner/repo/issues/2",
author="bob",
time_to_first_response=timedelta(days=2),
time_to_close=timedelta(days=4),
time_to_answer=timedelta(days=1),
Expand All @@ -50,6 +52,7 @@ def test_write_to_json(self):
{
"title": "Issue 1",
"html_url": "https://github.com/owner/repo/issues/1",
"author": "alice",
"time_to_first_response": "3 days, 0:00:00",
"time_to_close": "6 days, 0:00:00",
"time_to_answer": "None",
Expand All @@ -58,6 +61,7 @@ def test_write_to_json(self):
{
"title": "Issue 2",
"html_url": "https://github.com/owner/repo/issues/2",
"author": "bob",
"time_to_first_response": "2 days, 0:00:00",
"time_to_close": "4 days, 0:00:00",
"time_to_answer": "1 day, 0:00:00",
Expand Down
2 changes: 1 addition & 1 deletion test_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def setUp(self):
self.issues_with_metrics = MagicMock()
self.issues_with_metrics = [
IssueWithMetrics(
"issue1", "url1", None, None, None, {"bug": timedelta(days=2)}
"issue1", "url1", "alice", None, None, None, {"bug": timedelta(days=2)}
),
]

Expand Down
30 changes: 18 additions & 12 deletions test_markdown_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def test_write_to_markdown(self):
IssueWithMetrics(
"Issue 1",
"https://github.com/user/repo/issues/1",
"alice",
timedelta(days=1),
timedelta(days=2),
timedelta(days=3),
Expand All @@ -40,6 +41,7 @@ def test_write_to_markdown(self):
IssueWithMetrics(
"Issue 2\r",
"https://github.com/user/repo/issues/2",
"bob",
timedelta(days=3),
timedelta(days=4),
timedelta(days=5),
Expand Down Expand Up @@ -80,12 +82,12 @@ def test_write_to_markdown(self):
"| Number of items that remain open | 2 |\n"
"| Number of items closed | 1 |\n"
"| Total number of items created | 2 |\n\n"
"| Title | URL | Time to first response | Time to close |"
"| Title | URL | Author | Time to first response | Time to close |"
" Time to answer | Time spent in bug |\n"
"| --- | --- | --- | --- | --- | --- |\n"
"| Issue 1 | https://github.com/user/repo/issues/1 | 1 day, 0:00:00 | "
"| --- | --- | --- | --- | --- | --- | --- |\n"
"| Issue 1 | https://github.com/user/repo/issues/1 | alice | 1 day, 0:00:00 | "
"2 days, 0:00:00 | 3 days, 0:00:00 | 1 day, 0:00:00 |\n"
"| Issue 2 | https://github.com/user/repo/issues/2 | 3 days, 0:00:00 | "
"| Issue 2 | https://github.com/user/repo/issues/2 | bob | 3 days, 0:00:00 | "
"4 days, 0:00:00 | 5 days, 0:00:00 | 2 days, 0:00:00 |\n\n"
"_This report was generated with the [Issue Metrics Action](https://github.com/github/issue-metrics)_\n"
"Search query used to find these items: `is:issue is:open label:bug`\n"
Expand All @@ -107,6 +109,7 @@ def test_write_to_markdown_with_vertical_bar_in_title(self):
IssueWithMetrics(
"Issue 1",
"https://github.com/user/repo/issues/1",
"alice",
timedelta(days=1),
timedelta(days=2),
timedelta(days=3),
Expand All @@ -115,6 +118,7 @@ def test_write_to_markdown_with_vertical_bar_in_title(self):
IssueWithMetrics(
"feat| Issue 2", # title contains a vertical bar
"https://github.com/user/repo/issues/2",
"bob",
timedelta(days=3),
timedelta(days=4),
timedelta(days=5),
Expand Down Expand Up @@ -154,12 +158,12 @@ def test_write_to_markdown_with_vertical_bar_in_title(self):
"| Number of items that remain open | 2 |\n"
"| Number of items closed | 1 |\n"
"| Total number of items created | 2 |\n\n"
"| Title | URL | Time to first response | Time to close |"
"| Title | URL | Author | Time to first response | Time to close |"
" Time to answer | Time spent in bug |\n"
"| --- | --- | --- | --- | --- | --- |\n"
"| Issue 1 | https://github.com/user/repo/issues/1 | 1 day, 0:00:00 | "
"| --- | --- | --- | --- | --- | --- | --- |\n"
"| Issue 1 | https://github.com/user/repo/issues/1 | alice | 1 day, 0:00:00 | "
"2 days, 0:00:00 | 3 days, 0:00:00 | 1 day, 0:00:00 |\n"
"| feat| Issue 2 | https://github.com/user/repo/issues/2 | 3 days, 0:00:00 | "
"| feat| Issue 2 | https://github.com/user/repo/issues/2 | bob | 3 days, 0:00:00 | "
"4 days, 0:00:00 | 5 days, 0:00:00 | 2 days, 0:00:00 |\n\n"
"_This report was generated with the [Issue Metrics Action](https://github.com/github/issue-metrics)_\n"
)
Expand Down Expand Up @@ -208,6 +212,7 @@ def test_writes_markdown_file_with_non_hidden_columns_only(self):
IssueWithMetrics(
title="Issue 1",
html_url="https://github.com/user/repo/issues/1",
author="alice",
time_to_first_response=timedelta(minutes=10),
time_to_close=timedelta(days=1),
time_to_answer=timedelta(hours=2),
Expand All @@ -218,6 +223,7 @@ def test_writes_markdown_file_with_non_hidden_columns_only(self):
IssueWithMetrics(
title="Issue 2",
html_url="https://github.com/user/repo/issues/2",
author="bob",
time_to_first_response=timedelta(minutes=20),
time_to_close=timedelta(days=2),
time_to_answer=timedelta(hours=4),
Expand Down Expand Up @@ -258,10 +264,10 @@ def test_writes_markdown_file_with_non_hidden_columns_only(self):
"| Number of items that remain open | 2 |\n"
"| Number of items closed | 1 |\n"
"| Total number of items created | 2 |\n\n"
"| Title | URL |\n"
"| --- | --- |\n"
"| Issue 1 | https://github.com/user/repo/issues/1 |\n"
"| Issue 2 | https://github.com/user/repo/issues/2 |\n\n"
"| Title | URL | Author |\n"
"| --- | --- | --- |\n"
"| Issue 1 | https://github.com/user/repo/issues/1 | alice |\n"
"| Issue 2 | https://github.com/user/repo/issues/2 | bob |\n\n"
"_This report was generated with the [Issue Metrics Action](https://github.com/github/issue-metrics)_\n"
"Search query used to find these items: `repo:user/repo is:issue`\n"
)
Expand Down
10 changes: 5 additions & 5 deletions test_time_to_answer.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ def test_returns_none_for_list_with_no_time_to_answer(self):
"""
# Arrange
issues_with_metrics = [
IssueWithMetrics("issue1", None),
IssueWithMetrics("issue2", None),
IssueWithMetrics("issue1", None, None),
IssueWithMetrics("issue2", None, None),
]

# Act
Expand All @@ -53,9 +53,9 @@ def test_returns_average_time_to_answer(self):

# Arrange
issues_with_metrics = [
IssueWithMetrics("issue1", "url1", None, None, timedelta(seconds=10)),
IssueWithMetrics("issue2", "url2", None, None, timedelta(seconds=20)),
IssueWithMetrics("issue3", "url3", None, None, timedelta(seconds=30)),
IssueWithMetrics("issue1", "url1", "alice", None, None, timedelta(seconds=10)),
IssueWithMetrics("issue2", "url2", "bob", None, None, timedelta(seconds=20)),
IssueWithMetrics("issue3", "url3", "carol", None, None, timedelta(seconds=30)),
]

# Act
Expand Down
Loading