summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNejc Habjan <hab.nejc@gmail.com>2021-02-21 12:01:33 +0100
committerNejc Habjan <hab.nejc@gmail.com>2021-02-21 12:01:33 +0100
commit28d751811ffda45ff0b1c35e0599b655f3a5a68b (patch)
tree62d6990b1037fdc94be07469e84926b2a204171d
parent649385cc03065d023d74399237331d1ea64f766f (diff)
downloadgitlab-28d751811ffda45ff0b1c35e0599b655f3a5a68b.tar.gz
feat(objects): add Release Links API support
-rw-r--r--gitlab/tests/conftest.py10
-rw-r--r--gitlab/tests/objects/test_releases.py131
-rw-r--r--gitlab/v4/objects/__init__.py1
-rw-r--r--gitlab/v4/objects/projects.py3
-rw-r--r--gitlab/v4/objects/releases.py36
-rw-r--r--gitlab/v4/objects/tags.py13
6 files changed, 180 insertions, 14 deletions
diff --git a/gitlab/tests/conftest.py b/gitlab/tests/conftest.py
index 98d97ae..fc8312f 100644
--- a/gitlab/tests/conftest.py
+++ b/gitlab/tests/conftest.py
@@ -38,6 +38,11 @@ def default_config(tmpdir):
@pytest.fixture
+def tag_name():
+ return "v1.0.0"
+
+
+@pytest.fixture
def group(gl):
return gl.groups.get(1, lazy=True)
@@ -48,5 +53,10 @@ def project(gl):
@pytest.fixture
+def release(project, tag_name):
+ return project.releases.get(tag_name, lazy=True)
+
+
+@pytest.fixture
def user(gl):
return gl.users.get(1, lazy=True)
diff --git a/gitlab/tests/objects/test_releases.py b/gitlab/tests/objects/test_releases.py
new file mode 100644
index 0000000..6c38a7c
--- /dev/null
+++ b/gitlab/tests/objects/test_releases.py
@@ -0,0 +1,131 @@
+"""
+GitLab API:
+https://docs.gitlab.com/ee/api/releases/index.html
+https://docs.gitlab.com/ee/api/releases/links.html
+"""
+import re
+
+import pytest
+import responses
+
+from gitlab.v4.objects import ProjectReleaseLink
+
+encoded_tag_name = "v1%2E0%2E0"
+link_name = "hello-world"
+link_url = "https://gitlab.example.com/group/hello/-/jobs/688/artifacts/raw/bin/hello-darwin-amd64"
+direct_url = f"https://gitlab.example.com/group/hello/-/releases/{encoded_tag_name}/downloads/hello-world"
+new_link_type = "package"
+link_content = {
+ "id": 2,
+ "name": link_name,
+ "url": link_url,
+ "direct_asset_url": direct_url,
+ "external": False,
+ "link_type": "other",
+}
+
+links_url = re.compile(
+ rf"http://localhost/api/v4/projects/1/releases/{encoded_tag_name}/assets/links"
+)
+link_id_url = re.compile(
+ rf"http://localhost/api/v4/projects/1/releases/{encoded_tag_name}/assets/links/1"
+)
+
+
+@pytest.fixture
+def resp_list_links():
+ with responses.RequestsMock() as rsps:
+ rsps.add(
+ method=responses.GET,
+ url=links_url,
+ json=[link_content],
+ content_type="application/json",
+ status=200,
+ )
+ yield rsps
+
+
+@pytest.fixture
+def resp_get_link():
+ with responses.RequestsMock() as rsps:
+ rsps.add(
+ method=responses.GET,
+ url=link_id_url,
+ json=link_content,
+ content_type="application/json",
+ status=200,
+ )
+ yield rsps
+
+
+@pytest.fixture
+def resp_create_link():
+ with responses.RequestsMock() as rsps:
+ rsps.add(
+ method=responses.POST,
+ url=links_url,
+ json=link_content,
+ content_type="application/json",
+ status=200,
+ )
+ yield rsps
+
+
+@pytest.fixture
+def resp_update_link():
+ updated_content = dict(link_content)
+ updated_content["link_type"] = new_link_type
+
+ with responses.RequestsMock() as rsps:
+ rsps.add(
+ method=responses.PUT,
+ url=link_id_url,
+ json=updated_content,
+ content_type="application/json",
+ status=200,
+ )
+ yield rsps
+
+
+@pytest.fixture
+def resp_delete_link(no_content):
+ with responses.RequestsMock() as rsps:
+ rsps.add(
+ method=responses.DELETE,
+ url=link_id_url,
+ json=link_content,
+ content_type="application/json",
+ status=204,
+ )
+ yield rsps
+
+
+def test_list_release_links(release, resp_list_links):
+ links = release.links.list()
+ assert isinstance(links, list)
+ assert isinstance(links[0], ProjectReleaseLink)
+ assert links[0].url == link_url
+
+
+def test_get_release_link(release, resp_get_link):
+ link = release.links.get(1)
+ assert isinstance(link, ProjectReleaseLink)
+ assert link.url == link_url
+
+
+def test_create_release_link(release, resp_create_link):
+ link = release.links.create({"url": link_url, "name": link_name})
+ assert isinstance(link, ProjectReleaseLink)
+ assert link.url == link_url
+
+
+def test_update_release_link(release, resp_update_link):
+ link = release.links.get(1, lazy=True)
+ link.link_type = new_link_type
+ link.save()
+ assert link.link_type == new_link_type
+
+
+def test_delete_release_link(release, resp_delete_link):
+ link = release.links.get(1, lazy=True)
+ link.delete()
diff --git a/gitlab/v4/objects/__init__.py b/gitlab/v4/objects/__init__.py
index 9f91f53..8a2ed7c 100644
--- a/gitlab/v4/objects/__init__.py
+++ b/gitlab/v4/objects/__init__.py
@@ -56,6 +56,7 @@ from .pages import *
from .pipelines import *
from .projects import *
from .push_rules import *
+from .releases import *
from .runners import *
from .services import *
from .settings import *
diff --git a/gitlab/v4/objects/projects.py b/gitlab/v4/objects/projects.py
index 722b9ea..b354af9 100644
--- a/gitlab/v4/objects/projects.py
+++ b/gitlab/v4/objects/projects.py
@@ -33,6 +33,7 @@ from .packages import ProjectPackageManager
from .pages import ProjectPagesDomainManager
from .pipelines import ProjectPipelineManager, ProjectPipelineScheduleManager
from .push_rules import ProjectPushRulesManager
+from .releases import ProjectReleaseManager
from .runners import ProjectRunnerManager
from .services import ProjectServiceManager
from .snippets import ProjectSnippetManager
@@ -40,7 +41,7 @@ from .statistics import (
ProjectAdditionalStatisticsManager,
ProjectIssuesStatisticsManager,
)
-from .tags import ProjectProtectedTagManager, ProjectReleaseManager, ProjectTagManager
+from .tags import ProjectProtectedTagManager, ProjectTagManager
from .triggers import ProjectTriggerManager
from .users import ProjectUserManager
from .variables import ProjectVariableManager
diff --git a/gitlab/v4/objects/releases.py b/gitlab/v4/objects/releases.py
new file mode 100644
index 0000000..d9112e4
--- /dev/null
+++ b/gitlab/v4/objects/releases.py
@@ -0,0 +1,36 @@
+from gitlab import cli
+from gitlab import exceptions as exc
+from gitlab.base import * # noqa
+from gitlab.mixins import * # noqa
+
+
+__all__ = [
+ "ProjectRelease",
+ "ProjectReleaseManager",
+ "ProjectReleaseLink",
+ "ProjectReleaseLinkManager",
+]
+
+
+class ProjectRelease(RESTObject):
+ _id_attr = "tag_name"
+ _managers = (("links", "ProjectReleaseLinkManager"),)
+
+
+class ProjectReleaseManager(NoUpdateMixin, RESTManager):
+ _path = "/projects/%(project_id)s/releases"
+ _obj_cls = ProjectRelease
+ _from_parent_attrs = {"project_id": "id"}
+ _create_attrs = (("name", "tag_name", "description"), ("ref", "assets"))
+
+
+class ProjectReleaseLink(RESTObject, ObjectDeleteMixin, SaveMixin):
+ pass
+
+
+class ProjectReleaseLinkManager(CRUDMixin, RESTManager):
+ _path = "/projects/%(project_id)s/releases/%(tag_name)s/assets/links"
+ _obj_cls = ProjectReleaseLink
+ _from_parent_attrs = {"project_id": "project_id", "tag_name": "tag_name"}
+ _create_attrs = (("name", "url"), ("filepath", "link_type"))
+ _update_attrs = ((), ("name", "url", "filepath", "link_type"))
diff --git a/gitlab/v4/objects/tags.py b/gitlab/v4/objects/tags.py
index c4d60db..1f333c5 100644
--- a/gitlab/v4/objects/tags.py
+++ b/gitlab/v4/objects/tags.py
@@ -9,8 +9,6 @@ __all__ = [
"ProjectTagManager",
"ProjectProtectedTag",
"ProjectProtectedTagManager",
- "ProjectRelease",
- "ProjectReleaseManager",
]
@@ -71,14 +69,3 @@ class ProjectProtectedTagManager(NoUpdateMixin, RESTManager):
_obj_cls = ProjectProtectedTag
_from_parent_attrs = {"project_id": "id"}
_create_attrs = (("name",), ("create_access_level",))
-
-
-class ProjectRelease(RESTObject):
- _id_attr = "tag_name"
-
-
-class ProjectReleaseManager(NoUpdateMixin, RESTManager):
- _path = "/projects/%(project_id)s/releases"
- _obj_cls = ProjectRelease
- _from_parent_attrs = {"project_id": "id"}
- _create_attrs = (("name", "tag_name", "description"), ("ref", "assets"))