Skip to content

Commit

Permalink
chore: typehints + comments (#239)
Browse files Browse the repository at this point in the history
Before started working on the revamping app usage I took some time to access what we currently have.
This ended up manifesting in type annotations and a small cleanup in the install docs.

The only real addition is `services.github.dedicated_apps` config values for the
dedicated apps.
And some new TokenTypes
  • Loading branch information
giovanni-guidini authored Jun 5, 2024
1 parent e954d86 commit bf76a73
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 47 deletions.
27 changes: 16 additions & 11 deletions shared/torngit/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@


class TokenType(Enum):
read = auto()
admin = auto()
comment = auto()
status = auto()
tokenless = auto()
read = "read"
admin = "admin"
comment = "comment"
status = "status"
tokenless = "tokenless"
commit = "commit"
pull = "pull"


TokenTypeMapping = Dict[TokenType, Token]


class TorngitBaseAdapter(object):
Expand Down Expand Up @@ -60,7 +65,7 @@ def __init__(
oauth_consumer_token: OauthConsumerToken = None,
timeouts=None,
token: Token = None,
token_type_mapping: Dict[TokenType, Dict] = None,
token_type_mapping: TokenTypeMapping = None,
on_token_refresh: OnRefreshCallback = None,
verify_ssl=None,
**kwargs,
Expand Down Expand Up @@ -109,28 +114,28 @@ def get_token_by_type_if_none(self, token: Optional[str], token_type: TokenType)
return token
return self.get_token_by_type(token_type)

def _oauth_consumer_token(self):
def _oauth_consumer_token(self) -> OauthConsumerToken:
if not self._oauth:
raise Exception("Oauth consumer token not present")
return self._oauth

def _validate_language(self, language):
def _validate_language(self, language: str) -> str | None:
if language:
language = language.lower()
if language in self.valid_languages:
return language

def set_token(self, token: OauthConsumerToken):
def set_token(self, token: OauthConsumerToken) -> None:
self._token = token

@property
def token(self):
def token(self) -> Token:
if not self._token:
self._token = self._oauth_consumer_token()
return self._token

@property
def slug(self):
def slug(self) -> str | None:
if self.data.get("owner") and self.data.get("repo"):
if self.data["owner"].get("username") and self.data["repo"].get("name"):
return "%s/%s" % (
Expand Down
2 changes: 2 additions & 0 deletions shared/typings/oauth_token_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

class Token(TypedDict):
key: str
# This information is used to identify the token owner in the logs, if present
username: str | None


class OauthConsumerToken(Token):
Expand Down
97 changes: 61 additions & 36 deletions shared/validation/install.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Configuration options that affect an entire instance of Codecov"""

import logging

from shared.utils.enums import TaskConfigGroup
Expand All @@ -15,66 +17,72 @@ def check_task_config_key(field, value, error):
error(field, "Not a valid TaskConfigGroup")


# Bot is a git provider account configured to be used in place of another
bot_details_fields = {
# This is a PAT for some provider account that is going to be used as a bot
"key": {"type": "string", "required": True},
# This is used only for Bitbucket (uses Oauth1)
"secret": {"type": "string"},
# Identifies the bot in the logs
"username": {"type": "string"},
}

# Credentials used by the OAuth App used when logging into Codecov UI
# note: the OAuth App acts in behalf of the user. The user will need to authorize it
# and enter user's own credentials for logging into the git provider
oauth_credential_fields = {
"client_id": {"type": "string"},
"client_secret": {"type": "string"},
# The URI to redirect the user after authorization is granted to the OAuth App
"redirect_uri": {"type": "string"},
}

# Default app [GitHub exclusive] - Credentials for a GitHub app used by this installation
# note: these credentials are used to get access_tokens for installations
GitHub_app_fields = {
"expires": {"type": "integer"},
"id": {"type": "integer", "required": True},
"pem": {"type": ["string", "dict"], "required": True},
}

default_service_fields = {
"verify_ssl": {"type": "boolean"},
"ssl_pem": {"type": "string"},
"client_id": {"type": "string"},
"client_secret": {"type": "string"},
"integration": {
"type": "dict",
"schema": {
"expires": {"type": "integer"},
"id": {"type": "integer"},
"pem": {"type": ["string", "dict"]},
},
},
**oauth_credential_fields,
"url": {"type": "string"},
"api_url": {"type": "string"},
# bot [enterprise (self-hosted)] - Bot that is used for all repos belonging to a given service.
# bot [cloud] - Used as public bot fallback if bots.tokenless is not provided.
"bot": {
"type": "dict",
"schema": {
"key": {"type": "string"},
"secret": {"type": "string"},
"username": {"type": "string"},
},
"schema": bot_details_fields,
},
# global_upload_token [enterprise (self-hosted)] - Master upload token.
# Any upload (for any repo) made to the instance using this token will be validated.
"global_upload_token": {"type": "string"},
"organizations": {"type": "list", "schema": {"type": "string"}},
"webhook_secret": {"type": "string"},
# bots - Function-specific bots used as fallbacks for public repos
# Certain functions in the torngit adapter will use one of these tokens if none is present.
# 'bots.tokenless' is the default fallback
"bots": {
"type": "dict",
"schema": {
"read": {
"type": "dict",
"schema": {
"key": {"type": "string"},
"secret": {"type": "string"},
"username": {"type": "string"},
},
"schema": bot_details_fields,
},
"comment": {
"type": "dict",
"schema": {
"key": {"type": "string"},
"secret": {"type": "string"},
"username": {"type": "string"},
},
"schema": bot_details_fields,
},
"status": {
"type": "dict",
"schema": {
"key": {"type": "string"},
"secret": {"type": "string"},
"username": {"type": "string"},
},
"schema": bot_details_fields,
},
"tokenless": {
"type": "dict",
"schema": {
"key": {"type": "string"},
"secret": {"type": "string"},
"username": {"type": "string"},
},
"schema": bot_details_fields,
},
},
},
Expand Down Expand Up @@ -243,6 +251,7 @@ def check_task_config_key(field, value, error):
"type": "list",
"schema": {"type": "string"},
},
# guest_access [enterprise (self-hosted)] - Wether to allow non-logged in users to access the UI in this Codecov instance
"guest_access": {"type": "boolean"},
},
},
Expand Down Expand Up @@ -357,7 +366,23 @@ def check_task_config_key(field, value, error):
},
},
},
"github": {"type": "dict", "schema": {**default_service_fields}},
"github": {
"type": "dict",
"schema": {
**default_service_fields,
# integration - Credentials for the default Codecov App
"integration": {
"type": "dict",
"schema": GitHub_app_fields,
},
# dedicated_apps - Dedicated apps are used in specific tasks.
# They can have a different set of permissions than the default Codecov App, allowing us to provide different opt-in services
"dedicated_apps": {
"type": "dict",
"valuesrules": {"type": "dict", "schema": GitHub_app_fields},
},
},
},
"bitbucket": {"type": "dict", "schema": {**default_service_fields}},
"bitbucket_server": {"type": "dict", "schema": {**default_service_fields}},
"github_enterprise": {"type": "dict", "schema": {**default_service_fields}},
Expand Down
1 change: 1 addition & 0 deletions tests/unit/validation/test_install_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ def test_validate_sample_production_config(mocker):
}
mock_warning = mocker.patch.object(install_log, "warning")
res = validate_install_configuration(user_input)
print(mock_warning.call_args)
assert mock_warning.call_count == 0
assert res["site"] == expected_result["site"]
assert res == expected_result
Expand Down

0 comments on commit bf76a73

Please sign in to comment.