Repository: github/issue-metrics
Pull request #305 (2024-06-07 20:11:57)

chore: standardize github action types
# 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

- [x] use one line lists for types and branches
- [x] fix formatting (random 2 space column on some of the workflows)
- [x] add `edited` and `reopened` to some of the workflows
- [x] fix issue with get_bool_env_var function and add tests (new file)

## 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
- [ ] If publishing new data to the public (scorecards, security scan results, code quality results, live dashboards, etc.), please request review from `@jeffrey-luszcz`

### Reviewer

- [x] Label as either `fix`, `documentation`, `enhancement`, `infrastructure`, `maintenance`, or `breaking`



Patch:
diff --git a/.github/workflows/auto-labeler.yml b/.github/workflows/auto-labeler.yml
index 9cb7f26..7ee1928 100644
--- a/.github/workflows/auto-labeler.yml
+++ b/.github/workflows/auto-labeler.yml
@@ -1,24 +1,24 @@
 ---
-  name: Auto Labeler
+name: Auto Labeler
 
-  on:
-    # pull_request_target event is required for autolabeler to support all PRs including forks
-    pull_request_target:
-      types: [opened, reopened, synchronize]
+on:
+  # pull_request_target event is required for autolabeler to support all PRs including forks
+  pull_request_target:
+    types: [ opened, reopened, edited, synchronize ]
 
-  permissions:
-    contents: read
+permissions:
+  contents: read
 
-  jobs:
-    main:
-      permissions:
-        contents: write
-        pull-requests: write
-      name: Auto label pull requests
-      runs-on: ubuntu-latest
-      steps:
-        - uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348
-          env:
-            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          with:
-            config-name: release-drafter.yml
+jobs:
+  main:
+    permissions:
+      contents: write
+      pull-requests: write
+    name: Auto label pull requests
+    runs-on: ubuntu-latest
+    steps:
+      - uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          config-name: release-drafter.yml
diff --git a/.github/workflows/linter.yaml b/.github/workflows/linter.yaml
index 1a8a28a..2ff3373 100644
--- a/.github/workflows/linter.yaml
+++ b/.github/workflows/linter.yaml
@@ -3,7 +3,7 @@ name: Lint Code Base
 
 on:
   pull_request:
-    branches: main
+    branches: [ main ]
 
 permissions:
   contents: read
diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml
index 50a04a8..3746ac8 100644
--- a/.github/workflows/pr-title.yml
+++ b/.github/workflows/pr-title.yml
@@ -4,10 +4,7 @@ name: "Lint PR Title"
 
 on:
   pull_request_target:
-    types:
-      - opened
-      - edited
-      - synchronize
+    types: [ opened, reopened, edited, synchronize ]
 
 permissions:
   contents: read
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b1953de..34b1465 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,94 +1,92 @@
 ---
-  name: Release
+name: Release
 
-  on:
-    workflow_dispatch:
-    pull_request_target:
-      types:
-        - closed
-      branches:
-        - main
+on:
+  workflow_dispatch:
+  pull_request_target:
+    types: [ closed ]
+    branches: [ main ]
 
-  permissions:
-    contents: read
+permissions:
+  contents: read
 
