import uuid
import pytest
import gitlab
from gitlab.const import AccessLevel
from gitlab.v4.objects.projects import ProjectStorage
def test_projects_head(gl):
headers = gl.projects.head()
assert headers["x-total"]
def test_project_head(gl, project):
headers = gl.projects.head(project.id)
assert headers["content-type"] == "application/json"
def test_create_project(gl, user):
# Moved from group tests chunk in legacy tests, TODO cleanup
admin_project = gl.projects.create({"name": "admin_project"})
assert isinstance(admin_project, gitlab.v4.objects.Project)
assert admin_project in gl.projects.list(search="admin_project")
sudo_project = gl.projects.create({"name": "sudo_project"}, sudo=user.id)
created = gl.projects.list()
created_gen = gl.projects.list(iterator=True)
owned = gl.projects.list(owned=True)
assert admin_project in created and sudo_project in created
assert admin_project in owned and sudo_project not in owned
assert len(created) == len(list(created_gen))
admin_project.delete()
sudo_project.delete()
def test_project_members(user, project):
member = project.members.create(
{"user_id": user.id, "access_level": AccessLevel.DEVELOPER}
)
assert member in project.members.list()
assert member.access_level == 30
member.delete()
assert member not in project.members.list()
def test_project_badges(project):
badge_image = "http://example.com"
badge_link = "http://example/img.svg"
badge = project.badges.create({"link_url": badge_link, "image_url": badge_image})
assert badge in project.badges.list()
badge.image_url = "http://another.example.com"
badge.save()
badge = project.badges.get(badge.id)
assert badge.image_url == "http://another.example.com"
badge.delete()
assert badge not in project.badges.list()
@pytest.mark.skip(reason="Commented out in legacy test")
def test_project_boards(project):
boards = project.boards.list()
assert boards
board = boards[0]
lists = board.lists.list()
last_list = lists[-1]
last_list.position = 0
last_list.save()
last_list.delete()
assert last_list not in board.lists.list()
def test_project_custom_attributes(gl, project):
attrs = project.customattributes.list()
assert not attrs
attr = project.customattributes.set("key", "value1")
assert attr.key == "key"
assert attr.value == "value1"
assert attr in project.customattributes.list()
assert project in gl.projects.list(custom_attributes={"key": "value1"})
attr = project.customattributes.set("key", "value2")
attr = project.customattributes.get("key")
assert attr.value == "value2"
assert attr in project.customattributes.list()
attr.delete()
assert attr not in project.customattributes.list()
def test_project_environments(project):
environment = project.environments.create(
{"name": "env1", "external_url": "http://fake.env/whatever"}
)
environments = project.environments.list()
assert environment in environments
environment = environments[0]
environment.external_url = "http://new.env/whatever"
environment.save()
environment = project.environments.list()[0]
assert environment.external_url == "http://new.env/whatever"
environment.stop()
environment.delete()
assert environment not in project.environments.list()
def test_project_events(project):
events = project.events.list()
assert isinstance(events, list)
def test_project_file_uploads(project):
filename = "test.txt"
file_contents = "testing contents"
uploaded_file = project.upload(filename, file_contents)
alt, url = uploaded_file["alt"], uploaded_file["url"]
assert alt == filename
assert url.startswith("/uploads/")
assert url.endswith(f"/{filename}")
assert uploaded_file["markdown"] == f"[{alt}]({url})"
def test_project_forks(gl, project, user):
fork = project.forks.create({"namespace": user.username})
fork_project = gl.projects.get(fork.id)
assert fork_project.forked_from_project["id"] == project.id
forks = project.forks.list()
assert fork.id in map(lambda fork_project: fork_project.id, forks)
def test_project_hooks(project):
hook = project.hooks.create({"url": "http://hook.url"})
assert hook in project.hooks.list()
hook.note_events = True
hook.save()
hook = project.hooks.get(hook.id)
assert hook.note_events is True
hook.delete()
assert hook not in project.hooks.list()
def test_project_housekeeping(project):
project.housekeeping()
def test_project_labels(project):
label = project.labels.create({"name": "label", "color": "#778899"})
labels = project.labels.list()
assert label in labels
label = project.labels.get("label")
assert label == labels[0]
label.new_name = "Label:that requires:encoding"
label.save()
assert label.name == "Label:that requires:encoding"
label = project.labels.get("Label:that requires:encoding")
assert label.name == "Label:that requires:encoding"
label.subscribe()
assert label.subscribed is True
label.unsubscribe()
assert label.subscribed is False
label.delete()
assert label not in project.labels.list()
def test_project_label_promotion(gl, group):
"""
Label promotion requires the project to be a child of a group (not in a user namespace)
"""
_id = uuid.uuid4().hex
data = {
"name": f"test-project-{_id}",
"namespace_id": group.id,
}
project = gl.projects.create(data)
label_name = "promoteme"
promoted_label = project.labels.create({"name": label_name, "color": "#112233"})
promoted_label.promote()
assert any(label.name == label_name for label in group.labels.list())
group.labels.delete(label_name)
assert not any(label.name == label_name for label in group.labels.list())
def test_project_milestones(project):
milestone = project.milestones.create({"title": "milestone1"})
assert milestone in project.milestones.list()
milestone.due_date = "2020-01-01T00:00:00Z"
milestone.save()
milestone.state_event = "close"
milestone.save()
milestone = project.milestones.get(milestone.id)
assert milestone.state == "closed"
assert not milestone.issues()
assert not milestone.merge_requests()
def test_project_milestone_promotion(gl, group):
"""
Milestone promotion requires the project to be a child of a group (not in a user namespace)
"""
_id = uuid.uuid4().hex
data = {
"name": f"test-project-{_id}",
"namespace_id": group.id,
}
project = gl.projects.create(data)
milestone_title = "promoteme"
promoted_milestone = project.milestones.create({"title": milestone_title})
promoted_milestone.promote()
assert any(
milestone.title == milestone_title for milestone in group.milestones.list()
)
def test_project_pages_domains(gl, project):
domain = project.pagesdomains.create({"domain": "foo.domain.com"})
assert domain in project.pagesdomains.list()
assert domain in gl.pagesdomains.list()
domain = project.pagesdomains.get("foo.domain.com")
assert domain.domain == "foo.domain.com"
domain.delete()
assert domain not in project.pagesdomains.list()
def test_project_protected_branches(project):
p_b = project.protectedbranches.create({"name": "*-stable"})
assert p_b.name == "*-stable"
assert p_b in project.protectedbranches.list()
p_b = project.protectedbranches.get("*-stable")
p_b.delete()
assert p_b not in project.protectedbranches.list()
def test_project_remote_mirrors(project):
mirror_url = "https://gitlab.example.com/root/mirror.git"
mirror = project.remote_mirrors.create({"url": mirror_url})
assert mirror.url == mirror_url
mirror.enabled = True
mirror.save()
mirror = project.remote_mirrors.list()[0]
assert isinstance(mirror, gitlab.v4.objects.ProjectRemoteMirror)
assert mirror.url == mirror_url
assert mirror.enabled is True
def test_project_services(project):
# Use 'update' to create a service as we don't have a 'create' method and
# to add one is somewhat complicated so it hasn't been done yet.
project.services.update("asana", api_key="foo")
service = project.services.get("asana")
assert service.active is True
service.api_key = "whatever"
service.save()
service = project.services.get("asana")
assert service.active is True
service.delete()
service = project.services.get("asana")
assert service.active is False
def test_project_stars(project):
project.star()
assert project.star_count == 1
project.unstar()
assert project.star_count == 0
def test_project_storage(project):
storage = project.storage.get()
assert isinstance(storage, ProjectStorage)
assert storage.repository_storage == "default"
def test_project_tags(project, project_file):
tag = project.tags.create({"tag_name": "v1.0", "ref": "main"})
assert tag in project.tags.list()
tag.delete()
assert tag not in project.tags.list()
def test_project_triggers(project):
trigger = project.triggers.create({"description": "trigger1"})
assert trigger in project.triggers.list()
trigger.delete()
assert trigger not in project.triggers.list()
def test_project_wiki(project):
content = "Wiki page content"
wiki = project.wikis.create({"title": "wikipage", "content": content})
assert wiki in project.wikis.list()
wiki = project.wikis.get(wiki.slug)
assert wiki.content == content
# update and delete seem broken
wiki.content = "new content"
wiki.save()
wiki.delete()
assert wiki not in project.wikis.list()
def test_project_groups_list(gl, group):
"""Test listing groups of a project"""
# Create a subgroup of our top-group, we will place our new project inside
# this group.
group2 = gl.groups.create(
{"name": "group2_proj", "path": "group2_proj", "parent_id": group.id}
)
data = {
"name": "test-project-tpsg",
"namespace_id": group2.id,
}
project = gl.projects.create(data)
groups = project.groups.list()
group_ids = set([x.id for x in groups])
assert {group.id, group2.id} == group_ids
def test_project_transfer(gl, project, group):
assert project.namespace["path"] != group.full_path
project.transfer(group.id)
project = gl.projects.get(project.id)
assert project.namespace["path"] == group.full_path
gl.auth()
project.transfer(gl.user.username)
project = gl.projects.get(project.id)
assert project.namespace["path"] == gl.user.username