-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Add Codecov User Resolution #90411
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 Codecov User Resolution #90411
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
from dataclasses import dataclass | ||
from typing import Any | ||
|
||
from sentry.auth.services.access.service import access_service | ||
from sentry.auth.services.auth import RpcAuthIdentity | ||
from sentry.identity.services.identity import identity_service | ||
from sentry.identity.services.identity.model import RpcIdentity | ||
|
||
|
||
@dataclass | ||
class CodecovUser: | ||
external_id: str | ||
auth_token: Any | ||
|
||
|
||
def resolve_codecov_user(user_id: int, organization_id: int) -> CodecovUser | None: | ||
"""Given a Sentry User, and an organization id, find the GitHub user ID and GH access_token | ||
that is linked to Codecov's user. | ||
The user resolution will "fall-through" based on whether the Organization has a GitHub Auth Provider enabled. | ||
""" | ||
# Get identity from an AuthProvider if it's available. | ||
auth_provider = access_service.get_auth_provider(organization_id) | ||
if auth_provider and auth_provider.provider == "github": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are there constants/enums for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't seen an enum |
||
auth_identity: RpcAuthIdentity | None = access_service.get_auth_identity_for_user( | ||
auth_provider.id, user_id | ||
) | ||
if auth_identity: | ||
return CodecovUser( | ||
external_id=str(auth_identity.ident), | ||
auth_token=auth_identity.data.get("access_token"), | ||
) | ||
|
||
# Get identity from Identity if it's available. | ||
identities: list[RpcIdentity] = identity_service.get_user_identities_by_provider_type( | ||
user_id=user_id, provider_type="github" | ||
) | ||
if identities: | ||
# Note: There is currently either zero or one GitHub "identity" mapped to a user. | ||
identity = identities[0] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will we get many identities? And if so, why would we always choose the first? Perhaps a comment to help understand this 👌 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When I checked the database, there should be only one identity mapped to GitHub per user at this point. So, in practice, this is currently zero or one user. I can add a comment for this. 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gotchaa so this will be like a one off mapping? |
||
return CodecovUser( | ||
external_id=identity.external_id, | ||
auth_token=identity.data.get("access_token"), | ||
) | ||
|
||
# No GitHub identities tied to user, return None | ||
return None |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from sentry.codecov.helper import CodecovUser, resolve_codecov_user | ||
from sentry.testutils.cases import TestCase | ||
from sentry.testutils.silo import all_silo_test | ||
|
||
|
||
@all_silo_test | ||
class TestCodecovUserResolution(TestCase): | ||
def setUp(self): | ||
self.organization = self.create_organization() | ||
self.user = self.create_user() | ||
|
||
def test_get_auth_provider_identity_for_user(self): | ||
auth_provider = self.create_auth_provider( | ||
organization_id=self.organization.id, provider="github" | ||
) | ||
self.create_auth_identity( | ||
auth_provider=auth_provider, | ||
user=self.user, | ||
ident=12345, | ||
data={"access_token": "this_is_the_access_token_stored_here"}, | ||
) | ||
assert resolve_codecov_user(self.user.id, self.organization.id) == CodecovUser( | ||
external_id="12345", auth_token="this_is_the_access_token_stored_here" | ||
) | ||
|
||
def test_get_auth_identity_for_user(self): | ||
# Create the Auth Provider to fall through | ||
self.create_auth_provider(organization_id=self.organization.id, provider="github") | ||
|
||
identity_provider = self.create_identity_provider(type="github") | ||
self.create_identity( | ||
user=self.user, | ||
identity_provider=identity_provider, | ||
external_id="identity_id_12345", | ||
data={"access_token": "this_is_the_access_token_stored_here"}, | ||
) | ||
|
||
assert resolve_codecov_user(self.user.id, self.organization.id) == CodecovUser( | ||
external_id="identity_id_12345", auth_token="this_is_the_access_token_stored_here" | ||
) | ||
|
||
def test_no_linked_identity(self): | ||
assert resolve_codecov_user(self.user.id, self.organization.id) is 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.
"that is linked to Codecov's user" implies Codecov has its own notion of this user's identity. maybe word like "that we can provide in place of a Codecov User"?
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.
Technically, we're using the GH id to link it to Codecov's concept of a user (we are still using the
owner
object in Codecov). The name of the method might be confusing? As we're technically finding the GH user to link to Codecov.