-  jobs:
-    create_release:
-      # release if
-      # manual deployment OR
-      # merged to main and labelled with release labels
-      if: |
-        (github.event_name == 'workflow_dispatch') ||
-        (github.event.pull_request.merged == true &&
-        (contains(github.event.pull_request.labels.*.name, 'breaking') ||
-        contains(github.event.pull_request.labels.*.name, 'feature') ||
-        contains(github.event.pull_request.labels.*.name, 'vuln') ||
-        contains(github.event.pull_request.labels.*.name, 'release')))
-      outputs:
-        full-tag: ${{ steps.release-drafter.outputs.tag_name }}
-        short-tag: ${{ steps.get_tag_name.outputs.SHORT_TAG }}
-        body: ${{ steps.release-drafter.outputs.body }}
-      runs-on: ubuntu-latest
-      permissions:
-        contents: write
-        pull-requests: read
-      steps:
-        - uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348
-          id: release-drafter
-          env:
-            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          with:
-            config-name: release-drafter.yml
-            publish: true
-        - name: Get the short tag
-          id: get_tag_name
-          run: |
-            short_tag=$(echo ${{ steps.release-drafter.outputs.tag_name }} | cut -d. -f1)
-            echo "SHORT_TAG=$short_tag" >> $GITHUB_OUTPUT
-    create_action_images:
-      needs: create_release
-      runs-on: ubuntu-latest
-      permissions:
-        packages: write
-      env:
-        REGISTRY: ghcr.io
-        IMAGE_NAME: github/issue_metrics # different than repo name (underscore instead of dash)
-      steps:
-        - name: Set up Docker Buildx
-          uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb
-        - name: Log in to the Container registry
-          uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446
-          with:
-            registry: ${{ env.REGISTRY }}
-            username: ${{ github.actor }}
-            password: ${{ secrets.GITHUB_TOKEN }}
-        - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
-        - name: Push Docker Image
-          if: ${{ success() }}
-          uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0
-          with:
-            context: .
-            file: ./Dockerfile
-            push: true
-            tags: |
-              ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
-              ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create_release.outputs.full-tag }}
-              ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create_release.outputs.short-tag }}
-            platforms: linux/amd64
-            provenance: false
-            sbom: false
-    create_discussion:
-      needs: create_release
-      runs-on: ubuntu-latest
-      permissions:
-        discussions: write
-      steps:
-        - name: Create an announcement discussion for release
-          uses: abirismyname/create-discussion@6e6ef67e5eeb042343ef8b3d8d0f5d545cbdf024
-          env:
-            GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          with:
-            title: ${{ needs.create_release.outputs.full-tag }}
-            body: ${{ needs.create_release.outputs.body }}
-            repository-id: ${{ secrets.RELEASE_DISCUSSION_REPOSITORY_ID }}
-            category-id: ${{ secrets.RELEASE_DISCUSSION_CATEGORY_ID }}
+jobs:
+  create_release:
+    # release if
+    # manual deployment OR
+    # merged to main and labelled with release labels
+    if: |
+      (github.event_name == 'workflow_dispatch') ||
+      (github.event.pull_request.merged == true &&
+      (contains(github.event.pull_request.labels.*.name, 'breaking') ||
+      contains(github.event.pull_request.labels.*.name, 'feature') ||
+      contains(github.event.pull_request.labels.*.name, 'vuln') ||
+      contains(github.event.pull_request.labels.*.name, 'release')))
+    outputs:
+      full-tag: ${{ steps.release-drafter.outputs.tag_name }}
+      short-tag: ${{ steps.get_tag_name.outputs.SHORT_TAG }}
+      body: ${{ steps.release-drafter.outputs.body }}
+    runs-on: ubuntu-latest
+    permissions:
+      contents: write
+      pull-requests: read
+    steps:
+      - uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348
+        id: release-drafter
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          config-name: release-drafter.yml
+          publish: true
+      - name: Get the short tag
+        id: get_tag_name
+        run: |
+          short_tag=$(echo ${{ steps.release-drafter.outputs.tag_name }} | cut -d. -f1)
+          echo "SHORT_TAG=$short_tag" >> $GITHUB_OUTPUT
+  create_action_images:
+    needs: create_release
+    runs-on: ubuntu-latest
+    permissions:
+      packages: write
+    env:
+      REGISTRY: ghcr.io
+      IMAGE_NAME: github/issue_metrics # different than repo name (underscore instead of dash)
+    steps:
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb
+      - name: Log in to the Container registry
+        uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446
+        with:
+          registry: ${{ env.REGISTRY }}
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+      - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+      - name: Push Docker Image
+        if: ${{ success() }}
+        uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0
+        with:
+          context: .
+          file: ./Dockerfile
+          push: true
+          tags: |
+            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create_release.outputs.full-tag }}
+            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create_release.outputs.short-tag }}
+          platforms: linux/amd64
+          provenance: false
+          sbom: false
+  create_discussion:
+    needs: create_release
+    runs-on: ubuntu-latest
+    permissions:
+      discussions: write
+    steps:
+      - name: Create an announcement discussion for release
+        uses: abirismyname/create-discussion@6e6ef67e5eeb042343ef8b3d8d0f5d545cbdf024
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          title: ${{ needs.create_release.outputs.full-tag }}
+          body: ${{ needs.create_release.outputs.body }}
+          repository-id: ${{ secrets.RELEASE_DISCUSSION_REPOSITORY_ID }}
+          category-id: ${{ secrets.RELEASE_DISCUSSION_CATEGORY_ID }}
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index e378486..c5158ae 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -11,7 +11,7 @@ on:
   schedule:
     - cron: '29 11 * * 6'
   push:
-    branches: ["main"]
+    branches: [ main ]
 
 permissions: read-all
 
