Skip to content

Commit 5f8b8f5

Browse files
nejchJohnVillalovos
authored andcommitted
feat(api): add support for resource groups
1 parent 1816107 commit 5f8b8f5

File tree

6 files changed

+166
-0
lines changed

6 files changed

+166
-0
lines changed

docs/api-objects.rst

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ API examples
5151
gl_objects/remote_mirrors
5252
gl_objects/repositories
5353
gl_objects/repository_tags
54+
gl_objects/resource_groups
5455
gl_objects/search
5556
gl_objects/secure_files
5657
gl_objects/settings

docs/gl_objects/resource_groups.rst

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
###############
2+
Resource Groups
3+
###############
4+
5+
Reference
6+
---------
7+
8+
* v4 API:
9+
10+
+ :class:`gitlab.v4.objects.ProjectResourceGroup`
11+
+ :class:`gitlab.v4.objects.ProjectResourceGroupManager`
12+
+ :attr:`gitlab.v4.objects.Project.resource_groups`
13+
+ :class:`gitlab.v4.objects.ProjectResourceGroupUpcomingJob`
14+
+ :class:`gitlab.v4.objects.ProjectResourceGroupUpcomingJobManager`
15+
+ :attr:`gitlab.v4.objects.ProjectResourceGroup.upcoming_jobs`
16+
17+
* Gitlab API: https://docs.gitlab.com/ee/api/resource_groups.html
18+
19+
Examples
20+
--------
21+
22+
List resource groups for a project::
23+
24+
project = gl.projects.get(project_id, lazy=True)
25+
resource_group = project.resource_groups.list()
26+
27+
Get a single resource group::
28+
29+
resource_group = project.resource_groups.get("production")
30+
31+
Edit a resource group::
32+
33+
resource_group.process_mode = "oldest_first"
34+
resource_group.save()
35+
36+
List upcoming jobs for a resource group::
37+
38+
upcoming_jobs = resource_group.upcoming_jobs.list()

gitlab/v4/objects/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
from .push_rules import *
5353
from .releases import *
5454
from .repositories import *
55+
from .resource_groups import *
5556
from .runners import *
5657
from .secure_files import *
5758
from .settings import *

gitlab/v4/objects/projects.py

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
from .push_rules import ProjectPushRulesManager # noqa: F401
8282
from .releases import ProjectReleaseManager # noqa: F401
8383
from .repositories import RepositoryMixin
84+
from .resource_groups import ProjectResourceGroupManager
8485
from .runners import ProjectRunnerManager # noqa: F401
8586
from .secure_files import ProjectSecureFileManager # noqa: F401
8687
from .snippets import ProjectSnippetManager # noqa: F401
@@ -207,6 +208,7 @@ class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTO
207208
protectedtags: ProjectProtectedTagManager
208209
pushrules: ProjectPushRulesManager
209210
releases: ProjectReleaseManager
211+
resource_groups: ProjectResourceGroupManager
210212
remote_mirrors: "ProjectRemoteMirrorManager"
211213
repositories: ProjectRegistryRepositoryManager
212214
runners: ProjectRunnerManager

