zenml-nightly 0.80.1.dev20250407__py3-none-any.whl → 0.80.1.dev20250409__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 (183) hide show
  1. zenml/VERSION +1 -1
  2. zenml/cli/base.py +1 -1
  3. zenml/cli/integration.py +36 -0
  4. zenml/client.py +6 -0
  5. zenml/config/step_configurations.py +3 -2
  6. zenml/constants.py +1 -1
  7. zenml/entrypoints/step_entrypoint_configuration.py +2 -0
  8. zenml/integrations/airflow/orchestrators/airflow_orchestrator.py +7 -2
  9. zenml/integrations/aws/orchestrators/sagemaker_orchestrator.py +2 -0
  10. zenml/integrations/azure/orchestrators/azureml_orchestrator.py +2 -0
  11. zenml/integrations/databricks/orchestrators/databricks_orchestrator.py +3 -1
  12. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +2 -0
  13. zenml/integrations/hyperai/orchestrators/hyperai_orchestrator.py +3 -1
  14. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +3 -1
  15. zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +12 -0
  16. zenml/integrations/kubernetes/orchestrators/kube_utils.py +3 -0
  17. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator.py +4 -1
  18. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +164 -19
  19. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint_configuration.py +8 -1
  20. zenml/integrations/lightning/orchestrators/lightning_orchestrator.py +3 -1
  21. zenml/integrations/mlflow/__init__.py +0 -27
  22. zenml/integrations/mlflow/services/mlflow_deployment.py +25 -7
  23. zenml/integrations/pandas/materializers/pandas_materializer.py +41 -2
  24. zenml/integrations/seldon/services/seldon_deployment.py +1 -1
  25. zenml/integrations/skypilot/orchestrators/skypilot_base_vm_orchestrator.py +3 -1
  26. zenml/integrations/tekton/orchestrators/tekton_orchestrator.py +3 -1
  27. zenml/integrations/vllm/services/vllm_deployment.py +1 -1
  28. zenml/model/model.py +3 -1
  29. zenml/models/__init__.py +5 -0
  30. zenml/models/v2/core/run_template.py +32 -1
  31. zenml/orchestrators/base_orchestrator.py +3 -0
  32. zenml/orchestrators/dag_runner.py +48 -15
  33. zenml/orchestrators/local/local_orchestrator.py +3 -1
  34. zenml/orchestrators/local_docker/local_docker_orchestrator.py +3 -1
  35. zenml/steps/base_step.py +11 -8
  36. zenml/utils/secret_utils.py +2 -2
  37. zenml/zen_server/dashboard/assets/{404-2I8egBQu.js → 404-CYPi9d8E.js} +1 -1
  38. zenml/zen_server/dashboard/assets/@radix-C7hRs6Kx.js +95 -0
  39. zenml/zen_server/dashboard/assets/{@react-router-BUo5vhN4.js → @react-router-BGgzhn5D.js} +5 -5
  40. zenml/zen_server/dashboard/assets/@reactflow-CQi1Z1Wq.js +17 -0
  41. zenml/zen_server/dashboard/assets/@tanstack-CSxjHCME.js +22 -0
  42. zenml/zen_server/dashboard/assets/{AlertDialogDropdownItem-D7KZcPFw.js → AlertDialogDropdownItem-Dn8bgaXG.js} +1 -1
  43. zenml/zen_server/dashboard/assets/{CodeSnippet-DUkCnBpQ.js → CodeSnippet-CSINAl3I.js} +1 -1
  44. zenml/zen_server/dashboard/assets/{CollapsibleCard-B5-5Plnd.js → CollapsibleCard-CQOb53t9.js} +1 -1
  45. zenml/zen_server/dashboard/assets/{Commands-CbOMmarC.js → Commands-CPleXvse.js} +1 -1
  46. zenml/zen_server/dashboard/assets/{ComponentBadge-FrujKBC6.js → ComponentBadge-CIFj0W7T.js} +1 -1
  47. zenml/zen_server/dashboard/assets/{ComponentIcon-Dx5fBrDX.js → ComponentIcon-D3JHFhJU.js} +1 -1
  48. zenml/zen_server/dashboard/assets/{CsvVizualization-B8E3p9we.js → CsvVizualization-Cklc1Vb5.js} +6 -6
  49. zenml/zen_server/dashboard/assets/{DeleteAlertDialog-BgTZbbAt.js → DeleteAlertDialog-Bzq-uSd7.js} +1 -1
  50. zenml/zen_server/dashboard/assets/{DialogItem-CNWLiJcc.js → DialogItem-zjMgCmCl.js} +1 -1
  51. zenml/zen_server/dashboard/assets/{DisplayDate-C5Aw-Yca.js → DisplayDate-CYVBBSgr.js} +1 -1
  52. zenml/zen_server/dashboard/assets/{EmptyState-DpbfQBDE.js → EmptyState-M1jafpg6.js} +1 -1
  53. zenml/zen_server/dashboard/assets/{Error-BkUP4Luv.js → Error-kdeNHm_o.js} +1 -1
  54. zenml/zen_server/dashboard/assets/{ExecutionStatus-CD8Vj7sp.js → ExecutionStatus-UE6Rbmtk.js} +1 -1
  55. zenml/zen_server/dashboard/assets/{Helpbox-DIx6mDOH.js → Helpbox-CeM-FPQl.js} +1 -1
  56. zenml/zen_server/dashboard/assets/{Infobox-BHEdNmME.js → Infobox-CD0fDbYF.js} +1 -1
  57. zenml/zen_server/dashboard/assets/{InlineAvatar-Bin9UPKJ.js → InlineAvatar-CrHWwlf4.js} +1 -1
  58. zenml/zen_server/dashboard/assets/{Lock-tO9Z41I9.js → Lock-DW-0_M0o.js} +1 -1
  59. zenml/zen_server/dashboard/assets/{MarkdownVisualization-C3JLiPCY.js → MarkdownVisualization-URCyUPcZ.js} +2 -2
  60. zenml/zen_server/dashboard/assets/{NestedCollapsible-Da-k0Mff.js → NestedCollapsible-DfTTGG8u.js} +1 -1
  61. zenml/zen_server/dashboard/assets/{NumberBox-BvBJYxCu.js → NumberBox-D2A7ENHb.js} +1 -1
  62. zenml/zen_server/dashboard/assets/Partials-DggkUpWp.js +1 -0
  63. zenml/zen_server/dashboard/assets/{PasswordChecker-B4Uw6BJZ.js → PasswordChecker-lYTOtNom.js} +1 -1
  64. zenml/zen_server/dashboard/assets/ProBadge-BCdprj69.js +1 -0
  65. zenml/zen_server/dashboard/assets/{ProCta-7_FtpX3I.js → ProCta-szzPO0Y7.js} +1 -1
  66. zenml/zen_server/dashboard/assets/{ProviderIcon-CxeziA5a.js → ProviderIcon-MdqWDO6-.js} +1 -1
  67. zenml/zen_server/dashboard/assets/{ProviderRadio-DPmZHff_.js → ProviderRadio-B4CB4vzP.js} +1 -1
  68. zenml/zen_server/dashboard/assets/{RunSelector-BVKB4Z8F.js → RunSelector-Bhb83FyB.js} +1 -1
  69. zenml/zen_server/dashboard/assets/{RunsBody-Cj4sIqQB.js → RunsBody-Csn2VEOE.js} +1 -1
  70. zenml/zen_server/dashboard/assets/{SearchField-DjAOZic5.js → SearchField-Cce00eQL.js} +1 -1
  71. zenml/zen_server/dashboard/assets/{SecretTooltip-mMAAP4dM.js → SecretTooltip-DaDLBVj-.js} +1 -1
  72. zenml/zen_server/dashboard/assets/{SetPassword-B0o5kSJU.js → SetPassword-tX6fom1Y.js} +1 -1
  73. zenml/zen_server/dashboard/assets/{StackList-5UB8LoEq.js → StackList-CQt1xGRh.js} +1 -1
  74. zenml/zen_server/dashboard/assets/{Tabs-AuhCyzle.js → Tabs-CCQyIqRb.js} +1 -1
  75. zenml/zen_server/dashboard/assets/{Tick-CHW0jc8Y.js → Tick-D63_jhf1.js} +1 -1
  76. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-Bauivjf-.js → UpdatePasswordSchemas-CbbvoGYV.js} +1 -1
  77. zenml/zen_server/dashboard/assets/{UsageReason-Dr5ca5M4.js → UsageReason-C2cNrUeS.js} +1 -1
  78. zenml/zen_server/dashboard/assets/{Wizard-XEp9rGmf.js → Wizard-BVkN2a2x.js} +1 -1
  79. zenml/zen_server/dashboard/assets/WizardFooter-Bk7gIKiS.js +1 -0
  80. zenml/zen_server/dashboard/assets/{all-pipeline-runs-query-COvsm3bC.js → all-pipeline-runs-query-BLclwQSi.js} +1 -1
  81. zenml/zen_server/dashboard/assets/{arrow-left-B2hyhFky.js → arrow-left-CwgF2MEM.js} +1 -1
  82. zenml/zen_server/dashboard/assets/{check-DZ0KAh3W.js → check-DK77doTf.js} +1 -1
  83. zenml/zen_server/dashboard/assets/{check-circle-DyCCYTA0.js → check-circle-mvyzYvIW.js} +1 -1
  84. zenml/zen_server/dashboard/assets/{chevron-down-A3PXOshS.js → chevron-down-A-rmltmI.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{chevron-right-double-zKz7rAaU.js → chevron-right-double-uNWbJT-C.js} +1 -1
  86. zenml/zen_server/dashboard/assets/{clock-k5T5tYrt.js → clock-CPA5cYxq.js} +1 -1
  87. zenml/zen_server/dashboard/assets/{code-browser-DvB0W2Ix.js → code-browser-j2EpcxIA.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{configuration-form-BJUCr0wl.js → configuration-form-CjrAp0GS.js} +1 -1
  89. zenml/zen_server/dashboard/assets/{create-stack-B2c98UlP.js → create-stack-Bd2JdQer.js} +1 -1
  90. zenml/zen_server/dashboard/assets/delete-run-Cwpxu1-d.js +1 -0
  91. zenml/zen_server/dashboard/assets/{docker-B3Sqzd8J.js → docker-BuDBFEDL.js} +1 -1
  92. zenml/zen_server/dashboard/assets/{file-text-CgxVzNph.js → file-text-BdxZdjP_.js} +1 -1
  93. zenml/zen_server/dashboard/assets/{flavor-select-D8CranSY.js → flavor-select-c0w-6o9w.js} +1 -1
  94. zenml/zen_server/dashboard/assets/{form-schemas-Bm-dTV3L.js → form-schemas-B5Ax1SZf.js} +1 -1
  95. zenml/zen_server/dashboard/assets/{gcp-0u4le6mC.js → gcp-CHNvgEss.js} +1 -1
  96. zenml/zen_server/dashboard/assets/{help-CfT0tY2I.js → help-DyMolRxD.js} +1 -1
  97. zenml/zen_server/dashboard/assets/index-BW-KaQ2p.js +1 -0
  98. zenml/zen_server/dashboard/assets/{index-DPjvk73v.js → index-Be2jLIYM.js} +8 -8
  99. zenml/zen_server/dashboard/assets/{index-D-n6tspq.js → index-CjdtNrfJ.js} +1 -1
  100. zenml/zen_server/dashboard/assets/{index-BVVKxTWC.js → index-DR30v9MZ.js} +1 -1
  101. zenml/zen_server/dashboard/assets/{index-CzhJC6pc.js → index-d_40qKeY.js} +1 -1
  102. zenml/zen_server/dashboard/assets/index.esm-D7jFlf5N.js +1 -0
  103. zenml/zen_server/dashboard/assets/{key-icon-CjwWwoOU.js → key-icon-DO4DPJHZ.js} +1 -1
  104. zenml/zen_server/dashboard/assets/{kubernetes-eA-Y6gE7.js → kubernetes-D6OUjwSK.js} +1 -1
  105. zenml/zen_server/dashboard/assets/{layout-3_rgDUxf.js → layout-h3cbx8WZ.js} +1 -1
  106. zenml/zen_server/dashboard/assets/{link-external-BYm_zH_8.js → link-external-DUhCSKNm.js} +1 -1
  107. zenml/zen_server/dashboard/assets/{login-mutation-D6uiKsKk.js → login-mutation-DOajKct8.js} +1 -1
  108. zenml/zen_server/dashboard/assets/{logs-D6_diV2k.js → logs-B5n0U7tB.js} +1 -1
  109. zenml/zen_server/dashboard/assets/{not-found-DFrksY0r.js → not-found-DolTp0dr.js} +1 -1
  110. zenml/zen_server/dashboard/assets/{package-BOms6B-A.js → package-D1Mhqeh8.js} +1 -1
  111. zenml/zen_server/dashboard/assets/{page-DBNBYSwq.js → page-48DMcIQw.js} +2 -2
  112. zenml/zen_server/dashboard/assets/{page-DOzFoJuo.js → page-B32kCGPe.js} +1 -1
  113. zenml/zen_server/dashboard/assets/page-BAjhc2bs.js +1 -0
  114. zenml/zen_server/dashboard/assets/{page-D5GZlpKq.js → page-BBNrvxC1.js} +1 -1
  115. zenml/zen_server/dashboard/assets/{page-DF9q7ySu.js → page-BEAx6ZvH.js} +1 -1
  116. zenml/zen_server/dashboard/assets/{page-DDvwWgKP.js → page-BRfeowe0.js} +1 -1
  117. zenml/zen_server/dashboard/assets/{page-BJ15SGwt.js → page-BbRtQC2E.js} +1 -1
  118. zenml/zen_server/dashboard/assets/{page-D2F0Rvak.js → page-BgUR_5z3.js} +1 -1
  119. zenml/zen_server/dashboard/assets/{page-D0Zt2-7X.js → page-BiAjLLww.js} +1 -1
  120. zenml/zen_server/dashboard/assets/{page-B80TE04v.js → page-BkPPfNfG.js} +1 -1
  121. zenml/zen_server/dashboard/assets/{page-DkJfgcDi.js → page-BmTf1Lf1.js} +2 -2
  122. zenml/zen_server/dashboard/assets/{page-CAKBSE9f.js → page-BuZC8z6N.js} +1 -1
  123. zenml/zen_server/dashboard/assets/{page-BwAFqFCf.js → page-C4zMMcaH.js} +1 -1
  124. zenml/zen_server/dashboard/assets/{page-BnUwQBeg.js → page-CKVbEdX2.js} +1 -1
  125. zenml/zen_server/dashboard/assets/{page-BXh1mF-D.js → page-CPRymOIS.js} +1 -1
  126. zenml/zen_server/dashboard/assets/{page-BMZaECzB.js → page-CaTJVICi.js} +1 -1
  127. zenml/zen_server/dashboard/assets/{page-NIWnUdVg.js → page-CmzmFF4S.js} +1 -1
  128. zenml/zen_server/dashboard/assets/{page-BIseZTJt.js → page-CwAbTnvK.js} +2 -2
  129. zenml/zen_server/dashboard/assets/{page-BeFiRx31.js → page-D-MjLTXS.js} +1 -1
  130. zenml/zen_server/dashboard/assets/{page-B1Un9vAU.js → page-D3m9-YWJ.js} +1 -1
  131. zenml/zen_server/dashboard/assets/{page-DhNnHHmX.js → page-DCpZju6a.js} +1 -1
  132. zenml/zen_server/dashboard/assets/page-DEUeF3mO.js +1 -0
  133. zenml/zen_server/dashboard/assets/{page-B150LbzG.js → page-DWOAh8Pp.js} +1 -1
  134. zenml/zen_server/dashboard/assets/{page-EhqRFAZc.js → page-DezabeEO.js} +1 -1
  135. zenml/zen_server/dashboard/assets/{page-BTvnIFGR.js → page-DivlNKt9.js} +1 -1
  136. zenml/zen_server/dashboard/assets/{page-BqQ6y8Hb.js → page-DmOcZO8U.js} +1 -1
  137. zenml/zen_server/dashboard/assets/page-DnY59jOg.js +1 -0
  138. zenml/zen_server/dashboard/assets/{page-DaHH2ZEF.js → page-Dv3qtvm8.js} +1 -1
  139. zenml/zen_server/dashboard/assets/page-P81CcE2L.js +1 -0
  140. zenml/zen_server/dashboard/assets/{page-Dd-0y3SU.js → page-a1c6o4vv.js} +1 -1
  141. zenml/zen_server/dashboard/assets/{page-BJrZsPSh.js → page-bS5tHLDW.js} +1 -1
  142. zenml/zen_server/dashboard/assets/{page-C11vPVkH.js → page-gRfUvR0E.js} +1 -1
  143. zenml/zen_server/dashboard/assets/{page-BZUxCBoD.js → page-hNHJPQtK.js} +1 -1
  144. zenml/zen_server/dashboard/assets/{page-kYlFrH53.js → page-ir7Scz2Y.js} +1 -1
  145. zenml/zen_server/dashboard/assets/{page-ygCPGHAV.js → page-mtwS5oci.js} +1 -1
  146. zenml/zen_server/dashboard/assets/{persist-DHGuHP2H.js → persist-BUqILw7G.js} +1 -1
  147. zenml/zen_server/dashboard/assets/{persist-C5RlwSq6.js → persist-BbdfLc0W.js} +1 -1
  148. zenml/zen_server/dashboard/assets/{plus-CoKtHiA9.js → plus-COjQg3AG.js} +1 -1
  149. zenml/zen_server/dashboard/assets/{react-error-boundary.esm-BkGIR1Du.js → react-error-boundary.esm-fyoUBS25.js} +1 -1
  150. zenml/zen_server/dashboard/assets/{refresh-CupyU1Vs.js → refresh-CM5T3QeU.js} +1 -1
  151. zenml/zen_server/dashboard/assets/{rocket-k68ONPDS.js → rocket-Cf-B-XOR.js} +1 -1
  152. zenml/zen_server/dashboard/assets/{service-Do7yitqe.js → service-CV2zjc-p.js} +1 -1
  153. zenml/zen_server/dashboard/assets/{sharedSchema-i_9Y4WcA.js → sharedSchema-DpGc9kQg.js} +1 -1
  154. zenml/zen_server/dashboard/assets/stack-detail-query-BpzLZjvw.js +1 -0
  155. zenml/zen_server/dashboard/assets/{terminal-square-URAPn9DB.js → terminal-square-DMtel8mb.js} +1 -1
  156. zenml/zen_server/dashboard/assets/{tick-circle-AaVBszPn.js → tick-circle-m94Aa6Zt.js} +1 -1
  157. zenml/zen_server/dashboard/assets/{trash-B_JgTgqd.js → trash-BWSZ7NRK.js} +1 -1
  158. zenml/zen_server/dashboard/assets/update-server-settings-mutation-Dv6qHtK9.js +1 -0
  159. zenml/zen_server/dashboard/assets/{zod-CRNUMWWg.js → zod-C0xYeTvL.js} +1 -1
  160. zenml/zen_server/dashboard/index.html +6 -6
  161. zenml/zen_server/template_execution/utils.py +53 -33
  162. zenml/zen_stores/migrations/versions/6611d4bcc95b_add_hidden_option_for_templates.py +47 -0
  163. zenml/zen_stores/schemas/run_template_schemas.py +7 -0
  164. {zenml_nightly-0.80.1.dev20250407.dist-info → zenml_nightly-0.80.1.dev20250409.dist-info}/METADATA +2 -2
  165. {zenml_nightly-0.80.1.dev20250407.dist-info → zenml_nightly-0.80.1.dev20250409.dist-info}/RECORD +168 -167
  166. zenml/zen_server/dashboard/assets/@radix-AvWw-1nd.js +0 -95
  167. zenml/zen_server/dashboard/assets/@reactflow-BHoFKFSZ.js +0 -17
  168. zenml/zen_server/dashboard/assets/@tanstack-CcI3lvwB.js +0 -22
  169. zenml/zen_server/dashboard/assets/Partials-TNaYjHsV.js +0 -1
  170. zenml/zen_server/dashboard/assets/ProBadge-BfPp-B97.js +0 -1
  171. zenml/zen_server/dashboard/assets/WizardFooter-BtL1Gi1k.js +0 -1
  172. zenml/zen_server/dashboard/assets/delete-run-Do3XyF4W.js +0 -1
  173. zenml/zen_server/dashboard/assets/index-eIIP-0dQ.js +0 -1
  174. zenml/zen_server/dashboard/assets/index.esm-cf-8NBxV.js +0 -1
  175. zenml/zen_server/dashboard/assets/page-B-uHUFcm.js +0 -1
  176. zenml/zen_server/dashboard/assets/page-B0Llmzo_.js +0 -1
  177. zenml/zen_server/dashboard/assets/page-BzlVs5tC.js +0 -1
  178. zenml/zen_server/dashboard/assets/page-CPe9nQSo.js +0 -1
  179. zenml/zen_server/dashboard/assets/stack-detail-query-omCumL7U.js +0 -1
  180. zenml/zen_server/dashboard/assets/update-server-settings-mutation-B4eE33z-.js +0 -1
  181. {zenml_nightly-0.80.1.dev20250407.dist-info → zenml_nightly-0.80.1.dev20250409.dist-info}/LICENSE +0 -0
  182. {zenml_nightly-0.80.1.dev20250407.dist-info → zenml_nightly-0.80.1.dev20250409.dist-info}/WHEEL +0 -0
  183. {zenml_nightly-0.80.1.dev20250407.dist-info → zenml_nightly-0.80.1.dev20250409.dist-info}/entry_points.txt +0 -0
@@ -13,7 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Entrypoint configuration for the Kubernetes master/orchestrator pod."""
15
15
 
16
- from typing import TYPE_CHECKING, List, Set
16
+ from typing import TYPE_CHECKING, List, Optional, Set
17
17
 
18
18
  if TYPE_CHECKING:
19
19
  from uuid import UUID
@@ -21,6 +21,7 @@ if TYPE_CHECKING:
21
21
  RUN_NAME_OPTION = "run_name"
22
22
  DEPLOYMENT_ID_OPTION = "deployment_id"
23
23
  NAMESPACE_OPTION = "kubernetes_namespace"
24
+ RUN_ID_OPTION = "run_id"
24
25
 
25
26
 
26
27
  class KubernetesOrchestratorEntrypointConfiguration:
@@ -60,6 +61,7 @@ class KubernetesOrchestratorEntrypointConfiguration:
60
61
  run_name: str,
61
62
  deployment_id: "UUID",
62
63
  kubernetes_namespace: str,
64
+ run_id: Optional["UUID"] = None,
63
65
  ) -> List[str]:
64
66
  """Gets all arguments that the entrypoint command should be called with.
65
67
 
@@ -67,6 +69,7 @@ class KubernetesOrchestratorEntrypointConfiguration:
67
69
  run_name: Name of the ZenML run.
68
70
  deployment_id: ID of the deployment.
69
71
  kubernetes_namespace: Name of the Kubernetes namespace.
72
+ run_id: Optional ID of the pipeline run. Not set for scheduled runs.
70
73
 
71
74
  Returns:
72
75
  List of entrypoint arguments.
@@ -80,4 +83,8 @@ class KubernetesOrchestratorEntrypointConfiguration:
80
83
  kubernetes_namespace,
81
84
  ]
82
85
 
86
+ if run_id:
87
+ args.append(f"--{RUN_ID_OPTION}")
88
+ args.append(str(run_id))
89
+
83
90
  return args
@@ -46,7 +46,7 @@ from zenml.stack import StackValidator
46
46
  from zenml.utils import code_utils, io_utils, source_utils
47
47
 
48
48
  if TYPE_CHECKING:
49
- from zenml.models import PipelineDeploymentResponse
49
+ from zenml.models import PipelineDeploymentResponse, PipelineRunResponse
50
50
  from zenml.stack import Stack
51
51
 
52
52
 
@@ -199,6 +199,7 @@ class LightningOrchestrator(WheeledOrchestrator):
199
199
  deployment: "PipelineDeploymentResponse",
200
200
  stack: "Stack",
201
201
  environment: Dict[str, str],
202
+ placeholder_run: Optional["PipelineRunResponse"] = None,
202
203
  ) -> Any:
