change status when WIP prefix is removed (#73090)
gitea-wip/gitea-redmine/pipeline/pr-main This commit looks good Details
gitea/gitea-redmine/pipeline/head This commit looks good Details

This commit is contained in:
Frédéric Péters 2023-02-02 21:26:10 +01:00
parent 75633e9a2b
commit 48f4c83008
2 changed files with 109 additions and 26 deletions

View File

@ -91,9 +91,6 @@ def get_handler(payload):
return handle_pull_request_approved, 'pull_request.approved'
return None, None
if payload.get('action') == 'edited' and payload.get('pull_request'):
if payload['pull_request']['title'].lower().startswith('wip:'):
return handle_pull_request_draft, 'pull_request.draft'
return handle_pull_request_edited, 'pull_request.edited'
if (
payload.get('action') == 'closed'
@ -159,13 +156,14 @@ def make_handler(*actions):
def inner(issue, payload, project):
if is_excluded_project(project):
logging.info('Issue belongs to excluded project %s', project.id)
return
return False
flat_payload = flatten(payload)
for action in actions:
try:
action(issue, flat_payload)
except Abort:
return
return False
return True
return inner
@ -226,6 +224,17 @@ def skip_if_notes_include(field, reason):
return inner
def skip_unless_notes_include(text, reason):
def inner(issue, payload):
for entry in issue.journals:
if text in entry.notes:
break
else:
raise Abort(reason)
return inner
def skip_if_status(status):
def inner(issue, payload):
if issue.status.id == status:
@ -234,6 +243,14 @@ def skip_if_status(status):
return inner
def skip_if_not_status(status):
def inner(issue, payload):
if issue.status.id != status:
raise Abort(f'Issue not in status {status}')
return inner
def set_value_if_empty(field, value):
def inner(issue, payload):
if not payload.get(field):
@ -257,25 +274,43 @@ handle_pull_request_opened_draft = make_handler(
save(),
)
handle_pull_request_edited = make_handler(
skip_if_notes_include('pull_request_url', 'Pull request already linked in issue'),
assign_to('pull_request_user_username'),
set_status(REDMINE_STATUSES['En cours'], unless=CLOSED_STATUSES),
add_note(
'{pull_request_user_full_name} ({pull_request_user_username}) a lié une pull request sur Gitea concernant cette demande :\n\n* URL : {pull_request_url}\n* Titre : {pull_request_title}\n* Modifications : {pull_request_url}/files'
),
save(),
)
handle_pull_request_draft = make_handler(
skip_if_status(REDMINE_STATUSES['En cours']),
skip_if_not_draft,
set_status(REDMINE_STATUSES['En cours'], unless=CLOSED_STATUSES),
add_note(
'{pull_request_user_full_name} ({pull_request_user_username}) a commencé à travailler sur une pull request sur Gitea concernant cette demande :\n\n* URL : {pull_request_url}\n* Titre : {pull_request_title}\n* Modifications : {pull_request_url}/files'
),
save(),
)
def handle_pull_request_edited(issue, payload, project):
if payload['pull_request']['title'].lower().startswith('wip:'):
func = make_handler(
skip_if_status(REDMINE_STATUSES['En cours']),
skip_if_not_draft,
set_status(REDMINE_STATUSES['En cours'], unless=CLOSED_STATUSES),
add_note(
'{pull_request_user_full_name} ({pull_request_user_username}) a commencé à travailler sur une pull request sur Gitea concernant cette demande :\n\n* URL : {pull_request_url}\n* Titre : {pull_request_title}\n* Modifications : {pull_request_url}/files'
),
save(),
)
return func(issue, payload, project)
# maybe it was wip and is no more
func = make_handler(
skip_if_not_status(REDMINE_STATUSES['En cours']),
skip_unless_notes_include('Titre : WIP', 'Pull request do not mention a draft title'),
set_status(REDMINE_STATUSES['Solution proposée']),
save(),
)
if func(issue, payload, project) is True:
# the issue was changed, stop now.
return
# default behaviour
func = make_handler(
skip_if_notes_include('pull_request_url', 'Pull request already linked in issue'),
assign_to('pull_request_user_username'),
set_status(REDMINE_STATUSES['En cours'], unless=CLOSED_STATUSES),
add_note(
'{pull_request_user_full_name} ({pull_request_user_username}) a lié une pull request sur Gitea concernant cette demande :\n\n* URL : {pull_request_url}\n* Titre : {pull_request_title}\n* Modifications : {pull_request_url}/files'
),
save(),
)
return func(issue, payload, project)
handle_pull_request_merged = make_handler(
set_status(REDMINE_STATUSES['Résolu'], unless=CLOSED_STATUSES),

View File

@ -28,8 +28,8 @@ def client():
),
(
{'action': 'edited', 'pull_request': {'title': 'WIP: something'}},
gitea_redmine.handle_pull_request_draft,
'pull_request.draft',
gitea_redmine.handle_pull_request_edited,
'pull_request.edited',
),
(
{'action': 'reviewed', 'review': {"type": "pull_request_review_approved"}},
@ -201,6 +201,53 @@ def test_handle_pull_request_edited(mocker):
issue.save.assert_called_once()
def test_handle_pull_request_edited_wip_removal(mocker):
redmine_user = mocker.Mock(id=42)
get_redmine_user = mocker.patch.object(gitea_redmine, 'get_redmine_user', return_value=redmine_user)
payload = {
"action": "opened",
"number": 2,
"pull_request": {
"id": 7,
"url": "https://gitea.entrouvert.org/entrouvert/gitea-redmine/pulls/2",
"number": 2,
"user": {
"id": 7,
"login": "testuser",
"full_name": "Test User",
"email": "test_user@noreply.gitea.entrouvert.org",
"username": "testuser",
},
"title": "WIP: Foo",
"body": "...",
},
}
project = mocker.Mock()
project.parent = None
issue = mocker.Mock(journals=[])
gitea_redmine.handle_pull_request_opened_draft(issue, payload, project)
assert issue.assigned_to_id == redmine_user.id
assert issue.status_id == gitea_redmine.REDMINE_STATUSES['En cours']
issue.save.assert_called_once()
issue.status.id = issue.status_id
issue.journals = [
mocker.Mock(notes='* URL : %(url)s\n* Titre : %(title)s' % payload['pull_request']),
]
payload['action'] = 'edited'
payload['pull_request']['title'] = 'Foo' # remove WIP: prefix
gitea_redmine.handle_pull_request_edited(issue, payload, project)
assert issue.status_id == gitea_redmine.REDMINE_STATUSES['Solution proposée']
assert issue.save.call_count == 2
# another webhook call, do not change issue
issue.status.id = issue.status_id
gitea_redmine.handle_pull_request_edited(issue, payload, project)
assert issue.save.call_count == 2
def test_handle_pull_request_draft(mocker):
payload = {
"action": "edited",
@ -223,7 +270,7 @@ def test_handle_pull_request_draft(mocker):
project = mocker.Mock()
project.parent = None
issue = mocker.Mock(journals=[])
gitea_redmine.handle_pull_request_draft(issue, payload, project)
gitea_redmine.handle_pull_request_edited(issue, payload, project)
assert issue.status_id == gitea_redmine.REDMINE_STATUSES['En cours']
assert issue.notes == (
@ -241,6 +288,7 @@ def test_handle_pull_request_edited_already_linked_does_nothing(mocker):
"action": "edited",
"pull_request": {
"url": "https://gitea.entrouvert.org/entrouvert/gitea-redmine/pulls/2",
"title": "Foo",
},
}
project = mocker.Mock()