2020-11-12 19:17:37 +07:00
|
|
|
import json
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
2024-12-02 20:17:28 +07:00
|
|
|
from utils import seen, Commit, to_pr
|
2020-11-12 19:17:37 +07:00
|
|
|
|
|
|
|
|
|
|
|
def test_no_duplicates(env):
|
|
|
|
""" Should not have two override records for the same (context, repo)
|
|
|
|
"""
|
|
|
|
Overrides = env['res.partner.override']
|
|
|
|
Overrides.create({'context': 'a'})
|
|
|
|
with pytest.raises(Exception, match=r'already exists'):
|
|
|
|
Overrides.create({'context': 'a'})
|
|
|
|
|
|
|
|
def name_search(Model, name):
|
|
|
|
""" Convenience function to return a recordset instead of a craplist
|
|
|
|
"""
|
|
|
|
return Model.browse(id_ for id_, _ in Model.name_search(name))
|
|
|
|
def test_finding(env):
|
|
|
|
project = env['runbot_merge.project'].create({
|
|
|
|
'name': 'test',
|
|
|
|
'github_token': 'xxx', 'github_prefix': 'no',
|
2024-11-29 15:04:06 +07:00
|
|
|
'github_name': "xxx", 'github_email': "xxx@example.org",
|
2020-11-12 19:17:37 +07:00
|
|
|
})
|
|
|
|
repo_1 = env['runbot_merge.repository'].create({'project_id': project.id, 'name': 'r1'})
|
|
|
|
repo_2 = env['runbot_merge.repository'].create({'project_id': project.id, 'name': 'r2'})
|
|
|
|
|
|
|
|
Overrides = env['res.partner.override']
|
|
|
|
a = Overrides.create({'context': 'ctx1'})
|
|
|
|
b = Overrides.create({'context': 'ctx1', 'repository_id': repo_1.id})
|
|
|
|
c = Overrides.create({'context': 'ctx1', 'repository_id': repo_2.id})
|
|
|
|
d = Overrides.create({'context': 'ctx2', 'repository_id': repo_2.id})
|
|
|
|
|
|
|
|
assert name_search(Overrides, 'ctx1') == a|b|c
|
|
|
|
assert name_search(Overrides, 'ctx') == a|b|c|d
|
|
|
|
assert name_search(Overrides, 'r2') == c|d
|
|
|
|
|
|
|
|
def test_basic(env, project, make_repo, users, setreviewers, config):
|
|
|
|
"""
|
|
|
|
Test that we can override a status on a PR:
|
|
|
|
|
|
|
|
* @mergebot override context=status
|
|
|
|
* target url should be the comment (?)
|
|
|
|
* description should be overridden by <user>
|
|
|
|
"""
|
|
|
|
repo = make_repo('repo')
|
|
|
|
repo_id = env['runbot_merge.repository'].create({
|
|
|
|
'project_id': project.id,
|
|
|
|
'name': repo.name,
|
|
|
|
'status_ids': [(0, 0, {'context': 'l/int'})]
|
|
|
|
})
|
|
|
|
setreviewers(*project.repo_ids)
|
[ADD] *: per-repository webhook secret
Currently webhook secrets are configured per *project* which is an
issue both because different repositories may have different
administrators and thus creates safety concerns, and because multiple
repositories can feed into different projects (e.g. on mergebot,
odoo-dev/odoo is both an ancillary repository to the main RD project,
and the main repository to the minor / legacy master-wowl
project). This means it can be necessary to have multiple projects
share the same secret as well, this then mandates the secret for more
repositories per (1).
This is a pain in the ass, so just detach secrets from projects and
link them *only* to repositories, it's cleaner and easier to manage
and set up progressively.
This requires a lot of changes to the tests, as they all need to
correctly configure the signaling.
For `runbot_merge` there was *some* setup sharing already via the
module-level `repo` fixtures`, those were merged into a conftest-level
fixture which could handle the signaling setup. A few tests which
unnecessarily set up repositories ad-hoc were also moved to the
fixture. But for most of the ad-hoc setup in `runbot_merge`, as well
as `forwardport` where it's all ad-hoc, events sources setup was just
appended as is. This should probably be cleaned up at one point, with
the various requirements collected and organised into a small set of
fixtures doing the job more uniformly.
Fixes #887
2024-06-06 16:07:57 +07:00
|
|
|
env['runbot_merge.events_sources'].create({'repository': repo.name})
|
2020-11-12 19:17:37 +07:00
|
|
|
# "other" can override the lint
|
|
|
|
env['res.partner'].create({
|
|
|
|
'name': config['role_other'].get('name', 'Other'),
|
|
|
|
'github_login': users['other'],
|
|
|
|
'override_rights': [(0, 0, {
|
|
|
|
'repository_id': repo_id.id,
|
|
|
|
'context': 'l/int',
|
|
|
|
})]
|
|
|
|
})
|
|
|
|
|
|
|
|
with repo:
|
|
|
|
m = repo.make_commits(None, Commit('root', tree={'a': '1'}), ref='heads/master')
|
|
|
|
|
|
|
|
repo.make_commits(m, Commit('pr', tree={'a': '2'}), ref='heads/change')
|
|
|
|
pr = repo.make_pr(target='master', title='super change', head='change')
|
|
|
|
pr.post_comment('hansen r+', config['role_reviewer']['token'])
|
|
|
|
env.run_crons()
|
|
|
|
|
2024-12-02 20:17:28 +07:00
|
|
|
pr_id = to_pr(env, pr)
|
2020-11-12 19:17:37 +07:00
|
|
|
assert pr_id.state == 'approved'
|
|
|
|
|
|
|
|
with repo:
|
|
|
|
pr.post_comment('hansen override=l/int', config['role_reviewer']['token'])
|
|
|
|
env.run_crons()
|
|
|
|
assert pr_id.state == 'approved'
|
|
|
|
|
|
|
|
with repo:
|
|
|
|
pr.post_comment('hansen override=l/int', config['role_other']['token'])
|
|
|
|
env.run_crons()
|
|
|
|
assert pr_id.state == 'ready'
|
|
|
|
|
|
|
|
comments = pr.comments
|
|
|
|
assert comments == [
|
|
|
|
(users['reviewer'], 'hansen r+'),
|
2020-11-17 21:21:21 +07:00
|
|
|
seen(env, pr, users),
|
2020-11-12 19:17:37 +07:00
|
|
|
(users['reviewer'], 'hansen override=l/int'),
|
2023-10-16 15:46:29 +07:00
|
|
|
(users['user'], "@{} you are not allowed to override 'l/int'.".format(users['reviewer'])),
|
2020-11-12 19:17:37 +07:00
|
|
|
(users['other'], "hansen override=l/int"),
|
|
|
|
]
|
|
|
|
assert pr_id.statuses == '{}'
|
|
|
|
assert json.loads(pr_id.overrides) == {'l/int': {
|
|
|
|
'state': 'success',
|
|
|
|
'target_url': comments[-1]['html_url'],
|
|
|
|
'description': 'Overridden by @{}'.format(users['other']),
|
|
|
|
}}
|
|
|
|
|
2021-01-12 15:25:53 +07:00
|
|
|
def test_multiple(env, project, make_repo, users, setreviewers, config):
|
|
|
|
""" Test that overriding multiple statuses in the same comment works
|
|
|
|
"""
|
|
|
|
|
|
|
|
repo = make_repo('repo')
|
|
|
|
repo_id = env['runbot_merge.repository'].create({
|
|
|
|
'project_id': project.id,
|
|
|
|
'name': repo.name,
|
|
|
|
'status_ids': [(0, 0, {'context': 'l/int'}), (0, 0, {'context': 'c/i'})]
|
|
|
|
})
|
|
|
|
setreviewers(*project.repo_ids)
|
[ADD] *: per-repository webhook secret
Currently webhook secrets are configured per *project* which is an
issue both because different repositories may have different
administrators and thus creates safety concerns, and because multiple
repositories can feed into different projects (e.g. on mergebot,
odoo-dev/odoo is both an ancillary repository to the main RD project,
and the main repository to the minor / legacy master-wowl
project). This means it can be necessary to have multiple projects
share the same secret as well, this then mandates the secret for more
repositories per (1).
This is a pain in the ass, so just detach secrets from projects and
link them *only* to repositories, it's cleaner and easier to manage
and set up progressively.
This requires a lot of changes to the tests, as they all need to
correctly configure the signaling.
For `runbot_merge` there was *some* setup sharing already via the
module-level `repo` fixtures`, those were merged into a conftest-level
fixture which could handle the signaling setup. A few tests which
unnecessarily set up repositories ad-hoc were also moved to the
fixture. But for most of the ad-hoc setup in `runbot_merge`, as well
as `forwardport` where it's all ad-hoc, events sources setup was just
appended as is. This should probably be cleaned up at one point, with
the various requirements collected and organised into a small set of
fixtures doing the job more uniformly.
Fixes #887
2024-06-06 16:07:57 +07:00
|
|
|
env['runbot_merge.events_sources'].create({'repository': repo.name})
|
2021-01-12 15:25:53 +07:00
|
|
|
# "other" can override the lints
|
|
|
|
env['res.partner'].create({
|
|
|
|
'name': config['role_other'].get('name', 'Other'),
|
|
|
|
'github_login': users['other'],
|
|
|
|
'override_rights': [(0, 0, {
|
|
|
|
'repository_id': repo_id.id,
|
|
|
|
'context': 'l/int',
|
|
|
|
}), (0, 0, {
|
|
|
|
'repository_id': repo_id.id,
|
|
|
|
'context': 'c/i',
|
|
|
|
})]
|
|
|
|
})
|
|
|
|
|
|
|
|
with repo:
|
|
|
|
root = repo.make_commits(None, Commit('root', tree={'a': '0'}), ref='heads/master')
|
|
|
|
for i, comment in enumerate([
|
|
|
|
# style 1: multiple commands inline
|
|
|
|
'hansen override=l/int override=c/i',
|
|
|
|
# style 2: multiple parameters to command
|
|
|
|
'hansen override=l/int,c/i',
|
|
|
|
# style 3: multiple commands each on its own line
|
|
|
|
'hansen override=l/int\nhansen override=c/i',
|
|
|
|
], start=1):
|
|
|
|
with repo:
|
|
|
|
repo.make_commits(root, Commit(f'pr{i}', tree={'a': f'{i}'}), ref=f'heads/change{i}')
|
|
|
|
pr = repo.make_pr(target='master', title=f'super change {i}', head=f'change{i}')
|
|
|
|
env.run_crons()
|
|
|
|
|
2024-12-02 20:17:28 +07:00
|
|
|
pr_id = to_pr(env, pr)
|
2021-01-12 15:25:53 +07:00
|
|
|
assert pr_id.state == 'opened'
|
|
|
|
|
|
|
|
with repo:
|
|
|
|
pr.post_comment(comment, config['role_other']['token'])
|
|
|
|
env.run_crons()
|
|
|
|
assert pr_id.state == 'validated'
|
|
|
|
|
|
|
|
comments = pr.comments
|
|
|
|
assert pr_id.statuses == '{}'
|
|
|
|
assert json.loads(pr_id.overrides) == {
|
|
|
|
'l/int': {
|
|
|
|
'state': 'success',
|
|
|
|
'target_url': comments[-1]['html_url'],
|
|
|
|
'description': 'Overridden by @{}'.format(users['other']),
|
|
|
|
},
|
|
|
|
'c/i': {
|
|
|
|
'state': 'success',
|
|
|
|
'target_url': comments[-1]['html_url'],
|
|
|
|
'description': 'Overridden by @{}'.format(users['other']),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-11-12 19:17:37 +07:00
|
|
|
def test_no_repository(env, project, make_repo, users, setreviewers, config):
|
|
|
|
""" A repo missing from an override allows overriding the status in every repo
|
|
|
|
"""
|
|
|
|
repo = make_repo('repo')
|
|
|
|
env['runbot_merge.repository'].create({
|
|
|
|
'project_id': project.id,
|
|
|
|
'name': repo.name,
|
|
|
|
'status_ids': [(0, 0, {'context': 'l/int'})]
|
|
|
|
})
|
|
|
|
setreviewers(*project.repo_ids)
|
[ADD] *: per-repository webhook secret
Currently webhook secrets are configured per *project* which is an
issue both because different repositories may have different
administrators and thus creates safety concerns, and because multiple
repositories can feed into different projects (e.g. on mergebot,
odoo-dev/odoo is both an ancillary repository to the main RD project,
and the main repository to the minor / legacy master-wowl
project). This means it can be necessary to have multiple projects
share the same secret as well, this then mandates the secret for more
repositories per (1).
This is a pain in the ass, so just detach secrets from projects and
link them *only* to repositories, it's cleaner and easier to manage
and set up progressively.
This requires a lot of changes to the tests, as they all need to
correctly configure the signaling.
For `runbot_merge` there was *some* setup sharing already via the
module-level `repo` fixtures`, those were merged into a conftest-level
fixture which could handle the signaling setup. A few tests which
unnecessarily set up repositories ad-hoc were also moved to the
fixture. But for most of the ad-hoc setup in `runbot_merge`, as well
as `forwardport` where it's all ad-hoc, events sources setup was just
appended as is. This should probably be cleaned up at one point, with
the various requirements collected and organised into a small set of
fixtures doing the job more uniformly.
Fixes #887
2024-06-06 16:07:57 +07:00
|
|
|
env['runbot_merge.events_sources'].create({'repository': repo.name})
|
2020-11-12 19:17:37 +07:00
|
|
|
# "other" can override the lint
|
|
|
|
env['res.partner'].create({
|
|
|
|
'name': config['role_other'].get('name', 'Other'),
|
|
|
|
'github_login': users['other'],
|
|
|
|
'override_rights': [(0, 0, {'context': 'l/int'})]
|
|
|
|
})
|
|
|
|
|
|
|
|
with repo:
|
|
|
|
m = repo.make_commits(None, Commit('root', tree={'a': '1'}), ref='heads/master')
|
|
|
|
|
|
|
|
repo.make_commits(m, Commit('pr', tree={'a': '2'}), ref='heads/change')
|
|
|
|
pr = repo.make_pr(target='master', title='super change', head='change')
|
|
|
|
pr.post_comment('hansen r+', config['role_reviewer']['token'])
|
|
|
|
env.run_crons()
|
|
|
|
|
2024-12-02 20:17:28 +07:00
|
|
|
pr_id = to_pr(env, pr)
|
2020-11-12 19:17:37 +07:00
|
|
|
assert pr_id.state == 'approved'
|
|
|
|
|
|
|
|
with repo:
|
|
|
|
pr.post_comment('hansen override=l/int', config['role_other']['token'])
|
|
|
|
env.run_crons()
|
|
|
|
assert pr_id.state == 'ready'
|
|
|
|
|
|
|
|
comments = pr.comments
|
|
|
|
assert comments == [
|
|
|
|
(users['reviewer'], 'hansen r+'),
|
2020-11-17 21:21:21 +07:00
|
|
|
seen(env, pr, users),
|
2020-11-12 19:17:37 +07:00
|
|
|
(users['other'], "hansen override=l/int"),
|
|
|
|
]
|
|
|
|
assert pr_id.statuses == '{}'
|
|
|
|
assert json.loads(pr_id.overrides) == {'l/int': {
|
|
|
|
'state': 'success',
|
|
|
|
'target_url': comments[-1]['html_url'],
|
|
|
|
'description': 'Overridden by @{}'.format(users['other']),
|
|
|
|
}}
|