203
204
  """Creates a wheel and uploads the pipeline to Lightning.
204
205
 
@@ -223,6 +224,7 @@ class LightningOrchestrator(WheeledOrchestrator):
223
224
  stack: The stack the pipeline will run on.
224
225
  environment: Environment variables to set in the orchestration
225
226
  environment.
227
+ placeholder_run: An optional placeholder run for the deployment.
226
228
 
227
229
  Raises:
228
230
  ValueError: If the schedule is not set or if the cron expression
@@ -61,39 +61,12 @@ class MlflowIntegration(Integration):
61
61
  from zenml.integrations.numpy import NumpyIntegration
62
62
  from zenml.integrations.pandas import PandasIntegration
63
63
 
64
-
65
64
  reqs = [
66
65
  "mlflow>=2.1.1,<3",
67
66
  # TODO: remove this requirement once rapidjson is fixed
68
67
  "python-rapidjson<1.15",
69
- # When you do:
70
- # pip install zenml
71
- # You get all our required dependencies. However, if you follow it
72
- # with:
73
- # zenml integration install mlflow
74
- # This downgrades pydantic to v1 even though mlflow does not have
75
- # any issues with v2. This is why we have to pin it here so a
76
- # downgrade will not happen.
77
- "pydantic>=2.8.0,<2.9.0",
78
68
  ]
79
69
 
80
- if python_version:
81
- version_minor = version.parse(python_version).minor
82
- else:
83
- version_minor = sys.version_info.minor
84
-
85
- if version_minor >= 12:
86
- logger.debug(
87
- "The MLflow integration on Python 3.12 and above is not yet "
88
- "fully supported: The extra dependencies 'mlserver' and "
89
- "'mlserver-mlflow' will be skipped."
90
- )
91
- else:
92
- reqs.extend([
93
- "mlserver>=1.3.3",
94
- "mlserver-mlflow>=1.3.3",
95
- ])
96
-
97
70
  reqs.extend(NumpyIntegration.get_requirements(target_os=target_os, python_version=python_version))
98
71
  reqs.extend(PandasIntegration.get_requirements(target_os=target_os, python_version=python_version))
99
72
  return reqs
@@ -13,6 +13,7 @@
13
13
  # permissions and limitations under the License.
14
14
  """Implementation of the MLflow deployment functionality."""
15
15
 
16
+ import importlib
16
17
  import os
17
18
  import sys
18
19
  from typing import TYPE_CHECKING, Any, Dict, Optional, Union
@@ -126,14 +127,31 @@ class MLFlowDeploymentConfig(LocalDaemonServiceConfig):
126
127
  the validated value
127
128
 
128
129
  Raises:
129
- ValueError: if mlserver is set to true on Python 3.12 as it is not
130
- yet supported.
130
+ ValueError: if mlserver packages are not installed
131
131
  """
