Read about our upcoming Code of Conduct on this issue

Commit 7239e5cd authored by Georges Racinet's avatar Georges Racinet 🦑
Browse files

Merged tests about protected branches from stable branch

The stable branch is still for Heptapod 0.16, but there
probably won't be any release on it, now.
Pipeline #13283 passed with stage
in 26 minutes and 12 seconds
import json
from urllib.parse import parse_qs
import pytest
import re
import requests
from .utils import needs
from .utils.reverse_calls import HttpListener
from .utils.hg import LocalRepo
from .utils.project import (
extract_gitlab_branch_titles,
ProjectAccess,
)
from .utils.runner import Runner
......@@ -216,6 +219,167 @@ def test_push_corrupted(test_project, tmpdir):
repo.hg('push', test_project.owner_basic_auth_url)
def test_protected_branch_refusal(test_project, tmpdir):
"""Refusals due to branch protection are explained to the end user."""
repo_path = tmpdir.join('repo1')
url = test_project.owner_basic_auth_url
repo = LocalRepo.init(repo_path)
# let's have two branches
repo_path.join('foo').write('foo0')
repo.hg('commit', '-Am', "Commit 0")
repo_path.join('foo').write('foo1')
repo.hg('commit', '-Am', "Commit 1")
repo.hg('push', url) # make sure 'default' is the GitLab default branch
repo.hg('up', '0')
repo.hg('branch', 'a_branch')
repo_path.join('foo').write('in branch')
repo.hg('commit', '-Am', "Commit in branch")
repo.hg('phase', '-pr', "default+a_branch")
print(repo.graphlog())
repo.hg('push', '--new-branch', url)
# now let's protect the branch
resp = test_project.owner_api_post(subpath='protected_branches',
data=dict(name='branch/a_branch'))
assert resp.status_code in (200, 201, 202)
# Later on, we'll have a 'publisher' role. Meanwhile, let's
# avoid the check_publish hook to prevent developer pushing.
test_project.owner_api_hgrc_set(inherit=True, auto_publish='nothing')
test_project.grant_member_access(user_name='test_basic',
level=ProjectAccess.DEVELOPER)
basic_user_url = test_project.basic_auth_url(user_name='test_basic')
basic_user_ssh_params = test_project.ssh_params('test_basic')
repo_path.join('foo').write('still in branch')
repo.hg('commit', '-m', 'New commit that only maintainer can push')
code, out, err = repo.hg_unchecked('push', '--ssh', *basic_user_ssh_params)
assert code != 0
assert re.search("push.*protected branches", out)
code, out, err = repo.hg_unchecked('push', basic_user_url)
assert code != 0
assert re.search("push.*protected branches", out)
# it is also forbidden to remove protected branches
repo.hg('commit', '--close-branch', '-m', "closing")
code, out, err = repo.hg_unchecked('push', basic_user_url)
assert code != 0
# let's not depend too much on exact message wording
assert "delete protected branches" in out
# the failed pushes had indeed no effect on the hg repo
clone = LocalRepo.clone(url, tmpdir.join('repo2'))
log = clone.hg('log', '-T', '{desc}:{branch}\n').splitlines()
assert set(l.strip() for l in log) == {
'Commit 0:default',
'Commit 1:default',
'Commit in branch:a_branch',
}
def test_protected_branch_ultimate(test_project, tmpdir):
"""Mode in which even maintainers can't push."""
repo_path = tmpdir.join('repo1')
url = test_project.owner_basic_auth_url
repo = LocalRepo.init(repo_path)
# let's have two branches
repo_path.join('foo').write('foo0')
repo.hg('commit', '-Am', "Commit 0")
repo_path.join('foo').write('foo1')
repo.hg('commit', '-Am', "Commit 1")
repo.hg('push', url) # make sure 'default' is the GitLab default branch
repo.hg('up', '0')
repo.hg('branch', 'a_branch')
repo_path.join('foo').write('in branch')
repo.hg('commit', '-Am', "Commit in branch")
repo.hg('phase', '-pr', "default+a_branch")
print(repo.graphlog())
repo.hg('push', '--new-branch', url)
resp = test_project.owner_api_post(subpath='protected_branches',
data=dict(name='branch/a_branch',
push_access_level=0))
assert resp.status_code in (200, 201, 202)
repo_path.join('foo').write('still in branch')
repo.hg('commit', '-m', 'New commit that even Owner cannot push')
ssh_params = test_project.owner_ssh_params
code, out, err = repo.hg_unchecked('push', '--ssh', *ssh_params)
assert code != 0
assert re.search("push.*protected branches", out)
code, out, err = repo.hg_unchecked('push', url)
assert code != 0
assert re.search("push.*protected branches", out)
# regular owner is also instance-wide administrator, and should
# arguably still be allowed to remove the branch, let's make a Maintainer
test_project.grant_member_access(user_name='test_basic',
level=ProjectAccess.MAINTAINER)
maintainer_url = test_project.basic_auth_url(user_name='test_basic')
repo.hg('commit', '--close-branch', '-m', "closing")
code, out, err = repo.hg_unchecked('push', maintainer_url)
assert code != 0
# let's not depend too much on exact message wording
assert "delete protected branches" in out
# the failed pushes had indeed no effect on the hg repo
clone = LocalRepo.clone(url, tmpdir.join('repo2'))
log = clone.hg('log', '-T', '{desc}:{branch}\n').splitlines()
assert set(l.strip() for l in log) == {
'Commit 0:default',
'Commit 1:default',
'Commit in branch:a_branch',
}
# far from being completely blocked the newly appointed Maintainer
# can still accept MRs
repo.hg('topic', '-r', '.~1', 'zetop')
repo.hg('push', '-r', 'zetop', maintainer_url)
mr_id = test_project.api_create_merge_request(
source='topic/a_branch/zetop',
target='branch/a_branch',
)
# TODO looks like it's really time to put this kind of MR handling
# down to the project level or on a separate MergeRequest object
test_project.wait_assert_merge_request(
mr_id, lambda mr: mr.get('merge_status') == 'can_be_merged',
msg="Mergeability wrong or still unknown")
# we have nicer helpers for API requests from other users than owner
# in the default branch but can't use them right away (stable branch)
headers = {
'Private-Token': test_project.heptapod.get_user('test_basic').token,
}
resp = requests.put('%s/merge_requests/%d/merge' % (test_project.api_url,
mr_id),
headers=headers,
data=dict(merge_request_iid=mr_id,
id=test_project.id))
assert resp.status_code < 300
assert resp.json()['state'] == 'merged'
clone.hg('pull')
log = clone.hg('log', '-T', '{desc}:{branch}:{phase}\n').splitlines()
assert set(l.strip() for l in log) == {
'Commit 0:default:public',
'Commit 1:default:public',
'Commit in branch:a_branch:public',
'New commit that even Owner cannot push:a_branch:public',
}
@needs.docker
def test_push_corrupted_2(test_project, tmpdir):
"""If Git repo has more commits in a topic (issue heptapod#119)."""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment