From 824881d3ce565f0da2cb93e705f875c24556334e Mon Sep 17 00:00:00 2001 From: "John L. Villalovos" Date: Sun, 13 Jul 2025 23:27:01 -0700 Subject: [PATCH] feat: add sync method to force remote mirror updates Add ProjectRemoteMirror.sync() method to trigger immediate push mirror updates. Closes: #3223 --- docs/gl_objects/remote_mirrors.rst | 4 ++++ gitlab/v4/objects/projects.py | 15 ++++++++++++++- tests/unit/objects/test_remote_mirrors.py | 12 ++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/gl_objects/remote_mirrors.rst b/docs/gl_objects/remote_mirrors.rst index b4610117d..c672ca5bb 100644 --- a/docs/gl_objects/remote_mirrors.rst +++ b/docs/gl_objects/remote_mirrors.rst @@ -36,3 +36,7 @@ Update an existing remote mirror's attributes:: Delete an existing remote mirror:: mirror.delete() + +Force push mirror update:: + + mirror.sync() diff --git a/gitlab/v4/objects/projects.py b/gitlab/v4/objects/projects.py index b415a8b98..035b9b861 100644 --- a/gitlab/v4/objects/projects.py +++ b/gitlab/v4/objects/projects.py @@ -1233,7 +1233,20 @@ def create(self, data: dict[str, Any] | None = None, **kwargs: Any) -> ProjectFo class ProjectRemoteMirror(ObjectDeleteMixin, SaveMixin, RESTObject): - pass + @cli.register_custom_action(cls_names="ProjectRemoteMirror") + @exc.on_http_error(exc.GitlabCreateError) + def sync(self, **kwargs: Any) -> dict[str, Any] | requests.Response: + """Force push mirror update. + + Args: + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabCreateError: If the server cannot perform the request + """ + path = f"{self.manager.path}/{self.encoded_id}/sync" + return self.manager.gitlab.http_post(path, **kwargs) class ProjectRemoteMirrorManager( diff --git a/tests/unit/objects/test_remote_mirrors.py b/tests/unit/objects/test_remote_mirrors.py index f493032e8..be2aaaaba 100644 --- a/tests/unit/objects/test_remote_mirrors.py +++ b/tests/unit/objects/test_remote_mirrors.py @@ -54,6 +54,12 @@ def resp_remote_mirrors(): url="http://localhost/api/v4/projects/1/remote_mirrors/1", status=204, ) + + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/remote_mirrors/1/sync", + status=204, + ) yield rsps @@ -81,3 +87,9 @@ def test_update_project_remote_mirror(project, resp_remote_mirrors): def test_delete_project_remote_mirror(project, resp_remote_mirrors): mirror = project.remote_mirrors.create({"url": "https://example.com"}) mirror.delete() + + +def test_sync_project_remote_mirror(project, resp_remote_mirrors): + mirror = project.remote_mirrors.create({"url": "https://example.com"}) + response = mirror.sync() + assert response.status_code == 204