132
- if mlserver is True and sys.version_info.minor >= 12:
133
- raise ValueError(
134
- "The mlserver deployment is not yet supported on Python 3.12 "
135
- "or above."
136
- )
132
+ if mlserver is True:
133
+ # For the mlserver deployment, the mlserver and
134
+ # mlserver-mlflow packages need to be installed separately
135
+ # because they rely on an older version of Pydantic.
136
+
137
+ # Check if the mlserver and mlserver-mlflow packages are installed
138
+ try:
139
+ importlib.import_module("mlserver")
140
+ importlib.import_module("mlserver_mlflow")
141
+ except ModuleNotFoundError:
142
+ if sys.version_info.minor >= 12:
143
+ raise ValueError(
144
+ "The mlserver deployment is not yet supported on "
145
+ "Python 3.12 or above."
146
+ )
147
+
148
+ raise ValueError(
149
+ "The MLflow MLServer backend requires the `mlserver` and "
150
+ "`mlserver-mlflow` packages to be installed. These "
151
+ "packages are not included in the ZenML MLflow integration "
152
+ "requirements. Please install them manually."
153
+ )
154
+
137
155
  return mlserver
138
156
 
139
157
 
@@ -11,7 +11,14 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12
12
  # or implied. See the License for the specific language governing
13
13
  # permissions and limitations under the License.
