Skip to content

Commit 4cfaa2f

Browse files
committed
feat(api): add support for remote mirrors API (#1056)
1 parent c161852 commit 4cfaa2f

File tree

5 files changed

+159
-0
lines changed

5 files changed

+159
-0
lines changed

docs/api-objects.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ API examples
3737
gl_objects/projects
3838
gl_objects/protected_branches
3939
gl_objects/runners
40+
gl_objects/remote_mirrors
4041
gl_objects/repositories
4142
gl_objects/repository_tags
4243
gl_objects/search

docs/gl_objects/remote_mirrors.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
##########
2+
Project Remote Mirrors
3+
##########
4+
5+
Remote Mirrors allow you to set up push mirroring for a project.
6+
7+
References
8+
==========
9+
10+
* v4 API:
11+
12+
+ :class:`gitlab.v4.objects.ProjectRemoteMirror`
13+
+ :class:`gitlab.v4.objects.ProjectRemoteMirrorManager`
14+
+ :attr:`gitlab.v4.objects.Project.remote_mirrors`
15+
16+
* GitLab API: https://docs.gitlab.com/ce/api/remote_mirrors.html
17+
18+
Examples
19+
--------
20+
21+
Get the list of a project's remote mirrors::
22+
23+
mirrors = project.remote_mirrors.list()
24+
25+
Create (and enable) a remote mirror for a project::
26+
27+
mirror = project.wikis.create({'url': 'https://gitlab.com/example.git',
28+
'enabled': True})
29+
30+
Update an existing remote mirror's attributes::
31+
32+
mirror.enabled = False
33+
mirror.only_protected_branches = True
34+
mirror.save()

gitlab/tests/objects/test_projects.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,77 @@ def resp_import_github(url, request):
9090
return response(200, content, headers, None, 25, request)
9191

9292

93+
@urlmatch(
94+
scheme="http",
95+
netloc="localhost",
96+
path="/api/v4/projects/1/remote_mirrors",
97+
method="get",
98+
)
99+
def resp_get_remote_mirrors(url, request):
100+
"""Mock for Project Remote Mirrors GET response."""
101+
content = """[
102+
{
103+
"enabled": true,
104+
"id": 101486,
105+
"last_error": null,
106+
"last_successful_update_at": "2020-01-06T17:32:02.823Z",
107+
"last_update_at": "2020-01-06T17:32:02.823Z",
108+
"last_update_started_at": "2020-01-06T17:31:55.864Z",
109+
"only_protected_branches": true,
110+
"update_status": "finished",
111+
"url": "https://*****:*****@gitlab.com/gitlab-org/security/gitlab.git"
112+
}
113+
]"""
114+
content = content.encode("utf-8")
115+
return response(200, content, headers, None, 5, request)
116+
117+
118+
@urlmatch(
119+
scheme="http",
120+
netloc="localhost",
121+
path="/api/v4/projects/1/remote_mirrors",
122+
method="post",
123+
)
124+
def resp_create_remote_mirror(url, request):
125+
"""Mock for Project Remote Mirrors POST response."""
126+
content = """{
127+
"enabled": false,
128+
"id": 101486,
129+
"last_error": null,
130+
"last_successful_update_at": null,
131+
"last_update_at": null,
132+
"last_update_started_at": null,
133+
"only_protected_branches": false,
134+
"update_status": "none",
135+
"url": "https://*****:*****@example.com/gitlab/example.git"
136+
}"""
137+
content = content.encode("utf-8")
138+
return response(200, content, headers, None, 5, request)
139+
140+
141+
@urlmatch(
142+
scheme="http",
143+
netloc="localhost",
144+
path="/api/v4/projects/1/remote_mirrors/1",
145+
method="put",
146+
)
147+
def resp_update_remote_mirror(url, request):
148+
"""Mock for Project Remote Mirrors PUT response."""
149+
content = """{
150+
"enabled": false,
151+
"id": 101486,
152+
"last_error": null,
153+
"last_successful_update_at": "2020-01-06T17:32:02.823Z",
154+
"last_update_at": "2020-01-06T17:32:02.823Z",
155+
"last_update_started_at": "2020-01-06T17:31:55.864Z",
156+
"only_protected_branches": true,
157+
"update_status": "finished",
158+
"url": "https://*****:*****@gitlab.com/gitlab-org/security/gitlab.git"
159+
}"""
160+
content = content.encode("utf-8")
161+
return response(200, content, headers, None, 5, request)
162+
163+
93164
class TestProject(unittest.TestCase):
94165
"""Base class for GitLab Project tests."""
95166

@@ -262,3 +333,26 @@ def test_import_github(self):
262333
self.assertEqual(ret["name"], name)
263334
self.assertEqual(ret["full_path"], "/".join((base_path, name)))
264335
self.assertTrue(ret["full_name"].endswith(name))
336+
337+
338+
class TestProjectRemoteMirrors(TestProject):
339+
@with_httmock(resp_get_remote_mirrors)
340+
def test_list_project_remote_mirrors(self):
341+
mirrors = self.project.remote_mirrors.list()
342+
self.assertIsInstance(mirrors, list)
343+
self.assertIsInstance(mirrors[0], ProjectRemoteMirror)
344+
self.assertTrue(mirrors[0].enabled)
345+
346+
@with_httmock(resp_create_remote_mirror)
347+
def test_create_project_remote_mirror(self):
348+
mirror = self.project.remote_mirrors.create({"url": "https://example.com"})
349+
self.assertIsInstance(mirror, ProjectRemoteMirror)
350+
self.assertEqual(mirror.update_status, "none")
351+
352+
@with_httmock(resp_create_remote_mirror, resp_update_remote_mirror)
353+
def test_update_project_remote_mirror(self):
354+
mirror = self.project.remote_mirrors.create({"url": "https://example.com"})
355+
mirror.only_protected_branches = True
356+
mirror.save()
357+
self.assertEqual(mirror.update_status, "finished")
358+
self.assertTrue(mirror.only_protected_branches)

gitlab/v4/objects.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,18 @@ def delete_in_bulk(self, name_regex=".*", **kwargs):
17451745
self.gitlab.http_delete(self.path, query_data=data, **kwargs)
17461746

17471747

1748+
class ProjectRemoteMirror(SaveMixin, RESTObject):
1749+
pass
1750+
1751+
1752+
class ProjectRemoteMirrorManager(ListMixin, CreateMixin, UpdateMixin, RESTManager):
1753+
_path = "/projects/%(project_id)s/remote_mirrors"
1754+
_obj_cls = ProjectRemoteMirror
1755+
_from_parent_attrs = {"project_id": "id"}
1756+
_create_attrs = (("url",), ("enabled", "only_protected_branches"))
1757+
_update_attrs = (tuple(), ("enabled", "only_protected_branches"))
1758+
1759+
17481760
class ProjectBoardList(SaveMixin, ObjectDeleteMixin, RESTObject):
17491761
pass
17501762

@@ -4246,6 +4258,7 @@ class Project(SaveMixin, ObjectDeleteMixin, RESTObject):
42464258
("pipelineschedules", "ProjectPipelineScheduleManager"),
42474259
("pushrules", "ProjectPushRulesManager"),
42484260
("releases", "ProjectReleaseManager"),
4261+
("remote_mirrors", "ProjectRemoteMirrorManager"),
42494262
("repositories", "ProjectRegistryRepositoryManager"),
42504263
("runners", "ProjectRunnerManager"),
42514264
("services", "ProjectServiceManager"),

tools/python_test_v4.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,23 @@
10471047
assert len(release_test_project.releases.list()) == 0
10481048
release_test_project.delete()
10491049

1050+
# project remote mirrors
1051+
mirror_url = "http://gitlab.test/root/mirror.git"
1052+
1053+
# create remote mirror
1054+
mirror = admin_project.remote_mirrors.create({"url": mirror_url})
1055+
assert mirror.url == mirror_url
1056+
1057+
# update remote mirror
1058+
mirror.enabled = True
1059+
mirror.save()
1060+
1061+
# list remote mirrors
1062+
mirror = admin_project.remote_mirrors.list()[0]
1063+
assert isinstance(mirror, gitlab.v4.objects.ProjectRemoteMirror)
1064+
assert mirror.url == mirror_url
1065+
assert mirror.enabled is True
1066+
10501067
# status
10511068
message = "Test"
10521069
emoji = "thumbsup"

0 commit comments

Comments
 (0)