-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: introduce helpers and types
Part 1 of the bundle analysis notify refactor. This PR simply introduces `NotificationType` and helper functions to determine what notifications are configured based on the current_yaml. Some other helper functions are from the existing notify service slightly adjusted to not depend on the class they are declared in
- Loading branch information
1 parent
02be991
commit a22bdab
Showing
4 changed files
with
219 additions
and
2 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
from typing import Literal | ||
|
||
from shared.django_apps.codecov_auth.models import Service | ||
from shared.torngit.base import TorngitBaseAdapter | ||
from shared.yaml import UserYaml | ||
|
||
from database.models.core import Owner | ||
from services.bundle_analysis.new_notify.types import NotificationType | ||
|
||
|
||
def is_commit_status_configured( | ||
yaml: UserYaml, owner: Owner | ||
) -> None | NotificationType: | ||
"""Verifies if we should attempt to send bundle analysis commit status based on given YAML. | ||
Config field is `bundle_analysis.status` (default: "informational") | ||
If the user is from GitHub and has an app we can send NotificationType.GITHUB_COMMIT_CHECK. | ||
""" | ||
is_status_configured: bool | Literal["informational"] = yaml.read_yaml_field( | ||
"bundle_analysis", "status", _else="informational" | ||
) | ||
is_github = Service(owner.service) in (Service.GITHUB, Service.GITHUB_ENTERPRISE) | ||
owner_has_app = owner.github_app_installations != [] | ||
if is_status_configured: | ||
if is_github and owner_has_app: | ||
return NotificationType.GITHUB_COMMIT_CHECK | ||
return NotificationType.COMMIT_STATUS | ||
return None | ||
|
||
|
||
def is_comment_configured(yaml: UserYaml, owner: Owner) -> None | NotificationType: | ||
"""Verifies if we should attempt to send bundle analysis PR comment based on given YAML. | ||
Config field is `comment` (default: see shared.config) | ||
""" | ||
is_comment_configured: dict | bool = yaml.read_yaml_field("comment") is not False | ||
if is_comment_configured: | ||
return NotificationType.PR_COMMENT | ||
return None | ||
|
||
|
||
def get_notification_types_configured( | ||
yaml: UserYaml, owner: Owner | ||
) -> tuple[NotificationType]: | ||
"""Gets a tuple with all the different bundle analysis notifications that we should attempt to send, | ||
based on the given YAML""" | ||
notification_types = [ | ||
is_commit_status_configured(yaml, owner), | ||
is_comment_configured(yaml, owner), | ||
] | ||
return tuple(filter(None, notification_types)) | ||
|
||
|
||
def get_github_app_used(torngit: TorngitBaseAdapter | None) -> int | None: | ||
if torngit is None: | ||
return None | ||
torngit_installation = torngit.data.get("installation") | ||
selected_installation_id = ( | ||
torngit_installation.get("id") if torngit_installation else None | ||
) | ||
return selected_installation_id | ||
|
||
|
||
def bytes_readable(bytes: int) -> str: | ||
"""Converts bytes into human-readable string (up to GB)""" | ||
value = abs(bytes) | ||
expoent_index = 0 | ||
|
||
while value >= 1000 and expoent_index < 3: | ||
value /= 1000 | ||
expoent_index += 1 | ||
|
||
expoent_str = [" bytes", "kB", "MB", "GB"][expoent_index] | ||
rounted_value = round(value, 2) | ||
return f"{rounted_value}{expoent_str}" |
134 changes: 134 additions & 0 deletions
134
services/bundle_analysis/new_notify/tests/test_helpers.py
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,134 @@ | ||
from unittest.mock import MagicMock | ||
|
||
import pytest | ||
from shared.yaml import UserYaml | ||
|
||
from database.models.core import ( | ||
GITHUB_APP_INSTALLATION_DEFAULT_NAME, | ||
GithubAppInstallation, | ||
Owner, | ||
) | ||
from database.tests.factories.core import OwnerFactory | ||
from services.bundle_analysis.new_notify.helpers import ( | ||
bytes_readable, | ||
get_github_app_used, | ||
get_notification_types_configured, | ||
) | ||
from services.bundle_analysis.new_notify.types import NotificationType | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"input, expected", | ||
[ | ||
pytest.param(0, "0 bytes"), | ||
pytest.param(123, "123 bytes"), | ||
pytest.param(1000, "1.0kB"), | ||
pytest.param(1500, "1.5kB"), | ||
pytest.param(1000000, "1.0MB"), | ||
pytest.param(1500010, "1.5MB"), | ||
pytest.param(1e9, "1.0GB"), | ||
pytest.param(1230000000, "1.23GB"), | ||
], | ||
) | ||
def test_bytes_readable(input, expected): | ||
assert bytes_readable(input) == expected | ||
|
||
|
||
@pytest.fixture | ||
def github_owner_no_apps(dbsession) -> Owner: | ||
owner = OwnerFactory(service="github") | ||
dbsession.add(owner) | ||
dbsession.commit() | ||
assert owner.github_app_installations == [] | ||
return owner | ||
|
||
|
||
@pytest.fixture | ||
def github_owner_with_apps(dbsession) -> Owner: | ||
owner = OwnerFactory(service="github") | ||
ghapp = GithubAppInstallation( | ||
ownerid=owner.ownerid, | ||
owner=owner, | ||
name=GITHUB_APP_INSTALLATION_DEFAULT_NAME, | ||
) | ||
dbsession.add_all([owner, ghapp]) | ||
dbsession.commit() | ||
assert owner.github_app_installations == [ghapp] | ||
return owner | ||
|
||
|
||
@pytest.fixture | ||
def gitlab_owner(dbsession) -> Owner: | ||
owner = OwnerFactory(service="gitlab") | ||
dbsession.add(owner) | ||
dbsession.commit() | ||
return owner | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"config, owner_fixture, expected", | ||
[ | ||
pytest.param( | ||
{"comment": False, "bundle_analysis": {"status": False}}, | ||
"github_owner_no_apps", | ||
(), | ||
id="no_notification_configured", | ||
), | ||
# The default site configuration puts the `comment` as a dict | ||
pytest.param( | ||
{"comment": {"require_bundle_changes": False}}, | ||
"github_owner_no_apps", | ||
(NotificationType.COMMIT_STATUS, NotificationType.PR_COMMENT), | ||
id="default_values_github_no_apps", | ||
), | ||
pytest.param( | ||
{"comment": {"require_bundle_changes": False}}, | ||
"github_owner_with_apps", | ||
(NotificationType.GITHUB_COMMIT_CHECK, NotificationType.PR_COMMENT), | ||
id="default_values_github_with_apps", | ||
), | ||
pytest.param( | ||
{"comment": {"require_bundle_changes": False}}, | ||
"gitlab_owner", | ||
(NotificationType.COMMIT_STATUS, NotificationType.PR_COMMENT), | ||
id="default_values_gitlab", | ||
), | ||
pytest.param( | ||
{"comment": False, "bundle_analysis": {"status": True}}, | ||
"gitlab_owner", | ||
(NotificationType.COMMIT_STATUS,), | ||
id="just_commit_status", | ||
), | ||
pytest.param( | ||
{ | ||
"comment": {"require_bundle_changes": False}, | ||
"bundle_analysis": {"status": False}, | ||
}, | ||
"gitlab_owner", | ||
(NotificationType.PR_COMMENT,), | ||
id="just_pr_comment", | ||
), | ||
], | ||
) | ||
def test_get_configuration_types_configured(config, owner_fixture, expected, request): | ||
owner = request.getfixturevalue(owner_fixture) | ||
yaml = UserYaml.from_dict(config) | ||
assert get_notification_types_configured(yaml, owner) == expected | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"torngit, expected", | ||
[ | ||
pytest.param(None, None, id="no_torngit"), | ||
pytest.param( | ||
MagicMock(data={"installation": None}), None, id="torngit_no_installation" | ||
), | ||
pytest.param( | ||
MagicMock(data={"installation": {"id": 12}}), | ||
12, | ||
id="torngit_with_installation", | ||
), | ||
], | ||
) | ||
def test_get_github_app_used(torngit, expected): | ||
assert get_github_app_used(torngit) == expected |
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,9 @@ | ||
from enum import Enum | ||
|
||
|
||
class NotificationType(Enum): | ||
PR_COMMENT = "pr_comment" | ||
COMMIT_STATUS = "commit_status" | ||
# See docs on the difference between COMMIT_STATUS and GITHUB_COMMIT_CHECK | ||
# https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks#types-of-status-checks-on-github | ||
GITHUB_COMMIT_CHECK = "github_commit_check" |
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