Skip to content

Commit 4abcd17

Browse files
lgatelliernejch
andauthored
feat(api): add support for new runner creation API (#2635)
Co-authored-by: Nejc Habjan <hab.nejc@gmail.com>
1 parent 9b6d89e commit 4abcd17

File tree

5 files changed

+136
-0
lines changed

5 files changed

+136
-0
lines changed

docs/gl_objects/runners.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ Register a new runner::
7171

7272
runner = gl.runners.create({'token': secret_token})
7373

74+
.. note::
75+
76+
A new runner registration workflow has been introduced since GitLab 16.0. This new
77+
workflow comes with a new API endpoint to create runners, which does not use
78+
registration tokens.
79+
80+
The new endpoint can be called using ``gl.user.runners.create() after authenticating with `gl.auth()```.
81+
7482
Update a runner::
7583

7684
runner = gl.runners.get(runner_id)

docs/gl_objects/users.rst

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,3 +456,60 @@ Get the users activities::
456456
query_parameters={'from': '2018-07-01'},
457457
get_all=True,
458458
)
459+
460+
Create new runner
461+
=================
462+
463+
References
464+
----------
465+
466+
* New runner registration API endpoint (see `Migrating to the new runner registration workflow <https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html#creating-runners-programmatically>`_)
467+
468+
* v4 API:
469+
470+
+ :class:`gitlab.v4.objects.CurrentUserRunner`
471+
+ :class:`gitlab.v4.objects.CurrentUserRunnerManager`
472+
+ :attr:`gitlab.Gitlab.user.runners`
473+
474+
* GitLab API : https://docs.gitlab.com/ee/api/users.html#create-a-runner
475+
476+
Examples
477+
--------
478+
479+
Create an instance-wide runner::
480+
481+
runner = gl.user.runners.create({
482+
"runner_type": "instance_type",
483+
"description": "My brand new runner",
484+
"paused": True,
485+
"locked": False,
486+
"run_untagged": True
487+
"tag_list": ["linux", "docker", "testing"],
488+
"access_level": "not_protected"
489+
})
490+
491+
Create a group runner::
492+
493+
runner = gl.user.runners.create({
494+
"runner_type": "group_type",
495+
"group_id": 12345678,
496+
"description": "My brand new runner",
497+
"paused": True,
498+
"locked": False,
499+
"run_untagged": True
500+
"tag_list": ["linux", "docker", "testing"],
501+
"access_level": "not_protected"
502+
})
503+
504+
Create a project runner::
505+
506+
runner = gl.user.runners.create({
507+
"runner_type": "project_type",
508+
"project_id": 987564321,
509+
"description": "My brand new runner",
510+
"paused": True,
511+
"locked": False,
512+
"run_untagged": True
513+
"tag_list": ["linux", "docker", "testing"],
514+
"access_level": "not_protected"
515+
})

gitlab/v4/objects/users.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
"CurrentUserGPGKeyManager",
3737
"CurrentUserKey",
3838
"CurrentUserKeyManager",
39+
"CurrentUserRunner",
40+
"CurrentUserRunnerManager",
3941
"CurrentUserStatus",
4042
"CurrentUserStatusManager",
4143
"CurrentUser",
@@ -111,6 +113,31 @@ def get(
111113
return cast(CurrentUserKey, super().get(id=id, lazy=lazy, **kwargs))
112114

113115

116+
class CurrentUserRunner(RESTObject):
117+
pass
118+
119+
120+
class CurrentUserRunnerManager(CreateMixin, RESTManager):
121+
_path = "/user/runners"
122+
_obj_cls = CurrentUserRunner
123+
_types = {"tag_list": types.CommaSeparatedListAttribute}
124+
_create_attrs = RequiredOptional(
125+
required=("runner_type",),
126+
optional=(
127+
"group_id",
128+
"project_id",
129+
"description",
130+
"paused",
131+
"locked",
132+
"run_untagged",
133+
"tag_list",
134+
"access_level",
135+
"maximum_timeout",
136+
"maintenance_note",
137+
),
138+
)
139+
140+
114141
class CurrentUserStatus(SaveMixin, RESTObject):
115142
_id_attr = None
116143
_repr_attr = "message"
@@ -132,6 +159,7 @@ class CurrentUser(RESTObject):
132159
emails: CurrentUserEmailManager
133160
gpgkeys: CurrentUserGPGKeyManager
134161
keys: CurrentUserKeyManager
162+
runners: CurrentUserRunnerManager
135163
status: CurrentUserStatusManager
136164

137165

tests/unit/conftest.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pytest
2+
import responses
23

34
import gitlab
45
from tests.unit import helpers
@@ -59,6 +60,23 @@ def gl_retry():
5960
)
6061

6162

63+
@pytest.fixture
64+
def resp_get_current_user():
65+
with responses.RequestsMock() as rsps:
66+
rsps.add(
67+
method=responses.GET,
68+
url="http://localhost/api/v4/user",
69+
json={
70+
"id": 1,
71+
"username": "username",
72+
"web_url": "http://localhost/username",
73+
},
74+
content_type="application/json",
75+
status=200,
76+
)
77+
yield rsps
78+
79+
6280
# Todo: parametrize, but check what tests it's really useful for
6381
@pytest.fixture
6482
def gl_trailing():
@@ -129,6 +147,12 @@ def user(gl):
129147
return gl.users.get(1, lazy=True)
130148

131149

150+
@pytest.fixture
151+
def current_user(gl, resp_get_current_user):
152+
gl.auth()
153+
return gl.user
154+
155+
132156
@pytest.fixture
133157
def migration(gl):
134158
return gl.bulk_imports.get(1, lazy=True)

tests/unit/objects/test_users.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,19 @@ def resp_starred_projects():
241241
yield rsps
242242

243243

244+
@pytest.fixture
245+
def resp_runner_create():
246+
with responses.RequestsMock() as rsps:
247+
rsps.add(
248+
method=responses.POST,
249+
url="http://localhost/api/v4/user/runners",
250+
json={"id": "6", "token": "6337ff461c94fd3fa32ba3b1ff4125"},
251+
content_type="application/json",
252+
status=201,
253+
)
254+
yield rsps
255+
256+
244257
def test_get_user(gl, resp_get_user):
245258
user = gl.users.get(1)
246259
assert isinstance(user, User)
@@ -304,3 +317,9 @@ def test_list_starred_projects(user, resp_starred_projects):
304317
projects = user.starred_projects.list()
305318
assert isinstance(projects[0], StarredProject)
306319
assert projects[0].id == project_content["id"]
320+
321+
322+
def test_create_user_runner(current_user, resp_runner_create):
323+
runner = current_user.runners.create({"runner_type": "instance_type"})
324+
assert runner.id == "6"
325+
assert runner.token == "6337ff461c94fd3fa32ba3b1ff4125"

0 commit comments

Comments
 (0)