digitalai-release-api-client 26.3.0b1__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.
Files changed (66) hide show
  1. com/__init__.py +0 -0
  2. com/xebialabs/__init__.py +0 -0
  3. com/xebialabs/xlrelease/__init__.py +0 -0
  4. com/xebialabs/xlrelease/api/__init__.py +0 -0
  5. com/xebialabs/xlrelease/api/v1/__init__.py +63 -0
  6. com/xebialabs/xlrelease/api/v1/activity_logs_api.py +27 -0
  7. com/xebialabs/xlrelease/api/v1/api_base_task.py +296 -0
  8. com/xebialabs/xlrelease/api/v1/application_api.py +108 -0
  9. com/xebialabs/xlrelease/api/v1/archive_api.py +56 -0
  10. com/xebialabs/xlrelease/api/v1/attachment_api.py +80 -0
  11. com/xebialabs/xlrelease/api/v1/category_api.py +107 -0
  12. com/xebialabs/xlrelease/api/v1/configuration_api.py +226 -0
  13. com/xebialabs/xlrelease/api/v1/delivery_api.py +289 -0
  14. com/xebialabs/xlrelease/api/v1/delivery_pattern_api.py +328 -0
  15. com/xebialabs/xlrelease/api/v1/dsl_api.py +63 -0
  16. com/xebialabs/xlrelease/api/v1/environment_api.py +166 -0
  17. com/xebialabs/xlrelease/api/v1/environment_label_api.py +117 -0
  18. com/xebialabs/xlrelease/api/v1/environment_reservation_api.py +208 -0
  19. com/xebialabs/xlrelease/api/v1/environment_stage_api.py +117 -0
  20. com/xebialabs/xlrelease/api/v1/folder_api.py +634 -0
  21. com/xebialabs/xlrelease/api/v1/folder_versioning_api.py +344 -0
  22. com/xebialabs/xlrelease/api/v1/permissions_api.py +25 -0
  23. com/xebialabs/xlrelease/api/v1/phase_api.py +185 -0
  24. com/xebialabs/xlrelease/api/v1/release_api.py +493 -0
  25. com/xebialabs/xlrelease/api/v1/report_api.py +83 -0
  26. com/xebialabs/xlrelease/api/v1/risk_api.py +187 -0
  27. com/xebialabs/xlrelease/api/v1/roles_api.py +138 -0
  28. com/xebialabs/xlrelease/api/v1/search_api.py +136 -0
  29. com/xebialabs/xlrelease/api/v1/settings_api.py +26 -0
  30. com/xebialabs/xlrelease/api/v1/task_api.py +482 -0
  31. com/xebialabs/xlrelease/api/v1/task_reporting_api.py +77 -0
  32. com/xebialabs/xlrelease/api/v1/team_api.py +194 -0
  33. com/xebialabs/xlrelease/api/v1/template_api.py +383 -0
  34. com/xebialabs/xlrelease/api/v1/triggers_api.py +173 -0
  35. com/xebialabs/xlrelease/api/v1/user_api.py +157 -0
  36. com/xebialabs/xlrelease/api/v1/variable_api.py +137 -0
  37. com/xebialabs/xlrelease/domain/__init__.py +150 -0
  38. com/xebialabs/xlrelease/domain/activity_log.py +16 -0
  39. com/xebialabs/xlrelease/domain/attachment.py +15 -0
  40. com/xebialabs/xlrelease/domain/base.py +43 -0
  41. com/xebialabs/xlrelease/domain/category.py +26 -0
  42. com/xebialabs/xlrelease/domain/configuration.py +24 -0
  43. com/xebialabs/xlrelease/domain/delivery.py +86 -0
  44. com/xebialabs/xlrelease/domain/environment.py +106 -0
  45. com/xebialabs/xlrelease/domain/folder.py +13 -0
  46. com/xebialabs/xlrelease/domain/forms.py +79 -0
  47. com/xebialabs/xlrelease/domain/gate.py +21 -0
  48. com/xebialabs/xlrelease/domain/phase.py +26 -0
  49. com/xebialabs/xlrelease/domain/release.py +67 -0
  50. com/xebialabs/xlrelease/domain/reporting.py +49 -0
  51. com/xebialabs/xlrelease/domain/risk.py +52 -0
  52. com/xebialabs/xlrelease/domain/role.py +21 -0
  53. com/xebialabs/xlrelease/domain/task.py +43 -0
  54. com/xebialabs/xlrelease/domain/team.py +22 -0
  55. com/xebialabs/xlrelease/domain/trigger.py +21 -0
  56. com/xebialabs/xlrelease/domain/user.py +18 -0
  57. com/xebialabs/xlrelease/domain/variable.py +20 -0
  58. com/xebialabs/xlrelease/domain/versioning.py +87 -0
  59. com/xebialabs/xlrelease/scripting/__init__.py +18 -0
  60. com/xebialabs/xlrelease/scripting/dictionary.py +85 -0
  61. com/xebialabs/xlrelease/scripting/external_property.py +37 -0
  62. com/xebialabs/xlrelease/scripting/logger.py +71 -0
  63. digitalai_release_api_client-26.3.0b1.dist-info/METADATA +137 -0
  64. digitalai_release_api_client-26.3.0b1.dist-info/RECORD +66 -0
  65. digitalai_release_api_client-26.3.0b1.dist-info/WHEEL +4 -0
  66. digitalai_release_api_client-26.3.0b1.dist-info/licenses/LICENSE +21 -0
