vellum-ai 1.11.2__py3-none-any.whl → 1.13.5__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.
Potentially problematic release.
This version of vellum-ai might be problematic. Click here for more details.
- vellum/__init__.py +18 -0
- vellum/client/README.md +1 -1
- vellum/client/core/client_wrapper.py +2 -2
- vellum/client/core/force_multipart.py +4 -2
- vellum/client/core/http_response.py +1 -1
- vellum/client/core/pydantic_utilities.py +7 -4
- vellum/client/errors/too_many_requests_error.py +1 -2
- vellum/client/reference.md +677 -76
- vellum/client/resources/container_images/client.py +299 -0
- vellum/client/resources/container_images/raw_client.py +286 -0
- vellum/client/resources/documents/client.py +20 -10
- vellum/client/resources/documents/raw_client.py +20 -10
- vellum/client/resources/events/raw_client.py +4 -4
- vellum/client/resources/integration_auth_configs/client.py +2 -0
- vellum/client/resources/integration_auth_configs/raw_client.py +2 -0
- vellum/client/resources/integration_providers/client.py +28 -2
- vellum/client/resources/integration_providers/raw_client.py +24 -0
- vellum/client/resources/integrations/client.py +52 -4
- vellum/client/resources/integrations/raw_client.py +61 -0
- vellum/client/resources/workflow_deployments/client.py +156 -0
- vellum/client/resources/workflow_deployments/raw_client.py +334 -0
- vellum/client/resources/workflows/client.py +212 -8
- vellum/client/resources/workflows/raw_client.py +343 -6
- vellum/client/types/__init__.py +18 -0
- vellum/client/types/api_actor_type_enum.py +1 -1
- vellum/client/types/check_workflow_execution_status_error.py +21 -0
- vellum/client/types/check_workflow_execution_status_response.py +29 -0
- vellum/client/types/code_execution_package_request.py +21 -0
- vellum/client/types/composio_execute_tool_request.py +5 -0
- vellum/client/types/composio_tool_definition.py +1 -0
- vellum/client/types/container_image_build_config.py +1 -0
- vellum/client/types/container_image_container_image_tag.py +1 -0
- vellum/client/types/dataset_row_push_request.py +3 -0
- vellum/client/types/document_document_to_document_index.py +1 -0
- vellum/client/types/integration_name.py +24 -0
- vellum/client/types/node_execution_fulfilled_body.py +1 -0
- vellum/client/types/node_execution_log_body.py +24 -0
- vellum/client/types/node_execution_log_event.py +47 -0
- vellum/client/types/prompt_deployment_release_prompt_deployment.py +1 -0
- vellum/client/types/runner_config_request.py +24 -0
- vellum/client/types/severity_enum.py +5 -0
- vellum/client/types/slim_composio_tool_definition.py +1 -0
- vellum/client/types/slim_document_document_to_document_index.py +2 -0
- vellum/client/types/type_checker_enum.py +5 -0
- vellum/client/types/vellum_audio.py +5 -1
- vellum/client/types/vellum_audio_request.py +5 -1
- vellum/client/types/vellum_document.py +5 -1
- vellum/client/types/vellum_document_request.py +5 -1
- vellum/client/types/vellum_image.py +5 -1
- vellum/client/types/vellum_image_request.py +5 -1
- vellum/client/types/vellum_node_execution_event.py +2 -0
- vellum/client/types/vellum_variable.py +5 -0
- vellum/client/types/vellum_variable_extensions.py +1 -0
- vellum/client/types/vellum_variable_type.py +1 -0
- vellum/client/types/vellum_video.py +5 -1
- vellum/client/types/vellum_video_request.py +5 -1
- vellum/client/types/workflow_deployment_release_workflow_deployment.py +1 -0
- vellum/client/types/workflow_event.py +2 -0
- vellum/client/types/workflow_execution_fulfilled_body.py +1 -0
- vellum/client/types/workflow_result_event_output_data_array.py +1 -1
- vellum/client/types/workflow_result_event_output_data_chat_history.py +1 -1
- vellum/client/types/workflow_result_event_output_data_error.py +1 -1
- vellum/client/types/workflow_result_event_output_data_function_call.py +1 -1
- vellum/client/types/workflow_result_event_output_data_json.py +1 -1
- vellum/client/types/workflow_result_event_output_data_number.py +1 -1
- vellum/client/types/workflow_result_event_output_data_search_results.py +1 -1
- vellum/client/types/workflow_result_event_output_data_string.py +1 -1
- vellum/client/types/workflow_sandbox_execute_node_response.py +8 -0
- vellum/plugins/vellum_mypy.py +37 -2
- vellum/types/check_workflow_execution_status_error.py +3 -0
- vellum/types/check_workflow_execution_status_response.py +3 -0
- vellum/types/code_execution_package_request.py +3 -0
- vellum/types/node_execution_log_body.py +3 -0
- vellum/types/node_execution_log_event.py +3 -0
- vellum/types/runner_config_request.py +3 -0
- vellum/types/severity_enum.py +3 -0
- vellum/types/type_checker_enum.py +3 -0
- vellum/types/workflow_sandbox_execute_node_response.py +3 -0
- vellum/utils/files/mixin.py +26 -0
- vellum/utils/files/tests/test_mixin.py +62 -0
- vellum/utils/tests/test_vellum_client.py +95 -0
- vellum/utils/uuid.py +19 -2
- vellum/utils/vellum_client.py +10 -3
- vellum/workflows/__init__.py +7 -1
- vellum/workflows/descriptors/base.py +86 -0
- vellum/workflows/descriptors/tests/test_utils.py +9 -0
- vellum/workflows/errors/tests/__init__.py +0 -0
- vellum/workflows/errors/tests/test_types.py +52 -0
- vellum/workflows/errors/types.py +1 -0
- vellum/workflows/events/node.py +24 -0
- vellum/workflows/events/tests/test_event.py +123 -0
- vellum/workflows/events/types.py +2 -1
- vellum/workflows/events/workflow.py +28 -2
- vellum/workflows/expressions/add.py +3 -0
- vellum/workflows/expressions/tests/test_add.py +24 -0
- vellum/workflows/graph/graph.py +26 -5
- vellum/workflows/graph/tests/test_graph.py +228 -1
- vellum/workflows/inputs/base.py +22 -6
- vellum/workflows/inputs/dataset_row.py +121 -16
- vellum/workflows/inputs/tests/test_inputs.py +3 -3
- vellum/workflows/integrations/tests/test_vellum_integration_service.py +84 -0
- vellum/workflows/integrations/vellum_integration_service.py +12 -1
- vellum/workflows/loaders/base.py +2 -0
- vellum/workflows/nodes/bases/base.py +37 -16
- vellum/workflows/nodes/bases/tests/test_base_node.py +104 -1
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py +1 -0
- vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py +1 -1
- vellum/workflows/nodes/core/map_node/node.py +7 -5
- vellum/workflows/nodes/core/map_node/tests/test_node.py +33 -0
- vellum/workflows/nodes/core/retry_node/node.py +1 -0
- vellum/workflows/nodes/core/try_node/node.py +1 -0
- vellum/workflows/nodes/displayable/api_node/node.py +3 -2
- vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +38 -0
- vellum/workflows/nodes/displayable/bases/api_node/node.py +1 -1
- vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +18 -1
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +109 -2
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +13 -2
- vellum/workflows/nodes/displayable/code_execution_node/node.py +9 -15
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_node.py +65 -24
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +3 -0
- vellum/workflows/nodes/displayable/final_output_node/node.py +24 -69
- vellum/workflows/nodes/displayable/final_output_node/tests/test_node.py +53 -3
- vellum/workflows/nodes/displayable/note_node/node.py +4 -1
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +16 -5
- vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +47 -0
- vellum/workflows/nodes/displayable/tool_calling_node/node.py +74 -34
- vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py +204 -8
- vellum/workflows/nodes/displayable/tool_calling_node/utils.py +92 -71
- vellum/workflows/nodes/mocks.py +47 -213
- vellum/workflows/nodes/tests/test_mocks.py +0 -177
- vellum/workflows/nodes/utils.py +23 -8
- vellum/workflows/outputs/base.py +36 -3
- vellum/workflows/references/environment_variable.py +1 -11
- vellum/workflows/references/lazy.py +8 -0
- vellum/workflows/references/state_value.py +24 -1
- vellum/workflows/references/tests/test_lazy.py +58 -0
- vellum/workflows/references/trigger.py +8 -3
- vellum/workflows/references/workflow_input.py +8 -0
- vellum/workflows/resolvers/resolver.py +13 -3
- vellum/workflows/resolvers/tests/test_resolver.py +31 -0
- vellum/workflows/runner/runner.py +159 -14
- vellum/workflows/runner/tests/__init__.py +0 -0
- vellum/workflows/runner/tests/test_runner.py +170 -0
- vellum/workflows/sandbox.py +7 -8
- vellum/workflows/state/base.py +89 -30
- vellum/workflows/state/context.py +74 -3
- vellum/workflows/state/tests/test_state.py +269 -1
- vellum/workflows/tests/test_dataset_row.py +8 -7
- vellum/workflows/tests/test_sandbox.py +97 -8
- vellum/workflows/triggers/__init__.py +2 -1
- vellum/workflows/triggers/base.py +160 -28
- vellum/workflows/triggers/chat_message.py +141 -0
- vellum/workflows/triggers/integration.py +12 -0
- vellum/workflows/triggers/manual.py +3 -1
- vellum/workflows/triggers/schedule.py +3 -1
- vellum/workflows/triggers/tests/test_chat_message.py +257 -0
- vellum/workflows/types/core.py +18 -0
- vellum/workflows/types/definition.py +6 -13
- vellum/workflows/types/generics.py +12 -0
- vellum/workflows/types/tests/test_utils.py +12 -0
- vellum/workflows/types/utils.py +32 -2
- vellum/workflows/types/workflow_metadata.py +124 -0
- vellum/workflows/utils/functions.py +152 -16
- vellum/workflows/utils/pydantic_schema.py +19 -1
- vellum/workflows/utils/tests/test_functions.py +123 -8
- vellum/workflows/utils/tests/test_validate.py +79 -0
- vellum/workflows/utils/tests/test_vellum_variables.py +62 -2
- vellum/workflows/utils/uuids.py +90 -0
- vellum/workflows/utils/validate.py +108 -0
- vellum/workflows/utils/vellum_variables.py +96 -16
- vellum/workflows/workflows/base.py +177 -35
- vellum/workflows/workflows/tests/test_base_workflow.py +51 -0
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/METADATA +6 -1
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/RECORD +274 -227
- vellum_cli/__init__.py +21 -0
- vellum_cli/config.py +16 -2
- vellum_cli/pull.py +2 -0
- vellum_cli/push.py +23 -10
- vellum_cli/tests/conftest.py +8 -13
- vellum_cli/tests/test_image_push.py +4 -11
- vellum_cli/tests/test_pull.py +83 -68
- vellum_cli/tests/test_push.py +251 -2
- vellum_ee/assets/node-definitions.json +225 -12
- vellum_ee/scripts/generate_node_definitions.py +15 -3
- vellum_ee/workflows/display/base.py +4 -3
- vellum_ee/workflows/display/nodes/base_node_display.py +44 -11
- vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +93 -0
- vellum_ee/workflows/display/nodes/types.py +1 -0
- vellum_ee/workflows/display/nodes/vellum/__init__.py +0 -2
- vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +5 -2
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +10 -2
- vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +17 -14
- vellum_ee/workflows/display/nodes/vellum/map_node.py +2 -0
- vellum_ee/workflows/display/nodes/vellum/note_node.py +18 -3
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +37 -14
- vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +62 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_final_output_node.py +136 -0
- vellum_ee/workflows/display/nodes/vellum/tests/test_note_node.py +44 -7
- vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +5 -13
- vellum_ee/workflows/display/nodes/vellum/tests/test_subworkflow_deployment_node.py +27 -17
- vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py +145 -22
- vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +107 -2
- vellum_ee/workflows/display/nodes/vellum/utils.py +54 -12
- vellum_ee/workflows/display/tests/test_base_workflow_display.py +13 -16
- vellum_ee/workflows/display/tests/test_json_schema_validation.py +190 -0
- vellum_ee/workflows/display/tests/test_mocks.py +912 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +14 -2
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +109 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +3 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +187 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +34 -325
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +42 -393
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +13 -315
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +2 -122
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +24 -115
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +4 -93
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +7 -80
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +9 -101
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +77 -308
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +62 -324
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +3 -82
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +4 -142
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +1 -61
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_set_state_node_serialization.py +4 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +205 -134
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +34 -146
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +2 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_composio_serialization.py +8 -6
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +137 -266
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_tool_wrapper_serialization.py +84 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_mcp_serialization.py +55 -16
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +15 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_tool_wrapper_serialization.py +71 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_vellum_integration_serialization.py +119 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_workflow_deployment_serialization.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +0 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_chat_message_dict_reference_serialization.py +22 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_chat_message_trigger_serialization.py +412 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_code_tool_node_reference_error.py +106 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +9 -41
- vellum_ee/workflows/display/tests/workflow_serialization/test_duplicate_trigger_name_validation.py +208 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_final_output_node_not_referenced_by_workflow_outputs.py +45 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_infinite_loop_validation.py +66 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_int_input_serialization.py +40 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_serialization.py +8 -14
- vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_validation.py +173 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_with_entrypoint_node_id.py +16 -13
- vellum_ee/workflows/display/tests/workflow_serialization/test_list_vellum_document_serialization.py +5 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_manual_trigger_serialization.py +12 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_multi_trigger_same_node_serialization.py +111 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_no_triggers_no_entrypoint_validation.py +64 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_partial_workflow_meta_display_override.py +55 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_dataset_mocks_serialization.py +268 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_invalid_pdf_data_url.py +49 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_validation_errors.py +112 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_scheduled_trigger_serialization.py +25 -16
- vellum_ee/workflows/display/tests/workflow_serialization/test_terminal_node_in_unused_graphs_serialization.py +53 -0
- vellum_ee/workflows/display/utils/exceptions.py +34 -0
- vellum_ee/workflows/display/utils/expressions.py +463 -52
- vellum_ee/workflows/display/utils/metadata.py +98 -33
- vellum_ee/workflows/display/utils/tests/test_metadata.py +31 -0
- vellum_ee/workflows/display/utils/triggers.py +153 -0
- vellum_ee/workflows/display/utils/vellum.py +59 -5
- vellum_ee/workflows/display/workflows/base_workflow_display.py +656 -254
- vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +26 -0
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +77 -29
- vellum_ee/workflows/server/namespaces.py +18 -0
- vellum_ee/workflows/tests/test_display_meta.py +2 -0
- vellum_ee/workflows/tests/test_serialize_module.py +174 -7
- vellum_ee/workflows/tests/test_server.py +0 -3
- vellum_ee/workflows/display/nodes/vellum/function_node.py +0 -14
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/LICENSE +0 -0
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/WHEEL +0 -0
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/entry_points.txt +0 -0
vellum_cli/__init__.py
CHANGED
|
@@ -208,6 +208,11 @@ Helpful for running and debugging workflows locally.""",
|
|
|
208
208
|
help="""Directory to pull the workflow into. If not specified, \
|
|
209
209
|
the workflow will be pulled into the current working directory.""",
|
|
210
210
|
)
|
|
211
|
+
@click.option(
|
|
212
|
+
"--release-tag",
|
|
213
|
+
type=str,
|
|
214
|
+
help="""Release tag to use when pulling from a deployment.""",
|
|
215
|
+
)
|
|
211
216
|
def pull(
|
|
212
217
|
ctx: click.Context,
|
|
213
218
|
include_json: Optional[bool],
|
|
@@ -215,6 +220,7 @@ def pull(
|
|
|
215
220
|
strict: Optional[bool],
|
|
216
221
|
include_sandbox: Optional[bool],
|
|
217
222
|
target_directory: Optional[str],
|
|
223
|
+
release_tag: Optional[str],
|
|
218
224
|
) -> None:
|
|
219
225
|
"""Pull Resources from Vellum"""
|
|
220
226
|
|
|
@@ -225,6 +231,7 @@ def pull(
|
|
|
225
231
|
strict=strict,
|
|
226
232
|
include_sandbox=include_sandbox,
|
|
227
233
|
target_directory=target_directory,
|
|
234
|
+
release_tag=release_tag,
|
|
228
235
|
)
|
|
229
236
|
|
|
230
237
|
|
|
@@ -271,6 +278,11 @@ the workflow will be pulled into the current working directory.""",
|
|
|
271
278
|
type=str,
|
|
272
279
|
help="The specific Workspace config to use when pulling",
|
|
273
280
|
)
|
|
281
|
+
@click.option(
|
|
282
|
+
"--release-tag",
|
|
283
|
+
type=str,
|
|
284
|
+
help="""Release tag to use when pulling from a deployment.""",
|
|
285
|
+
)
|
|
274
286
|
def workflows_pull(
|
|
275
287
|
module: Optional[str],
|
|
276
288
|
include_json: Optional[bool],
|
|
@@ -281,6 +293,7 @@ def workflows_pull(
|
|
|
281
293
|
include_sandbox: Optional[bool],
|
|
282
294
|
target_directory: Optional[str],
|
|
283
295
|
workspace: Optional[str],
|
|
296
|
+
release_tag: Optional[str],
|
|
284
297
|
) -> None:
|
|
285
298
|
"""
|
|
286
299
|
Pull Workflows from Vellum. If a module is provided, only the Workflow for that module will be pulled.
|
|
@@ -297,6 +310,7 @@ def workflows_pull(
|
|
|
297
310
|
include_sandbox=include_sandbox,
|
|
298
311
|
target_directory=target_directory,
|
|
299
312
|
workspace=workspace,
|
|
313
|
+
release_tag=release_tag,
|
|
300
314
|
)
|
|
301
315
|
|
|
302
316
|
|
|
@@ -332,6 +346,11 @@ Helpful for running and debugging resources locally.""",
|
|
|
332
346
|
help="""Directory to pull the workflow into. If not specified, \
|
|
333
347
|
the workflow will be pulled into the current working directory.""",
|
|
334
348
|
)
|
|
349
|
+
@click.option(
|
|
350
|
+
"--release-tag",
|
|
351
|
+
type=str,
|
|
352
|
+
help="""Release tag to use when pulling from a deployment.""",
|
|
353
|
+
)
|
|
335
354
|
def pull_module(
|
|
336
355
|
ctx: click.Context,
|
|
337
356
|
include_json: Optional[bool],
|
|
@@ -339,6 +358,7 @@ def pull_module(
|
|
|
339
358
|
strict: Optional[bool],
|
|
340
359
|
include_sandbox: Optional[bool],
|
|
341
360
|
target_directory: Optional[str],
|
|
361
|
+
release_tag: Optional[str],
|
|
342
362
|
) -> None:
|
|
343
363
|
"""Pull a specific module from Vellum"""
|
|
344
364
|
|
|
@@ -350,6 +370,7 @@ def pull_module(
|
|
|
350
370
|
strict=strict,
|
|
351
371
|
include_sandbox=include_sandbox,
|
|
352
372
|
target_directory=target_directory,
|
|
373
|
+
release_tag=release_tag,
|
|
353
374
|
)
|
|
354
375
|
|
|
355
376
|
|
vellum_cli/config.py
CHANGED
|
@@ -120,22 +120,36 @@ def merge_workflows_by_sandbox_id(
|
|
|
120
120
|
else:
|
|
121
121
|
# If the user defines a workflow in the pyproject.toml with a sandbox_id,
|
|
122
122
|
# we merge the workflow with one of the ones in the lockfile with the same sandbox_id.
|
|
123
|
+
# First, try to find a lockfile workflow matching both sandbox_id AND workspace.
|
|
123
124
|
other_workflow = next(
|
|
124
125
|
(
|
|
125
126
|
other_workflow
|
|
126
127
|
for other_workflow in other_workflows
|
|
127
128
|
if self_workflow.workflow_sandbox_id == other_workflow.workflow_sandbox_id
|
|
129
|
+
and self_workflow.workspace == other_workflow.workspace
|
|
128
130
|
),
|
|
129
131
|
None,
|
|
130
132
|
)
|
|
133
|
+
# If no exact match, fall back to matching by sandbox_id alone.
|
|
134
|
+
if other_workflow is None:
|
|
135
|
+
other_workflow = next(
|
|
136
|
+
(
|
|
137
|
+
other_workflow
|
|
138
|
+
for other_workflow in other_workflows
|
|
139
|
+
if self_workflow.workflow_sandbox_id == other_workflow.workflow_sandbox_id
|
|
140
|
+
),
|
|
141
|
+
None,
|
|
142
|
+
)
|
|
131
143
|
if other_workflow is not None:
|
|
132
144
|
merged_workflows.append(self_workflow.merge(other_workflow))
|
|
133
145
|
else:
|
|
134
146
|
merged_workflows.append(self_workflow)
|
|
135
147
|
|
|
136
|
-
|
|
148
|
+
# Use (workflow_sandbox_id, workspace) as the dedupe key to preserve workflows
|
|
149
|
+
# with the same sandbox_id but different workspaces.
|
|
150
|
+
workflow_keys_so_far = {(workflow.workflow_sandbox_id, workflow.workspace) for workflow in merged_workflows}
|
|
137
151
|
for other_workflow in other_workflows:
|
|
138
|
-
if other_workflow.workflow_sandbox_id not in
|
|
152
|
+
if (other_workflow.workflow_sandbox_id, other_workflow.workspace) not in workflow_keys_so_far:
|
|
139
153
|
merged_workflows.append(other_workflow)
|
|
140
154
|
|
|
141
155
|
return merged_workflows
|
vellum_cli/pull.py
CHANGED
|
@@ -145,6 +145,7 @@ def pull_command(
|
|
|
145
145
|
include_sandbox: Optional[bool] = None,
|
|
146
146
|
target_directory: Optional[str] = None,
|
|
147
147
|
workspace: Optional[str] = None,
|
|
148
|
+
release_tag: Optional[str] = None,
|
|
148
149
|
) -> None:
|
|
149
150
|
load_dotenv(dotenv_path=os.path.join(os.getcwd(), ".env"))
|
|
150
151
|
logger = load_cli_logger()
|
|
@@ -198,6 +199,7 @@ def pull_command(
|
|
|
198
199
|
|
|
199
200
|
response = client.workflows.pull(
|
|
200
201
|
pk,
|
|
202
|
+
release_tag=release_tag,
|
|
201
203
|
request_options={"additional_query_parameters": query_parameters},
|
|
202
204
|
)
|
|
203
205
|
|
vellum_cli/push.py
CHANGED
|
@@ -130,13 +130,25 @@ def push_command(
|
|
|
130
130
|
)
|
|
131
131
|
sys.path.insert(0, os.getcwd())
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
try:
|
|
134
|
+
serialization_result = BaseWorkflowDisplay.serialize_module(
|
|
135
|
+
workflow_config.module,
|
|
136
|
+
client=client,
|
|
137
|
+
dry_run=dry_run or False,
|
|
138
|
+
)
|
|
139
|
+
except ValidationError as e:
|
|
140
|
+
handle_cli_error(
|
|
141
|
+
logger,
|
|
142
|
+
title=f"Validation error while trying to push {workflow_config.module}",
|
|
143
|
+
message=str(e),
|
|
144
|
+
)
|
|
145
|
+
except Exception as e:
|
|
146
|
+
handle_cli_error(
|
|
147
|
+
logger,
|
|
148
|
+
title=f"Error while trying to push {workflow_config.module}",
|
|
149
|
+
message=str(e),
|
|
150
|
+
)
|
|
151
|
+
|
|
140
152
|
exec_config = serialization_result.exec_config
|
|
141
153
|
|
|
142
154
|
container_tag = workflow_config.container_image_tag
|
|
@@ -189,7 +201,7 @@ def push_command(
|
|
|
189
201
|
module_dir = workflow_config.module.replace(".", os.path.sep)
|
|
190
202
|
for root, _, files in os.walk(module_dir):
|
|
191
203
|
for filename in files:
|
|
192
|
-
if not
|
|
204
|
+
if not BaseWorkflowDisplay.should_include_file(filename):
|
|
193
205
|
continue
|
|
194
206
|
|
|
195
207
|
file_path = os.path.join(root, filename)
|
|
@@ -208,16 +220,17 @@ def push_command(
|
|
|
208
220
|
|
|
209
221
|
provided_id = workflow_config.workflow_sandbox_id or workflow_sandbox_id
|
|
210
222
|
|
|
223
|
+
dataset_serialized = json.dumps(serialization_result.dataset) if serialization_result.dataset else OMIT
|
|
224
|
+
|
|
211
225
|
try:
|
|
212
226
|
response = client.workflows.push(
|
|
213
|
-
# Remove this once we could serialize using the artifact in Vembda
|
|
214
|
-
# https://app.shortcut.com/vellum/story/5585
|
|
215
227
|
exec_config=json.dumps(exec_config),
|
|
216
228
|
workflow_sandbox_id=provided_id,
|
|
217
229
|
artifact=artifact,
|
|
218
230
|
# We should check with fern if we could auto-serialize typed object fields for us
|
|
219
231
|
# https://app.shortcut.com/vellum/story/5568
|
|
220
232
|
deployment_config=deployment_config_serialized, # type: ignore[arg-type]
|
|
233
|
+
dataset=dataset_serialized, # type: ignore[arg-type]
|
|
221
234
|
dry_run=dry_run,
|
|
222
235
|
strict=strict,
|
|
223
236
|
)
|
vellum_cli/tests/conftest.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
from dataclasses import dataclass
|
|
3
|
-
import
|
|
4
|
-
import shutil
|
|
5
|
-
import tempfile
|
|
3
|
+
import pathlib
|
|
6
4
|
from uuid import uuid4
|
|
7
5
|
from typing import Any, Callable, Dict, Generator
|
|
8
6
|
|
|
@@ -18,17 +16,17 @@ class MockModuleResult:
|
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
@pytest.fixture
|
|
21
|
-
def mock_module(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
def mock_module(
|
|
20
|
+
request, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
21
|
+
) -> Generator[MockModuleResult, None, None]:
|
|
22
|
+
monkeypatch.chdir(tmp_path)
|
|
25
23
|
|
|
26
24
|
# Use the test name to create a unique module path
|
|
27
25
|
module = f"examples.mock.{request.node.name}"
|
|
28
26
|
workflow_sandbox_id = str(uuid4())
|
|
29
27
|
|
|
30
28
|
def set_pyproject_toml(vellum_config: Dict[str, Any]) -> None:
|
|
31
|
-
pyproject_toml_path =
|
|
29
|
+
pyproject_toml_path = tmp_path / "pyproject.toml"
|
|
32
30
|
with open(pyproject_toml_path, "wb") as f:
|
|
33
31
|
tomli_w.dump(
|
|
34
32
|
{"tool": {"vellum": vellum_config}},
|
|
@@ -46,19 +44,16 @@ def mock_module(request) -> Generator[MockModuleResult, None, None]:
|
|
|
46
44
|
}
|
|
47
45
|
)
|
|
48
46
|
|
|
49
|
-
with open(
|
|
47
|
+
with open(tmp_path / ".env", "w") as f:
|
|
50
48
|
f.write("VELLUM_API_KEY=abcdef123456")
|
|
51
49
|
|
|
52
50
|
yield MockModuleResult(
|
|
53
|
-
temp_dir=
|
|
51
|
+
temp_dir=str(tmp_path),
|
|
54
52
|
module=module,
|
|
55
53
|
set_pyproject_toml=set_pyproject_toml,
|
|
56
54
|
workflow_sandbox_id=workflow_sandbox_id,
|
|
57
55
|
)
|
|
58
56
|
|
|
59
|
-
os.chdir(current_dir)
|
|
60
|
-
shutil.rmtree(temp_dir)
|
|
61
|
-
|
|
62
57
|
|
|
63
58
|
@pytest.fixture
|
|
64
59
|
def info_log_level(monkeypatch):
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
|
-
import
|
|
4
|
+
import pathlib
|
|
5
5
|
import subprocess
|
|
6
|
-
import tempfile
|
|
7
6
|
from unittest.mock import MagicMock
|
|
8
7
|
from uuid import uuid4
|
|
9
8
|
from typing import Generator
|
|
@@ -16,15 +15,9 @@ from vellum_cli import main as cli_main
|
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
@pytest.fixture
|
|
19
|
-
def mock_temp_dir() -> Generator[str, None, None]:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
os.chdir(temp_dir)
|
|
23
|
-
|
|
24
|
-
yield temp_dir
|
|
25
|
-
|
|
26
|
-
os.chdir(current_dir)
|
|
27
|
-
shutil.rmtree(temp_dir)
|
|
18
|
+
def mock_temp_dir(monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path) -> Generator[str, None, None]:
|
|
19
|
+
monkeypatch.chdir(tmp_path)
|
|
20
|
+
yield str(tmp_path)
|
|
28
21
|
|
|
29
22
|
|
|
30
23
|
@pytest.fixture
|
vellum_cli/tests/test_pull.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
|
-
import
|
|
4
|
+
import pathlib
|
|
5
5
|
from unittest import mock
|
|
6
6
|
from uuid import uuid4
|
|
7
7
|
|
|
@@ -227,7 +227,7 @@ def test_pull__with_nested_target_dir(vellum_client, mock_module, base_command):
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
|
|
230
|
-
def test_pull__sandbox_id_with_no_config(vellum_client):
|
|
230
|
+
def test_pull__sandbox_id_with_no_config(vellum_client, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path):
|
|
231
231
|
# GIVEN a workflow sandbox id
|
|
232
232
|
workflow_sandbox_id = "87654321-0000-0000-0000-000000000000"
|
|
233
233
|
|
|
@@ -237,28 +237,25 @@ def test_pull__sandbox_id_with_no_config(vellum_client):
|
|
|
237
237
|
)
|
|
238
238
|
|
|
239
239
|
# AND we are currently in a new directory
|
|
240
|
-
|
|
241
|
-
temp_dir = tempfile.mkdtemp()
|
|
242
|
-
os.chdir(temp_dir)
|
|
240
|
+
monkeypatch.chdir(tmp_path)
|
|
243
241
|
|
|
244
242
|
# WHEN the user runs the pull command with the workflow sandbox id and no module
|
|
245
243
|
runner = CliRunner()
|
|
246
244
|
result = runner.invoke(cli_main, ["workflows", "pull", "--workflow-sandbox-id", workflow_sandbox_id])
|
|
247
|
-
os.chdir(current_dir)
|
|
248
245
|
|
|
249
246
|
# THEN the command returns successfully
|
|
250
247
|
assert result.exit_code == 0
|
|
251
248
|
|
|
252
249
|
# AND the pull api is called with the workflow sandbox id
|
|
253
250
|
vellum_client.workflows.pull.assert_called_once()
|
|
254
|
-
workflow_py =
|
|
255
|
-
assert
|
|
251
|
+
workflow_py = tmp_path / "super_cool_workflow" / "workflow.py"
|
|
252
|
+
assert workflow_py.exists()
|
|
256
253
|
with open(workflow_py) as f:
|
|
257
254
|
assert f.read() == "print('hello')"
|
|
258
255
|
|
|
259
256
|
# AND the vellum.lock.json file is created
|
|
260
|
-
vellum_lock_json =
|
|
261
|
-
assert
|
|
257
|
+
vellum_lock_json = tmp_path / "vellum.lock.json"
|
|
258
|
+
assert vellum_lock_json.exists()
|
|
262
259
|
with open(vellum_lock_json) as f:
|
|
263
260
|
lock_data = json.loads(f.read())
|
|
264
261
|
assert lock_data == {
|
|
@@ -310,7 +307,9 @@ def test_pull__sandbox_id_with_other_workflow_configured(vellum_client, mock_mod
|
|
|
310
307
|
assert f.read() == "print('hello')"
|
|
311
308
|
|
|
312
309
|
|
|
313
|
-
def test_pull__workflow_deployment_with_no_config(
|
|
310
|
+
def test_pull__workflow_deployment_with_no_config(
|
|
311
|
+
vellum_client, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
312
|
+
):
|
|
314
313
|
# GIVEN a workflow deployment
|
|
315
314
|
workflow_deployment = "my-deployment"
|
|
316
315
|
deployment_id = str(uuid4())
|
|
@@ -330,28 +329,25 @@ def test_pull__workflow_deployment_with_no_config(vellum_client):
|
|
|
330
329
|
)
|
|
331
330
|
|
|
332
331
|
# AND we are currently in a new directory
|
|
333
|
-
|
|
334
|
-
temp_dir = tempfile.mkdtemp()
|
|
335
|
-
os.chdir(temp_dir)
|
|
332
|
+
monkeypatch.chdir(tmp_path)
|
|
336
333
|
|
|
337
334
|
# WHEN the user runs the pull command with the workflow deployment
|
|
338
335
|
runner = CliRunner()
|
|
339
336
|
result = runner.invoke(cli_main, ["workflows", "pull", "--workflow-deployment", workflow_deployment])
|
|
340
|
-
os.chdir(current_dir)
|
|
341
337
|
|
|
342
338
|
# THEN the command returns successfully
|
|
343
339
|
assert result.exit_code == 0
|
|
344
340
|
|
|
345
341
|
# AND the pull api is called with the workflow deployment
|
|
346
342
|
vellum_client.workflows.pull.assert_called_once()
|
|
347
|
-
workflow_py =
|
|
348
|
-
assert
|
|
343
|
+
workflow_py = tmp_path / "my_deployment" / "workflow.py"
|
|
344
|
+
assert workflow_py.exists()
|
|
349
345
|
with open(workflow_py) as f:
|
|
350
346
|
assert f.read() == "print('hello')"
|
|
351
347
|
|
|
352
348
|
# AND the vellum.lock.json file is created
|
|
353
|
-
vellum_lock_json =
|
|
354
|
-
assert
|
|
349
|
+
vellum_lock_json = tmp_path / "vellum.lock.json"
|
|
350
|
+
assert vellum_lock_json.exists()
|
|
355
351
|
with open(vellum_lock_json) as f:
|
|
356
352
|
lock_data = json.loads(f.read())
|
|
357
353
|
assert lock_data == {
|
|
@@ -381,7 +377,9 @@ def test_pull__workflow_deployment_with_no_config(vellum_client):
|
|
|
381
377
|
}
|
|
382
378
|
|
|
383
379
|
|
|
384
|
-
def test_pull__both_workflow_sandbox_id_and_deployment(
|
|
380
|
+
def test_pull__both_workflow_sandbox_id_and_deployment(
|
|
381
|
+
vellum_client, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
382
|
+
):
|
|
385
383
|
# GIVEN a workflow sandbox id
|
|
386
384
|
workflow_sandbox_id = "87654321-0000-0000-0000-000000000000"
|
|
387
385
|
|
|
@@ -392,9 +390,7 @@ def test_pull__both_workflow_sandbox_id_and_deployment(vellum_client):
|
|
|
392
390
|
vellum_client.workflows.pull.return_value = iter([zip_file_map({"workflow.py": "print('hello')"})])
|
|
393
391
|
|
|
394
392
|
# AND we are currently in a new directory
|
|
395
|
-
|
|
396
|
-
temp_dir = tempfile.mkdtemp()
|
|
397
|
-
os.chdir(temp_dir)
|
|
393
|
+
monkeypatch.chdir(tmp_path)
|
|
398
394
|
|
|
399
395
|
# WHEN the user runs the pull command with the workflow deployment
|
|
400
396
|
runner = CliRunner()
|
|
@@ -409,7 +405,6 @@ def test_pull__both_workflow_sandbox_id_and_deployment(vellum_client):
|
|
|
409
405
|
workflow_deployment,
|
|
410
406
|
],
|
|
411
407
|
)
|
|
412
|
-
os.chdir(current_dir)
|
|
413
408
|
|
|
414
409
|
# THEN the command returns successfully
|
|
415
410
|
assert result.exit_code == 1
|
|
@@ -823,7 +818,7 @@ def test_pull__multiple_instances_of_same_module__keep_when_pulling_another_modu
|
|
|
823
818
|
assert len(lock_data["workflows"]) == 3
|
|
824
819
|
|
|
825
820
|
|
|
826
|
-
def test_pull__module_name_from_deployment_name(vellum_client):
|
|
821
|
+
def test_pull__module_name_from_deployment_name(vellum_client, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path):
|
|
827
822
|
# GIVEN a workflow deployment
|
|
828
823
|
workflow_deployment = "test-workflow-deployment-id"
|
|
829
824
|
|
|
@@ -840,29 +835,28 @@ def test_pull__module_name_from_deployment_name(vellum_client):
|
|
|
840
835
|
]
|
|
841
836
|
)
|
|
842
837
|
|
|
843
|
-
# AND we are currently in a new directory
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
838
|
+
# AND we are currently in a new directory with a .env file
|
|
839
|
+
monkeypatch.chdir(tmp_path)
|
|
840
|
+
with open(tmp_path / ".env", "w") as f:
|
|
841
|
+
f.write("VELLUM_API_KEY=test-api-key")
|
|
847
842
|
|
|
848
843
|
# WHEN the user runs the pull command with the workflow deployment
|
|
849
844
|
runner = CliRunner()
|
|
850
845
|
result = runner.invoke(cli_main, ["workflows", "pull", "--workflow-deployment", workflow_deployment])
|
|
851
|
-
os.chdir(current_dir)
|
|
852
846
|
|
|
853
847
|
# THEN the command returns successfully
|
|
854
848
|
assert result.exit_code == 0
|
|
855
849
|
|
|
856
850
|
# AND the module name is derived from the deployment_name in metadata.json (snake_cased)
|
|
857
|
-
vellum_lock_json =
|
|
858
|
-
assert
|
|
851
|
+
vellum_lock_json = tmp_path / "vellum.lock.json"
|
|
852
|
+
assert vellum_lock_json.exists()
|
|
859
853
|
with open(vellum_lock_json) as f:
|
|
860
854
|
lock_data = json.loads(f.read())
|
|
861
855
|
assert lock_data["workflows"][0]["module"] == "test_deployment"
|
|
862
856
|
|
|
863
857
|
# AND the workflow.py file is written to the module directory with the correct name
|
|
864
|
-
workflow_py =
|
|
865
|
-
assert
|
|
858
|
+
workflow_py = tmp_path / "test_deployment" / "workflow.py"
|
|
859
|
+
assert workflow_py.exists()
|
|
866
860
|
with open(workflow_py) as f:
|
|
867
861
|
assert f.read() == "print('hello')"
|
|
868
862
|
|
|
@@ -958,10 +952,12 @@ def test_pull__unexpected_error_path(vellum_client):
|
|
|
958
952
|
"workflow_deployment",
|
|
959
953
|
[
|
|
960
954
|
"test-workflow-deployment-id",
|
|
961
|
-
|
|
955
|
+
"377a59fb-1dd0-4760-9568-ae4bd6188da0",
|
|
962
956
|
],
|
|
963
957
|
)
|
|
964
|
-
def test_pull__workflow_deployment_adds_deployment_to_config(
|
|
958
|
+
def test_pull__workflow_deployment_adds_deployment_to_config(
|
|
959
|
+
vellum_client, workflow_deployment, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
960
|
+
):
|
|
965
961
|
# GIVEN a workflow deployment ID
|
|
966
962
|
deployment_id = str(uuid4()) # config will always use the deployment_id return from the API
|
|
967
963
|
deployment_name = "Test Deployment"
|
|
@@ -986,9 +982,8 @@ def test_pull__workflow_deployment_adds_deployment_to_config(vellum_client, work
|
|
|
986
982
|
)
|
|
987
983
|
|
|
988
984
|
# AND we are currently in a new directory
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
os.chdir(temp_dir)
|
|
985
|
+
monkeypatch.chdir(tmp_path)
|
|
986
|
+
monkeypatch.setenv("VELLUM_API_KEY", "abcdef123456")
|
|
992
987
|
|
|
993
988
|
# WHEN the user runs the pull command with the workflow deployment
|
|
994
989
|
runner = CliRunner()
|
|
@@ -998,8 +993,8 @@ def test_pull__workflow_deployment_adds_deployment_to_config(vellum_client, work
|
|
|
998
993
|
assert result.exit_code == 0
|
|
999
994
|
|
|
1000
995
|
# AND the deployment is saved in the config
|
|
1001
|
-
vellum_lock_json =
|
|
1002
|
-
assert
|
|
996
|
+
vellum_lock_json = tmp_path / "vellum.lock.json"
|
|
997
|
+
assert vellum_lock_json.exists()
|
|
1003
998
|
with open(vellum_lock_json) as f:
|
|
1004
999
|
lock_data = json.loads(f.read())
|
|
1005
1000
|
assert len(lock_data["workflows"]) == 1
|
|
@@ -1009,21 +1004,18 @@ def test_pull__workflow_deployment_adds_deployment_to_config(vellum_client, work
|
|
|
1009
1004
|
assert deployment["name"] == deployment_name
|
|
1010
1005
|
assert deployment["label"] == deployment_label
|
|
1011
1006
|
|
|
1012
|
-
os.chdir(current_dir)
|
|
1013
|
-
|
|
1014
1007
|
|
|
1015
|
-
def test_pull__workflow_deployment_name_is_uuid(vellum_client):
|
|
1008
|
+
def test_pull__workflow_deployment_name_is_uuid(vellum_client, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path):
|
|
1016
1009
|
# GIVEN a workflow deployment name that is a valid UUID
|
|
1017
1010
|
deployment_id = str(uuid4())
|
|
1018
1011
|
deployment_name = str(uuid4())
|
|
1019
1012
|
|
|
1020
1013
|
# AND an existing configuration with this deployment
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
os.chdir(temp_dir)
|
|
1014
|
+
monkeypatch.chdir(tmp_path)
|
|
1015
|
+
monkeypatch.setenv("VELLUM_API_KEY", "abcdef123456")
|
|
1024
1016
|
|
|
1025
1017
|
# Create initial config with a deployment
|
|
1026
|
-
vellum_lock_json =
|
|
1018
|
+
vellum_lock_json = tmp_path / "vellum.lock.json"
|
|
1027
1019
|
with open(vellum_lock_json, "w") as f:
|
|
1028
1020
|
json.dump(
|
|
1029
1021
|
{
|
|
@@ -1089,11 +1081,11 @@ def test_pull__workflow_deployment_name_is_uuid(vellum_client):
|
|
|
1089
1081
|
assert deployment["name"] == deployment_name
|
|
1090
1082
|
assert deployment["label"] == updated_label
|
|
1091
1083
|
|
|
1092
|
-
os.chdir(current_dir)
|
|
1093
|
-
|
|
1094
1084
|
|
|
1095
1085
|
@pytest.mark.parametrize("get_identifier", [(lambda d: d), (lambda d: "Test Name")])
|
|
1096
|
-
def test_pull__workflow_deployment_updates_existing_deployment(
|
|
1086
|
+
def test_pull__workflow_deployment_updates_existing_deployment(
|
|
1087
|
+
vellum_client, get_identifier, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
1088
|
+
):
|
|
1097
1089
|
"""
|
|
1098
1090
|
This test is to ensure that the deployment info is updated in the config
|
|
1099
1091
|
when the user runs the pull command with the workflow deployment
|
|
@@ -1106,12 +1098,11 @@ def test_pull__workflow_deployment_updates_existing_deployment(vellum_client, ge
|
|
|
1106
1098
|
deployment_name = "Test Name"
|
|
1107
1099
|
|
|
1108
1100
|
# AND an existing configuration with this deployment
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
os.chdir(temp_dir)
|
|
1101
|
+
monkeypatch.chdir(tmp_path)
|
|
1102
|
+
monkeypatch.setenv("VELLUM_API_KEY", "abcdef123456")
|
|
1112
1103
|
|
|
1113
1104
|
# Create initial config with a deployment
|
|
1114
|
-
vellum_lock_json =
|
|
1105
|
+
vellum_lock_json = tmp_path / "vellum.lock.json"
|
|
1115
1106
|
with open(vellum_lock_json, "w") as f:
|
|
1116
1107
|
json.dump(
|
|
1117
1108
|
{
|
|
@@ -1178,10 +1169,10 @@ def test_pull__workflow_deployment_updates_existing_deployment(vellum_client, ge
|
|
|
1178
1169
|
assert deployment["name"] == deployment_name
|
|
1179
1170
|
assert deployment["label"] == updated_label
|
|
1180
1171
|
|
|
1181
|
-
os.chdir(current_dir)
|
|
1182
|
-
|
|
1183
1172
|
|
|
1184
|
-
def test_pull__workflow_deployment_with_name_and_id(
|
|
1173
|
+
def test_pull__workflow_deployment_with_name_and_id(
|
|
1174
|
+
vellum_client, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path
|
|
1175
|
+
):
|
|
1185
1176
|
"""
|
|
1186
1177
|
This test is to ensure that pulling with id and name will not add a new deployment to the config
|
|
1187
1178
|
"""
|
|
@@ -1210,9 +1201,8 @@ def test_pull__workflow_deployment_with_name_and_id(vellum_client):
|
|
|
1210
1201
|
)
|
|
1211
1202
|
|
|
1212
1203
|
# AND we are currently in a new directory
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
os.chdir(temp_dir)
|
|
1204
|
+
monkeypatch.chdir(tmp_path)
|
|
1205
|
+
monkeypatch.setenv("VELLUM_API_KEY", "abcdef123456")
|
|
1216
1206
|
|
|
1217
1207
|
# WHEN the user runs the pull command with the workflow deployment
|
|
1218
1208
|
runner = CliRunner()
|
|
@@ -1222,8 +1212,8 @@ def test_pull__workflow_deployment_with_name_and_id(vellum_client):
|
|
|
1222
1212
|
assert result.exit_code == 0
|
|
1223
1213
|
|
|
1224
1214
|
# AND the deployment is saved in the config
|
|
1225
|
-
vellum_lock_json =
|
|
1226
|
-
assert
|
|
1215
|
+
vellum_lock_json = tmp_path / "vellum.lock.json"
|
|
1216
|
+
assert vellum_lock_json.exists()
|
|
1227
1217
|
with open(vellum_lock_json) as f:
|
|
1228
1218
|
lock_data = json.loads(f.read())
|
|
1229
1219
|
assert len(lock_data["workflows"]) == 1
|
|
@@ -1234,8 +1224,6 @@ def test_pull__workflow_deployment_with_name_and_id(vellum_client):
|
|
|
1234
1224
|
assert deployment["label"] == deployment_label
|
|
1235
1225
|
assert lock_data["workflows"][0]["workflow_sandbox_id"] == workflow_sandbox_id
|
|
1236
1226
|
|
|
1237
|
-
os.chdir(current_dir)
|
|
1238
|
-
|
|
1239
1227
|
# AND pull with name will not add a new deployment to the config
|
|
1240
1228
|
vellum_client.workflows.pull.return_value = iter(
|
|
1241
1229
|
[
|
|
@@ -1254,7 +1242,6 @@ def test_pull__workflow_deployment_with_name_and_id(vellum_client):
|
|
|
1254
1242
|
]
|
|
1255
1243
|
)
|
|
1256
1244
|
|
|
1257
|
-
os.chdir(temp_dir)
|
|
1258
1245
|
result = runner.invoke(cli_main, ["workflows", "pull", "--workflow-deployment", deployment_name])
|
|
1259
1246
|
assert result.exit_code == 0
|
|
1260
1247
|
with open(vellum_lock_json) as f:
|
|
@@ -1264,8 +1251,6 @@ def test_pull__workflow_deployment_with_name_and_id(vellum_client):
|
|
|
1264
1251
|
assert lock_data["workflows"][0]["deployments"][0]["name"] == deployment_name
|
|
1265
1252
|
assert lock_data["workflows"][0]["deployments"][0]["label"] == deployment_label
|
|
1266
1253
|
|
|
1267
|
-
os.chdir(current_dir)
|
|
1268
|
-
|
|
1269
1254
|
|
|
1270
1255
|
def test_pull__workspace_option__uses_different_api_key(mock_module, vellum_client_class):
|
|
1271
1256
|
# GIVEN a module and workflow_sandbox_id
|
|
@@ -1337,3 +1322,33 @@ MY_OTHER_VELLUM_API_KEY=aaabbbcccddd
|
|
|
1337
1322
|
assert os.path.exists(workflow_py)
|
|
1338
1323
|
with open(workflow_py) as f:
|
|
1339
1324
|
assert f.read() == "print('hello')"
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
@pytest.mark.parametrize(
|
|
1328
|
+
"base_command",
|
|
1329
|
+
[
|
|
1330
|
+
["pull"],
|
|
1331
|
+
["workflows", "pull"],
|
|
1332
|
+
],
|
|
1333
|
+
ids=["pull", "workflows_pull"],
|
|
1334
|
+
)
|
|
1335
|
+
def test_pull__release_tag(vellum_client, mock_module, base_command):
|
|
1336
|
+
"""Tests that the --release-tag option is passed to the API."""
|
|
1337
|
+
|
|
1338
|
+
# GIVEN a module on the user's filesystem
|
|
1339
|
+
module = mock_module.module
|
|
1340
|
+
|
|
1341
|
+
# AND the workflow pull API call returns a zip file
|
|
1342
|
+
vellum_client.workflows.pull.return_value = iter([zip_file_map({"workflow.py": "print('hello')"})])
|
|
1343
|
+
|
|
1344
|
+
# WHEN the user runs the pull command with --release-tag
|
|
1345
|
+
runner = CliRunner()
|
|
1346
|
+
result = runner.invoke(cli_main, base_command + [module, "--release-tag", "my-release-tag"])
|
|
1347
|
+
|
|
1348
|
+
# THEN the command returns successfully
|
|
1349
|
+
assert result.exit_code == 0
|
|
1350
|
+
|
|
1351
|
+
# AND the pull api is called with release_tag="my-release-tag"
|
|
1352
|
+
vellum_client.workflows.pull.assert_called_once()
|
|
1353
|
+
call_args = vellum_client.workflows.pull.call_args.kwargs
|
|
1354
|
+
assert call_args["release_tag"] == "my-release-tag"
|