runbot/forwardport/tests/test_backport.py
Xavier Morel cf4d162907 [ADD] *: PR backport wizard
This is not a full user-driven backport thingie for now, just one
admins can use to facilitate thing and debug issues with the
system. May eventually graduate to a frontend feature.

Fixes #925
2024-10-22 11:41:58 +02:00

118 lines
4.0 KiB
Python

from xmlrpc.client import Fault
import pytest
from utils import make_basic, Commit, to_pr, seen
@pytest.fixture
def repo(env, config, make_repo):
repo, _ = make_basic(env, config, make_repo, statuses="default")
return repo
@pytest.fixture
def pr_id(env, repo, config):
with repo:
repo.make_commits('c', Commit("c", tree={'x': '1'}), ref='heads/aref')
pr = repo.make_pr(target='c', head='aref')
repo.post_status('aref', 'success')
pr.post_comment('hansen r+', config['role_reviewer']['token'])
env.run_crons()
with repo:
repo.post_status('staging.c', 'success')
env.run_crons()
pr_id = to_pr(env, pr)
assert pr_id.merge_date
return pr_id
@pytest.fixture
def backport_id(env, pr_id):
action = pr_id.backport()
backport_id = env[action['res_model']].browse([action['res_id']])
assert backport_id._name == 'runbot_merge.pull_requests.backport'
assert backport_id
return backport_id
def test_golden_path(env, repo, config, pr_id, backport_id, users):
branch_a, branch_b, _branch_c = env['runbot_merge.branch'].search([], order='name')
backport_id.target = branch_a.id
act2 = backport_id.action_apply()
env.run_crons() # run cron to update labels
_, bp_id = env['runbot_merge.pull_requests'].search([], order='number')
assert bp_id.limit_id == branch_b
assert bp_id._name == act2['res_model']
assert bp_id.id == act2['res_id']
bp_head = repo.commit(bp_id.head)
assert repo.read_tree(bp_head) == {
'f': 'e',
'x': '1',
}
assert bp_head.message == f"""c
X-original-commit: {pr_id.head}\
"""
assert bp_id.message == f"[Backport] c\n\nBackport of {pr_id.display_name}"
assert repo.get_pr(bp_id.number).labels == {"backport"}
# check that the backport can actually be merged and forward-ports successfully...
with repo:
repo.post_status(bp_id.head, 'success')
repo.get_pr(bp_id.number).post_comment("hansen r+", config['role_reviewer']['token'])
env.run_crons()
with repo:
repo.post_status('staging.a', 'success')
env.run_crons()
_pr, _backport, fw_id = env['runbot_merge.pull_requests'].search([], order='number')
fw_pr = repo.get_pr(fw_id.number)
assert fw_pr.comments == [
seen(env, fw_pr, users),
(users['user'], '''\
@{user} @{reviewer} this PR targets b and is the last of the forward-port chain.
To merge the full chain, use
> @hansen r+
More info at https://github.com/odoo/odoo/wiki/Mergebot#forward-port
'''.format_map(users)),
]
def test_conflict(env, repo, config, backport_id):
with repo:
repo.make_commits('a', Commit('conflict', tree={'x': '-1'}), ref='heads/a', make=False)
branch_a, _branch_b, _branch_c = env['runbot_merge.branch'].search([], order='name')
backport_id.target = branch_a.id
with pytest.raises(Fault) as exc:
backport_id.action_apply()
assert exc.value.faultString == """\
backport conflict:
Auto-merging x
CONFLICT (add/add): Merge conflict in x
"""
def test_target_error(env, config, backport_id):
branch_a, _branch_b, branch_c = env['runbot_merge.branch'].search([], order='name')
with pytest.raises(Fault) as exc:
backport_id.action_apply()
assert exc.value.faultString == "A backport needs a backport target"
backport_id.target = branch_c.id
with pytest.raises(Fault) as exc:
backport_id.action_apply()
assert exc.value.faultString == "The backport branch needs to be before the source's branch (got 'c' and 'c')"
backport_id.target = branch_a.id
backport_id.action_apply()
@pytest.mark.skip(
reason="Currently no way to make just the PR creation fail, swapping the "
"fp_github_token for an invalid one breaks git itself"
)
def test_pr_fail(env, config, repo, pr_id, backport_id):
backport_id.target = env['runbot_merge.branch'].search([], order='name', limit=1).id
with pytest.raises(Fault) as exc:
backport_id.action_apply()
assert exc.value.faultString == 'Backport PR creation failure: '