com/__init__.py ADDED
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,63 @@
1
+ from com.xebialabs.xlrelease.api.v1.activity_logs_api import ActivityLogsApi
2
+ from com.xebialabs.xlrelease.api.v1.application_api import ApplicationApi
3
+ from com.xebialabs.xlrelease.api.v1.archive_api import ArchiveApi
4
+ from com.xebialabs.xlrelease.api.v1.attachment_api import AttachmentApi
5
+ from com.xebialabs.xlrelease.api.v1.category_api import CategoryApi
6
+ from com.xebialabs.xlrelease.api.v1.configuration_api import ConfigurationApi
7
+ from com.xebialabs.xlrelease.api.v1.delivery_api import DeliveryApi
8
+ from com.xebialabs.xlrelease.api.v1.delivery_pattern_api import DeliveryPatternApi
9
+ from com.xebialabs.xlrelease.api.v1.dsl_api import DslApi
10
+ from com.xebialabs.xlrelease.api.v1.environment_api import EnvironmentApi
11
+ from com.xebialabs.xlrelease.api.v1.environment_label_api import EnvironmentLabelApi
12
+ from com.xebialabs.xlrelease.api.v1.environment_reservation_api import (
13
+ EnvironmentReservationApi,
14
+ )
15
+ from com.xebialabs.xlrelease.api.v1.environment_stage_api import EnvironmentStageApi
16
+ from com.xebialabs.xlrelease.api.v1.folder_api import FolderApi
17
+ from com.xebialabs.xlrelease.api.v1.folder_versioning_api import FolderVersioningApi
18
+ from com.xebialabs.xlrelease.api.v1.permissions_api import PermissionsApi
19
+ from com.xebialabs.xlrelease.api.v1.phase_api import PhaseApi
20
+ from com.xebialabs.xlrelease.api.v1.release_api import ReleaseApi
21
+ from com.xebialabs.xlrelease.api.v1.report_api import ReportApi
22
+ from com.xebialabs.xlrelease.api.v1.risk_api import RiskApi
23
+ from com.xebialabs.xlrelease.api.v1.roles_api import RolesApi
24
+ from com.xebialabs.xlrelease.api.v1.search_api import SearchApi
25
+ from com.xebialabs.xlrelease.api.v1.task_api import TaskApi
26
+ from com.xebialabs.xlrelease.api.v1.task_reporting_api import TaskReportingApi
27
+ from com.xebialabs.xlrelease.api.v1.team_api import TeamApi
28
+ from com.xebialabs.xlrelease.api.v1.template_api import TemplateApi
29
+ from com.xebialabs.xlrelease.api.v1.triggers_api import TriggersApi
30
+ from com.xebialabs.xlrelease.api.v1.user_api import UserApi
31
+ from com.xebialabs.xlrelease.api.v1.variable_api import VariableApi
32
+
33
+ __all__ = [
34
+ "ActivityLogsApi",
35
+ "ApplicationApi",
36
+ "ArchiveApi",
37
+ "AttachmentApi",
38
+ "CategoryApi",
39
+ "ConfigurationApi",
40
+ "DeliveryApi",
41
+ "DeliveryPatternApi",
42
+ "DslApi",
43
+ "EnvironmentApi",
44
+ "EnvironmentLabelApi",
45
+ "EnvironmentReservationApi",
46
+ "EnvironmentStageApi",
47
+ "FolderApi",
48
+ "FolderVersioningApi",
49
+ "PermissionsApi",
50
+ "PhaseApi",
51
+ "ReleaseApi",
52
+ "ReportApi",
53
+ "RiskApi",
54
+ "RolesApi",
55
+ "SearchApi",
56
+ "TaskApi",
57
+ "TaskReportingApi",
58
+ "TeamApi",
59
+ "TemplateApi",
60
+ "TriggersApi",
61
+ "UserApi",
62
+ "VariableApi",
63
+ ]
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ from digitalai.release.release_api_client import ReleaseAPIClient
4
+
5
+ from com.xebialabs.xlrelease.domain.activity_log import ActivityLogEntry
6
+
7
+
8
+ class ActivityLogsApi:
9
+ """Operations on activity logs."""
10
+
11
+ def __init__(self, api: ReleaseAPIClient):
12
+ """
13
+ Initializes the ActivityLogsApi.
14
+
15
+ :param api: an instance of ReleaseAPIClient used to make HTTP requests.
16
+ """
17
+ self.api = api
18
+
19
+ def getActivityLogs(self, containerId: str) -> list[ActivityLogEntry]:
20
+ """
21
+ Gets activity logs for a container (Release, Task, Delivery, or Trigger).
22
+
23
+ :param containerId: the container identifier.
24
+ :return: a list of activity log entries.
25
+ """
26
+ response = self.api.get(f"/api/v1/activities/{containerId}")
27
+ return ActivityLogEntry.from_response_to_list(response)
@@ -0,0 +1,296 @@
1
+ from typing import Dict, Type, TypeVar
2
+
3
+ from digitalai.release.integration import BaseTask
4
+ from digitalai.release.release_api_client import ReleaseAPIClient
5
+
6
+ from com.xebialabs.xlrelease.domain.folder import Folder
7
+ from com.xebialabs.xlrelease.domain.phase import Phase
8
+ from com.xebialabs.xlrelease.domain.release import Release
9
+ from com.xebialabs.xlrelease.domain.task import Task
10
+
11
+ from com.xebialabs.xlrelease.api.v1.activity_logs_api import ActivityLogsApi
12
+ from com.xebialabs.xlrelease.api.v1.application_api import ApplicationApi
13
+ from com.xebialabs.xlrelease.api.v1.archive_api import ArchiveApi
14
+ from com.xebialabs.xlrelease.api.v1.attachment_api import AttachmentApi
15
+ from com.xebialabs.xlrelease.api.v1.category_api import CategoryApi
16
+ from com.xebialabs.xlrelease.api.v1.configuration_api import ConfigurationApi
17
+ from com.xebialabs.xlrelease.api.v1.delivery_api import DeliveryApi
18
+ from com.xebialabs.xlrelease.api.v1.delivery_pattern_api import DeliveryPatternApi
19
+ from com.xebialabs.xlrelease.api.v1.dsl_api import DslApi
20
+ from com.xebialabs.xlrelease.api.v1.environment_api import EnvironmentApi
21
+ from com.xebialabs.xlrelease.api.v1.environment_label_api import EnvironmentLabelApi
22
+ from com.xebialabs.xlrelease.api.v1.environment_reservation_api import (
23
+ EnvironmentReservationApi,
24
+ )
25
+ from com.xebialabs.xlrelease.api.v1.environment_stage_api import EnvironmentStageApi
26
+ from com.xebialabs.xlrelease.api.v1.folder_api import FolderApi
27
+ from com.xebialabs.xlrelease.api.v1.folder_versioning_api import FolderVersioningApi
28
+ from com.xebialabs.xlrelease.api.v1.permissions_api import PermissionsApi
29
+ from com.xebialabs.xlrelease.api.v1.phase_api import PhaseApi
30
+ from com.xebialabs.xlrelease.api.v1.release_api import ReleaseApi
31
+ from com.xebialabs.xlrelease.api.v1.report_api import ReportApi
32
+ from com.xebialabs.xlrelease.api.v1.risk_api import RiskApi
33
+ from com.xebialabs.xlrelease.api.v1.roles_api import RolesApi
34
+ from com.xebialabs.xlrelease.api.v1.search_api import SearchApi
35
+ from com.xebialabs.xlrelease.api.v1.settings_api import SettingsApi
36
+ from com.xebialabs.xlrelease.api.v1.task_api import TaskApi
37
+ from com.xebialabs.xlrelease.api.v1.task_reporting_api import TaskReportingApi
38
+ from com.xebialabs.xlrelease.api.v1.team_api import TeamApi
39
+ from com.xebialabs.xlrelease.api.v1.template_api import TemplateApi
40
+ from com.xebialabs.xlrelease.api.v1.triggers_api import TriggersApi
41
+ from com.xebialabs.xlrelease.api.v1.user_api import UserApi
42
+ from com.xebialabs.xlrelease.api.v1.variable_api import VariableApi
43
+
44
+ T = TypeVar("T")
45
+
46
+
47
+ class ApiBaseTask(BaseTask):
48
+ """
49
+ Base class for Release container tasks that need the v1 REST API.
50
+
51
+ Subclass this instead of :class:`BaseTask` to get a ready-to-use, lazily
52
+ created instance of every ``com.xebialabs.xlrelease.api.v1`` wrapper as a
53
+ property (``releaseApi``, ``phaseApi``, ``taskApi``, ...). All wrappers
54
+ share a single :class:`ReleaseAPIClient` built from the task's
55
+ "Run as user" context, so the client and each API object are created only
56
+ once and only when first accessed.
57
+
58
+ Example::
59
+
60
+ class MyTask(ApiBaseTask):
61
+ def execute(self) -> None:
62
+ release = self.releaseApi.getRelease(self.get_release_id())
63
+ self.add_comment(f"Working on {release.title}")
64
+ """
65
+
66
+ def __init__(self):
67
+ super().__init__()
68
+ self._api_client: ReleaseAPIClient = None
69
+ self._api_instances: Dict[Type, object] = {}
70
+
71
+ # -- client / instance management ---------------------------------------
72
+
73
+ @property
74
+ def apiClient(self) -> ReleaseAPIClient:
75
+ """The shared :class:`ReleaseAPIClient`, created on first access."""
76
+ if self._api_client is None:
77
+ self._api_client = self.get_release_api_client()
78
+ return self._api_client
79
+
80
+ def _api(self, api_class: Type[T]) -> T:
81
+ """Return a cached instance of ``api_class``, creating it on first use."""
82
+ instance = self._api_instances.get(api_class)
83
+ if instance is None:
84
+ instance = api_class(self.apiClient)
85
+ self._api_instances[api_class] = instance
86
+ return instance
87
+
88
+ def reset_api_clients(self) -> None:
89
+ """Drop the cached client and API instances (e.g. to re-authenticate)."""
90
+ self._api_client = None
91
+ self._api_instances = {}
92
+
93
+ # -- API wrappers -------------------------------------------------------
94
+
95
+ @property
96
+ def activityLogsApi(self) -> ActivityLogsApi:
97
+ return self._api(ActivityLogsApi)
98
+
99
+ @property
100
+ def applicationApi(self) -> ApplicationApi:
101
+ return self._api(ApplicationApi)
102
+
103
+ @property
104
+ def archiveApi(self) -> ArchiveApi:
105
+ return self._api(ArchiveApi)
106
+
107
+ @property
108
+ def attachmentApi(self) -> AttachmentApi:
109
+ return self._api(AttachmentApi)
110
+
111
+ @property
112
+ def categoryApi(self) -> CategoryApi:
113
+ return self._api(CategoryApi)
114
+
115
+ @property
116
+ def configurationApi(self) -> ConfigurationApi:
117
+ return self._api(ConfigurationApi)
118
+
119
+ @property
120
+ def deliveryApi(self) -> DeliveryApi:
121
+ return self._api(DeliveryApi)
122
+
123
+ @property
124
+ def deliveryPatternApi(self) -> DeliveryPatternApi:
125
+ return self._api(DeliveryPatternApi)
126
+
127
+ @property
128
+ def dslApi(self) -> DslApi:
129
+ return self._api(DslApi)
130
+
131
+ @property
132
+ def environmentApi(self) -> EnvironmentApi:
133
+ return self._api(EnvironmentApi)
134
+
135
+ @property
136
+ def environmentLabelApi(self) -> EnvironmentLabelApi:
137
+ return self._api(EnvironmentLabelApi)
138
+
139
+ @property
140
+ def environmentReservationApi(self) -> EnvironmentReservationApi:
141
+ return self._api(EnvironmentReservationApi)
142
+
143
+ @property
144
+ def environmentStageApi(self) -> EnvironmentStageApi:
145
+ return self._api(EnvironmentStageApi)
146
+
147
+ @property
148
+ def folderApi(self) -> FolderApi:
149
+ return self._api(FolderApi)
150
+
151
+ @property
152
+ def folderVersioningApi(self) -> FolderVersioningApi:
153
+ return self._api(FolderVersioningApi)
154
+
155
+ @property
156
+ def permissionsApi(self) -> PermissionsApi:
157
+ return self._api(PermissionsApi)
158
+
159
+ @property
160
+ def phaseApi(self) -> PhaseApi:
161
+ return self._api(PhaseApi)
162
+
163
+ @property
164
+ def releaseApi(self) -> ReleaseApi:
165
+ return self._api(ReleaseApi)
166
+
167
+ @property
168
+ def reportApi(self) -> ReportApi:
169
+ return self._api(ReportApi)
170
+
171
+ @property
172
+ def riskApi(self) -> RiskApi:
173
+ return self._api(RiskApi)
174
+
175
+ @property
176
+ def rolesApi(self) -> RolesApi:
177
+ return self._api(RolesApi)
178
+
179
+ @property
180
+ def searchApi(self) -> SearchApi:
181
+ return self._api(SearchApi)
182
+
183
+ @property
184
+ def settingsApi(self) -> SettingsApi:
185
+ return self._api(SettingsApi)
186
+
187
+ @property
188
+ def taskApi(self) -> TaskApi:
189
+ return self._api(TaskApi)
190
+
191
+ @property
192
+ def taskReportingApi(self) -> TaskReportingApi:
193
+ return self._api(TaskReportingApi)
194
+
195
+ @property
196
+ def teamApi(self) -> TeamApi:
197
+ return self._api(TeamApi)
198
+
199
+ @property
200
+ def templateApi(self) -> TemplateApi:
201
+ return self._api(TemplateApi)
202
+
203
+ @property
204
+ def triggersApi(self) -> TriggersApi:
205
+ return self._api(TriggersApi)
206
+
207
+ @property
208
+ def userApi(self) -> UserApi:
209
+ return self._api(UserApi)
210
+
211
+ @property
212
+ def variableApi(self) -> VariableApi:
213
+ return self._api(VariableApi)
214
+
215
+ # -- current-context helpers --------------------------------------------
216
+ # Convenience methods that resolve the release object the task is running
217
+ # in, mirroring the helpers the Jython script API offers on the server
218
+ # (XLReleaseApi.py). Each derives the relevant id from the task's context
219
+ # and fetches the object through the matching API wrapper above.
220
+
221
+ def getCurrentTask(self) -> Task:
222
+ """
223
+ Return the task that is running this code.
224
+
225
+ Fetches the task via ``taskApi`` using the task's own id.
226
+ """
227
+ return self.taskApi.getTask(self.get_task_id())
228
+
229
+ def getCurrentPhase(self) -> Phase:
230
+ """
231
+ Return the phase that contains this task.
232
+
233
+ The phase id is derived from the task id, then fetched via ``phaseApi``.
234
+ """
235
+ return self.phaseApi.getPhase(self.get_phase_id())
236
+
237
+ def getCurrentRelease(self) -> Release:
238
+ """
239
+ Return the release this task belongs to.
240
+
241
+ Fetches the release via ``releaseApi`` using the task's release id, so
242
+ the caller does not need to know or substitute the id itself.
243
+ """
244
+ return self.releaseApi.getRelease(self.get_release_id())
245
+
246
+ def getCurrentFolder(self) -> Folder:
247
+ """
248
+ Return the folder that contains the current release.
249
+
250
+ The folder id is derived from the release id, then fetched via
251
+ ``folderApi``.
252
+ """
253
+ return self.folderApi.getFolder(self.get_folder_id())
254
+
255
+ def getTasksByTitle(self, taskTitle: str, phaseTitle: str | None = None,
256
+ releaseId: str | None = None) -> list[Task]:
257
+ """
258
+ Find tasks by title.
259
+
260
+ :param taskTitle: the task title to search for.
261
+ :param phaseTitle: optional phase title to scope the search; searches the
262
+ whole release when omitted.
263
+ :param releaseId: optional release to search; the current release when
264
+ omitted.
265
+ :return: the matching tasks.
266
+ """
267
+ return self.taskApi.searchTasksByTitle(
268
+ taskTitle, releaseId or self.get_release_id(), phaseTitle)
269
+
270
+ def getPhasesByTitle(self, phaseTitle: str,
271
+ releaseId: str | None = None) -> list[Phase]:
272
+ """
273
+ Find phases by title.
274
+
275
+ :param phaseTitle: the phase title to search for.
276
+ :param releaseId: optional release to search; the current release when
277
+ omitted.
278
+ :return: the matching phases.
279
+ """
280
+ return self.phaseApi.searchPhasesByTitle(
281
+ phaseTitle, releaseId or self.get_release_id())
282
+
283
+ def getReleasesByTitle(self, releaseTitle: str) -> list[Release]:
284
+ """
285
+ Find releases by title.
286
+
287
+ :param releaseTitle: the release title to search for.
288
+ :return: the matching releases.
289
+ """
290
+ return self.releaseApi.searchReleasesByTitle(releaseTitle)
291
+
292
+ def getVersion(self) -> str | None:
293
+ """
294
+ Return the version of this Digital.ai Release instance.
295
+ """
296
+ return self.settingsApi.getInstanceInformation().get('version')
@@ -0,0 +1,108 @@
1
+ from __future__ import annotations
2
+
3
+ from digitalai.release.release_api_client import ReleaseAPIClient
4
+
5
+ from com.xebialabs.xlrelease.domain.environment import (
6
+ Application,
7
+ ApplicationFilters,
8
+ )
9
+
10
+
11
+ class ApplicationApi:
12
+ """Operations on applications."""
13
+
14
+ def __init__(self, api: ReleaseAPIClient):
15
+ """
16
+ Initializes the ApplicationApi.
17
+
18
+ :param api: an instance of ReleaseAPIClient used to make HTTP requests.
19
+ """
20
+ self.api = api
21
+
22
+ def createApplication(self, applicationForm: Application) -> Application:
23
+ """
24
+ Creates a new application.
25
+
26
+ :param applicationForm: an Application (form) describing the new application.
27
+ :return: the created application.
28
+ """
29
+ response = self.api.post(
30
+ "/api/v1/applications",
31
+ json=applicationForm.model_dump(exclude_none=True)
32
+ )
33
+ return Application.from_response(response)
34
+
35
+ def getApplication(self, applicationId: str) -> Application:
36
+ """
37
+ Gets an application by id.
38
+
39
+ :param applicationId: the application identifier.
40
+ :return: the application.
41
+ """
42
+ response = self.api.get(f"/api/v1/applications/{applicationId}")
43
+ return Application.from_response(response)
44
+
45
+ def updateApplication(self, applicationId: str, applicationForm: Application) -> Application:
46
+ """
47
+ Updates an existing application.
48
+
49
+ :param applicationId: the application identifier.
50
+ :param applicationForm: an Application (form) describing the new properties.
51
+ :return: the updated application.
52
+ """
53
+ response = self.api.put(
54
+ f"/api/v1/applications/{applicationId}",
55
+ json=applicationForm.model_dump(exclude_none=True)
56
+ )
57
+ return Application.from_response(response)
58
+
59
+ def searchApplications(self, applicationFilters: ApplicationFilters | None = None) -> list[Application]:
60
+ """
61
+ Searches applications by filters.
62
+
63
+ :param applicationFilters: the search criteria.
64
+ :return: the list of matching applications.
65
+ """
66
+ body = applicationFilters.model_dump(exclude_none=True) if applicationFilters else {}
67
+ response = self.api.post("/api/v1/applications/search", json=body)
68
+ return Application.from_response_to_list(response)
69
+
70
+ def deleteApplication(self, applicationId: str) -> None:
71
+ """
72
+ Deletes an application.
73
+
74
+ :param applicationId: the application identifier.
75
+ """
76
+ response = self.api.delete(f"/api/v1/applications/{applicationId}")
77
+ response.raise_for_status()
78
+
79
+ # --- Convenience aliases matching the Jython script API ---
80
+
81
+ def create(self, application: Application) -> Application:
82
+ """
83
+ Creates a new application.
84
+
85
+ :param application: an Application object describing the new application.
86
+ :return: the created application.
87
+ """
88
+ return self.createApplication(application)
89
+
90
+ def update(self, application: Application) -> Application:
91
+ """
92
+ Updates an existing application.
93
+
94
+ :param application: an Application object describing the new properties.
95
+ :return: the updated application.
96
+ """
97
+ if not application.id:
98
+ raise ValueError("application.id must be set to update an application")
99
+ return self.updateApplication(application.id, application)
100
+
101
+ def search(self, filters: ApplicationFilters | None = None) -> list[Application]:
102
+ """
103
+ Searches applications by filters.
104
+
105
+ :param filters: the search criteria.
106
+ :return: the list of matching applications.
107
+ """
108
+ return self.searchApplications(filters)
@@ -0,0 +1,56 @@
1
+ from __future__ import annotations
2
+
3
+ from digitalai.release.release_api_client import ReleaseAPIClient
4
+
5
+ from com.xebialabs.xlrelease.domain.release import Release
6
+
7
+
8
+ class ArchiveApi:
9
+ """Operations on archived releases."""
10
+
11
+ def __init__(self, api: ReleaseAPIClient):
12
+ """
13
+ Initializes the ArchiveApi.
14
+
15
+ :param api: an instance of ReleaseAPIClient used to make HTTP requests.
16
+ """
17
+ self.api = api
18
+
19
+ def getArchivedRelease(self, releaseId: str) -> Release:
20
+ """
21
+ Returns the archived release for the given ID.
22
+
23
+ :param releaseId: the identifier of the release.
24
+ :return: the archived release.
25
+ """
26
+ response = self.api.get(f"/api/v1/releases/archived/{releaseId}")
27
+ return Release.from_response(response)
28
+
29
+ def searchArchivedReleases(
30
+ self,
31
+ title: str | None = None,
32
+ tags: list[str] | None = None,
33
+ page: int | None = None,
34
+ resultsPerPage: int | None = None
35
+ ) -> list[Release]:
36
+ """
37
+ Searches archived releases.
38
+
39
+ :param title: filter by release title.
40
+ :param tags: filter by release tags.
41
+ :param page: the page of results to return.
42
+ :param resultsPerPage: the number of results per page.
43
+ :return: the list of matching archived releases.
44
+ """
45
+ body = {"onlyArchived": True}
46
+ if title is not None:
47
+ body["title"] = title
48
+ if tags is not None:
49
+ body["tags"] = tags
50
+ params = {}
51
+ if page is not None:
52
+ params["page"] = page
53
+ if resultsPerPage is not None:
54
+ params["resultsPerPage"] = resultsPerPage
55
+ response = self.api.post("/api/v1/releases/search", json=body, params=params)
56
+ return Release.from_response_to_list(response)
@@ -0,0 +1,80 @@
1
+ from __future__ import annotations
2
+
3
+ from digitalai.release.release_api_client import ReleaseAPIClient
4
+
5
+ from com.xebialabs.xlrelease.domain.attachment import Attachment
6
+
7
+
8
+ class AttachmentApi:
9
+ """Operations on attachments."""
10
+
11
+ def __init__(self, api: ReleaseAPIClient):
12
+ """
13
+ Initializes the AttachmentApi.
14
+
15
+ :param api: an instance of ReleaseAPIClient used to make HTTP requests.
16
+ """
17
+ self.api = api
18
+
19
+ def getAttachment(self, attachmentId: str) -> bytes:
20
+ """
21
+ Returns the attachment file with the given ID.
22
+
23
+ :param attachmentId: the identifier of the attachment.
24
+ :return: the attachment file content as bytes.
25
+ """
26
+ response = self.api.get(
27
+ f"/api/v1/releases/attachments/{attachmentId}",
28
+ headers={"Accept": "application/octet-stream"}
29
+ )
30
+ response.raise_for_status()
31
+ return response.content
32
+
33
+ def addAttachment(self, taskId: str, fileName: str, fileBytes: bytes) -> Attachment:
34
+ """
35
+ Adds one attachment file to a task.
36
+
37
+ :param taskId: the task identifier.
38
+ :param fileName: the name of the attachment file.
39
+ :param fileBytes: the file content as bytes.
40
+ :return: the domain object of the uploaded attachment.
41
+ """
42
+ files = {"file": (fileName, fileBytes)}
43
+ response = self.api.post(
44
+ f"/api/v1/tasks/{taskId}/attachments",
45
+ files=files
46
+ )
47
+ response.raise_for_status()
48
+ data = response.json()
49
+ if isinstance(data, list):
50
+ return Attachment.model_validate(data[0])
51
+ return Attachment.model_validate(data)
52
+
53
+ def addAttachments(self, taskId: str, fileList: list[tuple[str, bytes]]) -> list[Attachment]:
54
+ """
55
+ Adds multiple attachment files to a task.
56
+
57
+ :param taskId: the task identifier.
58
+ :param fileList: list of (fileName, fileBytes) tuples.
59
+ :return: list of uploaded Attachment domain objects.
60
+ """
61
+ files = [("file", (name, content)) for name, content in fileList]
62
+ response = self.api.post(
63
+ f"/api/v1/tasks/{taskId}/attachments",
64
+ files=files
65
+ )
66
+ response.raise_for_status()
67
+ data = response.json()
68
+ if isinstance(data, list):
69
+ return [Attachment.model_validate(item) for item in data]
70
+ return [Attachment.model_validate(data)]
71
+
72
+ def deleteAttachment(self, taskId: str, attachmentId: str) -> None:
73
+ """
74
+ Deletes an attachment from a task.
75
+
76
+ :param taskId: the task identifier.
77
+ :param attachmentId: the attachment identifier.
78
+ """
79
+ response = self.api.delete(f"/api/v1/tasks/{taskId}/attachments/{attachmentId}")
80
+ response.raise_for_status()