Repository: github/issue-metrics
Pull request #460 (2025-01-21 22:12:18)

feat: Adding 'Created_At' column, defaulting to false
# Pull Request

<!--
PR title needs to be prefixed with a conventional commit type
(build,chore,ci,docs,feat,fix,perf,refactor,revert,style,test)

It should also be brief and descriptive for a good changelog entry

examples: "feat: add new logger" or "fix: remove unused imports"
-->

## Proposed Changes

<!-- Describe what the changes are and link to a GitHub Issue if one exists -->

We use this internally to pull metrics on open PR's and they would like to see the creation timestamp. 

This PR adds the `created_at` column, defaulting to false with the `HIDE_CREATED_AT` environment variable.

## Readiness Checklist

### Author/Contributor

- [x] If documentation is needed for this change, has that been included in this pull request
- [ ] 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
- [ ] If publishing new data to the public (scorecards, security scan results, code quality results, live dashboards, etc.), please request review from `@jeffrey-luszcz`

### Reviewer

- [ ] Label as either `fix`, `documentation`, `enhancement`, `infrastructure`, `maintenance`, or `breaking`



Patch:
diff --git a/README.md b/README.md
index 494708d..b08ecea 100644
--- a/README.md
+++ b/README.md
@@ -153,6 +153,7 @@ This action can be configured to authenticate with GitHub App Installation or Pe
 | `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.                                                                                                                                                                                                         |
+| `HIDE_CREATED_AT`             | False    | True                                       | If set to `true`, the creation timestmap will not be displayed in the generated Markdown file.                                                                                                                                                                                                             |
 | `DRAFT_PR_TRACKING`           | False    | False                                      | If set to `true`, draft PRs will be included in the metrics as a new column and in the summary stats.                                                                                                                                                                                                      |
 | `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                                                                                                                                                                                   |
diff --git a/auth.py b/auth.py
index 5357419..aa95f0d 100644
--- a/auth.py
+++ b/auth.py
@@ -59,7 +59,7 @@ def get_github_app_installation_token(
 ) -> str | None:
     """
     Get a GitHub App Installation token.
-    API: https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation
+    API: https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation # noqa: E501
 
     Args:
         ghe (str): the GitHub Enterprise endpoint
diff --git a/classes.py b/classes.py
index 7428d31..414ab82 100644
--- a/classes.py
+++ b/classes.py
@@ -21,7 +21,7 @@ class IssueWithMetrics:
         time_in_draft (timedelta, optional): The time the PR was in draft state.
         label_metrics (dict, optional): A dictionary containing the label metrics
         mentor_activity (dict, optional): A dictionary containing active mentors
-
+        created_at (datetime, optional): The time the issue was created.
     """
 
     # pylint: disable=too-many-instance-attributes
@@ -37,6 +37,7 @@ class IssueWithMetrics:
         time_in_draft=None,
         labels_metrics=None,
         mentor_activity=None,
+        created_at=None,
     ):
         self.title = title
         self.html_url = html_url
@@ -47,3 +48,4 @@ class IssueWithMetrics:
         self.time_in_draft = time_in_draft
         self.label_metrics = labels_metrics
         self.mentor_activity = mentor_activity
+        self.created_at = created_at
diff --git a/config.py b/config.py
index ba68ddd..38a7353 100644
--- a/config.py
+++ b/config.py
@@ -70,6 +70,7 @@ class EnvVars:
         hide_time_to_answer: bool,
         hide_time_to_close: bool,
         hide_time_to_first_response: bool,
+        hide_created_at: bool,
         ignore_user: List[str],
         labels_to_measure: List[str],
         enable_mentor_count: bool,
@@ -97,6 +98,7 @@ class EnvVars:
         self.hide_time_to_answer = hide_time_to_answer
         self.hide_time_to_close = hide_time_to_close
         self.hide_time_to_first_response = hide_time_to_first_response
+        self.hide_created_at = hide_created_at
         self.enable_mentor_count = enable_mentor_count
         self.min_mentor_comments = min_mentor_comments
         self.max_comments_eval = max_comments_eval
@@ -123,6 +125,7 @@ class EnvVars:
             f"{self.hide_time_to_answer},"
             f"{self.hide_time_to_close},"
             f"{self.hide_time_to_first_response},"
