Skip to content

Commit

Permalink
🔥 Get rid of unneeded things for issue assigments (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
lig committed Sep 5, 2023
1 parent 94cec81 commit 2bd7ce0
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 36 deletions.
31 changes: 18 additions & 13 deletions src/logic/issues.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import enum
from dataclasses import dataclass, field
from typing import Final

import redis
from github.Issue import Issue as GhIssue
Expand All @@ -12,12 +13,14 @@
from .common import BaseActor


class IssueAction(str, enum.Enum):
# TODO: Use StrEnum in Python 3.11
class IssueAction(enum.StrEnum):
OPENED = 'opened'
REOPENED = 'reopened'


ISSUE_ACTIONS_TO_PROCESS: Final[tuple[IssueAction, ...]] = (IssueAction.OPENED,)


def process_issue(*, event: models.IssueEvent, settings: Settings) -> tuple[bool, str]:
"""Processes an issue in the repo
Expand All @@ -30,8 +33,8 @@ def process_issue(*, event: models.IssueEvent, settings: Settings) -> tuple[bool
- use "please update" magic comment to reassign to the author
- reassign from the author back to contributor after any author's comment
"""
if event.action not in iter(IssueAction):
return False, f'Ignored action "{event.action}"'
if event.action not in ISSUE_ACTIONS_TO_PROCESS:
return False, f'Ignoring event action "{event.action}"'

with get_repo_client(event.repository.full_name, settings) as gh_repo:
gh_issue = gh_repo.get_issue(event.issue.number)
Expand All @@ -42,7 +45,7 @@ def process_issue(*, event: models.IssueEvent, settings: Settings) -> tuple[bool
label_assign = LabelAssign(
gh_issue=gh_issue,
gh_repo=gh_repo,
action=IssueAction,
action=IssueAction(event.action),
author=event.issue.user,
repo_fullname=event.repository.full_name,
config=config,
Expand All @@ -59,20 +62,25 @@ class LabelAssign(BaseActor):
gh_issue: GhIssue
gh_repo: GhRepository
action: IssueAction
author: str
author: models.User
repo_fullname: str
config: RepoConfig
settings: Settings
assignees: list[str] = field(init=False)

def __post_init__(self):
self.assignees = self.config.assignees or [user.login for user in self.gh_repo.get_collaborators()]
self.assignees = self.config.assignees

def assign_new(self) -> tuple[bool, str]:
if self.action not in ISSUE_ACTIONS_TO_PROCESS:
return False, f'Ignoring issue action "{self.action}"'

if self.author.login in self.assignees:
return False, f'@{self.author.login} is in repo assignees list, doing nothing'

def assign_new(self):
assignee = self._select_assignee()
self._assign_user(assignee)
self._add_label(self.config.unconfirmed_label)
self._add_reaction()

return (True, f'@{assignee} successfully assigned to issue, "{self.config.unconfirmed_label}" label added')

Expand All @@ -87,10 +95,7 @@ def _select_assignee(self) -> str:
assignee_index %= assignees_count
redis_client.set(key, assignee_index + 1)

assignee = self.assignees[assignee_index % assignees_count]

self.gh_issue.edit(body=f'{self.gh_issue.body}\n\nSelected Assignee: @{assignee}')
return assignee
return self.assignees[assignee_index % assignees_count]

def _assign_user(self, username: str) -> None:
if username in (gh_user.login for gh_user in self.gh_issue.assignees):
Expand Down
5 changes: 3 additions & 2 deletions tests/dummy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,10 @@ async def remove_assignee(_request: Request) -> Response:
return json_response({'assignees': []})


config_with_reviewers = b"""
sample_config = b"""
[tool.hooky]
reviewers = ['user1', 'user2']
assignees = ['user3', 'user4']
"""


Expand All @@ -103,7 +104,7 @@ async def py_project_content(request: Request) -> Response:
return json_response({}, status=404)
else:
return json_response(
{'content': base64.b64encode(config_with_reviewers).decode(), 'encoding': 'base64', 'type': 'file'}
{'content': base64.b64encode(sample_config).decode(), 'encoding': 'base64', 'type': 'file'}
)


Expand Down
53 changes: 37 additions & 16 deletions tests/test_logic_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import redis

from src.logic.issues import IssueAction, LabelAssign
from src.logic.models import User
from src.repo_config import RepoConfig

from .blocks import AttrBlock, CallableBlock, IterBlock
Expand Down Expand Up @@ -31,26 +32,21 @@ def test_assign_new(settings, gh_issue, gh_repo, redis_cli):
gh_issue=gh_issue,
gh_repo=gh_repo,
action=IssueAction.OPENED,
author='the_author',
author=User(login='the_author'),
repo_fullname='org/repo',
config=RepoConfig(assignees=['user1', 'user2']),
settings=settings,
)
acted, msg = la.assign_new()
assert acted, msg
assert msg == '@user1 successfully assigned to issue, "unconfirmed" label added'
assert gh_issue.__history__ == [
"edit: Call(body='this is the issue body\\n\\nSelected Assignee: @user1')",
"add_to_assignees: Call('user1')",
"add_to_labels: Call('unconfirmed')",
"create_reaction: Call('+1')",
]
assert gh_issue.__history__ == ["add_to_assignees: Call('user1')", "add_to_labels: Call('unconfirmed')"]

la2 = LabelAssign(
gh_issue=gh_issue,
gh_repo=gh_repo,
action=IssueAction.OPENED,
author='the_author',
author=User(login='the_author'),
repo_fullname='org/repo',
config=RepoConfig(assignees=['user1', 'user2']),
settings=settings,
Expand All @@ -65,28 +61,53 @@ def test_assign_new_one_assignee(settings, gh_issue, gh_repo, redis_cli):
gh_issue=gh_issue,
gh_repo=gh_repo,
action=IssueAction.OPENED,
author='the_author',
author=User(login='the_author'),
repo_fullname='org/repo',
config=RepoConfig(assignees=['user1']),
settings=settings,
)
acted, msg = la.assign_new()
assert acted, msg
assert msg == '@user1 successfully assigned to issue, "unconfirmed" label added'
assert gh_issue.__history__ == [
"edit: Call(body='this is the issue body\\n\\nSelected Assignee: @user1')",
"add_to_assignees: Call('user1')",
"add_to_labels: Call('unconfirmed')",
"create_reaction: Call('+1')",
]
assert gh_issue.__history__ == ["add_to_assignees: Call('user1')", "add_to_labels: Call('unconfirmed')"]


def test_do_not_assign_from_one_of_assignees(settings, gh_issue, gh_repo, redis_cli):
la = LabelAssign(
gh_issue=gh_issue,
gh_repo=gh_repo,
action=IssueAction.OPENED,
author=User(login='user2'),
repo_fullname='org/repo',
config=RepoConfig(assignees=['user1', 'user2']),
settings=settings,
)
acted, msg = la.assign_new()
assert not acted, msg
assert gh_issue.__history__ == []


def test_do_not_assign_on_reopen(settings, gh_issue, gh_repo, redis_cli):
la = LabelAssign(
gh_issue=gh_issue,
gh_repo=gh_repo,
action=IssueAction.REOPENED,
author=User(login='the_author'),
repo_fullname='org/repo',
config=RepoConfig(assignees=['user1']),
settings=settings,
)
acted, msg = la.assign_new()
assert not acted, msg
assert gh_issue.__history__ == []


def test_many_assignments(settings, gh_issue, gh_repo, redis_cli: redis.Redis):
la = LabelAssign(
gh_issue=gh_issue,
gh_repo=gh_repo,
action=IssueAction.OPENED,
author='the_author',
author=User(login='the_author'),
repo_fullname='org/repo',
config=RepoConfig(assignees=['user1', 'user2', 'user3', 'user4']),
settings=settings,
Expand Down
41 changes: 36 additions & 5 deletions tests/test_webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def test_created(client: Client):
}
)
assert r.status_code == 202, r.text
assert r.text == 'Ignored action "created", no action taken'
assert r.text == 'Ignoring event action "created", no action taken'


def test_please_review(dummy_server: DummyServer, client: Client):
Expand Down Expand Up @@ -226,7 +226,7 @@ def test_issue_opened(dummy_server: DummyServer, client: Client):
}
)
assert r.status_code == 200, r.text
assert r.text == '@user1 successfully assigned to issue, "unconfirmed" label added'
assert r.text == '@user3 successfully assigned to issue, "unconfirmed" label added'
assert dummy_server.log == [
'GET /repos/user1/repo1/installation > 200',
'POST /app/installations/654321/access_tokens > 200',
Expand All @@ -235,9 +235,40 @@ def test_issue_opened(dummy_server: DummyServer, client: Client):
'GET /repos/user1/repo1 > 200',
'GET /repos/user1/repo1/contents/.hooky.toml > 404',
'GET /repos/user1/repo1/contents/pyproject.toml > 200',
'GET /repos/user1/repo1/collaborators > 200',
'PATCH /repos/user1/repo1/issues/123 > 200',
'POST /repos/user1/repo1/issues/123/assignees > 200',
'POST /repos/user1/repo1/issues/123/labels > 200',
'POST /repos/user1/repo1/issues/123/reactions > 200',
]


def test_issue_opened_by_assignee(dummy_server: DummyServer, client: Client):
r = client.webhook(
{
'action': 'opened',
'issue': {'user': {'login': 'user3'}, 'number': 123},
'repository': {'full_name': 'user1/repo1', 'owner': {'login': 'user1'}},
}
)
assert r.status_code == 202, r.text
assert r.text == '@user3 is in repo assignees list, doing nothing, no action taken'
assert dummy_server.log == [
'GET /repos/user1/repo1/installation > 200',
'POST /app/installations/654321/access_tokens > 200',
'GET /repos/user1/repo1 > 200',
'GET /repos/user1/repo1/issues/123 > 200',
'GET /repos/user1/repo1 > 200',
'GET /repos/user1/repo1/contents/.hooky.toml > 404',
'GET /repos/user1/repo1/contents/pyproject.toml > 200',
]


def test_issue_reopened(dummy_server: DummyServer, client: Client):
r = client.webhook(
{
'action': 'reopened',
'issue': {'user': {'login': 'user1'}, 'number': 123},
'repository': {'full_name': 'user1/repo1', 'owner': {'login': 'user1'}},
}
)
assert r.status_code == 202, r.text
assert r.text == 'Ignoring event action "reopened", no action taken'
assert dummy_server.log == []

0 comments on commit 2bd7ce0

Please sign in to comment.