Repository: github/issue-metrics
Pull request #148 (2023-10-18 21:33:36)

Split out the summary table into 2 tables
<!-- Please ensure your PR title is brief and descriptive for a good changelog entry -->
<!-- Link to issue if there is one -->
Addresses part of #144
<!-- Describe what the changes are -->

## Proposed Changes
Split out the summary table into 2 tables in order to improve readability

## Readiness Checklist

### Author/Contributor
- [x] If documentation is needed for this change, has that been included in this pull request
- [x] run `make lint` and fix any issues that you have introduced
- [x] run `make test` and ensure you have test coverage for the lines you are introducing

### Reviewer
- [x] Label as either `bug`, `documentation`, `enhancement`, `infrastructure`, or `breaking`



Patch:
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 3e99ede..60561a4 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,5 +3,9 @@
         "."
     ],
     "python.testing.unittestEnabled": false,
-    "python.testing.pytestEnabled": true
+    "python.testing.pytestEnabled": true,
+    "[python]": {
+        "editor.defaultFormatter": "ms-python.black-formatter"
+    },
+    "python.formatting.provider": "none"
 }
\ No newline at end of file
diff --git a/markdown_writer.py b/markdown_writer.py
index dc2d317..052281a 100644
--- a/markdown_writer.py
+++ b/markdown_writer.py
@@ -78,6 +78,7 @@ def write_to_markdown(
     num_issues_closed: Union[int, None],
     labels=None,
     search_query=None,
+    hide_label_metrics=False,
 ) -> None:
     """Write the issues with metrics to a markdown file.
 
@@ -94,6 +95,7 @@ def write_to_markdown(
         num_issues_closed (int): The number of issues that were closed.
         labels (List[str]): A list of the labels that are used in the issues.
         search_query (str): The search query used to find the issues.
+        hide_label_metrics (bool): Represents whether the user has chosen to hide label metrics in the output
 
     Returns:
         None.
@@ -112,7 +114,7 @@ def write_to_markdown(
         file.write("# Issue Metrics\n\n")
 
         # Write first table with overall metrics
-        write_overall_metrics_table(
+        write_overall_metrics_tables(
             issues_with_metrics,
             average_time_to_first_response,
             average_time_to_close,
@@ -123,6 +125,7 @@ def write_to_markdown(
             labels,
             columns,
             file,
+            hide_label_metrics,
         )
 
         # Write second table with individual issue/pr/discussion metrics
@@ -168,7 +171,7 @@ def write_to_markdown(
     print("Wrote issue metrics to issue_metrics.md")
 
 
-def write_overall_metrics_table(
+def write_overall_metrics_tables(
     issues_with_metrics,
     stats_time_to_first_response,
     stats_time_to_close,
@@ -179,49 +182,63 @@ def write_overall_metrics_table(
     labels,
     columns,
     file,
+    hide_label_metrics,
 ):
-    """Write the overall metrics table to the markdown file."""
-    file.write("| Metric | Average | Median | 90th percentile |\n")
-    file.write("| --- | --- | --- | ---: |\n")
-    if "Time to first response" in columns:
-        if stats_time_to_first_response is not None:
-            file.write(
-                f"| Time to first response "
-                f"| {stats_time_to_first_response['avg']} "
-                f"| {stats_time_to_first_response['med']} "
-                f"| {stats_time_to_first_response['90p']} |\n"
-            )
-        else:
-            file.write("| Time to first response | None | None | None |\n")
-    if "Time to close" in columns:
-        if stats_time_to_close is not None:
-            file.write(
-                f"| Time to close "
-                f"| {stats_time_to_close['avg']} "
-                f"| {stats_time_to_close['med']} "
-                f"| {stats_time_to_close['90p']} |\n"
-            )
-        else:
-            file.write("| Time to close | None | None | None |\n")
-    if "Time to answer" in columns:
-        if stats_time_to_answer is not None:
-            file.write(
-                f"| Time to answer "
-                f"| {stats_time_to_answer['avg']} "
-                f"| {stats_time_to_answer['med']} "
-                f"| {stats_time_to_answer['90p']} |\n"
-            )
-        else:
-            file.write("| Time to answer | None | None | None |\n")
-    if labels and stats_time_in_labels:
-        for label in labels:
-            if f"Time spent in {label}" in columns and label in stats_time_in_labels['avg']:
+    """Write the overall metrics tables to the markdown file."""
+    if (
+        "Time to first response" in columns
+        or "Time to close" in columns
+        or "Time to answer" in columns
+        or (hide_label_metrics is False and len(labels) > 0)
+    ):
+        file.write("| Metric | Average | Median | 90th percentile |\n")
+        file.write("| --- | --- | --- | ---: |\n")
+        if "Time to first response" in columns:
+            if stats_time_to_first_response is not None:
+                file.write(
+                    f"| Time to first response "
+                    f"| {stats_time_to_first_response['avg']} "
+                    f"| {stats_time_to_first_response['med']} "
+                    f"| {stats_time_to_first_response['90p']} |\n"
+                )
+            else:
+                file.write("| Time to first response | None | None | None |\n")
+        if "Time to close" in columns:
+            if stats_time_to_close is not None:
                 file.write(
-                    f"| Time spent in {label} "
-                    f"| {stats_time_in_labels['avg'][label]} "
-                    f"| {stats_time_in_labels['med'][label]} "
-                    f"| {stats_time_in_labels['90p'][label]} |\n"
+                    f"| Time to close "
+                    f"| {stats_time_to_close['avg']} "
+                    f"| {stats_time_to_close['med']} "
+                    f"| {stats_time_to_close['90p']} |\n"
                 )
+            else:
+                file.write("| Time to close | None | None | None |\n")
+        if "Time to answer" in columns:
+            if stats_time_to_answer is not None:
+                file.write(
+                    f"| Time to answer "
+                    f"| {stats_time_to_answer['avg']} "
+                    f"| {stats_time_to_answer['med']} "
+                    f"| {stats_time_to_answer['90p']} |\n"
+                )
+            else:
+                file.write("| Time to answer | None | None | None |\n")
+        if labels and stats_time_in_labels:
+            for label in labels:
+                if (
+                    f"Time spent in {label}" in columns
+                    and label in stats_time_in_labels["avg"]
+                ):
+                    file.write(
+                        f"| Time spent in {label} "
+                        f"| {stats_time_in_labels['avg'][label]} "
+                        f"| {stats_time_in_labels['med'][label]} "
+                        f"| {stats_time_in_labels['90p'][label]} |\n"
+                    )
+        file.write("\n")
+    # Write count stats to a separate table
+    file.write("| Metric | Count |\n")
+    file.write("| --- | ---: |\n")
     file.write(f"| Number of items that remain open | {num_issues_opened} |\n")
     file.write(f"| Number of items closed | {num_issues_closed} |\n")
     file.write(f"| Total number of items created | {len(issues_with_metrics)} |\n\n")


Test patch:
diff --git a/test_markdown_writer.py b/test_markdown_writer.py
index 152233f..1eac4b0 100644
--- a/test_markdown_writer.py
+++ b/test_markdown_writer.py
@@ -17,6 +17,7 @@ from markdown_writer import write_to_markdown
 
 class TestWriteToMarkdown(unittest.TestCase):
     """Test the write_to_markdown function."""
+
     maxDiff = None
 
     def test_write_to_markdown(self):
@@ -50,21 +51,25 @@ class TestWriteToMarkdown(unittest.TestCase):
             ),
         ]
         time_to_first_response = {
-                'avg': timedelta(days=2),
-                'med': timedelta(days=2),
-                '90p': timedelta(days=2)}
+            "avg": timedelta(days=2),
+            "med": timedelta(days=2),
+            "90p": timedelta(days=2),
+        }
         time_to_close = {
-                'avg': timedelta(days=3),
-                'med': timedelta(days=3),
-                '90p': timedelta(days=3)}
+            "avg": timedelta(days=3),
+            "med": timedelta(days=3),
+            "90p": timedelta(days=3),
+        }
         time_to_answer = {
-                'avg': timedelta(days=4),
-                'med': timedelta(days=4),
-                '90p': timedelta(days=4)}
+            "avg": timedelta(days=4),
+            "med": timedelta(days=4),
+            "90p": timedelta(days=4),
+        }
         time_in_labels = {
-                'avg': {"bug": "1 day, 12:00:00"},
-                'med': {"bug": "1 day, 12:00:00"},
-                '90p': {"bug": "1 day, 12:00:00"}}
+            "avg": {"bug": "1 day, 12:00:00"},
+            "med": {"bug": "1 day, 12:00:00"},
+            "90p": {"bug": "1 day, 12:00:00"},
+        }
 
         num_issues_opened = 2
         num_issues_closed = 1
@@ -93,6 +98,9 @@ class TestWriteToMarkdown(unittest.TestCase):
             "| Time to close | 3 days, 0:00:00 | 3 days, 0:00:00 | 3 days, 0:00:00 |\n"
             "| Time to answer | 4 days, 0:00:00 | 4 days, 0:00:00 | 4 days, 0:00:00 |\n"
             "| Time spent in bug | 1 day, 12:00:00 | 1 day, 12:00:00 | 1 day, 12:00:00 |\n"
+            "\n"
+            "| Metric | Count |\n"
+            "| --- | ---: |\n"
             "| Number of items that remain open | 2 |\n"
             "| Number of items closed | 1 |\n"
             "| Total number of items created | 2 |\n\n"
@@ -140,21 +148,25 @@ class TestWriteToMarkdown(unittest.TestCase):
             ),
         ]
         average_time_to_first_response = {
-             'avg': timedelta(days=2),
-             'med': timedelta(days=2),
-             '90p': timedelta(days=2)}
+            "avg": timedelta(days=2),
+            "med": timedelta(days=2),
+            "90p": timedelta(days=2),
+        }
         average_time_to_close = {
-             'avg': timedelta(days=3),
-             'med': timedelta(days=3),
-             '90p': timedelta(days=3)}
+            "avg": timedelta(days=3),
+            "med": timedelta(days=3),
+            "90p": timedelta(days=3),
+        }
         average_time_to_answer = {
-             'avg': timedelta(days=4),
-             'med': timedelta(days=4),
-             '90p': timedelta(days=4)}
+            "avg": timedelta(days=4),
+            "med": timedelta(days=4),
+            "90p": timedelta(days=4),
+        }
         average_time_in_labels = {
-             'avg': {"bug": "1 day, 12:00:00"},
-             'med': {"bug": "1 day, 12:00:00"},
-             '90p': {"bug": "1 day, 12:00:00"}}
+            "avg": {"bug": "1 day, 12:00:00"},
+            "med": {"bug": "1 day, 12:00:00"},
+            "90p": {"bug": "1 day, 12:00:00"},
+        }
 
         num_issues_opened = 2
         num_issues_closed = 1
@@ -182,6 +194,9 @@ class TestWriteToMarkdown(unittest.TestCase):
             "| Time to close | 3 days, 0:00:00 | 3 days, 0:00:00 | 3 days, 0:00:00 |\n"
             "| Time to answer | 4 days, 0:00:00 | 4 days, 0:00:00 | 4 days, 0:00:00 |\n"
             "| Time spent in bug | 1 day, 12:00:00 | 1 day, 12:00:00 | 1 day, 12:00:00 |\n"
+            "\n"
+            "| Metric | Count |\n"
+            "| --- | ---: |\n"
             "| Number of items that remain open | 2 |\n"
             "| Number of items closed | 1 |\n"
             "| Total number of items created | 2 |\n\n"
@@ -279,6 +294,7 @@ class TestWriteToMarkdownWithEnv(unittest.TestCase):
             num_issues_closed=num_issues_closed,
             labels=["label1"],
             search_query="repo:user/repo is:issue",
+            hide_label_metrics=True,
         )
 
         # Check that the function writes the correct markdown file
@@ -286,8 +302,8 @@ class TestWriteToMarkdownWithEnv(unittest.TestCase):
             content = file.read()
         expected_content = (
             "# Issue Metrics\n\n"
-            "| Metric | Average | Median | 90th percentile |\n"
-            "| --- | --- | --- | ---: |\n"
+            "| Metric | Count |\n"
+            "| --- | ---: |\n"
             "| Number of items that remain open | 2 |\n"
             "| Number of items closed | 1 |\n"
             "| Total number of items created | 2 |\n\n"