Skip to content

fix: cast gh_app_id to string for JWT encoding compatibility#510

Merged
jmeridth merged 3 commits intomainfrom
fix/gh-app-id-string-cast
Mar 19, 2026
Merged

fix: cast gh_app_id to string for JWT encoding compatibility#510
jmeridth merged 3 commits intomainfrom
fix/gh-app-id-string-cast

Conversation

@jmeridth
Copy link
Copy Markdown
Collaborator

@jmeridth jmeridth commented Mar 18, 2026

Fixes #508

What

Cast gh_app_id to str() when passing it to login_as_app_installation, which internally calls jwt.encode expecting the iss claim to be a string. Updated tests to pass integer app IDs and assert the string conversion occurs.

Why

Since v2.0.0, GitHub App authentication fails with "TypeError: Issuer (iss) must be a string" because newer versions of PyJWT enforce that the iss claim is a string, but gh_app_id was being passed as an integer.

Notes

  • Tests now use assert_called_once_with instead of assert_called_once to verify the exact arguments, preventing this class of regression
  • Test inputs changed from strings to integers to mirror real-world usage where env vars are parsed as ints
  • Relates to GitHub App auth broken since v2.0.0 #508

Relates to #508

## What

Cast gh_app_id to str() when passing it to login_as_app_installation,
which internally calls jwt.encode expecting the iss claim to be a string.
Updated tests to pass integer app IDs and assert the string conversion
occurs.

## Why

Since v2.0.0, GitHub App authentication fails with
"TypeError: Issuer (iss) must be a string" because newer versions of
PyJWT enforce that the iss claim is a string, but gh_app_id was being
passed as an integer.

## Notes

- Tests now use assert_called_once_with instead of assert_called_once to verify the exact arguments, preventing this class of regression
- Test inputs changed from strings to integers to mirror real-world usage where env vars are parsed as ints

Signed-off-by: jmeridth <jmeridth@gmail.com>
@jmeridth jmeridth requested a review from zkoppert as a code owner March 18, 2026 23:52
Copilot AI review requested due to automatic review settings March 18, 2026 23:52
@github-actions github-actions bot added the fix label Mar 18, 2026
@jmeridth jmeridth self-assigned this Mar 18, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes GitHub App authentication failures caused by newer PyJWT versions enforcing the JWT iss claim to be a string, by ensuring the GitHub App ID is stringified before passing it into github3.py app-login flows.

Changes:

  • Cast gh_app_id to str when calling gh.login_as_app_installation(...) in auth_to_github.
  • Update app-auth tests to pass integer IDs and assert the exact arguments used in the app-login call.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
auth.py String-casts gh_app_id for login_as_app_installation compatibility with stricter JWT encoding.
test_auth.py Adjusts tests to use integer IDs and verify the exact call signature/arguments.

Signed-off-by: jmeridth <jmeridth@gmail.com>
Copy link
Copy Markdown
Collaborator

@zkoppert zkoppert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch on the str(gh_app_id) fix in auth_to_github - we've also got the same problem one step later. In evergreen.py lines 64-65, gh_app_id is still being passed as an int to get_github_app_installation_token, which passes it straight to github3.apps.create_jwt_headers on auth.py line 71. PyJWT 2.x will throw TypeError: Issuer (iss) must be a string there too.

# Current:
token = auth.get_github_app_installation_token(
    ghe, gh_app_id, gh_app_private_key, gh_app_installation_id
)

# Should be:
token = auth.get_github_app_installation_token(
    ghe, str(gh_app_id), gh_app_private_key, gh_app_installation_id
)

## What

Extended the str(gh_app_id) cast to get_github_app_installation_token,
which passes gh_app_id directly to github3.apps.create_jwt_headers.
Updated type hints to int | None to match what get_int_env_var returns.

## Why

The existing fix only covered auth_to_github but missed the second code
path through get_github_app_installation_token, which would still hit
PyJWT's "Issuer (iss) must be a string" TypeError at runtime.

## Notes

- The str() cast happens inside get_github_app_installation_token rather than at the call site in evergreen.py, keeping the function defensive regardless of caller.

Signed-off-by: jmeridth <jmeridth@gmail.com>
@jmeridth jmeridth requested a review from zkoppert March 19, 2026 12:26
@jmeridth jmeridth merged commit a292dbb into main Mar 19, 2026
36 checks passed
@jmeridth jmeridth deleted the fix/gh-app-id-string-cast branch March 19, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GitHub App auth broken since v2.0.0

3 participants