From d8b88f519e625e060c3d0fd3c0638f7038366037 Mon Sep 17 00:00:00 2001 From: jmeridth Date: Tue, 3 Mar 2026 04:05:17 -0600 Subject: [PATCH] fix: convert app_id to string before login_as_app_installation call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What Wrapped `gh_app_id` with `str()` in the `login_as_app_installation` call in auth.py, and added a targeted test for integer app_id inputs. Existing tests were also tightened to assert on exact call arguments. ### Why When `gh_app_id` is passed as an integer, PyJWT raises a TypeError on the `iss` claim during JWT encoding because it expects a string. This surfaces at runtime when the environment variable is parsed as an int rather than str. ### Notes - Only `gh_app_id` is converted; `gh_app_installation_id` is left as-is since `login_as_app_installation` accepts it in its original form — reviewers should verify this is intentional - The existing tests previously used `assert_called_once()` without argument checks, so bugs like this were invisible; the tightened assertions now catch argument type mismatches Signed-off-by: jmeridth --- .github/pull_request_template.md | 1 - .gitignore | 3 +++ auth.py | 2 +- test_auth.py | 18 ++++++++++++++++-- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d9febb2..7258072 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -20,4 +20,3 @@ examples: "feat: add new logger" or "fix: remove unused imports" - [ ] 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 - [ ] 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` diff --git a/.gitignore b/.gitignore index 2446185..0eec7c0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ __pycache__/ # C extensions *.so +# ai +**/.claude/*.local.* + # Distribution / packaging .Python build/ diff --git a/auth.py b/auth.py index 6669f54..a5e551a 100644 --- a/auth.py +++ b/auth.py @@ -32,7 +32,7 @@ def auth_to_github( else: gh = github3.github.GitHub() gh.login_as_app_installation( - gh_app_private_key_bytes, gh_app_id, gh_app_installation_id + gh_app_private_key_bytes, str(gh_app_id), gh_app_installation_id ) github_connection = gh elif ghe and token: diff --git a/test_auth.py b/test_auth.py index 9337abc..a7ed25b 100644 --- a/test_auth.py +++ b/test_auth.py @@ -58,7 +58,7 @@ def test_auth_to_github_with_ghe_and_ghe_app(self, mock_ghe): result = auth.auth_to_github( "", "123", "123", b"123", "https://github.example.com", True ) - mock.login_as_app_installation.assert_called_once() + mock.login_as_app_installation.assert_called_once_with(b"123", "123", "123") self.assertEqual(result, mock) @patch("github3.github.GitHub") @@ -71,7 +71,21 @@ def test_auth_to_github_with_app(self, mock_gh): result = auth.auth_to_github( "", "123", "123", b"123", "https://github.example.com", False ) - mock.login_as_app_installation.assert_called_once() + mock.login_as_app_installation.assert_called_once_with(b"123", "123", "123") + self.assertEqual(result, mock) + + @patch("github3.github.GitHub") + def test_auth_to_github_with_app_int_app_id(self, mock_gh): + """ + Test that an integer app_id is converted to a string before passing + to login_as_app_installation, to avoid PyJWT TypeError on the iss claim. + """ + mock = mock_gh.return_value + mock.login_as_app_installation = MagicMock(return_value=True) + result = auth.auth_to_github("", 123, 456, b"private_key", "", False) + mock.login_as_app_installation.assert_called_once_with( + b"private_key", "123", 456 + ) self.assertEqual(result, mock) @patch("github3.apps.create_jwt_headers", MagicMock(return_value="gh_token"))