mirror of
https://github.com/odoo/runbot.git
synced 2025-03-19 17:35:45 +07:00

* Cherrypicking is handrolled because there seems to be no easy way to programmatically edit commit messages during the cherrypicking sequence: `-n` basically squashes all commits and `-e` invokes a subprocess. `-e` with `VISUAL=false` kinda sorta works (in that it interrupts the process before each commit), however there doesn't seem to be clean status codes so it's difficult to know if the cherrypick failed or if it's just waiting for a commit of this step. Instead, cherrypick commits individually then edit / rewrite their commit messages: * add a reference to the original commit * convert signed-off-by to something else as the original commit was signed off but not necessarily this one * Can't assign users when creating PRs: only repository collaborators or people who commented on the issue / PR (which we're in the process of creating) can be assigned. PR authors are as likely to be collaborators as not, and we can have non-collaborator reviewers. So pinging via a regular comment seems less fraught as a way to notify users.
144 lines
5.1 KiB
Python
144 lines
5.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
import sys
|
|
|
|
import pytest
|
|
import re
|
|
|
|
from utils import *
|
|
|
|
def make_basic(env, config, make_repo, *, fp_token, fp_remote):
|
|
""" Creates a basic repo with 3 forking branches
|
|
|
|
0 -- 1 -- 2 -- 3 -- 4 : a
|
|
|
|
|
`-- 11 -- 22 : b
|
|
|
|
|
`-- 111 : c
|
|
each branch just adds and modifies a file (resp. f, g and h) through the
|
|
contents sequence a b c d e
|
|
"""
|
|
Projects = env['runbot_merge.project']
|
|
project = Projects.search([('name', '=', 'myproject')])
|
|
if not project:
|
|
project = env['runbot_merge.project'].create({
|
|
'name': 'myproject',
|
|
'github_token': config['github']['token'],
|
|
'github_prefix': 'hansen',
|
|
'fp_github_token': fp_token and config['github']['token'],
|
|
'required_statuses': 'legal/cla,ci/runbot',
|
|
'branch_ids': [
|
|
(0, 0, {'name': 'a', 'fp_sequence': 2, 'fp_target': True}),
|
|
(0, 0, {'name': 'b', 'fp_sequence': 1, 'fp_target': True}),
|
|
(0, 0, {'name': 'c', 'fp_sequence': 0, 'fp_target': True}),
|
|
],
|
|
})
|
|
|
|
prod = make_repo('proj')
|
|
with prod:
|
|
a_0, a_1, a_2, a_3, a_4, = prod.make_commits(
|
|
None,
|
|
Commit("0", tree={'f': 'a'}),
|
|
Commit("1", tree={'f': 'b'}),
|
|
Commit("2", tree={'f': 'c'}),
|
|
Commit("3", tree={'f': 'd'}),
|
|
Commit("4", tree={'f': 'e'}),
|
|
ref='heads/a',
|
|
)
|
|
b_1, b_2 = prod.make_commits(
|
|
a_2,
|
|
Commit('11', tree={'g': 'a'}),
|
|
Commit('22', tree={'g': 'b'}),
|
|
ref='heads/b',
|
|
)
|
|
prod.make_commits(
|
|
b_1,
|
|
Commit('111', tree={'h': 'a'}),
|
|
ref='heads/c',
|
|
)
|
|
other = prod.fork()
|
|
project.write({
|
|
'repo_ids': [(0, 0, {
|
|
'name': prod.name,
|
|
'fp_remote_target': fp_remote and other.name,
|
|
})],
|
|
})
|
|
|
|
return project, prod, other
|
|
|
|
def test_no_token(env, config, make_repo):
|
|
""" if there's no token on the repo, nothing should break though should
|
|
log
|
|
"""
|
|
# create project configured with remotes on the repo but no token
|
|
proj, prod, _ = make_basic(env, config, make_repo, fp_token=False, fp_remote=True)
|
|
|
|
with prod:
|
|
prod.make_commits(
|
|
'a', Commit('c0', tree={'a': '0'}), ref='heads/abranch'
|
|
)
|
|
pr = prod.make_pr(target='a', head='abranch')
|
|
prod.post_status(pr.head, 'success', 'legal/cla')
|
|
prod.post_status(pr.head, 'success', 'ci/runbot')
|
|
pr.post_comment('hansen r+', config['role_reviewer']['token'])
|
|
|
|
env.run_crons()
|
|
with prod:
|
|
prod.post_status('staging.a', 'success', 'legal/cla')
|
|
prod.post_status('staging.a', 'success', 'ci/runbot')
|
|
|
|
# wanted to use capfd, however it's not compatible with the subprocess
|
|
# being created beforehand and server() depending on capfd() would remove
|
|
# all its output from the normal pytest capture (dumped on test failure)
|
|
#
|
|
# so I'd really have to hand-roll the entire thing by having server()
|
|
# pipe stdout/stderr to temp files, yield those temp files, and have the
|
|
# tests mess around with reading those files, and finally have the server
|
|
# dump the file contents back to the test runner's stdout/stderr on
|
|
# fixture teardown...
|
|
env.run_crons()
|
|
assert len(env['runbot_merge.pull_requests'].search([], order='number')) == 1,\
|
|
"should not have created forward port"
|
|
|
|
def test_remove_token(env, config, make_repo):
|
|
proj, prod, _ = make_basic(env, config, make_repo, fp_token=True, fp_remote=True)
|
|
proj.fp_github_token = False
|
|
|
|
with prod:
|
|
prod.make_commits(
|
|
'a', Commit('c0', tree={'a': '0'}), ref='heads/abranch'
|
|
)
|
|
pr = prod.make_pr(target='a', head='abranch')
|
|
prod.post_status(pr.head, 'success', 'legal/cla')
|
|
prod.post_status(pr.head, 'success', 'ci/runbot')
|
|
pr.post_comment('hansen r+', config['role_reviewer']['token'])
|
|
|
|
env.run_crons()
|
|
with prod:
|
|
prod.post_status('staging.a', 'success', 'legal/cla')
|
|
prod.post_status('staging.a', 'success', 'ci/runbot')
|
|
|
|
env.run_crons()
|
|
assert len(env['runbot_merge.pull_requests'].search([], order='number')) == 1,\
|
|
"should not have created forward port"
|
|
|
|
def test_no_target(env, config, make_repo):
|
|
proj, prod, _ = make_basic(env, config, make_repo, fp_token=True, fp_remote=False)
|
|
|
|
with prod:
|
|
prod.make_commits(
|
|
'a', Commit('c0', tree={'a': '0'}), ref='heads/abranch'
|
|
)
|
|
pr = prod.make_pr(target='a', head='abranch')
|
|
prod.post_status(pr.head, 'success', 'legal/cla')
|
|
prod.post_status(pr.head, 'success', 'ci/runbot')
|
|
pr.post_comment('hansen r+', config['role_reviewer']['token'])
|
|
|
|
env.run_crons()
|
|
with prod:
|
|
prod.post_status('staging.a', 'success', 'legal/cla')
|
|
prod.post_status('staging.a', 'success', 'ci/runbot')
|
|
|
|
env.run_crons()
|
|
assert len(env['runbot_merge.pull_requests'].search([], order='number')) == 1,\
|
|
"should not have created forward port"
|