-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: use GitHub App token when authed with GitHub App #257
Merged
jmeridth
merged 2 commits into
main
from
jm-use-app-token-in-graphql-when-using-github-app
Apr 29, 2024
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
""" | ||
This is the module that contains functions related to authenticating | ||
to GitHub. | ||
""" | ||
|
||
import github3 | ||
import requests | ||
|
||
|
||
def auth_to_github( | ||
gh_app_id: str, | ||
gh_app_installation_id: int, | ||
gh_app_private_key_bytes: bytes, | ||
token: str, | ||
ghe: str, | ||
) -> github3.GitHub: | ||
""" | ||
Connect to GitHub.com or GitHub Enterprise, depending on env variables. | ||
Returns: | ||
github3.GitHub: A github api connection. | ||
""" | ||
|
||
if gh_app_id and gh_app_private_key_bytes and gh_app_installation_id: | ||
gh = github3.github.GitHub() | ||
gh.login_as_app_installation( | ||
gh_app_private_key_bytes, gh_app_id, gh_app_installation_id | ||
) | ||
github_connection = gh | ||
elif ghe and token: | ||
github_connection = github3.github.GitHubEnterprise(ghe, token=token) | ||
elif token: | ||
github_connection = github3.login(token=token) | ||
else: | ||
raise ValueError( | ||
"GH_TOKEN or the set of [GH_APP_ID, GH_APP_INSTALLATION_ID, GH_APP_PRIVATE_KEY] environment variables are not set" | ||
) | ||
|
||
return github_connection # type: ignore | ||
|
||
|
||
def get_github_app_installation_token( | ||
gh_app_id: str, gh_app_private_key_bytes: bytes, gh_app_installation_id: str | ||
) -> str | None: | ||
""" | ||
Get a GitHub App Installation token. | ||
Args: | ||
gh_app_id (str): the GitHub App ID | ||
gh_app_private_key_bytes (bytes): the GitHub App Private Key | ||
gh_app_installation_id (str): the GitHub App Installation ID | ||
Returns: | ||
str: the GitHub App token | ||
""" | ||
jwt_headers = github3.apps.create_jwt_headers(gh_app_private_key_bytes, gh_app_id) | ||
url = f"https://api.github.com/app/installations/{gh_app_installation_id}/access_tokens" | ||
|
||
try: | ||
response = requests.post(url, headers=jwt_headers, json=None, timeout=5) | ||
response.raise_for_status() | ||
except requests.exceptions.RequestException as e: | ||
print(f"Request failed: {e}") | ||
return None | ||
return response.json().get("token") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
"""A module containing unit tests for the auth module. | ||
This module contains unit tests for the functions in the auth module | ||
that authenticate to github. | ||
Classes: | ||
TestAuthToGithub: A class to test the auth_to_github function. | ||
""" | ||
|
||
import unittest | ||
from unittest.mock import MagicMock, patch | ||
|
||
import github3 | ||
from auth import auth_to_github, get_github_app_installation_token | ||
|
||
|
||
class TestAuthToGithub(unittest.TestCase): | ||
"""Test the auth_to_github function.""" | ||
|
||
@patch("github3.github.GitHub.login_as_app_installation") | ||
def test_auth_to_github_with_github_app(self, mock_login): | ||
""" | ||
Test the auth_to_github function when GitHub app | ||
parameters provided. | ||
""" | ||
mock_login.return_value = MagicMock() | ||
result = auth_to_github(12345, 678910, b"hello", "", "") | ||
|
||
self.assertIsInstance(result, github3.github.GitHub) | ||
|
||
def test_auth_to_github_with_token(self): | ||
""" | ||
Test the auth_to_github function when the token is provided. | ||
""" | ||
result = auth_to_github(None, None, b"", "token", "") | ||
|
||
self.assertIsInstance(result, github3.github.GitHub) | ||
|
||
def test_auth_to_github_without_authentication_information(self): | ||
""" | ||
Test the auth_to_github function when authentication information is not provided. | ||
Expect a ValueError to be raised. | ||
""" | ||
with self.assertRaises(ValueError): | ||
auth_to_github(None, None, b"", "", "") | ||
|
||
def test_auth_to_github_with_ghe(self): | ||
""" | ||
Test the auth_to_github function when the GitHub Enterprise URL is provided. | ||
""" | ||
result = auth_to_github(None, None, b"", "token", "https://github.example.com") | ||
|
||
self.assertIsInstance(result, github3.github.GitHubEnterprise) | ||
|
||
@patch("github3.apps.create_jwt_headers", MagicMock(return_value="gh_token")) | ||
@patch("requests.post") | ||
def test_get_github_app_installation_token(self, mock_post): | ||
""" | ||
Test the get_github_app_installation_token function. | ||
""" | ||
dummy_token = "dummytoken" | ||
mock_response = MagicMock() | ||
mock_response.raise_for_status.return_value = None | ||
mock_response.json.return_value = {"token": dummy_token} | ||
mock_post.return_value = mock_response | ||
|
||
result = get_github_app_installation_token( | ||
b"gh_private_token", "gh_app_id", "gh_installation_id" | ||
) | ||
|
||
self.assertEqual(result, dummy_token) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uh oh. This should have been caught by a test. Added one at 79a3995
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local linting caught it for me. mypy ftw. excellent idea to add tests. thank you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is mypy disabled in our super-linter? Wondering how this status check passed so we could merge.