zenml-nightly 0.68.0.dev20241027__py3-none-any.whl → 0.68.1.dev20241101__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 (125) hide show
  1. README.md +17 -11
  2. RELEASE_NOTES.md +9 -0
  3. zenml/VERSION +1 -1
  4. zenml/__init__.py +1 -1
  5. zenml/analytics/context.py +16 -1
  6. zenml/analytics/utils.py +18 -7
  7. zenml/artifacts/utils.py +40 -216
  8. zenml/cli/__init__.py +63 -90
  9. zenml/cli/base.py +3 -3
  10. zenml/cli/login.py +951 -0
  11. zenml/cli/server.py +462 -353
  12. zenml/cli/service_accounts.py +4 -4
  13. zenml/cli/stack.py +77 -2
  14. zenml/cli/stack_components.py +5 -16
  15. zenml/cli/user_management.py +0 -12
  16. zenml/cli/utils.py +24 -77
  17. zenml/client.py +46 -14
  18. zenml/config/compiler.py +1 -0
  19. zenml/config/global_config.py +9 -0
  20. zenml/config/pipeline_configurations.py +2 -1
  21. zenml/config/pipeline_run_configuration.py +2 -1
  22. zenml/constants.py +3 -9
  23. zenml/enums.py +1 -1
  24. zenml/exceptions.py +11 -0
  25. zenml/integrations/github/code_repositories/github_code_repository.py +1 -1
  26. zenml/login/__init__.py +16 -0
  27. zenml/login/credentials.py +346 -0
  28. zenml/login/credentials_store.py +603 -0
  29. zenml/login/pro/__init__.py +16 -0
  30. zenml/login/pro/client.py +496 -0
  31. zenml/login/pro/constants.py +34 -0
  32. zenml/login/pro/models.py +25 -0
  33. zenml/login/pro/organization/__init__.py +14 -0
  34. zenml/login/pro/organization/client.py +79 -0
  35. zenml/login/pro/organization/models.py +32 -0
  36. zenml/login/pro/tenant/__init__.py +14 -0
  37. zenml/login/pro/tenant/client.py +92 -0
  38. zenml/login/pro/tenant/models.py +174 -0
  39. zenml/login/pro/utils.py +121 -0
  40. zenml/{cli → login}/web_login.py +64 -28
  41. zenml/materializers/base_materializer.py +43 -9
  42. zenml/materializers/built_in_materializer.py +1 -1
  43. zenml/metadata/metadata_types.py +49 -0
  44. zenml/model/model.py +0 -38
  45. zenml/models/__init__.py +3 -0
  46. zenml/models/v2/base/base.py +12 -8
  47. zenml/models/v2/base/filter.py +9 -0
  48. zenml/models/v2/core/artifact_version.py +49 -10
  49. zenml/models/v2/core/component.py +54 -19
  50. zenml/models/v2/core/flavor.py +13 -13
  51. zenml/models/v2/core/model.py +3 -1
  52. zenml/models/v2/core/model_version.py +3 -5
  53. zenml/models/v2/core/model_version_artifact.py +3 -1
  54. zenml/models/v2/core/model_version_pipeline_run.py +3 -1
  55. zenml/models/v2/core/pipeline.py +3 -1
  56. zenml/models/v2/core/pipeline_run.py +23 -1
  57. zenml/models/v2/core/run_template.py +3 -1
  58. zenml/models/v2/core/stack.py +7 -3
  59. zenml/models/v2/core/step_run.py +43 -2
  60. zenml/models/v2/misc/auth_models.py +11 -2
  61. zenml/models/v2/misc/server_models.py +2 -0
  62. zenml/orchestrators/base_orchestrator.py +8 -4
  63. zenml/orchestrators/step_launcher.py +1 -0
  64. zenml/orchestrators/step_run_utils.py +10 -2
  65. zenml/orchestrators/step_runner.py +67 -55
  66. zenml/orchestrators/utils.py +45 -22
  67. zenml/pipelines/pipeline_decorator.py +5 -0
  68. zenml/pipelines/pipeline_definition.py +206 -160
  69. zenml/pipelines/run_utils.py +11 -10
  70. zenml/services/local/local_daemon_entrypoint.py +4 -4
  71. zenml/services/service.py +2 -2
  72. zenml/stack/stack.py +2 -6
  73. zenml/stack/stack_component.py +2 -7
  74. zenml/stack/utils.py +26 -14
  75. zenml/steps/base_step.py +8 -2
  76. zenml/steps/step_context.py +0 -3
  77. zenml/steps/step_invocation.py +14 -5
  78. zenml/steps/utils.py +1 -0
  79. zenml/utils/materializer_utils.py +1 -1
  80. zenml/utils/requirements_utils.py +71 -0
  81. zenml/utils/singleton.py +15 -3
  82. zenml/utils/source_utils.py +39 -2
  83. zenml/utils/visualization_utils.py +1 -1
  84. zenml/zen_server/auth.py +44 -39
  85. zenml/zen_server/deploy/__init__.py +7 -7
  86. zenml/zen_server/deploy/base_provider.py +46 -73
  87. zenml/zen_server/deploy/{local → daemon}/__init__.py +3 -3
  88. zenml/zen_server/deploy/{local/local_provider.py → daemon/daemon_provider.py} +44 -63
  89. zenml/zen_server/deploy/{local/local_zen_server.py → daemon/daemon_zen_server.py} +50 -22
  90. zenml/zen_server/deploy/deployer.py +90 -171
  91. zenml/zen_server/deploy/deployment.py +20 -12
  92. zenml/zen_server/deploy/docker/docker_provider.py +9 -28
  93. zenml/zen_server/deploy/docker/docker_zen_server.py +19 -3
  94. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  95. zenml/zen_server/deploy/helm/README.md +2 -2
  96. zenml/zen_server/exceptions.py +11 -0
  97. zenml/zen_server/jwt.py +9 -9
  98. zenml/zen_server/routers/auth_endpoints.py +30 -8
  99. zenml/zen_server/routers/stack_components_endpoints.py +1 -1
  100. zenml/zen_server/routers/workspaces_endpoints.py +1 -1
  101. zenml/zen_server/template_execution/runner_entrypoint_configuration.py +7 -4
  102. zenml/zen_server/template_execution/utils.py +6 -61
  103. zenml/zen_server/utils.py +64 -36
  104. zenml/zen_stores/base_zen_store.py +4 -49
  105. zenml/zen_stores/migrations/versions/0.68.1_release.py +23 -0
  106. zenml/zen_stores/migrations/versions/c22561cbb3a9_add_artifact_unique_constraints.py +86 -0
  107. zenml/zen_stores/rest_zen_store.py +325 -147
  108. zenml/zen_stores/schemas/api_key_schemas.py +9 -4
  109. zenml/zen_stores/schemas/artifact_schemas.py +21 -2
  110. zenml/zen_stores/schemas/artifact_visualization_schemas.py +1 -1
  111. zenml/zen_stores/schemas/component_schemas.py +49 -6
  112. zenml/zen_stores/schemas/device_schemas.py +9 -4
  113. zenml/zen_stores/schemas/flavor_schemas.py +1 -1
  114. zenml/zen_stores/schemas/model_schemas.py +1 -1
  115. zenml/zen_stores/schemas/service_schemas.py +1 -1
  116. zenml/zen_stores/schemas/step_run_schemas.py +1 -1
  117. zenml/zen_stores/schemas/trigger_schemas.py +1 -1
  118. zenml/zen_stores/sql_zen_store.py +393 -140
  119. zenml/zen_stores/template_utils.py +3 -1
  120. {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/METADATA +18 -12
  121. {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/RECORD +124 -107
  122. zenml/api.py +0 -60
  123. {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/LICENSE +0 -0
  124. {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/WHEEL +0 -0
  125. {zenml_nightly-0.68.0.dev20241027.dist-info → zenml_nightly-0.68.1.dev20241101.dist-info}/entry_points.txt +0 -0
@@ -586,6 +586,7 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
586
586
  "stack",
587
587
  "code_repository",
588
588
  "model",
589
+ "stack_component",
589
590
  "pipeline_name",
590
591
  "templatable",
591
592
  ]
@@ -688,6 +689,10 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
688
689
  default=None,
689
690
  description="Name/ID of the model associated with the run.",
690
691
  )
692
+ stack_component: Optional[Union[UUID, str]] = Field(
693
+ default=None,
694
+ description="Name/ID of the stack component associated with the run.",
695
+ )
691
696
  templatable: Optional[bool] = Field(
692
697
  default=None, description="Whether the run is templatable."
693
698
  )
@@ -716,6 +721,8 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
716
721
  PipelineRunSchema,
717
722
  PipelineSchema,
718
723
  ScheduleSchema,
724
+ StackComponentSchema,
725
+ StackCompositionSchema,
719
726
  StackSchema,
720
727
  UserSchema,
721
728
  )
@@ -772,7 +779,9 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
772
779
  user_filter = and_(
773
780
  PipelineRunSchema.user_id == UserSchema.id,
774
781
  self.generate_name_or_id_query_conditions(
775
- value=self.user, table=UserSchema
782
+ value=self.user,
783
+ table=UserSchema,
784
+ additional_columns=["full_name"],
776
785
  ),
777
786
  )
778
787
  custom_filters.append(user_filter)
@@ -821,6 +830,19 @@ class PipelineRunFilter(WorkspaceScopedTaggableFilter):
821
830
  )