14
- """Materializer for Pandas."""
14
+ """Materializer for Pandas.
15
+
16
+ This materializer handles pandas DataFrame and Series objects.
17
+
18
+ Environment Variables:
19
+ ZENML_PANDAS_SAMPLE_ROWS: Controls the number of sample rows to include in
20
+ visualizations. Defaults to 10 if not set.
21
+ """
15
22
 
16
23
  import os
17
24
  from typing import Any, ClassVar, Dict, Optional, Tuple, Type, Union
@@ -31,6 +38,9 @@ COMPRESSION_TYPE = "gzip"
31
38
 
32
39
  CSV_FILENAME = "df.csv"
33
40
 
41
+ # Default number of sample rows to display in visualizations
42
+ DEFAULT_SAMPLE_ROWS = 10
43
+
34
44
 
35
45
  class PandasMaterializer(BaseMaterializer):
36
46
  """Materializer to read data to and from pandas."""
@@ -142,17 +152,46 @@ class PandasMaterializer(BaseMaterializer):
142
152
  ) -> Dict[str, VisualizationType]:
143
153
  """Save visualizations of the given pandas dataframe or series.
144
154
 
155
+ Creates two visualizations:
156
+ 1. A statistical description of the data (using df.describe())
157
+ 2. A sample of the data (first N rows controlled by ZENML_PANDAS_SAMPLE_ROWS)
158
+
159
+ Note:
160
+ The number of sample rows shown can be controlled with the
161
+ ZENML_PANDAS_SAMPLE_ROWS environment variable.
162
+
145
163
  Args:
146
164
  df: The pandas dataframe or series to visualize.
147
165
 
148
166
  Returns:
149
167
  A dictionary of visualization URIs and their types.
150
168
  """
