python-gitlab 4.5.0__py3-none-any.whl → 4.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gitlab/_version.py +1 -1
- gitlab/cli.py +44 -45
- gitlab/client.py +2 -2
- gitlab/mixins.py +22 -14
- gitlab/v4/cli.py +25 -12
- gitlab/v4/objects/__init__.py +1 -0
- gitlab/v4/objects/artifacts.py +5 -2
- gitlab/v4/objects/ci_lint.py +4 -4
- gitlab/v4/objects/commits.py +6 -6
- gitlab/v4/objects/container_registry.py +2 -2
- gitlab/v4/objects/deploy_keys.py +6 -1
- gitlab/v4/objects/deployments.py +2 -2
- gitlab/v4/objects/environments.py +1 -1
- gitlab/v4/objects/files.py +15 -7
- gitlab/v4/objects/geo_nodes.py +4 -4
- gitlab/v4/objects/groups.py +13 -7
- gitlab/v4/objects/integrations.py +3 -1
- gitlab/v4/objects/issues.py +6 -4
- gitlab/v4/objects/iterations.py +29 -2
- gitlab/v4/objects/jobs.py +11 -14
- gitlab/v4/objects/merge_request_approvals.py +8 -3
- gitlab/v4/objects/merge_requests.py +13 -12
- gitlab/v4/objects/milestones.py +4 -4
- gitlab/v4/objects/namespaces.py +3 -1
- gitlab/v4/objects/packages.py +4 -4
- gitlab/v4/objects/pipelines.py +25 -4
- gitlab/v4/objects/projects.py +21 -18
- gitlab/v4/objects/repositories.py +13 -9
- gitlab/v4/objects/runners.py +2 -2
- gitlab/v4/objects/secure_files.py +1 -1
- gitlab/v4/objects/service_accounts.py +18 -0
- gitlab/v4/objects/sidekiq.py +4 -4
- gitlab/v4/objects/snippets.py +3 -3
- gitlab/v4/objects/todos.py +2 -2
- gitlab/v4/objects/topics.py +2 -2
- gitlab/v4/objects/users.py +10 -10
- {python_gitlab-4.5.0.dist-info → python_gitlab-4.7.0.dist-info}/METADATA +3 -3
- {python_gitlab-4.5.0.dist-info → python_gitlab-4.7.0.dist-info}/RECORD +43 -42
- {python_gitlab-4.5.0.dist-info → python_gitlab-4.7.0.dist-info}/WHEEL +1 -1
- {python_gitlab-4.5.0.dist-info → python_gitlab-4.7.0.dist-info}/AUTHORS +0 -0
- {python_gitlab-4.5.0.dist-info → python_gitlab-4.7.0.dist-info}/COPYING +0 -0
- {python_gitlab-4.5.0.dist-info → python_gitlab-4.7.0.dist-info}/entry_points.txt +0 -0
- {python_gitlab-4.5.0.dist-info → python_gitlab-4.7.0.dist-info}/top_level.txt +0 -0
gitlab/v4/objects/groups.py
CHANGED
@@ -46,6 +46,7 @@ from .packages import GroupPackageManager # noqa: F401
|
|
46
46
|
from .projects import GroupProjectManager, SharedProjectManager # noqa: F401
|
47
47
|
from .push_rules import GroupPushRulesManager
|
48
48
|
from .runners import GroupRunnerManager # noqa: F401
|
49
|
+
from .service_accounts import GroupServiceAccountManager # noqa: F401
|
49
50
|
from .statistics import GroupIssuesStatisticsManager # noqa: F401
|
50
51
|
from .variables import GroupVariableManager # noqa: F401
|
51
52
|
from .wikis import GroupWikiManager # noqa: F401
|
@@ -102,8 +103,9 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
102
103
|
variables: GroupVariableManager
|
103
104
|
wikis: GroupWikiManager
|
104
105
|
saml_group_links: "GroupSAMLGroupLinkManager"
|
106
|
+
service_accounts: "GroupServiceAccountManager"
|
105
107
|
|
106
|
-
@cli.register_custom_action("Group", ("project_id",))
|
108
|
+
@cli.register_custom_action(cls_names="Group", required=("project_id",))
|
107
109
|
@exc.on_http_error(exc.GitlabTransferProjectError)
|
108
110
|
def transfer_project(self, project_id: int, **kwargs: Any) -> None:
|
109
111
|
"""Transfer a project to this group.
|
@@ -119,7 +121,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
119
121
|
path = f"/groups/{self.encoded_id}/projects/{project_id}"
|
120
122
|
self.manager.gitlab.http_post(path, **kwargs)
|
121
123
|
|
122
|
-
@cli.register_custom_action("Group", (), ("group_id",))
|
124
|
+
@cli.register_custom_action(cls_names="Group", required=(), optional=("group_id",))
|
123
125
|
@exc.on_http_error(exc.GitlabGroupTransferError)
|
124
126
|
def transfer(self, group_id: Optional[int] = None, **kwargs: Any) -> None:
|
125
127
|
"""Transfer the group to a new parent group or make it a top-level group.
|
@@ -141,7 +143,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
141
143
|
post_data["group_id"] = group_id
|
142
144
|
self.manager.gitlab.http_post(path, post_data=post_data, **kwargs)
|
143
145
|
|
144
|
-
@cli.register_custom_action("Group", ("scope", "search"))
|
146
|
+
@cli.register_custom_action(cls_names="Group", required=("scope", "search"))
|
145
147
|
@exc.on_http_error(exc.GitlabSearchError)
|
146
148
|
def search(
|
147
149
|
self, scope: str, search: str, **kwargs: Any
|
@@ -164,7 +166,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
164
166
|
path = f"/groups/{self.encoded_id}/search"
|
165
167
|
return self.manager.gitlab.http_list(path, query_data=data, **kwargs)
|
166
168
|
|
167
|
-
@cli.register_custom_action("Group")
|
169
|
+
@cli.register_custom_action(cls_names="Group")
|
168
170
|
@exc.on_http_error(exc.GitlabCreateError)
|
169
171
|
def ldap_sync(self, **kwargs: Any) -> None:
|
170
172
|
"""Sync LDAP groups.
|
@@ -179,7 +181,11 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
179
181
|
path = f"/groups/{self.encoded_id}/ldap_sync"
|
180
182
|
self.manager.gitlab.http_post(path, **kwargs)
|
181
183
|
|
182
|
-
@cli.register_custom_action(
|
184
|
+
@cli.register_custom_action(
|
185
|
+
cls_names="Group",
|
186
|
+
required=("group_id", "group_access"),
|
187
|
+
optional=("expires_at",),
|
188
|
+
)
|
183
189
|
@exc.on_http_error(exc.GitlabCreateError)
|
184
190
|
def share(
|
185
191
|
self,
|
@@ -213,7 +219,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
213
219
|
assert isinstance(server_data, dict)
|
214
220
|
self._update_attrs(server_data)
|
215
221
|
|
216
|
-
@cli.register_custom_action("Group", ("group_id",))
|
222
|
+
@cli.register_custom_action(cls_names="Group", required=("group_id",))
|
217
223
|
@exc.on_http_error(exc.GitlabDeleteError)
|
218
224
|
def unshare(self, group_id: int, **kwargs: Any) -> None:
|
219
225
|
"""Delete a shared group link within a group.
|
@@ -229,7 +235,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
229
235
|
path = f"/groups/{self.encoded_id}/share/{group_id}"
|
230
236
|
self.manager.gitlab.http_delete(path, **kwargs)
|
231
237
|
|
232
|
-
@cli.register_custom_action("Group")
|
238
|
+
@cli.register_custom_action(cls_names="Group")
|
233
239
|
@exc.on_http_error(exc.GitlabRestoreError)
|
234
240
|
def restore(self, **kwargs: Any) -> None:
|
235
241
|
"""Restore a group marked for deletion..
|
@@ -270,7 +270,9 @@ class ProjectIntegrationManager(
|
|
270
270
|
) -> ProjectIntegration:
|
271
271
|
return cast(ProjectIntegration, super().get(id=id, lazy=lazy, **kwargs))
|
272
272
|
|
273
|
-
@cli.register_custom_action(
|
273
|
+
@cli.register_custom_action(
|
274
|
+
cls_names=("ProjectIntegrationManager", "ProjectServiceManager")
|
275
|
+
)
|
274
276
|
def available(self) -> List[str]:
|
275
277
|
"""List the services known by python-gitlab.
|
276
278
|
|
gitlab/v4/objects/issues.py
CHANGED
@@ -126,7 +126,7 @@ class ProjectIssue(
|
|
126
126
|
resource_iteration_events: ProjectIssueResourceIterationEventManager
|
127
127
|
resource_weight_events: ProjectIssueResourceWeightEventManager
|
128
128
|
|
129
|
-
@cli.register_custom_action("ProjectIssue", ("to_project_id",))
|
129
|
+
@cli.register_custom_action(cls_names="ProjectIssue", required=("to_project_id",))
|
130
130
|
@exc.on_http_error(exc.GitlabUpdateError)
|
131
131
|
def move(self, to_project_id: int, **kwargs: Any) -> None:
|
132
132
|
"""Move the issue to another project.
|
@@ -146,7 +146,9 @@ class ProjectIssue(
|
|
146
146
|
assert isinstance(server_data, dict)
|
147
147
|
self._update_attrs(server_data)
|
148
148
|
|
149
|
-
@cli.register_custom_action(
|
149
|
+
@cli.register_custom_action(
|
150
|
+
cls_names="ProjectIssue", required=("move_after_id", "move_before_id")
|
151
|
+
)
|
150
152
|
@exc.on_http_error(exc.GitlabUpdateError)
|
151
153
|
def reorder(
|
152
154
|
self,
|
@@ -178,7 +180,7 @@ class ProjectIssue(
|
|
178
180
|
assert isinstance(server_data, dict)
|
179
181
|
self._update_attrs(server_data)
|
180
182
|
|
181
|
-
@cli.register_custom_action("ProjectIssue")
|
183
|
+
@cli.register_custom_action(cls_names="ProjectIssue")
|
182
184
|
@exc.on_http_error(exc.GitlabGetError)
|
183
185
|
def related_merge_requests(self, **kwargs: Any) -> Dict[str, Any]:
|
184
186
|
"""List merge requests related to the issue.
|
@@ -199,7 +201,7 @@ class ProjectIssue(
|
|
199
201
|
assert isinstance(result, dict)
|
200
202
|
return result
|
201
203
|
|
202
|
-
@cli.register_custom_action("ProjectIssue")
|
204
|
+
@cli.register_custom_action(cls_names="ProjectIssue")
|
203
205
|
@exc.on_http_error(exc.GitlabGetError)
|
204
206
|
def closed_by(self, **kwargs: Any) -> Dict[str, Any]:
|
205
207
|
"""List merge requests that will close the issue when merged.
|
gitlab/v4/objects/iterations.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
from gitlab import types
|
1
2
|
from gitlab.base import RESTManager, RESTObject
|
2
3
|
from gitlab.mixins import ListMixin
|
3
4
|
|
@@ -16,11 +17,37 @@ class GroupIterationManager(ListMixin, RESTManager):
|
|
16
17
|
_path = "/groups/{group_id}/iterations"
|
17
18
|
_obj_cls = GroupIteration
|
18
19
|
_from_parent_attrs = {"group_id": "id"}
|
19
|
-
|
20
|
+
# When using the API, the "in" keyword collides with python's "in" keyword
|
21
|
+
# raising a SyntaxError.
|
22
|
+
# For this reason, we have to use the query_parameters argument:
|
23
|
+
# group.iterations.list(query_parameters={"in": "title"})
|
24
|
+
_list_filters = (
|
25
|
+
"include_ancestors",
|
26
|
+
"include_descendants",
|
27
|
+
"in",
|
28
|
+
"search",
|
29
|
+
"state",
|
30
|
+
"updated_after",
|
31
|
+
"updated_before",
|
32
|
+
)
|
33
|
+
_types = {"in": types.ArrayAttribute}
|
20
34
|
|
21
35
|
|
22
36
|
class ProjectIterationManager(ListMixin, RESTManager):
|
23
37
|
_path = "/projects/{project_id}/iterations"
|
24
38
|
_obj_cls = GroupIteration
|
25
39
|
_from_parent_attrs = {"project_id": "id"}
|
26
|
-
|
40
|
+
# When using the API, the "in" keyword collides with python's "in" keyword
|
41
|
+
# raising a SyntaxError.
|
42
|
+
# For this reason, we have to use the query_parameters argument:
|
43
|
+
# project.iterations.list(query_parameters={"in": "title"})
|
44
|
+
_list_filters = (
|
45
|
+
"include_ancestors",
|
46
|
+
"include_descendants",
|
47
|
+
"in",
|
48
|
+
"search",
|
49
|
+
"state",
|
50
|
+
"updated_after",
|
51
|
+
"updated_before",
|
52
|
+
)
|
53
|
+
_types = {"in": types.ArrayAttribute}
|
gitlab/v4/objects/jobs.py
CHANGED
@@ -16,7 +16,7 @@ __all__ = [
|
|
16
16
|
|
17
17
|
|
18
18
|
class ProjectJob(RefreshMixin, RESTObject):
|
19
|
-
@cli.register_custom_action("ProjectJob")
|
19
|
+
@cli.register_custom_action(cls_names="ProjectJob")
|
20
20
|
@exc.on_http_error(exc.GitlabJobCancelError)
|
21
21
|
def cancel(self, **kwargs: Any) -> Dict[str, Any]:
|
22
22
|
"""Cancel the job.
|
@@ -34,7 +34,7 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
34
34
|
assert isinstance(result, dict)
|
35
35
|
return result
|
36
36
|
|
37
|
-
@cli.register_custom_action("ProjectJob")
|
37
|
+
@cli.register_custom_action(cls_names="ProjectJob")
|
38
38
|
@exc.on_http_error(exc.GitlabJobRetryError)
|
39
39
|
def retry(self, **kwargs: Any) -> Dict[str, Any]:
|
40
40
|
"""Retry the job.
|
@@ -52,7 +52,7 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
52
52
|
assert isinstance(result, dict)
|
53
53
|
return result
|
54
54
|
|
55
|
-
@cli.register_custom_action("ProjectJob")
|
55
|
+
@cli.register_custom_action(cls_names="ProjectJob")
|
56
56
|
@exc.on_http_error(exc.GitlabJobPlayError)
|
57
57
|
def play(self, **kwargs: Any) -> None:
|
58
58
|
"""Trigger a job explicitly.
|
@@ -70,7 +70,7 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
70
70
|
assert isinstance(result, dict)
|
71
71
|
self._update_attrs(result)
|
72
72
|
|
73
|
-
@cli.register_custom_action("ProjectJob")
|
73
|
+
@cli.register_custom_action(cls_names="ProjectJob")
|
74
74
|
@exc.on_http_error(exc.GitlabJobEraseError)
|
75
75
|
def erase(self, **kwargs: Any) -> None:
|
76
76
|
"""Erase the job (remove job artifacts and trace).
|
@@ -85,7 +85,7 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
85
85
|
path = f"{self.manager.path}/{self.encoded_id}/erase"
|
86
86
|
self.manager.gitlab.http_post(path, **kwargs)
|
87
87
|
|
88
|
-
@cli.register_custom_action("ProjectJob")
|
88
|
+
@cli.register_custom_action(cls_names="ProjectJob")
|
89
89
|
@exc.on_http_error(exc.GitlabCreateError)
|
90
90
|
def keep_artifacts(self, **kwargs: Any) -> None:
|
91
91
|
"""Prevent artifacts from being deleted when expiration is set.
|
@@ -100,7 +100,7 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
100
100
|
path = f"{self.manager.path}/{self.encoded_id}/artifacts/keep"
|
101
101
|
self.manager.gitlab.http_post(path, **kwargs)
|
102
102
|
|
103
|
-
@cli.register_custom_action("ProjectJob")
|
103
|
+
@cli.register_custom_action(cls_names="ProjectJob")
|
104
104
|
@exc.on_http_error(exc.GitlabCreateError)
|
105
105
|
def delete_artifacts(self, **kwargs: Any) -> None:
|
106
106
|
"""Delete artifacts of a job.
|
@@ -115,7 +115,7 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
115
115
|
path = f"{self.manager.path}/{self.encoded_id}/artifacts"
|
116
116
|
self.manager.gitlab.http_delete(path, **kwargs)
|
117
117
|
|
118
|
-
@cli.register_custom_action("ProjectJob")
|
118
|
+
@cli.register_custom_action(cls_names="ProjectJob")
|
119
119
|
@exc.on_http_error(exc.GitlabGetError)
|
120
120
|
def artifacts(
|
121
121
|
self,
|
@@ -156,7 +156,7 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
156
156
|
result, streamed, action, chunk_size, iterator=iterator
|
157
157
|
)
|
158
158
|
|
159
|
-
@cli.register_custom_action("ProjectJob")
|
159
|
+
@cli.register_custom_action(cls_names="ProjectJob")
|
160
160
|
@exc.on_http_error(exc.GitlabGetError)
|
161
161
|
def artifact(
|
162
162
|
self,
|
@@ -199,7 +199,7 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
199
199
|
result, streamed, action, chunk_size, iterator=iterator
|
200
200
|
)
|
201
201
|
|
202
|
-
@cli.register_custom_action("ProjectJob")
|
202
|
+
@cli.register_custom_action(cls_names="ProjectJob")
|
203
203
|
@exc.on_http_error(exc.GitlabGetError)
|
204
204
|
def trace(
|
205
205
|
self,
|
@@ -209,7 +209,7 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
209
209
|
*,
|
210
210
|
iterator: bool = False,
|
211
211
|
**kwargs: Any,
|
212
|
-
) ->
|
212
|
+
) -> Optional[Union[bytes, Iterator[Any]]]:
|
213
213
|
"""Get the job trace.
|
214
214
|
|
215
215
|
Args:
|
@@ -236,12 +236,9 @@ class ProjectJob(RefreshMixin, RESTObject):
|
|
236
236
|
)
|
237
237
|
if TYPE_CHECKING:
|
238
238
|
assert isinstance(result, requests.Response)
|
239
|
-
|
239
|
+
return utils.response_content(
|
240
240
|
result, streamed, action, chunk_size, iterator=iterator
|
241
241
|
)
|
242
|
-
if TYPE_CHECKING:
|
243
|
-
assert isinstance(return_value, dict)
|
244
|
-
return return_value
|
245
242
|
|
246
243
|
|
247
244
|
class ProjectJobManager(RetrieveMixin, RESTManager):
|
@@ -89,6 +89,8 @@ class ProjectMergeRequestApprovalManager(GetWithoutIdMixin, UpdateMixin, RESTMan
|
|
89
89
|
approver_ids: Optional[List[int]] = None,
|
90
90
|
approver_group_ids: Optional[List[int]] = None,
|
91
91
|
approval_rule_name: str = "name",
|
92
|
+
*,
|
93
|
+
approver_usernames: Optional[List[str]] = None,
|
92
94
|
**kwargs: Any,
|
93
95
|
) -> RESTObject:
|
94
96
|
"""Change MR-level allowed approvers and approver groups.
|
@@ -104,6 +106,7 @@ class ProjectMergeRequestApprovalManager(GetWithoutIdMixin, UpdateMixin, RESTMan
|
|
104
106
|
"""
|
105
107
|
approver_ids = approver_ids or []
|
106
108
|
approver_group_ids = approver_group_ids or []
|
109
|
+
approver_usernames = approver_usernames or []
|
107
110
|
|
108
111
|
data = {
|
109
112
|
"name": approval_rule_name,
|
@@ -111,6 +114,7 @@ class ProjectMergeRequestApprovalManager(GetWithoutIdMixin, UpdateMixin, RESTMan
|
|
111
114
|
"rule_type": "regular",
|
112
115
|
"user_ids": approver_ids,
|
113
116
|
"group_ids": approver_group_ids,
|
117
|
+
"usernames": approver_usernames,
|
114
118
|
}
|
115
119
|
if TYPE_CHECKING:
|
116
120
|
assert self._parent is not None
|
@@ -118,12 +122,13 @@ class ProjectMergeRequestApprovalManager(GetWithoutIdMixin, UpdateMixin, RESTMan
|
|
118
122
|
self._parent.approval_rules
|
119
123
|
)
|
120
124
|
# update any existing approval rule matching the name
|
121
|
-
existing_approval_rules = approval_rules.list()
|
125
|
+
existing_approval_rules = approval_rules.list(iterator=True)
|
122
126
|
for ar in existing_approval_rules:
|
123
127
|
if ar.name == approval_rule_name:
|
124
128
|
ar.user_ids = data["user_ids"]
|
125
129
|
ar.approvals_required = data["approvals_required"]
|
126
130
|
ar.group_ids = data["group_ids"]
|
131
|
+
ar.usernames = data["usernames"]
|
127
132
|
ar.save()
|
128
133
|
return ar
|
129
134
|
# if there was no rule matching the rule name, create a new one
|
@@ -145,14 +150,14 @@ class ProjectMergeRequestApprovalRuleManager(CRUDMixin, RESTManager):
|
|
145
150
|
"name",
|
146
151
|
"approvals_required",
|
147
152
|
),
|
148
|
-
optional=("user_ids", "group_ids"),
|
153
|
+
optional=("user_ids", "group_ids", "usernames"),
|
149
154
|
)
|
150
155
|
# Important: When approval_project_rule_id is set, the name, users and
|
151
156
|
# groups of project-level rule will be copied. The approvals_required
|
152
157
|
# specified will be used.
|
153
158
|
_create_attrs = RequiredOptional(
|
154
159
|
required=("name", "approvals_required"),
|
155
|
-
optional=("approval_project_rule_id", "user_ids", "group_ids"),
|
160
|
+
optional=("approval_project_rule_id", "user_ids", "group_ids", "usernames"),
|
156
161
|
)
|
157
162
|
|
158
163
|
def get(
|
@@ -168,7 +168,7 @@ class ProjectMergeRequest(
|
|
168
168
|
resourcestateevents: ProjectMergeRequestResourceStateEventManager
|
169
169
|
reviewer_details: ProjectMergeRequestReviewerDetailManager
|
170
170
|
|
171
|
-
@cli.register_custom_action("ProjectMergeRequest")
|
171
|
+
@cli.register_custom_action(cls_names="ProjectMergeRequest")
|
172
172
|
@exc.on_http_error(exc.GitlabMROnBuildSuccessError)
|
173
173
|
def cancel_merge_when_pipeline_succeeds(self, **kwargs: Any) -> Dict[str, str]:
|
174
174
|
"""Cancel merge when the pipeline succeeds.
|
@@ -197,7 +197,7 @@ class ProjectMergeRequest(
|
|
197
197
|
assert isinstance(server_data, dict)
|
198
198
|
return server_data
|
199
199
|
|
200
|
-
@cli.register_custom_action("ProjectMergeRequest")
|
200
|
+
@cli.register_custom_action(cls_names="ProjectMergeRequest")
|
201
201
|
@exc.on_http_error(exc.GitlabListError)
|
202
202
|
def closes_issues(self, **kwargs: Any) -> RESTObjectList:
|
203
203
|
"""List issues that will close on merge."
|
@@ -222,7 +222,7 @@ class ProjectMergeRequest(
|
|
222
222
|
manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)
|
223
223
|
return RESTObjectList(manager, ProjectIssue, data_list)
|
224
224
|
|
225
|
-
@cli.register_custom_action("ProjectMergeRequest")
|
225
|
+
@cli.register_custom_action(cls_names="ProjectMergeRequest")
|
226
226
|
@exc.on_http_error(exc.GitlabListError)
|
227
227
|
def commits(self, **kwargs: Any) -> RESTObjectList:
|
228
228
|
"""List the merge request commits.
|
@@ -248,7 +248,9 @@ class ProjectMergeRequest(
|
|
248
248
|
manager = ProjectCommitManager(self.manager.gitlab, parent=self.manager._parent)
|
249
249
|
return RESTObjectList(manager, ProjectCommit, data_list)
|
250
250
|
|
251
|
-
@cli.register_custom_action(
|
251
|
+
@cli.register_custom_action(
|
252
|
+
cls_names="ProjectMergeRequest", optional=("access_raw_diffs",)
|
253
|
+
)
|
252
254
|
@exc.on_http_error(exc.GitlabListError)
|
253
255
|
def changes(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
|
254
256
|
"""List the merge request changes.
|
@@ -266,7 +268,7 @@ class ProjectMergeRequest(
|
|
266
268
|
path = f"{self.manager.path}/{self.encoded_id}/changes"
|
267
269
|
return self.manager.gitlab.http_get(path, **kwargs)
|
268
270
|
|
269
|
-
@cli.register_custom_action("ProjectMergeRequest", (
|
271
|
+
@cli.register_custom_action(cls_names="ProjectMergeRequest", optional=("sha",))
|
270
272
|
@exc.on_http_error(exc.GitlabMRApprovalError)
|
271
273
|
def approve(self, sha: Optional[str] = None, **kwargs: Any) -> Dict[str, Any]:
|
272
274
|
"""Approve the merge request.
|
@@ -295,7 +297,7 @@ class ProjectMergeRequest(
|
|
295
297
|
self._update_attrs(server_data)
|
296
298
|
return server_data
|
297
299
|
|
298
|
-
@cli.register_custom_action("ProjectMergeRequest")
|
300
|
+
@cli.register_custom_action(cls_names="ProjectMergeRequest")
|
299
301
|
@exc.on_http_error(exc.GitlabMRApprovalError)
|
300
302
|
def unapprove(self, **kwargs: Any) -> None:
|
301
303
|
"""Unapprove the merge request.
|
@@ -317,7 +319,7 @@ class ProjectMergeRequest(
|
|
317
319
|
assert isinstance(server_data, dict)
|
318
320
|
self._update_attrs(server_data)
|
319
321
|
|
320
|
-
@cli.register_custom_action("ProjectMergeRequest")
|
322
|
+
@cli.register_custom_action(cls_names="ProjectMergeRequest")
|
321
323
|
@exc.on_http_error(exc.GitlabMRRebaseError)
|
322
324
|
def rebase(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
|
323
325
|
"""Attempt to rebase the source branch onto the target branch
|
@@ -333,7 +335,7 @@ class ProjectMergeRequest(
|
|
333
335
|
data: Dict[str, Any] = {}
|
334
336
|
return self.manager.gitlab.http_put(path, post_data=data, **kwargs)
|
335
337
|
|
336
|
-
@cli.register_custom_action("ProjectMergeRequest")
|
338
|
+
@cli.register_custom_action(cls_names="ProjectMergeRequest")
|
337
339
|
@exc.on_http_error(exc.GitlabMRResetApprovalError)
|
338
340
|
def reset_approvals(
|
339
341
|
self, **kwargs: Any
|
@@ -351,7 +353,7 @@ class ProjectMergeRequest(
|
|
351
353
|
data: Dict[str, Any] = {}
|
352
354
|
return self.manager.gitlab.http_put(path, post_data=data, **kwargs)
|
353
355
|
|
354
|
-
@cli.register_custom_action("ProjectMergeRequest")
|
356
|
+
@cli.register_custom_action(cls_names="ProjectMergeRequest")
|
355
357
|
@exc.on_http_error(exc.GitlabGetError)
|
356
358
|
def merge_ref(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
|
357
359
|
"""Attempt to merge changes between source and target branches into
|
@@ -367,9 +369,8 @@ class ProjectMergeRequest(
|
|
367
369
|
return self.manager.gitlab.http_get(path, **kwargs)
|
368
370
|
|
369
371
|
@cli.register_custom_action(
|
370
|
-
"ProjectMergeRequest",
|
371
|
-
(
|
372
|
-
(
|
372
|
+
cls_names="ProjectMergeRequest",
|
373
|
+
optional=(
|
373
374
|
"merge_commit_message",
|
374
375
|
"should_remove_source_branch",
|
375
376
|
"merge_when_pipeline_succeeds",
|
gitlab/v4/objects/milestones.py
CHANGED
@@ -31,7 +31,7 @@ __all__ = [
|
|
31
31
|
class GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
|
32
32
|
_repr_attr = "title"
|
33
33
|
|
34
|
-
@cli.register_custom_action("GroupMilestone")
|
34
|
+
@cli.register_custom_action(cls_names="GroupMilestone")
|
35
35
|
@exc.on_http_error(exc.GitlabListError)
|
36
36
|
def issues(self, **kwargs: Any) -> RESTObjectList:
|
37
37
|
"""List issues related to this milestone.
|
@@ -58,7 +58,7 @@ class GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
58
58
|
# FIXME(gpocentek): the computed manager path is not correct
|
59
59
|
return RESTObjectList(manager, GroupIssue, data_list)
|
60
60
|
|
61
|
-
@cli.register_custom_action("GroupMilestone")
|
61
|
+
@cli.register_custom_action(cls_names="GroupMilestone")
|
62
62
|
@exc.on_http_error(exc.GitlabListError)
|
63
63
|
def merge_requests(self, **kwargs: Any) -> RESTObjectList:
|
64
64
|
"""List the merge requests related to this milestone.
|
@@ -108,7 +108,7 @@ class ProjectMilestone(PromoteMixin, SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
108
108
|
_repr_attr = "title"
|
109
109
|
_update_method = UpdateMethod.POST
|
110
110
|
|
111
|
-
@cli.register_custom_action("ProjectMilestone")
|
111
|
+
@cli.register_custom_action(cls_names="ProjectMilestone")
|
112
112
|
@exc.on_http_error(exc.GitlabListError)
|
113
113
|
def issues(self, **kwargs: Any) -> RESTObjectList:
|
114
114
|
"""List issues related to this milestone.
|
@@ -135,7 +135,7 @@ class ProjectMilestone(PromoteMixin, SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
135
135
|
# FIXME(gpocentek): the computed manager path is not correct
|
136
136
|
return RESTObjectList(manager, ProjectIssue, data_list)
|
137
137
|
|
138
|
-
@cli.register_custom_action("ProjectMilestone")
|
138
|
+
@cli.register_custom_action(cls_names="ProjectMilestone")
|
139
139
|
@exc.on_http_error(exc.GitlabListError)
|
140
140
|
def merge_requests(self, **kwargs: Any) -> RESTObjectList:
|
141
141
|
"""List the merge requests related to this milestone.
|
gitlab/v4/objects/namespaces.py
CHANGED
@@ -24,7 +24,9 @@ class NamespaceManager(RetrieveMixin, RESTManager):
|
|
24
24
|
def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Namespace:
|
25
25
|
return cast(Namespace, super().get(id=id, lazy=lazy, **kwargs))
|
26
26
|
|
27
|
-
@cli.register_custom_action(
|
27
|
+
@cli.register_custom_action(
|
28
|
+
cls_names="NamespaceManager", required=("namespace", "parent_id")
|
29
|
+
)
|
28
30
|
@exc.on_http_error(exc.GitlabGetError)
|
29
31
|
def exists(self, namespace: str, **kwargs: Any) -> Namespace:
|
30
32
|
"""Get existence of a namespace by path.
|
gitlab/v4/objects/packages.py
CHANGED
@@ -48,8 +48,8 @@ class GenericPackageManager(RESTManager):
|
|
48
48
|
_from_parent_attrs = {"project_id": "id"}
|
49
49
|
|
50
50
|
@cli.register_custom_action(
|
51
|
-
"GenericPackageManager",
|
52
|
-
("package_name", "package_version", "file_name", "path"),
|
51
|
+
cls_names="GenericPackageManager",
|
52
|
+
required=("package_name", "package_version", "file_name", "path"),
|
53
53
|
)
|
54
54
|
@exc.on_http_error(exc.GitlabUploadError)
|
55
55
|
def upload(
|
@@ -123,8 +123,8 @@ class GenericPackageManager(RESTManager):
|
|
123
123
|
return self._obj_cls(self, attrs=attrs)
|
124
124
|
|
125
125
|
@cli.register_custom_action(
|
126
|
-
"GenericPackageManager",
|
127
|
-
("package_name", "package_version", "file_name"),
|
126
|
+
cls_names="GenericPackageManager",
|
127
|
+
required=("package_name", "package_version", "file_name"),
|
128
128
|
)
|
129
129
|
@exc.on_http_error(exc.GitlabGetError)
|
130
130
|
def download(
|
gitlab/v4/objects/pipelines.py
CHANGED
@@ -60,7 +60,7 @@ class ProjectPipeline(RefreshMixin, ObjectDeleteMixin, RESTObject):
|
|
60
60
|
test_report_summary: "ProjectPipelineTestReportSummaryManager"
|
61
61
|
variables: "ProjectPipelineVariableManager"
|
62
62
|
|
63
|
-
@cli.register_custom_action("ProjectPipeline")
|
63
|
+
@cli.register_custom_action(cls_names="ProjectPipeline")
|
64
64
|
@exc.on_http_error(exc.GitlabPipelineCancelError)
|
65
65
|
def cancel(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
|
66
66
|
"""Cancel the job.
|
@@ -75,7 +75,7 @@ class ProjectPipeline(RefreshMixin, ObjectDeleteMixin, RESTObject):
|
|
75
75
|
path = f"{self.manager.path}/{self.encoded_id}/cancel"
|
76
76
|
return self.manager.gitlab.http_post(path, **kwargs)
|
77
77
|
|
78
|
-
@cli.register_custom_action("ProjectPipeline")
|
78
|
+
@cli.register_custom_action(cls_names="ProjectPipeline")
|
79
79
|
@exc.on_http_error(exc.GitlabPipelineRetryError)
|
80
80
|
def retry(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
|
81
81
|
"""Retry the job.
|
@@ -139,6 +139,27 @@ class ProjectPipelineManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManage
|
|
139
139
|
ProjectPipeline, CreateMixin.create(self, data, path=path, **kwargs)
|
140
140
|
)
|
141
141
|
|
142
|
+
def latest(self, ref: Optional[str] = None, lazy: bool = False) -> ProjectPipeline:
|
143
|
+
"""Get the latest pipeline for the most recent commit
|
144
|
+
on a specific ref in a project
|
145
|
+
|
146
|
+
Args:
|
147
|
+
ref: The branch or tag to check for the latest pipeline.
|
148
|
+
Defaults to the default branch when not specified.
|
149
|
+
Returns:
|
150
|
+
A Pipeline instance
|
151
|
+
"""
|
152
|
+
data = {}
|
153
|
+
if ref:
|
154
|
+
data = {"ref": ref}
|
155
|
+
if TYPE_CHECKING:
|
156
|
+
assert self._obj_cls is not None
|
157
|
+
assert self.path is not None
|
158
|
+
server_data = self.gitlab.http_get(self.path + "/latest", query_data=data)
|
159
|
+
if TYPE_CHECKING:
|
160
|
+
assert not isinstance(server_data, requests.Response)
|
161
|
+
return self._obj_cls(self, server_data, lazy=lazy)
|
162
|
+
|
142
163
|
|
143
164
|
class ProjectPipelineJob(RESTObject):
|
144
165
|
pass
|
@@ -201,7 +222,7 @@ class ProjectPipelineSchedule(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
201
222
|
variables: ProjectPipelineScheduleVariableManager
|
202
223
|
pipelines: ProjectPipelineSchedulePipelineManager
|
203
224
|
|
204
|
-
@cli.register_custom_action("ProjectPipelineSchedule")
|
225
|
+
@cli.register_custom_action(cls_names="ProjectPipelineSchedule")
|
205
226
|
@exc.on_http_error(exc.GitlabOwnershipError)
|
206
227
|
def take_ownership(self, **kwargs: Any) -> None:
|
207
228
|
"""Update the owner of a pipeline schedule.
|
@@ -219,7 +240,7 @@ class ProjectPipelineSchedule(SaveMixin, ObjectDeleteMixin, RESTObject):
|
|
219
240
|
assert isinstance(server_data, dict)
|
220
241
|
self._update_attrs(server_data)
|
221
242
|
|
222
|
-
@cli.register_custom_action("ProjectPipelineSchedule")
|
243
|
+
@cli.register_custom_action(cls_names="ProjectPipelineSchedule")
|
223
244
|
@exc.on_http_error(exc.GitlabPipelinePlayError)
|
224
245
|
def play(self, **kwargs: Any) -> Dict[str, Any]:
|
225
246
|
"""Trigger a new scheduled pipeline, which runs immediately.
|