822
831
  custom_filters.append(model_filter)
823
832
 
833
+ if self.stack_component:
834
+ component_filter = and_(
835
+ PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
836
+ PipelineDeploymentSchema.stack_id == StackSchema.id,
837
+ StackSchema.id == StackCompositionSchema.stack_id,
838
+ StackCompositionSchema.component_id == StackComponentSchema.id,
839
+ self.generate_name_or_id_query_conditions(
840
+ value=self.stack_component,
841
+ table=StackComponentSchema,
842
+ ),
843
+ )
844
+ custom_filters.append(component_filter)
845
+
824
846
  if self.pipeline_name:
825
847
  pipeline_name_filter = and_(
826
848
  PipelineRunSchema.pipeline_id == PipelineSchema.id,
@@ -413,7 +413,9 @@ class RunTemplateFilter(WorkspaceScopedTaggableFilter):
413
413
  user_filter = and_(
414
414
  RunTemplateSchema.user_id == UserSchema.id,
415
415
  self.generate_name_or_id_query_conditions(
416
- value=self.user, table=UserSchema
416
+ value=self.user,
417
+ table=UserSchema,
418
+ additional_columns=["full_name"],
417
419
  ),
418
420
  )
419
421
  custom_filters.append(user_filter)
@@ -228,7 +228,7 @@ class StackResponse(
228
228
  component_dict = dict(
229
229
  name=component.name,
230
230
  type=str(component.type),
231
- flavor=component.flavor,
231
+ flavor=component.flavor_name,
232
232
  )
233
233
  configuration = json.loads(
234
234
  component.get_metadata().model_dump_json(
@@ -255,7 +255,9 @@ class StackResponse(
255
255
  Dict of analytics metadata.
256
256
  """
257
257
  metadata = super().get_analytics_metadata()
258
- metadata.update({ct: c[0].flavor for ct, c in self.components.items()})
258
+ metadata.update(
259
+ {ct: c[0].flavor_name for ct, c in self.components.items()}
260
+ )
259
261
 
260
262
  if self.labels is not None:
261
263
  metadata.update(
@@ -381,7 +383,9 @@ class StackFilter(WorkspaceScopedFilter):
381
383
  user_filter = and_(
382
384
  StackSchema.user_id == UserSchema.id,
383
385
  self.generate_name_or_id_query_conditions(
384
- value=self.user, table=UserSchema
386
+ value=self.user,
387
+ table=UserSchema,
388
+ additional_columns=["full_name"],
385
389
  ),
386
390
  )
387
391
  custom_filters.append(user_filter)
@@ -14,7 +14,7 @@
14
14
  """Models representing steps runs."""
15
15
 
16
16
  from datetime import datetime
17
- from typing import TYPE_CHECKING, Dict, List, Optional, Union
17
+ from typing import TYPE_CHECKING, ClassVar, Dict, List, Optional, Union
18
18
  from uuid import UUID
19
19
 
20
20
  from pydantic import BaseModel, ConfigDict, Field
@@ -33,6 +33,8 @@ from zenml.models.v2.base.scoped import (
33
33
  from zenml.models.v2.core.model_version import ModelVersionResponse
34
34
 
35
35
  if TYPE_CHECKING:
36
+ from sqlalchemy.sql.elements import ColumnElement
37
+
36
38
  from zenml.models.v2.core.artifact_version import ArtifactVersionResponse
37
39
  from zenml.models.v2.core.logs import (
38
40
  LogsRequest,
@@ -488,6 +490,11 @@ class StepRunResponse(
488
490
  class StepRunFilter(WorkspaceScopedFilter):
489
491
  """Model to enable advanced filtering of step runs."""
490
492
 
493
+ FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
494
+ *WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
495
+ "model",
496
+ ]
497
+
491
498
  name: Optional[str] = Field(
492
499
  default=None,
493
500
  description="Name of the step run",
@@ -541,8 +548,42 @@ class StepRunFilter(WorkspaceScopedFilter):
541
548
  )
542
549
  model_version_id: Optional[Union[UUID, str]] = Field(
543
550
  default=None,
544
- description="Model version associated with the pipeline run.",
551
+ description="Model version associated with the step run.",
545
552
  union_mode="left_to_right",
546
553
  )
554
+ model: Optional[Union[UUID, str]] = Field(
555
+ default=None,
556
+ description="Name/ID of the model associated with the step run.",
557
+ )
547
558
 
548
559
  model_config = ConfigDict(protected_namespaces=())
560
+
561
+ def get_custom_filters(
562
+ self,
563
+ ) -> List["ColumnElement[bool]"]:
564
+ """Get custom filters.
565
+
566
+ Returns:
567
+ A list of custom filters.
568
+ """
569
+ custom_filters = super().get_custom_filters()
570
+
571
+ from sqlmodel import and_
572
+
573
+ from zenml.zen_stores.schemas import (
574
+ ModelSchema,
575
+ ModelVersionSchema,
576
+ StepRunSchema,
577
+ )
578
+
579
+ if self.model:
580
+ model_filter = and_(
581
+ StepRunSchema.model_version_id == ModelVersionSchema.id,
582
+ ModelVersionSchema.model_id == ModelSchema.id,
583
+ self.generate_name_or_id_query_conditions(
584
+ value=self.model, table=ModelSchema
585
+ ),
586
+ )
587
+ custom_filters.append(model_filter)
588
+
589
+ return custom_filters
@@ -13,10 +13,10 @@
13
13
  # permissions and limitations under the License.
14
14
  """Models representing OAuth2 requests and responses."""
15
15
 
16
- from typing import Optional
16
+ from typing import Any, Dict, Optional
17
17
  from uuid import UUID
18
18
 
19
- from pydantic import BaseModel
19
+ from pydantic import BaseModel, ConfigDict
20
20
 
21
21
  from zenml.enums import OAuthGrantTypes
22
22
 
@@ -29,6 +29,7 @@ class OAuthDeviceAuthorizationRequest(BaseModel):
29
29
  """OAuth2 device authorization grant request."""
30
30
 
31
31
  client_id: UUID
32
+ device_id: Optional[UUID] = None
32
33
 
33
34
 
34
35
  class OAuthDeviceVerificationRequest(BaseModel):
@@ -119,6 +120,14 @@ class OAuthTokenResponse(BaseModel):
119
120
  expires_in: Optional[int] = None
120
121
  refresh_token: Optional[str] = None
121
122
  scope: Optional[str] = None
123
+ cookie_name: Optional[str] = None
124
+ device_id: Optional[UUID] = None
125
+ device_metadata: Optional[Dict[str, Any]] = None
126
+
127
+ model_config = ConfigDict(
128
+ # Allow extra attributes to allow compatibility with different versions
129
+ extra="allow",
130
+ )
122
131
 
123
132
 
124
133
  class OAuthRedirectResponse(BaseModel):
@@ -52,6 +52,8 @@ class ServerModel(BaseModel):
52
52
 
53
53
  id: UUID = Field(default_factory=uuid4, title="The unique server id.")
54
54
 
55
+ name: Optional[str] = Field(None, title="The name of the ZenML server.")
56
+
55
57
  version: str = Field(
56
58
  title="The ZenML version that the server is running.",
57
59
  )
@@ -166,9 +166,8 @@ class BaseOrchestrator(StackComponent, ABC):
166
166
  environment: Environment variables to set in the orchestration
167
167
  environment. These don't need to be set if running locally.
168
168
 
169
- Returns:
170
- The optional return value from this method will be returned by the
171
- `pipeline_instance.run()` call when someone is running a pipeline.
169
+ Yields:
170
+ Metadata for the pipeline run.
172
171
  """
173
172
 
174
173
  def run(
@@ -176,7 +175,7 @@ class BaseOrchestrator(StackComponent, ABC):
176
175
  deployment: "PipelineDeploymentResponse",
177
176
  stack: "Stack",
178
177
  placeholder_run: Optional["PipelineRunResponse"] = None,
179
- ) -> Any:
178
+ ) -> None:
180
179
  """Runs a pipeline on a stack.
181
180
 
182
181
  Args:
@@ -211,6 +210,11 @@ class BaseOrchestrator(StackComponent, ABC):
211
210
  # the orchestrator does not try to run them
212
211
  deployment.step_configurations.pop(invocation_id)
213
212
 
213
+ for step in deployment.step_configurations.values():
214
+ for invocation_id in cached_invocations:
215
+ if invocation_id in step.spec.upstream_steps:
216
+ step.spec.upstream_steps.remove(invocation_id)
217
+
214
218
  if len(deployment.step_configurations) == 0:
215
219
  # All steps were cached, we update the pipeline run status and
216
220
  # don't actually use the orchestrator to run the pipeline
@@ -331,6 +331,7 @@ class StepLauncher:
331
331
  status=ExecutionStatus.RUNNING,
332
332
  orchestrator_environment=get_run_environment_dict(),
333
333
  start_time=datetime.utcnow(),
334
+ tags=self._deployment.pipeline_configuration.tags,
334
335
  )
335
336
  return client.zen_store.get_or_create_run(pipeline_run)
336
337
 
@@ -35,7 +35,7 @@ from zenml.models import (
35
35
  )
36
36
  from zenml.orchestrators import cache_utils, input_utils, utils
37
37
  from zenml.stack import Stack
38
- from zenml.utils import string_utils
38
+ from zenml.utils import pagination_utils, string_utils
39
39
 
40
40
  if TYPE_CHECKING:
41
41
  from zenml.model.model import Model
@@ -424,7 +424,15 @@ def get_model_version_created_by_pipeline_run(
424
424
  ):
425
425
  return pipeline_run.model_version
426
426
 
427
- for step_run in pipeline_run.steps.values():
427
+ # We fetch a list of hydrated step runs here in order to avoid hydration
428
+ # calls for each step separately.
429
+ candidate_step_runs = pagination_utils.depaginate(
430
+ Client().list_run_steps,
431
+ pipeline_run_id=pipeline_run.id,
432
+ model=model_name,
433
+ hydrate=True,
434
+ )
435
+ for step_run in candidate_step_runs:
428
436
  if step_run.config.model and step_run.model_version:
429
437
  if (
430
438
  step_run.config.model.name == model_name
@@ -57,6 +57,7 @@ from zenml.utils import materializer_utils, source_utils
57
57
  from zenml.utils.typing_utils import get_origin, is_union
58
58
 
59
59
  if TYPE_CHECKING:
60
+ from zenml.artifact_stores import BaseArtifactStore
60
61
  from zenml.config.source import Source
61
62
  from zenml.config.step_configurations import Step
62
63
  from zenml.models import (
@@ -190,61 +191,62 @@ class StepRunner:
190
191
  )
191
192
  raise
192
193
  finally:
193
- step_run_metadata = self._stack.get_step_run_metadata(
194
- info=step_run_info,
195
- )
196
- publish_step_run_metadata(
197
- step_run_id=step_run_info.step_run_id,
198
- step_run_metadata=step_run_metadata,
199
- )
200
- self._stack.cleanup_step_run(
201
- info=step_run_info, step_failed=step_failed
202
- )
203
- if not step_failed:
204
- if (
205
- success_hook_source
206
- := self.configuration.success_hook_source
207
- ):
208
- logger.info("Detected success hook. Running...")
209
- self.load_and_run_hook(
210
- success_hook_source,
211
- step_exception=None,
212
- )
213
-
214
- # Store and publish the output artifacts of the step function.
215
- output_data = self._validate_outputs(
216
- return_values, output_annotations
194
+ try:
195
+ step_run_metadata = self._stack.get_step_run_metadata(
196
+ info=step_run_info,
217
197
  )
218
- artifact_metadata_enabled = is_setting_enabled(
219
- is_enabled_on_step=step_run_info.config.enable_artifact_metadata,
220
- is_enabled_on_pipeline=step_run_info.pipeline.enable_artifact_metadata,
198
+ publish_step_run_metadata(
199
+ step_run_id=step_run_info.step_run_id,
200
+ step_run_metadata=step_run_metadata,
221
201
  )
222
- artifact_visualization_enabled = is_setting_enabled(
223
- is_enabled_on_step=step_run_info.config.enable_artifact_visualization,
224
- is_enabled_on_pipeline=step_run_info.pipeline.enable_artifact_visualization,
202
+ self._stack.cleanup_step_run(
203
+ info=step_run_info, step_failed=step_failed
225
204
  )
226
- output_artifacts = self._store_output_artifacts(
227
- output_data=output_data,
228
- output_artifact_uris=output_artifact_uris,
229
- output_materializers=output_materializers,
230
- output_annotations=output_annotations,
231
- artifact_metadata_enabled=artifact_metadata_enabled,
232
- artifact_visualization_enabled=artifact_visualization_enabled,
233
- )
234
-
235
- if (
236
- model_version := step_run.model_version
237
- or pipeline_run.model_version
238
- ):
239
- from zenml.orchestrators import step_run_utils
240
-
241
- step_run_utils.link_output_artifacts_to_model_version(
242
- artifacts=output_artifacts,
243
- output_configurations=step_run.config.outputs,
244
- model_version=model_version,
205
+ if not step_failed:
206
+ if (
207
+ success_hook_source
208
+ := self.configuration.success_hook_source
209
+ ):
210
+ logger.info("Detected success hook. Running...")
211
+ self.load_and_run_hook(
212
+ success_hook_source,
213
+ step_exception=None,
214
+ )
215
+
216
+ # Store and publish the output artifacts of the step function.
217
+ output_data = self._validate_outputs(
218
+ return_values, output_annotations
219
+ )
220
+ artifact_metadata_enabled = is_setting_enabled(
221
+ is_enabled_on_step=step_run_info.config.enable_artifact_metadata,
222
+ is_enabled_on_pipeline=step_run_info.pipeline.enable_artifact_metadata,
223
+ )
224
+ artifact_visualization_enabled = is_setting_enabled(
225
+ is_enabled_on_step=step_run_info.config.enable_artifact_visualization,
226
+ is_enabled_on_pipeline=step_run_info.pipeline.enable_artifact_visualization,
245
227
  )
228
+ output_artifacts = self._store_output_artifacts(
229
+ output_data=output_data,
230
+ output_artifact_uris=output_artifact_uris,
231
+ output_materializers=output_materializers,
232
+ output_annotations=output_annotations,
233
+ artifact_metadata_enabled=artifact_metadata_enabled,
234
+ artifact_visualization_enabled=artifact_visualization_enabled,
235
+ )
236
+
237
+ if (
238
+ model_version := step_run.model_version
239
+ or pipeline_run.model_version
240
+ ):
241
+ from zenml.orchestrators import step_run_utils
246
242
 
247
- StepContext._clear() # Remove the step context singleton
243
+ step_run_utils.link_output_artifacts_to_model_version(
244
+ artifacts=output_artifacts,
245
+ output_configurations=step_run.config.outputs,
246
+ model_version=model_version,
247
+ )
248
+ finally:
249
+ StepContext._clear() # Remove the step context singleton
248
250
 
249
251
  # Update the status and output artifacts of the step run.
250
252
  output_artifact_ids = {
@@ -406,15 +408,25 @@ class StepRunner:
406
408
  )
407
409
  )
408
410
 
409
- with register_artifact_store_filesystem(
410
- artifact.artifact_store_id
411
- ) as target_artifact_store:
411
+ def _load_artifact(artifact_store: "BaseArtifactStore") -> Any:
412
412
  materializer: BaseMaterializer = materializer_class(
413
- uri=artifact.uri, artifact_store=target_artifact_store
413
+ uri=artifact.uri, artifact_store=artifact_store
414
414
  )
415
- materializer.validate_type_compatibility(data_type)
415
+ materializer.validate_load_type_compatibility(data_type)
416
416
  return materializer.load(data_type=data_type)
417
417
 
418
+ if artifact.artifact_store_id == self._stack.artifact_store.id:
419
+ # Register the artifact store of the active stack here to avoid
420
+ # unnecessary component/flavor calls when using
421
+ # `register_artifact_store_filesystem(...)`
422
+ self._stack.artifact_store._register()
423
+ return _load_artifact(artifact_store=self._stack.artifact_store)
424
+ else:
425
+ with register_artifact_store_filesystem(
426
+ artifact.artifact_store_id
427
+ ) as target_artifact_store:
428
+ return _load_artifact(artifact_store=target_artifact_store)
429
+
418
430
  def _validate_outputs(
419
431
  self,
420
432
  return_values: Any,
@@ -25,11 +25,12 @@ from zenml.config.global_config import (
25
25
  from zenml.constants import (
26
26
  ENV_ZENML_ACTIVE_STACK_ID,
27
27
  ENV_ZENML_ACTIVE_WORKSPACE_ID,
28
+ ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING,
28
29
  ENV_ZENML_SERVER,
29
30
  ENV_ZENML_STORE_PREFIX,
30
31
  PIPELINE_API_TOKEN_EXPIRES_MINUTES,
31
32
  )
32
- from zenml.enums import StackComponentType, StoreType
33
+ from zenml.enums import AuthScheme, StackComponentType, StoreType
33
34
  from zenml.logger import get_logger
34
35
  from zenml.stack import StackComponent
35
36
  from zenml.utils.string_utils import format_name_template
@@ -93,32 +94,54 @@ def get_config_environment_vars(
93
94
  Returns:
94
95
  Environment variable dict.
95
96
  """
97
+ from zenml.login.credentials_store import get_credentials_store
96
98
  from zenml.zen_stores.rest_zen_store import RestZenStore
97
99
 
98
100
  global_config = GlobalConfiguration()
99
101
  environment_vars = global_config.get_config_environment_vars()
100
102
 
101
- if deployment and global_config.store_configuration.type == StoreType.REST:
102
- # When connected to a ZenML server, if a pipeline deployment is
103
- # supplied, we need to fetch an API token that will be valid for the
104
- # duration of the pipeline run.
105
- assert isinstance(global_config.zen_store, RestZenStore)
106
- pipeline_id: Optional[UUID] = None
107
- if deployment.pipeline:
108
- pipeline_id = deployment.pipeline.id
109
- schedule_id: Optional[UUID] = None
110
- expires_minutes: Optional[int] = PIPELINE_API_TOKEN_EXPIRES_MINUTES
111
- if deployment.schedule:
112
- schedule_id = deployment.schedule.id
113
- # If a schedule is given, this is a long running pipeline that
114
- # should not have an API token that expires.
115
- expires_minutes = None
116
- api_token = global_config.zen_store.get_api_token(
117
- pipeline_id=pipeline_id,
118
- schedule_id=schedule_id,
119
- expires_minutes=expires_minutes,
120
- )
121
- environment_vars[ENV_ZENML_STORE_PREFIX + "API_TOKEN"] = api_token
103
+ if (
104
+ global_config.store_configuration.type == StoreType.REST
105
+ and global_config.zen_store.get_store_info().auth_scheme
106
+ != AuthScheme.NO_AUTH
107
+ ):
108
+ credentials_store = get_credentials_store()
109
+ url = global_config.store_configuration.url
110
+ api_key = credentials_store.get_api_key(url)
111
+ api_token = credentials_store.get_token(url, allow_expired=False)
112
+ if api_key:
113
+ environment_vars[ENV_ZENML_STORE_PREFIX + "API_KEY"] = api_key
114
+ elif deployment:
115
+ # When connected to an authenticated ZenML server, if a pipeline
116
+ # deployment is supplied, we need to fetch an API token that will be
117
+ # valid for the duration of the pipeline run.
118
+ assert isinstance(global_config.zen_store, RestZenStore)
119
+ pipeline_id: Optional[UUID] = None
120
+ if deployment.pipeline:
121
+ pipeline_id = deployment.pipeline.id
122
+ schedule_id: Optional[UUID] = None
123
+ expires_minutes: Optional[int] = PIPELINE_API_TOKEN_EXPIRES_MINUTES
124
+ if deployment.schedule:
125
+ schedule_id = deployment.schedule.id
126
+ # If a schedule is given, this is a long running pipeline that
127
+ # should not have an API token that expires.
128
+ expires_minutes = None
129
+ new_api_token = global_config.zen_store.get_api_token(
130
+ pipeline_id=pipeline_id,
131
+ schedule_id=schedule_id,
132
+ expires_minutes=expires_minutes,
133
+ )
134
+ environment_vars[ENV_ZENML_STORE_PREFIX + "API_TOKEN"] = (
135
+ new_api_token
136
+ )
137
+ elif api_token:
138
+ environment_vars[ENV_ZENML_STORE_PREFIX + "API_TOKEN"] = (
139
+ api_token.access_token
140
+ )
141
+
142
+ # Disable credentials caching to avoid storing sensitive information
143
+ # in the pipeline run environment
144
+ environment_vars[ENV_ZENML_DISABLE_CREDENTIALS_DISK_CACHING] = "true"
122
145
 
123
146
  # Make sure to use the correct active stack/workspace which might come
124
147
  # from a .zen repository and not the global config
@@ -18,6 +18,7 @@ from typing import (
18
18
  Any,
19
19
  Callable,
20
20
  Dict,
21
+ List,
21
22
  Optional,
22
23
  TypeVar,
23
24
  Union,
@@ -49,6 +50,7 @@ def pipeline(
49
50
  enable_artifact_metadata: Optional[bool] = None,
50
51
  enable_step_logs: Optional[bool] = None,
51
52
  settings: Optional[Dict[str, "SettingsOrDict"]] = None,
53
+ tags: Optional[List[str]] = None,
52
54
  extra: Optional[Dict[str, Any]] = None,
53
55
  on_failure: Optional["HookSpecification"] = None,
54
56
  on_success: Optional["HookSpecification"] = None,
@@ -64,6 +66,7 @@ def pipeline(
64
66
  enable_artifact_metadata: Optional[bool] = None,
65
67
  enable_step_logs: Optional[bool] = None,
66
68
  settings: Optional[Dict[str, "SettingsOrDict"]] = None,
69
+ tags: Optional[List[str]] = None,
67
70
  extra: Optional[Dict[str, Any]] = None,
68
71
  on_failure: Optional["HookSpecification"] = None,
69
72
  on_success: Optional["HookSpecification"] = None,
@@ -79,6 +82,7 @@ def pipeline(
79
82
  enable_artifact_metadata: Whether to enable artifact metadata or not.
80
83
  enable_step_logs: If step logs should be enabled for this pipeline.
81
84
  settings: Settings for this pipeline.
85
+ tags: Tags to apply to runs of the pipeline.
82
86
  extra: Extra configurations for this pipeline.
83
87
  on_failure: Callback function in event of failure of the step. Can be a
84
88
  function with a single argument of type `BaseException`, or a source
@@ -101,6 +105,7 @@ def pipeline(
101
105
  enable_artifact_metadata=enable_artifact_metadata,
102
106
  enable_step_logs=enable_step_logs,
103
107
  settings=settings,
108
+ tags=tags,
104
109
  extra=extra,
105
110
  on_failure=on_failure,
106
111
  on_success=on_success,