169
+ visualizations = {}
151
170
  describe_uri = os.path.join(self.uri, "describe.csv")
152
171
  describe_uri = describe_uri.replace("\\", "/")
153
172
  with self.artifact_store.open(describe_uri, mode="wb") as f:
154
173
  df.describe().to_csv(f)
155
- return {describe_uri: VisualizationType.CSV}
174
+ visualizations[describe_uri] = VisualizationType.CSV
175
+
176
+ # Get the number of sample rows from environment variable or use default
177
+ sample_rows = int(
178
+ os.environ.get("ZENML_PANDAS_SAMPLE_ROWS", DEFAULT_SAMPLE_ROWS)
179
+ )
180
+
181
+ # Add our sample visualization (with configurable number of rows)
182
+ if isinstance(df, pd.Series):
183
+ sample_df = df.head(sample_rows).to_frame()
184
+ else:
185
+ sample_df = df.head(sample_rows)
186
+
187
+ sample_uri = os.path.join(self.uri, "sample.csv")
188
+ sample_uri = sample_uri.replace("\\", "/")
189
+ with self.artifact_store.open(sample_uri, mode="wb") as f:
190
+ sample_df.to_csv(f)
191
+
192
+ visualizations[sample_uri] = VisualizationType.CSV
193
+
194
+ return visualizations
156
195
 