gitlab/v4/objects/resource_groups.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from typing import Any, cast, Union
2+
3+
from gitlab.base import RESTManager, RESTObject
4+
from gitlab.mixins import ListMixin, RetrieveMixin, SaveMixin, UpdateMixin
5+
from gitlab.types import RequiredOptional
6+
7+
__all__ = [
8+
"ProjectResourceGroup",
9+
"ProjectResourceGroupManager",
10+
"ProjectResourceGroupUpcomingJob",
11+
"ProjectResourceGroupUpcomingJobManager",
12+
]
13+
14+
15+
class ProjectResourceGroup(SaveMixin, RESTObject):
16+
_id_attr = "key"
17+
18+
upcoming_jobs: "ProjectResourceGroupUpcomingJobManager"
19+
20+
21+
class ProjectResourceGroupManager(RetrieveMixin, UpdateMixin, RESTManager):
22+
_path = "/projects/{project_id}/resource_groups"
23+
_obj_cls = ProjectResourceGroup
24+
_from_parent_attrs = {"project_id": "id"}
25+
_list_filters = (
26+
"order_by",
27+
"sort",
28+
"include_html_description",
29+
)
30+
_update_attrs = RequiredOptional(optional=("process_mode",))
31+
32+
def get(
33+
self, id: Union[str, int], lazy: bool = False, **kwargs: Any
34+
) -> ProjectResourceGroup:
35+
return cast(ProjectResourceGroup, super().get(id=id, lazy=lazy, **kwargs))
36+
37+
38+
class ProjectResourceGroupUpcomingJob(RESTObject):
39+
pass
40+
41+
42+
class ProjectResourceGroupUpcomingJobManager(ListMixin, RESTManager):
43+
_path = "/projects/{project_id}/resource_groups/{resource_group_key}/upcoming_jobs"
44+
_obj_cls = ProjectResourceGroupUpcomingJob
45+
_from_parent_attrs = {"project_id": "project_id", "resource_group_key": "key"}
+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""
2+
GitLab API:
3+
https://docs.gitlab.com/ee/api/resource_groups.html
4+
"""
5+
import pytest
6+
import responses
7+
8+
from gitlab.v4.objects import ProjectResourceGroup, ProjectResourceGroupUpcomingJob
9+
10+
from .test_jobs import job_content
11+
12+
resource_group_content = {
13+
"id": 3,
14+
"key": "production",
15+
"process_mode": "unordered",
16+
"created_at": "2021-09-01T08:04:59.650Z",
17+
"updated_at": "2021-09-01T08:04:59.650Z",
18+
}
19+
20+
21+
@pytest.fixture
22+
def resp_list_resource_groups():
23+
with responses.RequestsMock() as rsps:
24+
rsps.add(
25+
method=responses.GET,
26+
url="http://localhost/api/v4/projects/1/resource_groups",
27+
json=[resource_group_content],
28+
content_type="application/json",
29+
status=200,
30+
)
31+
yield rsps
32+
33+
34+
@pytest.fixture
35+
def resp_get_resource_group():
36+
with responses.RequestsMock() as rsps:
37+
rsps.add(
38+
method=responses.GET,
39+
url="http://localhost/api/v4/projects/1/resource_groups/production",
40+
json=resource_group_content,
41+
content_type="application/json",
42+
status=200,
43+
)
44+
yield rsps
45+
46+
47+
@pytest.fixture
48+
def resp_list_upcoming_jobs():
49+
with responses.RequestsMock() as rsps:
50+
rsps.add(
51+
method=responses.GET,
52+
url="http://localhost/api/v4/projects/1/resource_groups/production/upcoming_jobs",
53+
json=[job_content],
54+
content_type="application/json",
55+
status=200,
56+
)
57+
yield rsps
58+
59+
60+
def test_list_project_resource_groups(project, resp_list_resource_groups):
61+
resource_groups = project.resource_groups.list()
62+
assert isinstance(resource_groups, list)
63+
assert isinstance(resource_groups[0], ProjectResourceGroup)
64+
assert resource_groups[0].process_mode == "unordered"
65+
66+
67+
def test_get_project_resource_group(project, resp_get_resource_group):
68+
resource_group = project.resource_groups.get("production")
69+
assert isinstance(resource_group, ProjectResourceGroup)
70+
assert resource_group.process_mode == "unordered"
71+
72+
73+
def test_list_resource_group_upcoming_jobs(project, resp_list_upcoming_jobs):
74+
resource_group = project.resource_groups.get("production", lazy=True)
75+
upcoming_jobs = resource_group.upcoming_jobs.list()
76+
77+
assert isinstance(upcoming_jobs, list)
78+
assert isinstance(upcoming_jobs[0], ProjectResourceGroupUpcomingJob)
79+
assert upcoming_jobs[0].ref == "main"

0 commit comments

Comments
 (0)