diff --git a/config.py b/config.py
index 30e91aa..d6c2c75 100644
--- a/config.py
+++ b/config.py
@@ -102,16 +102,20 @@ class EnvVars:
         )
 
 
-def get_bool_env_var(env_var_name: str) -> bool:
+def get_bool_env_var(env_var_name: str, default: bool = False) -> bool:
     """Get a boolean environment variable.
 
     Args:
         env_var_name: The name of the environment variable to retrieve.
+        default: The default value to return if the environment variable is not set.
 
     Returns:
         The value of the environment variable as a boolean.
     """
-    return os.environ.get(env_var_name, "").strip().lower() == "true"
+    ev = os.environ.get(env_var_name, "")
+    if ev == "" and default:
+        return default
+    return ev.strip().lower() == "true"
 
 
 def get_int_env_var(env_var_name: str) -> int | None:
@@ -177,12 +181,12 @@ def get_env_vars(test: bool = False) -> EnvVars:
         ignore_users_list = ignore_users.split(",")
 
     # Hidden columns
-    hide_author = get_bool_env_var("HIDE_AUTHOR")
-    hide_label_metrics = get_bool_env_var("HIDE_LABEL_METRICS")
-    hide_time_to_answer = get_bool_env_var("HIDE_TIME_TO_ANSWER")
-    hide_time_to_close = get_bool_env_var("HIDE_TIME_TO_CLOSE")
-    hide_time_to_first_response = get_bool_env_var("HIDE_TIME_TO_FIRST_RESPONSE")
-    enable_mentor_count = get_bool_env_var("ENABLE_MENTOR_COUNT")
+    hide_author = get_bool_env_var("HIDE_AUTHOR", False)
+    hide_label_metrics = get_bool_env_var("HIDE_LABEL_METRICS", False)
+    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)
+    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")
     heavily_involved_cutoff = os.getenv("HEAVILY_INVOLVED_CUTOFF", "3")


Test patch:
diff --git a/test_config_get_bool.py b/test_config_get_bool.py
new file mode 100644
index 0000000..c19f7ab
--- /dev/null
+++ b/test_config_get_bool.py
@@ -0,0 +1,81 @@
+"""Test the get_get_bool_env_var function"""
+
+import os
+import unittest
+from unittest.mock import patch
+
+from config import get_bool_env_var
+
+
+class TestEnv(unittest.TestCase):
+    """Test the get_bool_env_var function"""
+
+    @patch.dict(
+        os.environ,
+        {
+            "TEST_BOOL": "true",
+        },
+        clear=True,
+    )
+    def test_get_bool_env_var_that_exists_and_is_true(self):
+        """Test that gets a boolean environment variable that exists and is true"""
+        result = get_bool_env_var("TEST_BOOL", False)
+        self.assertTrue(result)
+
+    @patch.dict(
+        os.environ,
+        {
+            "TEST_BOOL": "false",
+        },
+        clear=True,
+    )
+    def test_get_bool_env_var_that_exists_and_is_false(self):
+        """Test that gets a boolean environment variable that exists and is false"""
+        result = get_bool_env_var("TEST_BOOL", False)
+        self.assertFalse(result)
+
+    @patch.dict(
+        os.environ,
+        {
+            "TEST_BOOL": "nope",
+        },
+        clear=True,
+    )
+    def test_get_bool_env_var_that_exists_and_is_false_due_to_invalid_value(self):
+        """Test that gets a boolean environment variable that exists and is false
+        due to an invalid value
+        """
+        result = get_bool_env_var("TEST_BOOL", False)
+        self.assertFalse(result)
+
+    @patch.dict(
+        os.environ,
+        {
+            "TEST_BOOL": "false",
+        },
+        clear=True,
+    )
+    def test_get_bool_env_var_that_does_not_exist_and_default_value_returns_true(self):
+        """Test that gets a boolean environment variable that does not exist
+        and default value returns: true
+        """
+        result = get_bool_env_var("DOES_NOT_EXIST", True)
+        self.assertTrue(result)
+
+    @patch.dict(
+        os.environ,
+        {
+            "TEST_BOOL": "true",
+        },
+        clear=True,
+    )
+    def test_get_bool_env_var_that_does_not_exist_and_default_value_returns_false(self):
+        """Test that gets a boolean environment variable that does not exist
+        and default value returns: false
+        """
+        result = get_bool_env_var("DOES_NOT_EXIST", False)
+        self.assertFalse(result)
+
+
+if __name__ == "__main__":
+    unittest.main()