157
196
  def extract_metadata(
158
197
  self, df: Union[pd.DataFrame, pd.Series]
@@ -72,7 +72,7 @@ class SeldonDeploymentConfig(ServiceConfig):
72
72
  model_metadata: Dict[str, Any] = Field(default_factory=dict)
73
73
  extra_args: Dict[str, Any] = Field(default_factory=dict)
74
74
  is_custom_deployment: Optional[bool] = False
75
- spec: Optional[Dict[Any, Any]] = Field(default_factory=dict)
75
+ spec: Optional[Dict[Any, Any]] = Field(default_factory=dict) # type: ignore[arg-type]
76
76
  serviceAccountName: Optional[str] = None
77
77
 
78
78
  def get_seldon_deployment_labels(self) -> Dict[str, str]:
@@ -39,7 +39,7 @@ from zenml.orchestrators.utils import get_orchestrator_run_name
39
39
  from zenml.stack import StackValidator
40
40
 
41
41
  if TYPE_CHECKING:
42
- from zenml.models import PipelineDeploymentResponse
42
+ from zenml.models import PipelineDeploymentResponse, PipelineRunResponse
43
43
  from zenml.stack import Stack
44
44
 
45
45
 
@@ -149,6 +149,7 @@ class SkypilotBaseOrchestrator(ContainerizedOrchestrator):
149
149
  deployment: "PipelineDeploymentResponse",
150
150
  stack: "Stack",
151
151
  environment: Dict[str, str],
152
+ placeholder_run: Optional["PipelineRunResponse"] = None,
152
153
  ) -> Any:
153
154
  """Runs each pipeline step in a separate Skypilot container.
154
155
 
@@ -157,6 +158,7 @@ class SkypilotBaseOrchestrator(ContainerizedOrchestrator):
157
158
  stack: The stack the pipeline will run on.
158
159
  environment: Environment variables to set in the orchestration
159
160
  environment.
161
+ placeholder_run: An optional placeholder run for the deployment.
160
162
 
161
163
  Raises:
162
164
  Exception: If the pipeline run fails.
@@ -53,7 +53,7 @@ from zenml.utils import io_utils, yaml_utils
53
53
 
54
54
  if TYPE_CHECKING:
55
55
  from zenml.config.base_settings import BaseSettings
56
- from zenml.models import PipelineDeploymentResponse
56
+ from zenml.models import PipelineDeploymentResponse, PipelineRunResponse
57
57
  from zenml.stack import Stack
58
58
 
59
59
 
@@ -460,6 +460,7 @@ class TektonOrchestrator(ContainerizedOrchestrator):
460
460
  deployment: "PipelineDeploymentResponse",
461
461
  stack: "Stack",
462
462
  environment: Dict[str, str],
463
+ placeholder_run: Optional["PipelineRunResponse"] = None,
463
464
  ) -> Any:
464
465
  """Runs the pipeline on Tekton.
465
466
 
@@ -471,6 +472,7 @@ class TektonOrchestrator(ContainerizedOrchestrator):
471
472
  stack: The stack the pipeline will run on.
472
473
  environment: Environment variables to set in the orchestration
473
474
  environment.
475
+ placeholder_run: An optional placeholder run for the deployment.
474
476
 
475
477
  Raises:
476
478
  RuntimeError: If you try to run the pipelines in a notebook
@@ -150,7 +150,7 @@ class VLLMDeploymentService(LocalDaemonService, BaseDeploymentService):
150
150
 
151
151
  try:
152
152
  parser: argparse.ArgumentParser = make_arg_parser(
153
- FlexibleArgumentParser()
153
+ FlexibleArgumentParser() # type: ignore[no-untyped-call]
154
154
  )
155
155
  # pass in empty list to get default args
156
156
  # otherwise it will try to get the args from sys.argv
zenml/model/model.py CHANGED
@@ -81,7 +81,7 @@ class Model(BaseModel):
81
81
  # technical attributes
82
82
  model_version_id: Optional[UUID] = None
83
83
  suppress_class_validation_warnings: bool = False
84
- _model_id: UUID = PrivateAttr(None)
84
+ _model_id: Optional[UUID] = PrivateAttr(None)
85
85
  _number: Optional[int] = PrivateAttr(None)
86
86
  _created_model_version: bool = PrivateAttr(False)
87
87
 
@@ -130,6 +130,8 @@ class Model(BaseModel):
130
130
  """
131
131
  if self._model_id is None:
132
132
  self._get_or_create_model()
133
+
134
+ assert self._model_id is not None
133
135
  return self._model_id
134
136
 
135
137
  @property
zenml/models/__init__.py CHANGED
@@ -418,7 +418,11 @@ from zenml.models.v2.misc.info_models import (
418
418
 
419
419
  # V2
420
420
  ActionResponseResources.model_rebuild()
421
+ ActionResponseMetadata.model_rebuild()
421
422
  APIKeyResponseBody.model_rebuild()
423
+ ArtifactResponse.model_rebuild()
424
+ ArtifactResponseBody.model_rebuild()
425
+ ArtifactResponseMetadata.model_rebuild()
422
426
  ArtifactVersionRequest.model_rebuild()
423
427
  ArtifactVersionResponseBody.model_rebuild()
424
428
  ArtifactVersionResponseMetadata.model_rebuild()
@@ -477,6 +481,7 @@ StepRunRequest.model_rebuild()
477
481
  StepRunResponseBody.model_rebuild()
478
482
  StepRunResponseMetadata.model_rebuild()
479
483
  StepRunResponseResources.model_rebuild()
484
+ TagResponseBody.model_rebuild()
480
485
  TriggerExecutionResponseResources.model_rebuild()
481
486
  TriggerResponseBody.model_rebuild()
482
487
  TriggerResponseMetadata.model_rebuild()
@@ -79,6 +79,10 @@ class RunTemplateRequest(ProjectScopedRequest):
79
79
  source_deployment_id: UUID = Field(
80
80
  title="The deployment that should be the base of the created template."
81
81
  )
82
+ hidden: bool = Field(
83
+ default=False,
84
+ title="Whether the run template is hidden.",
85
+ )
82
86
  tags: Optional[List[str]] = Field(
83
87
  default=None,
84
88
  title="Tags of the run template.",
@@ -101,6 +105,10 @@ class RunTemplateUpdate(BaseUpdate):
101
105
  title="The description of the run template.",
102
106
  max_length=TEXT_FIELD_MAX_LENGTH,
103
107
  )
108
+ hidden: Optional[bool] = Field(
109
+ default=None,
110
+ title="Whether the run template is hidden.",
111
+ )
104
112
  add_tags: Optional[List[str]] = Field(
105
113
  default=None, title="New tags to add to the run template."
106
114
  )
@@ -118,6 +126,10 @@ class RunTemplateResponseBody(ProjectScopedResponseBody):
118
126
  runnable: bool = Field(
119
127
  title="If a run can be started from the template.",
120
128
  )
129
+ hidden: bool = Field(
130
+ default=False,
131
+ title="Whether the run template is hidden.",
132
+ )
121
133
  latest_run_id: Optional[UUID] = Field(
122
134
  default=None,
123
135
  title="The ID of the latest run of the run template.",
@@ -205,6 +217,15 @@ class RunTemplateResponse(
205
217
  """
