lucius-mcp 0.3.0__py3-none-any.whl → 0.4.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.
- lucius_mcp-0.4.0.dist-info/METADATA +124 -0
- {lucius_mcp-0.3.0.dist-info → lucius_mcp-0.4.0.dist-info}/RECORD +38 -29
- src/client/__init__.py +6 -0
- src/client/client.py +271 -7
- src/client/exceptions.py +23 -0
- src/client/generated/README.md +18 -0
- src/client/generated/__init__.py +2 -0
- src/client/generated/api/__init__.py +1 -0
- src/client/generated/api/integration_controller_api.py +5285 -0
- src/client/generated/docs/IntegrationControllerApi.md +1224 -0
- src/services/__init__.py +9 -1
- src/services/custom_field_value_service.py +301 -0
- src/services/integration_service.py +205 -0
- src/services/launch_service.py +29 -1
- src/services/shared_step_service.py +34 -17
- src/services/test_case_service.py +269 -37
- src/services/test_layer_service.py +11 -0
- src/tools/__init__.py +19 -1
- src/tools/create_custom_field_value.py +38 -0
- src/tools/create_test_case.py +32 -2
- src/tools/delete_custom_field_value.py +57 -0
- src/tools/delete_test_case.py +5 -4
- src/tools/delete_test_layer.py +17 -4
- src/tools/delete_test_layer_schema.py +17 -4
- src/tools/launches.py +86 -0
- src/tools/link_shared_step.py +18 -12
- src/tools/list_custom_field_values.py +72 -0
- src/tools/list_integrations.py +77 -0
- src/tools/search.py +3 -3
- src/tools/shared_steps.py +23 -8
- src/tools/unlink_shared_step.py +19 -5
- src/tools/update_custom_field_value.py +55 -0
- src/tools/update_test_case.py +67 -2
- src/tools/update_test_layer.py +15 -4
- src/tools/update_test_layer_schema.py +16 -5
- lucius_mcp-0.3.0.dist-info/METADATA +0 -297
- {lucius_mcp-0.3.0.dist-info → lucius_mcp-0.4.0.dist-info}/WHEEL +0 -0
- {lucius_mcp-0.3.0.dist-info → lucius_mcp-0.4.0.dist-info}/entry_points.txt +0 -0
- {lucius_mcp-0.3.0.dist-info → lucius_mcp-0.4.0.dist-info}/licenses/LICENSE +0 -0
src/tools/search.py
CHANGED
|
@@ -122,12 +122,12 @@ async def search_test_cases(
|
|
|
122
122
|
Examples:
|
|
123
123
|
search_test_cases(query="login")
|
|
124
124
|
→ "Found 5 test cases matching 'login':
|
|
125
|
-
- [
|
|
126
|
-
- [
|
|
125
|
+
- [#1] User Login Flow (tags: smoke, auth)
|
|
126
|
+
- [#2] Admin Login Test (tags: admin)"
|
|
127
127
|
|
|
128
128
|
search_test_cases(aql='status="failed" and tag="regression"')
|
|
129
129
|
→ "Found 12 test cases matching 'status=\"failed\" and tag=\"regression\"':
|
|
130
|
-
- [
|
|
130
|
+
- [#5] Critical Path Test ..."
|
|
131
131
|
"""
|
|
132
132
|
# Validate that at least one search parameter is provided
|
|
133
133
|
if not aql and not query:
|
src/tools/shared_steps.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Annotated
|
|
1
|
+
from typing import Annotated
|
|
2
2
|
|
|
3
3
|
from pydantic import Field
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ from src.services.shared_step_service import SharedStepService
|
|
|
9
9
|
async def create_shared_step(
|
|
10
10
|
name: Annotated[str, Field(description='The name of the shared step (e.g., "Login as Admin").')],
|
|
11
11
|
steps: Annotated[
|
|
12
|
-
list[dict[str,
|
|
12
|
+
list[dict[str, object]] | None,
|
|
13
13
|
Field(
|
|
14
14
|
description="Optional list of steps. Each step is a dictionary with:"
|
|
15
15
|
' - action (str): The step description (e.g., "Enter username").'
|
|
@@ -86,9 +86,11 @@ async def update_shared_step(
|
|
|
86
86
|
step_id: Annotated[int, Field(description="The shared step ID to update (required).")],
|
|
87
87
|
name: Annotated[str | None, Field(description="New name for the shared step (optional).")] = None,
|
|
88
88
|
description: Annotated[str | None, Field(description="New description (optional).")] = None,
|
|
89
|
+
confirm: Annotated[bool, Field(description="Must be set to True to proceed with update. Safety measure.")] = False,
|
|
89
90
|
project_id: Annotated[int | None, Field(description="Optional override for the default Project ID.")] = None,
|
|
90
91
|
) -> str:
|
|
91
92
|
"""Update an existing shared step.
|
|
93
|
+
⚠️ CAUTION: Destructive.
|
|
92
94
|
|
|
93
95
|
⚠️ IMPORTANT: Changes propagate to ALL test cases using this shared step.
|
|
94
96
|
|
|
@@ -100,6 +102,8 @@ async def update_shared_step(
|
|
|
100
102
|
Found via list_shared_steps or in the Allure URL.
|
|
101
103
|
name: New name for the shared step (optional).
|
|
102
104
|
description: New description (optional).
|
|
105
|
+
confirm: Must be set to True to proceed with update.
|
|
106
|
+
This is a safety measure to prevent accidental updates.
|
|
103
107
|
project_id: Optional override for the default Project ID.
|
|
104
108
|
|
|
105
109
|
Returns:
|
|
@@ -108,9 +112,16 @@ async def update_shared_step(
|
|
|
108
112
|
Example:
|
|
109
113
|
update_shared_step(
|
|
110
114
|
step_id=789,
|
|
111
|
-
name="Login as Admin (Updated)"
|
|
115
|
+
name="Login as Admin (Updated)",
|
|
116
|
+
confirm=True
|
|
112
117
|
)
|
|
113
118
|
"""
|
|
119
|
+
if not confirm:
|
|
120
|
+
return (
|
|
121
|
+
"⚠️ Update requires confirmation.\n\n"
|
|
122
|
+
"Changes propagate to ALL test cases using this shared step. "
|
|
123
|
+
f"Please call again with confirm=True to proceed with updating shared step {step_id}."
|
|
124
|
+
)
|
|
114
125
|
|
|
115
126
|
async with AllureClient.from_env(project=project_id) as client:
|
|
116
127
|
service = SharedStepService(client=client)
|
|
@@ -136,6 +147,7 @@ async def delete_shared_step(
|
|
|
136
147
|
project_id: Annotated[int | None, Field(description="Optional override for the default Project ID.")] = None,
|
|
137
148
|
) -> str:
|
|
138
149
|
"""Delete a shared step from the library.
|
|
150
|
+
⚠️ CAUTION: Destructive.
|
|
139
151
|
|
|
140
152
|
⚠️ CAUTION: If this shared step is used by test cases, deleting it
|
|
141
153
|
will break those references.
|
|
@@ -157,13 +169,16 @@ async def delete_shared_step(
|
|
|
157
169
|
"""
|
|
158
170
|
if not confirm:
|
|
159
171
|
return (
|
|
160
|
-
"⚠️
|
|
161
|
-
"
|
|
162
|
-
"
|
|
172
|
+
"⚠️ Deletion requires confirmation.\n\n"
|
|
173
|
+
"Deleting a shared step used by test cases will be breaking those references. "
|
|
174
|
+
f"Please call again with confirm=True to proceed with archiving shared step {step_id}."
|
|
163
175
|
)
|
|
164
176
|
|
|
165
177
|
async with AllureClient.from_env(project=project_id) as client:
|
|
166
178
|
service = SharedStepService(client=client)
|
|
167
|
-
await service.delete_shared_step(step_id=step_id)
|
|
179
|
+
deleted = await service.delete_shared_step(step_id=step_id)
|
|
168
180
|
|
|
169
|
-
|
|
181
|
+
if deleted:
|
|
182
|
+
return f"✅ Archived Shared Step {step_id}\n\nThe shared step has been successfully archived."
|
|
183
|
+
else:
|
|
184
|
+
return f"ℹ️ Shared Step {step_id} was already archived or doesn't exist." # noqa: RUF001
|
src/tools/unlink_shared_step.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Tool for unlinking Shared Steps from Test Cases."""
|
|
2
2
|
|
|
3
|
-
from typing import Annotated
|
|
3
|
+
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
from pydantic import Field
|
|
6
6
|
|
|
@@ -9,13 +9,14 @@ from src.client.generated.models.shared_step_step_dto import SharedStepStepDto
|
|
|
9
9
|
from src.services.test_case_service import TestCaseService
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def _format_steps(scenario:
|
|
12
|
+
def _format_steps(scenario: object) -> str:
|
|
13
13
|
"""Format steps for display."""
|
|
14
|
-
|
|
14
|
+
steps = getattr(scenario, "steps", None)
|
|
15
|
+
if not isinstance(steps, list) or not steps:
|
|
15
16
|
return "No steps."
|
|
16
17
|
|
|
17
18
|
output = []
|
|
18
|
-
for i, step in enumerate(
|
|
19
|
+
for i, step in enumerate(steps):
|
|
19
20
|
if step.actual_instance and isinstance(step.actual_instance, SharedStepStepDto):
|
|
20
21
|
output.append(f"{i + 1}. [Shared Step] ID: {step.actual_instance.shared_step_id}")
|
|
21
22
|
else:
|
|
@@ -30,8 +31,12 @@ async def unlink_shared_step(
|
|
|
30
31
|
test_case_id: Annotated[int, Field(description="The test case to modify.")],
|
|
31
32
|
shared_step_id: Annotated[int, Field(description="The shared step to unlink.")],
|
|
32
33
|
project_id: Annotated[int | None, Field(description="Optional override for the default Project ID.")] = None,
|
|
34
|
+
confirm: Annotated[
|
|
35
|
+
bool, Field(description="Must be set to True to proceed with unlinking. Safety measure.")
|
|
36
|
+
] = False,
|
|
33
37
|
) -> str:
|
|
34
38
|
"""Remove a shared step reference from a test case.
|
|
39
|
+
⚠️ CAUTION: Destructive.
|
|
35
40
|
|
|
36
41
|
Removes the link to the shared step. The test case will no longer
|
|
37
42
|
include those steps at execution time.
|
|
@@ -40,6 +45,8 @@ async def unlink_shared_step(
|
|
|
40
45
|
test_case_id: The test case to modify.
|
|
41
46
|
shared_step_id: The shared step to unlink.
|
|
42
47
|
project_id: Optional override for the default Project ID.
|
|
48
|
+
confirm: Must be set to True to proceed with unlinking.
|
|
49
|
+
This is a safety measure to prevent accidental unlinking.
|
|
43
50
|
|
|
44
51
|
Returns:
|
|
45
52
|
Confirmation with updated step list.
|
|
@@ -48,8 +55,15 @@ async def unlink_shared_step(
|
|
|
48
55
|
remains in the library and other test cases are unaffected.
|
|
49
56
|
|
|
50
57
|
Example:
|
|
51
|
-
unlink_shared_step(test_case_id=12345, shared_step_id=789)
|
|
58
|
+
unlink_shared_step(test_case_id=12345, shared_step_id=789, confirm=True)
|
|
52
59
|
"""
|
|
60
|
+
if not confirm:
|
|
61
|
+
return (
|
|
62
|
+
"⚠️ Unlinking requires confirmation.\n\n"
|
|
63
|
+
"This will remove a shared step from the test case scenario. "
|
|
64
|
+
f"Please call again with confirm=True to proceed with unlinking "
|
|
65
|
+
f"shared step {shared_step_id} from test case {test_case_id}."
|
|
66
|
+
)
|
|
53
67
|
|
|
54
68
|
async with AllureClient.from_env(project=project_id) as client:
|
|
55
69
|
service = TestCaseService(client=client)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from typing import Annotated
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
|
|
5
|
+
from src.client import AllureClient
|
|
6
|
+
from src.services.custom_field_value_service import CustomFieldValueService
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def update_custom_field_value(
|
|
10
|
+
cfv_id: Annotated[int, Field(description="Custom field value ID to update.")],
|
|
11
|
+
name: Annotated[str, Field(description="New name for the custom field value.")],
|
|
12
|
+
custom_field_id: Annotated[
|
|
13
|
+
int | None,
|
|
14
|
+
Field(description="Project-scoped custom field ID (optional, resolves by name if missing)."),
|
|
15
|
+
] = None,
|
|
16
|
+
custom_field_name: Annotated[
|
|
17
|
+
str | None,
|
|
18
|
+
Field(description="Custom field name to resolve when custom_field_id is not provided."),
|
|
19
|
+
] = None,
|
|
20
|
+
project_id: Annotated[int | None, Field(description="Optional override for the default Project ID.")] = None,
|
|
21
|
+
confirm: Annotated[bool, Field(description="Must be set to True to proceed with update. Safety measure.")] = False,
|
|
22
|
+
) -> str:
|
|
23
|
+
"""Update an existing custom field value.
|
|
24
|
+
⚠️ CAUTION: Destructive.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
cfv_id: Custom field value ID to update.
|
|
28
|
+
name: New name for the custom field value.
|
|
29
|
+
custom_field_id: Project-scoped custom field ID (optional, resolves by name if missing).
|
|
30
|
+
custom_field_name: Custom field name to resolve when custom_field_id is not provided.
|
|
31
|
+
project_id: Optional Allure TestOps project ID override.
|
|
32
|
+
confirm: Must be set to True to proceed with update.
|
|
33
|
+
This is a safety measure to prevent accidental updates.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Confirmation message indicating whether changes were made.
|
|
37
|
+
"""
|
|
38
|
+
if not confirm:
|
|
39
|
+
return (
|
|
40
|
+
"⚠️ Update requires confirmation.\n\n"
|
|
41
|
+
"Updating a custom field value affects all test cases using it. "
|
|
42
|
+
f"Please call again with confirm=True to proceed with updating custom field value {cfv_id}."
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
async with AllureClient.from_env(project=project_id) as client:
|
|
46
|
+
service = CustomFieldValueService(client=client)
|
|
47
|
+
await service.update_custom_field_value(
|
|
48
|
+
project_id=project_id,
|
|
49
|
+
cfv_id=cfv_id,
|
|
50
|
+
custom_field_id=custom_field_id,
|
|
51
|
+
custom_field_name=custom_field_name,
|
|
52
|
+
name=name,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return f"✅ Custom field value {cfv_id} updated successfully!\nNew name: {name}"
|
src/tools/update_test_case.py
CHANGED
|
@@ -33,14 +33,48 @@ async def update_test_case( # noqa: C901
|
|
|
33
33
|
expected_result: Annotated[str | None, Field(description="Global expected result for the test case")] = None,
|
|
34
34
|
status_id: Annotated[int | None, Field(description="ID of the test case status")] = None,
|
|
35
35
|
test_layer_id: Annotated[int | None, Field(description="ID of the test layer")] = None,
|
|
36
|
+
test_layer_name: Annotated[str | None, Field(description="Name of the test layer")] = None,
|
|
36
37
|
workflow_id: Annotated[int | None, Field(description="ID of the workflow")] = None,
|
|
37
38
|
links: Annotated[
|
|
38
39
|
list[dict[str, str]] | None,
|
|
39
40
|
Field(description="New list of external links. Each dict has 'name', 'url', and optional 'type'."),
|
|
40
41
|
] = None,
|
|
42
|
+
# Issue Linking
|
|
43
|
+
issues: Annotated[
|
|
44
|
+
list[str] | None,
|
|
45
|
+
Field(description="List of issue keys to ADD (e.g. ['PROJ-123'])."),
|
|
46
|
+
] = None,
|
|
47
|
+
remove_issues: Annotated[
|
|
48
|
+
list[str] | None,
|
|
49
|
+
Field(description="List of issue keys to REMOVE."),
|
|
50
|
+
] = None,
|
|
51
|
+
clear_issues: Annotated[
|
|
52
|
+
bool | None,
|
|
53
|
+
Field(description="If True, remove ALL issues from the test case."),
|
|
54
|
+
] = None,
|
|
55
|
+
integration_id: Annotated[
|
|
56
|
+
int | None,
|
|
57
|
+
Field(
|
|
58
|
+
description=(
|
|
59
|
+
"Optional integration ID for issue linking (use list_integrations to find IDs). "
|
|
60
|
+
"Required when multiple integrations exist and adding issues. Mutually exclusive with integration_name."
|
|
61
|
+
)
|
|
62
|
+
),
|
|
63
|
+
] = None,
|
|
64
|
+
integration_name: Annotated[
|
|
65
|
+
str | None,
|
|
66
|
+
Field(
|
|
67
|
+
description=(
|
|
68
|
+
"Optional integration name for issue linking (exact case-sensitive match). "
|
|
69
|
+
"Required when multiple integrations exist and adding issues. Mutually exclusive with integration_id."
|
|
70
|
+
)
|
|
71
|
+
),
|
|
72
|
+
] = None,
|
|
41
73
|
project_id: Annotated[int | None, Field(description="Optional override for the default Project ID.")] = None,
|
|
74
|
+
confirm: Annotated[bool, Field(description="Must be set to True to proceed with update. Safety measure.")] = False,
|
|
42
75
|
) -> str:
|
|
43
76
|
"""Update an existing test case in Allure TestOps.
|
|
77
|
+
⚠️ CAUTION: Destructive.
|
|
44
78
|
|
|
45
79
|
Performs a partial update: only supplied fields are sent to the API. When
|
|
46
80
|
provided, ``steps`` replace all existing steps, and ``attachments`` replace
|
|
@@ -61,10 +95,18 @@ async def update_test_case( # noqa: C901
|
|
|
61
95
|
expected_result: Global expected result for the test case.
|
|
62
96
|
status_id: ID of the test case status.
|
|
63
97
|
test_layer_id: ID of the test layer.
|
|
98
|
+
test_layer_name: Name of the test layer.
|
|
64
99
|
workflow_id: ID of the workflow.
|
|
65
100
|
links: New list of external links. Each dict has ``name``, ``url``,
|
|
66
101
|
and optional ``type``.
|
|
102
|
+
issues: List of issue keys to ADD (e.g. ['PROJ-123']).
|
|
103
|
+
remove_issues: List of issue keys to REMOVE.
|
|
104
|
+
clear_issues: If True, remove ALL issues from the test case.
|
|
105
|
+
integration_id: Optional integration ID for issue linking.
|
|
106
|
+
integration_name: Optional integration name for issue linking.
|
|
67
107
|
project_id: Optional override for the default Project ID.
|
|
108
|
+
confirm: Must be set to True to proceed with update.
|
|
109
|
+
This is a safety measure to prevent accidental updates.
|
|
68
110
|
|
|
69
111
|
Returns:
|
|
70
112
|
A confirmation message summarizing the update.
|
|
@@ -73,6 +115,12 @@ async def update_test_case( # noqa: C901
|
|
|
73
115
|
AuthenticationError: If no API token available from environment or
|
|
74
116
|
arguments.
|
|
75
117
|
"""
|
|
118
|
+
if not confirm:
|
|
119
|
+
return (
|
|
120
|
+
"⚠️ Update requires confirmation.\n\n"
|
|
121
|
+
"This will modify test case properties and may overwrite existing data. "
|
|
122
|
+
f"Please call again with confirm=True to proceed with updating test case {test_case_id}."
|
|
123
|
+
)
|
|
76
124
|
|
|
77
125
|
async with AllureClient.from_env(project=project_id) as client:
|
|
78
126
|
service = TestCaseService(client=client)
|
|
@@ -89,8 +137,14 @@ async def update_test_case( # noqa: C901
|
|
|
89
137
|
expected_result=expected_result,
|
|
90
138
|
status_id=status_id,
|
|
91
139
|
test_layer_id=test_layer_id,
|
|
140
|
+
test_layer_name=test_layer_name,
|
|
92
141
|
workflow_id=workflow_id,
|
|
93
142
|
links=links,
|
|
143
|
+
issues=issues,
|
|
144
|
+
remove_issues=remove_issues,
|
|
145
|
+
clear_issues=clear_issues,
|
|
146
|
+
integration_id=integration_id,
|
|
147
|
+
integration_name=integration_name,
|
|
94
148
|
)
|
|
95
149
|
|
|
96
150
|
updated_case = await service.update_test_case(test_case_id, update_data)
|
|
@@ -130,10 +184,14 @@ async def update_test_case( # noqa: C901
|
|
|
130
184
|
current_status_id = getattr(current_status, "id", None) if current_status else None
|
|
131
185
|
if status_id != current_status_id:
|
|
132
186
|
changes.append("status updated")
|
|
133
|
-
if test_layer_id is not None:
|
|
187
|
+
if test_layer_id is not None or test_layer_name is not None:
|
|
134
188
|
current_test_layer = getattr(current_case, "test_layer", None)
|
|
135
189
|
current_test_layer_id = getattr(current_test_layer, "id", None) if current_test_layer else None
|
|
136
|
-
|
|
190
|
+
|
|
191
|
+
updated_test_layer = getattr(updated_case, "test_layer", None)
|
|
192
|
+
updated_test_layer_id = getattr(updated_test_layer, "id", None) if updated_test_layer else None
|
|
193
|
+
|
|
194
|
+
if updated_test_layer_id != current_test_layer_id:
|
|
137
195
|
changes.append("test layer updated")
|
|
138
196
|
if workflow_id is not None:
|
|
139
197
|
current_workflow = getattr(current_case, "workflow", None)
|
|
@@ -145,6 +203,13 @@ async def update_test_case( # noqa: C901
|
|
|
145
203
|
if normalize_links(current_links) != normalize_links(links):
|
|
146
204
|
changes.append("links updated")
|
|
147
205
|
|
|
206
|
+
if issues:
|
|
207
|
+
changes.append(f"added {len(issues)} issues ({', '.join(issues)})")
|
|
208
|
+
if remove_issues:
|
|
209
|
+
changes.append(f"removed {len(remove_issues)} issues ({', '.join(remove_issues)})")
|
|
210
|
+
if clear_issues:
|
|
211
|
+
changes.append("cleared all issues")
|
|
212
|
+
|
|
148
213
|
summary = ", ".join(changes) if changes else "No changes made (idempotent)"
|
|
149
214
|
|
|
150
215
|
return f"Test Case {updated_case.id} updated successfully. Changes: {summary}"
|
src/tools/update_test_layer.py
CHANGED
|
@@ -12,17 +12,28 @@ async def update_test_layer(
|
|
|
12
12
|
layer_id: Annotated[int, Field(description="ID of the test layer to update.")],
|
|
13
13
|
name: Annotated[str, Field(description="New name for the test layer.")],
|
|
14
14
|
project_id: Annotated[int | None, Field(description="Allure TestOps project ID.")] = None,
|
|
15
|
+
confirm: Annotated[bool, Field(description="Must be set to True to proceed with update. Safety measure.")] = False,
|
|
15
16
|
) -> str:
|
|
16
17
|
"""Update an existing test layer's name.
|
|
18
|
+
⚠️ CAUTION: Destructive.
|
|
17
19
|
|
|
18
20
|
Args:
|
|
19
|
-
layer_id: ID of the test layer to update
|
|
20
|
-
name: New name for the test layer
|
|
21
|
-
project_id: Optional project ID override
|
|
21
|
+
layer_id: ID of the test layer to update.
|
|
22
|
+
name: New name for the test layer.
|
|
23
|
+
project_id: Optional Allure TestOps project ID override.
|
|
24
|
+
confirm: Must be set to True to proceed with update.
|
|
25
|
+
This is a safety measure to prevent accidental updates.
|
|
22
26
|
|
|
23
27
|
Returns:
|
|
24
|
-
Confirmation message indicating whether changes were made
|
|
28
|
+
Confirmation message indicating whether changes were made.
|
|
25
29
|
"""
|
|
30
|
+
if not confirm:
|
|
31
|
+
return (
|
|
32
|
+
"⚠️ Update requires confirmation.\n\n"
|
|
33
|
+
"Renaming a test layer affects all associated test cases. "
|
|
34
|
+
f"Please call again with confirm=True to proceed with updating test layer {layer_id}."
|
|
35
|
+
)
|
|
36
|
+
|
|
26
37
|
async with AllureClient.from_env(project=project_id) as client:
|
|
27
38
|
service = TestLayerService(client)
|
|
28
39
|
updated, changed = await service.update_test_layer(layer_id=layer_id, name=name)
|
|
@@ -13,18 +13,29 @@ async def update_test_layer_schema(
|
|
|
13
13
|
test_layer_id: Annotated[int | None, Field(description="New test layer ID to link to.")] = None,
|
|
14
14
|
key: Annotated[str | None, Field(description="New schema key.")] = None,
|
|
15
15
|
project_id: Annotated[int | None, Field(description="Allure TestOps project ID.")] = None,
|
|
16
|
+
confirm: Annotated[bool, Field(description="Must be set to True to proceed with update. Safety measure.")] = False,
|
|
16
17
|
) -> str:
|
|
17
18
|
"""Update an existing test layer schema.
|
|
19
|
+
⚠️ CAUTION: Destructive.
|
|
18
20
|
|
|
19
21
|
Args:
|
|
20
|
-
schema_id: ID of the schema to update
|
|
21
|
-
test_layer_id: Optional new test layer ID
|
|
22
|
-
key: Optional new schema key
|
|
23
|
-
project_id: Optional project ID override
|
|
22
|
+
schema_id: ID of the schema to update.
|
|
23
|
+
test_layer_id: Optional new test layer ID to link to.
|
|
24
|
+
key: Optional new schema key.
|
|
25
|
+
project_id: Optional Allure TestOps project ID override.
|
|
26
|
+
confirm: Must be set to True to proceed with update.
|
|
27
|
+
This is a safety measure to prevent accidental updates.
|
|
24
28
|
|
|
25
29
|
Returns:
|
|
26
|
-
Confirmation message indicating whether changes were made
|
|
30
|
+
Confirmation message indicating whether changes were made.
|
|
27
31
|
"""
|
|
32
|
+
if not confirm:
|
|
33
|
+
return (
|
|
34
|
+
"⚠️ Update requires confirmation.\n\n"
|
|
35
|
+
"Modifying a schema affects how test layers are automatically assigned. "
|
|
36
|
+
f"Please call again with confirm=True to proceed with updating test layer schema {schema_id}."
|
|
37
|
+
)
|
|
38
|
+
|
|
28
39
|
async with AllureClient.from_env(project=project_id) as client:
|
|
29
40
|
service = TestLayerService(client)
|
|
30
41
|
updated, changed = await service.update_test_layer_schema(
|