+            f"{self.hide_created_at},"
             f"{self.ignore_users},"
             f"{self.labels_to_measure},"
             f"{self.enable_mentor_count},"
@@ -229,6 +232,7 @@ def get_env_vars(test: bool = False) -> EnvVars:
     hide_time_to_answer = get_bool_env_var("HIDE_TIME_TO_ANSWER", False)
     hide_time_to_close = get_bool_env_var("HIDE_TIME_TO_CLOSE", False)
     hide_time_to_first_response = get_bool_env_var("HIDE_TIME_TO_FIRST_RESPONSE", False)
+    hide_created_at = get_bool_env_var("HIDE_CREATED_AT", True)
     enable_mentor_count = get_bool_env_var("ENABLE_MENTOR_COUNT", False)
     min_mentor_comments = os.getenv("MIN_MENTOR_COMMENTS", "10")
     max_comments_eval = os.getenv("MAX_COMMENTS_EVAL", "20")
@@ -248,6 +252,7 @@ def get_env_vars(test: bool = False) -> EnvVars:
         hide_time_to_answer,
         hide_time_to_close,
         hide_time_to_first_response,
+        hide_created_at,
         ignore_users_list,
         labels_to_measure_list,
         enable_mentor_count,
diff --git a/issue_metrics.py b/issue_metrics.py
index 0fd3a19..0084bb4 100644
--- a/issue_metrics.py
+++ b/issue_metrics.py
@@ -159,6 +159,8 @@ def get_per_issue_metrics(
                         )
             elif issue.state == "open":  # type: ignore
                 num_issues_open += 1
+        if not env_vars.hide_created_at:
+            issue_with_metrics.created_at = issue["createdAt"]
         issues_with_metrics.append(issue_with_metrics)
 
     return issues_with_metrics, num_issues_open, num_issues_closed
diff --git a/markdown_writer.py b/markdown_writer.py
index ded4c11..1b515c5 100644
--- a/markdown_writer.py
+++ b/markdown_writer.py
@@ -79,6 +79,9 @@ def get_non_hidden_columns(labels) -> List[str]:
     if not hide_label_metrics and labels:
         for label in labels:
             columns.append(f"Time spent in {label}")
+    hide_created_at = env_vars.hide_created_at
+    if not hide_created_at:
+        columns.append("Created At")
 
     return columns
 
@@ -212,6 +215,8 @@ def write_to_markdown(
                 for label in labels:
                     if f"Time spent in {label}" in columns:
                         file.write(f" {issue.label_metrics[label]} |")
+            if "Created At" in columns:
+                file.write(f" {issue.created_at} |")
             file.write("\n")
         file.write(
             "\n_This report was generated with the \
@@ -303,6 +308,7 @@ def write_overall_metrics_tables(
                         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")


Test patch:
diff --git a/test_config.py b/test_config.py
index 9197dd1..7a41ad1 100644
--- a/test_config.py
+++ b/test_config.py
@@ -128,6 +128,7 @@ class TestGetEnvVars(unittest.TestCase):
             hide_time_to_answer=False,
             hide_time_to_close=False,
             hide_time_to_first_response=False,
+            hide_created_at=True,
             ignore_user=[],
             labels_to_measure=[],
             enable_mentor_count=False,
@@ -181,6 +182,7 @@ class TestGetEnvVars(unittest.TestCase):
             hide_time_to_answer=False,
             hide_time_to_close=False,
             hide_time_to_first_response=False,
+            hide_created_at=True,
             ignore_user=[],
             labels_to_measure=[],
             enable_mentor_count=False,
@@ -269,6 +271,7 @@ class TestGetEnvVars(unittest.TestCase):
             hide_time_to_answer=True,
             hide_time_to_close=True,
             hide_time_to_first_response=True,
+            hide_created_at=True,
             ignore_user=[],
             labels_to_measure=["waiting-for-review", "waiting-for-manager"],
             enable_mentor_count=False,
@@ -311,6 +314,7 @@ class TestGetEnvVars(unittest.TestCase):
             hide_time_to_answer=False,
             hide_time_to_close=False,
             hide_time_to_first_response=False,
+            hide_created_at=True,
             ignore_user=[],
             labels_to_measure=[],
             enable_mentor_count=False,