206
218
  return self.get_body().runnable
207
219
 
220
+ @property
221
+ def hidden(self) -> bool:
222
+ """The `hidden` property.
223
+
224
+ Returns:
225
+ the value of the property.
226
+ """
227
+ return self.get_body().hidden
228
+
208
229
  @property
209
230
  def latest_run_id(self) -> Optional[UUID]:
210
231
  """The `latest_run_id` property.
@@ -320,6 +341,7 @@ class RunTemplateFilter(ProjectScopedFilter, TaggableFilter):
320
341
  "pipeline_id",
321
342
  "pipeline",
322
343
  "stack",
344
+ "hidden",
323
345
  ]
324
346
  CUSTOM_SORTING_OPTIONS = [
325
347
  *ProjectScopedFilter.CUSTOM_SORTING_OPTIONS,
@@ -334,6 +356,10 @@ class RunTemplateFilter(ProjectScopedFilter, TaggableFilter):
334
356
  default=None,
335
357
  description="Name of the run template.",
336
358
  )
359
+ hidden: Optional[bool] = Field(
360
+ default=None,
361
+ description="Whether the run template is hidden.",
362
+ )
337
363
  pipeline_id: Optional[Union[UUID, str]] = Field(
338
364
  default=None,
339
365
  description="Pipeline associated with the template.",
@@ -376,7 +402,7 @@ class RunTemplateFilter(ProjectScopedFilter, TaggableFilter):
376
402
  """
377
403
  custom_filters = super().get_custom_filters(table)
378
404
 
379
- from sqlmodel import and_
405
+ from sqlmodel import and_, col
380
406
 
381
407
  from zenml.zen_stores.schemas import (
382
408
  CodeReferenceSchema,
@@ -386,6 +412,11 @@ class RunTemplateFilter(ProjectScopedFilter, TaggableFilter):
386
412
  StackSchema,
387
413
  )
388
414
 
415
+ if self.hidden is not None:
416
+ custom_filters.append(
417
+ col(RunTemplateSchema.hidden).is_(self.hidden)
418
+ )
419
+
389
420
  if self.code_repository_id:
390
421
  code_repo_filter = and_(
391
422
  RunTemplateSchema.source_deployment_id
@@ -140,6 +140,7 @@ class BaseOrchestrator(StackComponent, ABC):
140
140
  deployment: "PipelineDeploymentResponse",
141
141
  stack: "Stack",
142
142
  environment: Dict[str, str],
143
+ placeholder_run: Optional["PipelineRunResponse"] = None,
143
144
  ) -> Optional[Iterator[Dict[str, MetadataType]]]:
144
145
  """The method needs to be implemented by the respective orchestrator.
145
146
 
@@ -175,6 +176,7 @@ class BaseOrchestrator(StackComponent, ABC):
175
176
  stack: The stack the pipeline will run on.
176
177
  environment: Environment variables to set in the orchestration
177
178
  environment. These don't need to be set if running locally.
179
+ placeholder_run: An optional placeholder run for the deployment.
178
180
 
179
181
  Yields:
180
182
  Metadata for the pipeline run.
@@ -250,6 +252,7 @@ class BaseOrchestrator(StackComponent, ABC):
250
252
  deployment=deployment,
251
253
  stack=stack,
252
254
  environment=environment,
255
+ placeholder_run=placeholder_run,
253
256
  ):
254
257
  for metadata_dict in metadata_iterator:
255
258
  try:
@@ -17,7 +17,7 @@ import threading
17
17
  import time
18
18
  from collections import defaultdict
19
19
  from enum import Enum
20
- from typing import Any, Callable, Dict, List
20
+ from typing import Any, Callable, Dict, List, Optional
21
21
 
22
22
  from zenml.logger import get_logger
23
23
 
@@ -54,6 +54,7 @@ class NodeStatus(Enum):
54
54
  WAITING = "Waiting"
55
55
  RUNNING = "Running"
56
56
  COMPLETED = "Completed"
57
+ FAILED = "Failed"
57
58
 
58
59
 
59
60
  class ThreadedDagRunner:
@@ -70,6 +71,7 @@ class ThreadedDagRunner:
70
71
  self,
71
72
  dag: Dict[str, List[str]],
72
73
  run_fn: Callable[[str], Any],
74
+ finalize_fn: Optional[Callable[[Dict[str, NodeStatus]], None]] = None,
73
75
  parallel_node_startup_waiting_period: float = 0.0,
74
76
  ) -> None:
75
77
  """Define attributes and initialize all nodes in waiting state.
@@ -79,6 +81,8 @@ class ThreadedDagRunner:
79
81
  E.g.: [(1->2), (1->3), (2->4), (3->4)] should be represented as
80
82
  `dag={2: [1], 3: [1], 4: [2, 3]}`
81
83
  run_fn: A function `run_fn(node)` that runs a single node
84
+ finalize_fn: A function `finalize_fn(node_states)` that is called
85
+ when all nodes have completed.
82
86
  parallel_node_startup_waiting_period: Delay in seconds to wait in
83
87
  between starting parallel nodes.
