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 @@ def __repr__(self): ) -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") 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()