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
Add support for get_app() with App authentication #2549
Conversation
@EnricoMi , I am not super satisfied of the current solution. Let me know how you would see this better integrated. It seems to me that wether through GithubIntegration, or Github main object, we need to detect that the authentication will be done using JWT. In MainClass.py, I use the token_type as a proxy for this. |
Codecov ReportPatch coverage:
❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more. Additional details and impacted files@@ Coverage Diff @@
## master #2549 +/- ##
=======================================
Coverage 98.50% 98.50%
=======================================
Files 128 128
Lines 12753 12757 +4
=======================================
+ Hits 12562 12566 +4
Misses 191 191
☔ View full report in Codecov by Sentry. |
Thanks @EnricoMi Applied your recommendations in the second commit. If that works out, feel free to squash it into the first one. |
running manually, this is failing due to utcnow deprecation:
While cI can fix the deprecation for pygithub, httpretty will still generate a warning. |
I am introducing |
Then use the recommended |
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.
Almost there!
tests/GithubApp.py
Outdated
|
||
class GithubAppAuth(Framework.TestCase): | ||
def setUp(self): | ||
self.appAuthMode = True |
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.
This sets auth mode for all subsequent tests, this should only be used by tests.conftest.pytest_configure
via command line arguments like --record
.
Please use the same way of authentication as used in tests/GithubIntegration.py
:
auth = github.Auth.AppAuth(APP_ID, PRIVATE_KEY)
g = github.Github(auth=auth)
app = g.get_app()
You can import APP_ID
and PRIVATE_KEY
from tests/GithubIntegration.py
.
So this GithubAppAuth
class and def setUp
can be removed.
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.
ok, I removed this code from the PR then as it is not required. This feature would then be orthogonal to this PR.
tests/Framework.py
Outdated
@@ -410,6 +437,10 @@ def activateJWTAuthMode(): # pragma no cover (Function useful only when recordi | |||
BasicTestCase.jwtAuthMode = True | |||
|
|||
|
|||
def activateAppAuthMode(): # pragma no cover (Function useful only when recording new tests, not used during automated tests) |
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.
this needs to be added to tests.conftest.pytest_configure
to be useful
github/MainClass.py
Outdated
"github.GithubIntegration(auth=github.Auth.AppAuth(...)).get_app() instead", | ||
category=DeprecationWarning, | ||
) | ||
return GithubIntegration(auth=self.__requester._Requester__auth).get_app() |
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.
Please rebase and access Requester.auth
:
return GithubIntegration(auth=self.__requester._Requester__auth).get_app() | |
return GithubIntegration(auth=self.__requester.auth).get_app() |
Per my commit message in c3a2d35 , datetime.UTC was introduced in 3.11, datetime.timezone.utc works across the board of python 3.X tested in this project. |
ok, I force-pushed an update, but TL;DR:
|
bf72672
to
f09c6b8
Compare
tests/GithubApp.py
Outdated
self.assertWarningIn( | ||
warning, | ||
"Argument slug is mandatory, calling this method without the slug argument is deprecated, please use github.GithubIntegration(auth=github.Auth.AppAuth(...)).get_app() instead", | ||
) |
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.
self.assertWarningIn( | |
warning, | |
"Argument slug is mandatory, calling this method without the slug argument is deprecated, please use github.GithubIntegration(auth=github.Auth.AppAuth(...)).get_app() instead", | |
) | |
self.assertWarningIn( | |
warning, | |
"Argument slug is mandatory, calling this method without the slug argument is deprecated, " | |
"please use github.GithubIntegration(auth=github.Auth.AppAuth(...)).get_app() instead", | |
) |
tests/GithubIntegration.py
Outdated
with self.assertRaisesRegex( | ||
AssertionError, | ||
"GithubIntegration requires github.Auth.AppAuth authentication, not .*", | ||
): | ||
github.GithubIntegration(auth=self.oauth_token) |
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.
with self.assertRaisesRegex( | |
AssertionError, | |
"GithubIntegration requires github.Auth.AppAuth authentication, not .*", | |
): | |
github.GithubIntegration(auth=self.oauth_token) | |
with self.assertRaises( | |
AssertionError, | |
f"GithubIntegration requires github.Auth.AppAuth authentication, not {type(auth)}", | |
): | |
github.GithubIntegration(auth=auth) |
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.
good catch on the auth vs self.oauth_token :)
tests/Framework.py
Outdated
) | ||
if GithubCredentials.app_id and GithubCredentials.app_private_key | ||
else None | ||
) |
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.
No need to remove this existing code.
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.
I had added this, do you want me to re-add it even if this is not used here?
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.
This diff tells me, this was there before and your pull-request removes it.
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.
This is the last bit left. I'd say there is no need to remove this code by this pull request.
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.
hum, I was sure I had added that when I was creating a new test class.... I may have it mixed up with something else. Will re-introduce.
tests/GithubApp.py
Outdated
with self.assertWarns(DeprecationWarning) as warning: | ||
app = g.get_app() | ||
|
||
self.assertWarningIn( |
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.
self.assertWarningIn( | |
self.assertWarning( |
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.
The problem is that httpretty/core generates another warning, see #2549 (comment)
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.
Which Python version are you using?
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.
That's happening with 3.12. See this run/failure: https://github.com/PyGithub/PyGithub/actions/runs/5226324529/jobs/9436862034#step:5:153
tests/GithubApp.py
Outdated
with self.assertWarns(DeprecationWarning) as warning: | ||
app = g.get_app() | ||
|
||
self.assertWarningIn( |
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.
To be honest, I don't like assertWarningIn
, because it may hide unexpected warnings that we want to fail on.
Having httpretty
warn here is annoying, but we can disable that and everything works as expected:
with self.assertWarns(DeprecationWarning) as warning: | |
app = g.get_app() | |
self.assertWarningIn( | |
with self.assertWarns(DeprecationWarning) as warning: | |
# we ignore warnings from httpretty dependency | |
import warnings | |
warnings.filterwarnings("ignore", module="httpretty") | |
app = g.get_app() | |
self.assertWarning( |
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.
oh great, I did not know we could filter the warnings. Will change. Thanks
tests/Framework.py
Outdated
def assertWarnings(self, warning, *expecteds): | ||
self.assertEqual(len(warning.warnings), len(expecteds)) | ||
for message, expected in zip(warning.warnings, expecteds): | ||
self.assertIsInstance(message, warnings.WarningMessage) | ||
self.assertIsInstance(message.message, DeprecationWarning) | ||
self.assertEqual(message.message.args, (expected,)) |
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.
An error like
E AssertionError: 2 != 1
is not really helpful, lets improve this:
def assertWarnings(self, warning, *expecteds): | |
self.assertEqual(len(warning.warnings), len(expecteds)) | |
for message, expected in zip(warning.warnings, expecteds): | |
self.assertIsInstance(message, warnings.WarningMessage) | |
self.assertIsInstance(message.message, DeprecationWarning) | |
self.assertEqual(message.message.args, (expected,)) | |
def assertWarnings(self, warning, *expecteds): | |
actual = [(type(message), type(message.message), message.message.args) for message in warning.warnings] | |
expected = [(warnings.WarningMessage, DeprecationWarning, (expected,)) for expected in expecteds] | |
self.assertSequenceEqual(actual, expected) |
An authenticated app can call `/app` to get details about itself. Authentication must be done using jwt for authentication or it will fail with an error like https://gist.github.com/chantra/209819389b2dec6cc6e03a13d301f5e5
6d5e5eb
to
8b1df3f
Compare
rebased, re-ported utcnow change and got rid of assertWarningIn. |
…e can re-use it across tests. * assert deprecation warning and transparently call GithubIntegration.get_app() when no slug is provided * check that deprecation warning happens in test case * assert that auth is an AppAuth in GithubIntegration and test it
https://docs.python.org/dev/whatsnew/3.12.html > datetime.datetime’s utcnow() and utcfromtimestamp() are deprecated and will be removed in a future version. Instead, use timezone-aware objects to represent datetimes in UTC: respectively, call now() and fromtimestamp() with the tz parameter set to datetime.UTC. (Contributed by Paul Ganssle in gh-103857.) `datetime.UTC is new in 3.11, but is essentially an alias to datetime.timezone.utc This change replaces the occurences of utcnow() with datetime.timezone.utc so it works on older python releases.
In some cases, some deprecation messages may be generated by third-party libraries depedending on the python version we are using. This is a problem when we want to insure that a specific message is raised. This change introduce `assertWarningIn`, which will check if a specific deprecation warning is in the list of warnings.
ok, if I did not mess up, the CI should be green in a few and all feedback addressed :D |
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.
LGTM
Thank you for your patience! |
Thanks to you too! |
An authenticated app can call
/app
to get details about itself.Authentication must be done using jwt for authentication or it will fail with an error like https://gist.github.com/chantra/209819389b2dec6cc6e03a13d301f5e5