84
88
  """
@@ -88,6 +92,7 @@ class ThreadedDagRunner:
88
92
  self.dag = dag
89
93
  self.reversed_dag = reverse_dag(dag)
90
94
  self.run_fn = run_fn
95
+ self.finalize_fn = finalize_fn
91
96
  self.nodes = dag.keys()
92
97
  self.node_states = {node: NodeStatus.WAITING for node in self.nodes}
93
98
  self._lock = threading.Lock()
@@ -123,8 +128,12 @@ class ThreadedDagRunner:
123
128
  Args:
124
129
  node: The node.
125
130
  """
126
- self.run_fn(node)
127
- self._finish_node(node)
131
+ try:
132
+ self.run_fn(node)
133
+ self._finish_node(node)
134
+ except Exception as e:
135
+ self._finish_node(node, failed=True)
136
+ logger.exception(f"Node `{node}` failed: {e}")
128
137
 
129
138
  def _run_node_in_thread(self, node: str) -> threading.Thread:
130
139
  """Run a single node in a separate thread.
@@ -148,7 +157,7 @@ class ThreadedDagRunner:
148
157
  thread.start()
149
158
  return thread
150
159
 
151
- def _finish_node(self, node: str) -> None:
160
+ def _finish_node(self, node: str, failed: bool = False) -> None:
152
161
  """Finish a node run.
153
162
 
154
163
  First updates the node status to completed.
@@ -156,20 +165,28 @@ class ThreadedDagRunner:
156
165
 
157
166
  Args:
158
167
  node: The node.
168
+ failed: Whether the node failed.
159
169
  """
160
170
  # Update node status to completed.
161
171
  assert self.node_states[node] == NodeStatus.RUNNING
162
172
  with self._lock:
163
- self.node_states[node] = NodeStatus.COMPLETED
173
+ if failed:
174
+ self.node_states[node] = NodeStatus.FAILED
175
+ else:
176
+ self.node_states[node] = NodeStatus.COMPLETED
177
+
178
+ if failed:
179
+ # If the node failed, we don't need to run any downstream nodes.
180
+ return
164
181
 
165
182
  # Run downstream nodes.
166
183
  threads: List[threading.Thread] = []
167
- for downstram_node in self.reversed_dag[node]:
168
- if self._can_run(downstram_node):
184
+ for downstream_node in self.reversed_dag[node]:
185
+ if self._can_run(downstream_node):
169
186
  if threads and self.parallel_node_startup_waiting_period > 0:
170
187
  time.sleep(self.parallel_node_startup_waiting_period)
171
188
 
172
- thread = self._run_node_in_thread(downstram_node)
189
+ thread = self._run_node_in_thread(downstream_node)
173
190
  threads.append(thread)
174
191
 
175
192
  # Wait for all downstream nodes to complete.
@@ -198,11 +215,27 @@ class ThreadedDagRunner:
198
215
  for thread in threads:
199
216
  thread.join()
200
217
 
201
- # Make sure all nodes were run, otherwise print a warning.
218
+ # Call the finalize function.
219
+ if self.finalize_fn:
220
+ self.finalize_fn(self.node_states)
221
+
222
+ # Print a status report.
223
+ failed_nodes = []
224
+ skipped_nodes = []
202
225
  for node in self.nodes:
203
- if self.node_states[node] == NodeStatus.WAITING:
204
- upstream_nodes = self.dag[node]
205
- logger.warning(
206
- f"Node `{node}` was never run, because it was still"
207
- f" waiting for the following nodes: `{upstream_nodes}`."
208
- )
226
+ if self.node_states[node] == NodeStatus.FAILED:
227
+ failed_nodes.append(node)
228
+ elif self.node_states[node] == NodeStatus.WAITING:
229
+ skipped_nodes.append(node)
230
+
231
+ if failed_nodes:
232
+ logger.error(
233
+ "The following nodes failed: " + ", ".join(failed_nodes)
234
+ )
235
+ if skipped_nodes:
236
+ logger.warning(
237
+ "The following nodes were not run because they depend on other "
238
+ "nodes that didn't complete: " + ", ".join(skipped_nodes)
239
+ )
240
+ if not failed_nodes and not skipped_nodes:
241
+ logger.info("All nodes completed successfully.")
@@ -27,7 +27,7 @@ from zenml.stack import Stack
27
27
  from zenml.utils import string_utils
28
28
 
29
29
  if TYPE_CHECKING:
30
- from zenml.models import PipelineDeploymentResponse
30
+ from zenml.models import PipelineDeploymentResponse, PipelineRunResponse
31
31
 
32
32
  logger = get_logger(__name__)
33
33
 
@@ -46,6 +46,7 @@ class LocalOrchestrator(BaseOrchestrator):
46
46
  deployment: "PipelineDeploymentResponse",
47
47
  stack: "Stack",
48
48
  environment: Dict[str, str],
49
+ placeholder_run: Optional["PipelineRunResponse"] = None,
49
50
  ) -> Any:
50
51
  """Iterates through all steps and executes them sequentially.
51
52
 
@@ -54,6 +55,7 @@ class LocalOrchestrator(BaseOrchestrator):
54
55
  stack: The stack on which the pipeline is deployed.
55
56
  environment: Environment variables to set in the orchestration
56
57
  environment.
58
+ placeholder_run: An optional placeholder run for the deployment.
57
59
  """
58
60
  if deployment.schedule:
59
61
  logger.warning(
@@ -39,7 +39,7 @@ from zenml.stack import Stack, StackValidator
39
39
  from zenml.utils import docker_utils, string_utils
40
40
 
41
41
  if TYPE_CHECKING:
42
- from zenml.models import PipelineDeploymentResponse
42
+ from zenml.models import PipelineDeploymentResponse, PipelineRunResponse
43
43
 
44
44
  logger = get_logger(__name__)
45
45
 
@@ -96,6 +96,7 @@ class LocalDockerOrchestrator(ContainerizedOrchestrator):
96
96
  deployment: "PipelineDeploymentResponse",
97
97
  stack: "Stack",
98
98
  environment: Dict[str, str],
99
+ placeholder_run: Optional["PipelineRunResponse"] = None,
99
100
  ) -> Any:
100
101
  """Sequentially runs all pipeline steps in local Docker containers.
101
102
 
@@ -104,6 +105,7 @@ class LocalDockerOrchestrator(ContainerizedOrchestrator):
104
105
  stack: The stack the pipeline will run on.
105
106
  environment: Environment variables to set in the orchestration
106
107
  environment.
108
+ placeholder_run: An optional placeholder run for the deployment.
107
109
 
108
110
  Raises:
109
111
  RuntimeError: If a step fails.