diff --git a/docs/gl_objects/projects.rst b/docs/gl_objects/projects.rst index 7935bf90b..77b32babe 100644 --- a/docs/gl_objects/projects.rst +++ b/docs/gl_objects/projects.rst @@ -412,10 +412,6 @@ Create a tag:: tag = project.tags.create({'tag_name': '1.0', 'ref': 'master'}) -Set or update the release note for a tag:: - - tag.set_release_description('awesome v1.0 release') - Delete a tag:: project.tags.delete('1.0') diff --git a/docs/gl_objects/releases.rst b/docs/gl_objects/releases.rst index 38138570c..6077fe922 100644 --- a/docs/gl_objects/releases.rst +++ b/docs/gl_objects/releases.rst @@ -27,6 +27,12 @@ Get a single release:: release = project.releases.get('v1.2.3') +Edit a release:: + + release.name = "Demo Release" + release.description = "release notes go here" + release.save() + Create a release for a project tag:: release = project.releases.create({'name':'Demo Release', 'tag_name':'v1.2.3', 'description':'release notes go here'}) diff --git a/gitlab/v4/objects/releases.py b/gitlab/v4/objects/releases.py index ab490dd9f..6216e4573 100644 --- a/gitlab/v4/objects/releases.py +++ b/gitlab/v4/objects/releases.py @@ -1,5 +1,5 @@ from gitlab.base import RequiredOptional, RESTManager, RESTObject -from gitlab.mixins import CRUDMixin, NoUpdateMixin, ObjectDeleteMixin, SaveMixin +from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin __all__ = [ "ProjectRelease", @@ -9,18 +9,21 @@ ] -class ProjectRelease(RESTObject): +class ProjectRelease(SaveMixin, RESTObject): _id_attr = "tag_name" _managers = (("links", "ProjectReleaseLinkManager"),) -class ProjectReleaseManager(NoUpdateMixin, RESTManager): +class ProjectReleaseManager(CRUDMixin, RESTManager): _path = "/projects/%(project_id)s/releases" _obj_cls = ProjectRelease _from_parent_attrs = {"project_id": "id"} _create_attrs = RequiredOptional( required=("name", "tag_name", "description"), optional=("ref", "assets") ) + _update_attrs = RequiredOptional( + optional=("name", "description", "milestones", "released_at") + ) class ProjectReleaseLink(ObjectDeleteMixin, SaveMixin, RESTObject): diff --git a/tests/functional/api/test_releases.py b/tests/functional/api/test_releases.py index f49181aff..81ae7def6 100644 --- a/tests/functional/api/test_releases.py +++ b/tests/functional/api/test_releases.py @@ -23,6 +23,15 @@ def test_create_project_release(project, project_file): assert release.description == release_description +def test_update_save_project_release(project, release): + updated_description = f"{release.description} updated" + release.description = updated_description + release.save() + + release = project.releases.get(release.tag_name) + assert release.description == updated_description + + def test_delete_project_release(project, release): project.releases.delete(release.tag_name) assert release not in project.releases.list() diff --git a/tests/unit/objects/test_releases.py b/tests/unit/objects/test_releases.py index 6c38a7c48..58ab5d07b 100644 --- a/tests/unit/objects/test_releases.py +++ b/tests/unit/objects/test_releases.py @@ -10,7 +10,11 @@ from gitlab.v4.objects import ProjectReleaseLink +tag_name = "v1.0.0" encoded_tag_name = "v1%2E0%2E0" +release_name = "demo-release" +release_description = "my-rel-desc" +released_at = "2019-03-15T08:00:00Z" 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" @@ -24,6 +28,18 @@ "link_type": "other", } +release_content = { + "id": 3, + "tag_name": tag_name, + "name": release_name, + "description": release_description, + "milestones": [], + "released_at": released_at, +} + +release_url = re.compile( + rf"http://localhost/api/v4/projects/1/releases/{encoded_tag_name}" +) links_url = re.compile( rf"http://localhost/api/v4/projects/1/releases/{encoded_tag_name}/assets/links" ) @@ -100,6 +116,21 @@ def resp_delete_link(no_content): yield rsps +@pytest.fixture +def resp_update_release(): + updated_content = dict(release_content) + + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.PUT, + url=release_url, + json=updated_content, + content_type="application/json", + status=200, + ) + yield rsps + + def test_list_release_links(release, resp_list_links): links = release.links.list() assert isinstance(links, list) @@ -129,3 +160,11 @@ def test_update_release_link(release, resp_update_link): def test_delete_release_link(release, resp_delete_link): link = release.links.get(1, lazy=True) link.delete() + + +def test_update_release(release, resp_update_release): + release.name = release_name + release.description = release_description + release.save() + assert release.name == release_name + assert release.description == release_description
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: