truefoundry 0.11.11rc1__py3-none-any.whl → 0.11.12__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 truefoundry might be problematic. Click here for more details.

Files changed (24) hide show
  1. truefoundry/common/constants.py +1 -8
  2. truefoundry/common/storage_provider_utils.py +35 -10
  3. truefoundry/deploy/__init__.py +0 -3
  4. truefoundry/deploy/_autogen/models.py +144 -191
  5. truefoundry/deploy/builder/__init__.py +0 -1
  6. truefoundry/deploy/builder/builders/tfy_python_buildpack/__init__.py +6 -3
  7. truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py +84 -347
  8. truefoundry/deploy/builder/builders/tfy_spark_buildpack/__init__.py +7 -3
  9. truefoundry/deploy/builder/builders/tfy_spark_buildpack/dockerfile_template.py +18 -18
  10. truefoundry/deploy/builder/builders/tfy_task_pyspark_buildpack/__init__.py +7 -3
  11. truefoundry/deploy/builder/builders/tfy_task_pyspark_buildpack/dockerfile_template.py +18 -18
  12. truefoundry/deploy/builder/constants.py +0 -12
  13. truefoundry/deploy/builder/utils.py +21 -210
  14. truefoundry/deploy/lib/util.py +0 -35
  15. truefoundry/deploy/v2/lib/deploy.py +1 -3
  16. truefoundry/deploy/v2/lib/patched_models.py +3 -76
  17. truefoundry/deploy/v2/lib/source.py +0 -4
  18. truefoundry/ml/artifact/truefoundry_artifact_repo.py +25 -11
  19. truefoundry/ml/log_types/artifacts/artifact.py +3 -2
  20. truefoundry/ml/log_types/artifacts/model.py +1 -0
  21. {truefoundry-0.11.11rc1.dist-info → truefoundry-0.11.12.dist-info}/METADATA +1 -2
  22. {truefoundry-0.11.11rc1.dist-info → truefoundry-0.11.12.dist-info}/RECORD +24 -24
  23. {truefoundry-0.11.11rc1.dist-info → truefoundry-0.11.12.dist-info}/WHEEL +0 -0
  24. {truefoundry-0.11.11rc1.dist-info → truefoundry-0.11.12.dist-info}/entry_points.txt +0 -0
@@ -74,8 +74,7 @@ class TrueFoundrySdkEnv(BaseSettings):
74
74
  TFY_CLI_LOCAL_DEV_MODE: bool = False
75
75
 
76
76
  TFY_PYTHON_BUILD_PACKAGE_MANAGER: PythonPackageManager = PythonPackageManager.UV
77
- TFY_PYTHON_BUILD_UV_IMAGE_REPO: str = "ghcr.io/astral-sh/uv"
78
- TFY_PYTHON_BUILD_UV_IMAGE_TAG: str = "latest"
77
+ TFY_PYTHON_BUILD_UV_IMAGE_URI: str = "ghcr.io/astral-sh/uv:latest"
79
78
 
80
79
  # Global Constants for OpenAI Integration
81
80
  OPENAI_API_KEY: Optional[str] = Field(default=None, env=OPENAI_API_KEY_KEY)
@@ -94,12 +93,6 @@ class TrueFoundrySdkEnv(BaseSettings):
94
93
  )
95
94
  TFY_ASK_SYSTEM_PROMPT_NAME: str = Field(default="tfy-ask-k8s-prompt")
96
95
  TFY_INTERNAL_ASK_CONFIG_OVERRIDE_FILE: Optional[str] = Field(default=None)
97
- TFY_PYTHON_BUILD_POETRY_VERSION: str = Field(
98
- default="2.0", env="TFY_PYTHON_BUILD_POETRY_VERSION"
99
- )
100
- TFY_PYTHON_BUILD_LATEST_POETRY_MAJOR_VERSION: int = Field(
101
- default=2, env="TFY_PYTHON_BUILD_LATEST_POETRY_MAJOR_VERSION"
102
- )
103
96
 
104
97
  # This is a hack to fresh read the env vars because people can end up importing this file
105
98
  # before setting the correct env vars. E.g. in notebook environments.
@@ -22,6 +22,23 @@ from truefoundry.pydantic_v1 import BaseModel
22
22
  logger = logging.getLogger("truefoundry")
23
23
 
24
24
 
25
+ def truncate_path_for_progress(
26
+ path: str, max_length: int, relpath: bool = False
27
+ ) -> str:
28
+ if relpath:
29
+ path = os.path.relpath(path)
30
+ if len(path) <= max_length:
31
+ return path
32
+ parts = path.split(os.sep)
33
+ result = parts[-1] # start with filename
34
+ i = len(parts) - 2
35
+ # keep prepending directories until adding more would exceed max_len - 3
36
+ while i >= 0 and len(result) + len(parts[i]) + 1 <= max_length - 3:
37
+ result = parts[i] + os.sep + result
38
+ i -= 1
39
+ return "..." + os.sep + result
40
+
41
+
25
42
  class MultiPartUploadStorageProvider(str, Enum):
26
43
  S3_COMPATIBLE = "S3_COMPATIBLE"
27
44
  AZURE_BLOB = "AZURE_BLOB"
@@ -182,7 +199,7 @@ def _file_part_upload(
182
199
  return response
183
200
 
184
201
 
185
- def s3_compatible_multipart_upload(
202
+ def s3_compatible_multipart_upload( # noqa: C901
186
203
  multipart_upload: MultiPartUpload,
187
204
  local_file: str,
188
205
  multipart_info: _FileMultiPartInfo,
@@ -190,13 +207,15 @@ def s3_compatible_multipart_upload(
190
207
  progress_bar: Optional[Progress] = None,
191
208
  abort_event: Optional[Event] = None,
192
209
  exception_class=HttpRequestException,
193
- ):
210
+ ) -> None:
194
211
  abort_event = abort_event or Event()
195
212
  parts = []
196
213
 
197
- if progress_bar:
214
+ if progress_bar is not None:
198
215
  multi_part_upload_progress = progress_bar.add_task(
199
- f"[green]Uploading {local_file}:", start=True
216
+ f"[green] {truncate_path_for_progress(local_file, 64, relpath=True)}",
217
+ start=True,
218
+ visible=True,
200
219
  )
201
220
 
202
221
  def upload(part_number: int, seek: int) -> None:
@@ -221,7 +240,7 @@ def s3_compatible_multipart_upload(
221
240
  multipart_info.num_parts,
222
241
  local_file,
223
242
  )
224
- if progress_bar:
243
+ if progress_bar is not None:
225
244
  progress_bar.update(
226
245
  multi_part_upload_progress,
227
246
  advance=multipart_info.part_size,
@@ -254,10 +273,12 @@ def s3_compatible_multipart_upload(
254
273
  timeout=2 * 60,
255
274
  )
256
275
  response.raise_for_status()
276
+ if progress_bar is not None:
277
+ progress_bar.refresh()
257
278
  logger.debug("Multipart upload of %s completed", local_file)
258
279
 
259
280
 
260
- def azure_multi_part_upload(
281
+ def azure_multi_part_upload( # noqa: C901
261
282
  multipart_upload: MultiPartUpload,
262
283
  local_file: str,
263
284
  multipart_info: _FileMultiPartInfo,
@@ -265,12 +286,14 @@ def azure_multi_part_upload(
265
286
  progress_bar: Optional[Progress] = None,
266
287
  abort_event: Optional[Event] = None,
267
288
  exception_class=HttpRequestException,
268
- ):
289
+ ) -> None:
269
290
  abort_event = abort_event or Event()
270
291
 
271
- if progress_bar:
292
+ if progress_bar is not None:
272
293
  multi_part_upload_progress = progress_bar.add_task(
273
- f"[green]Uploading {local_file}:", start=True
294
+ f"[green] {truncate_path_for_progress(local_file, 64, relpath=True)}",
295
+ start=True,
296
+ visible=True,
274
297
  )
275
298
 
276
299
  def upload(part_number: int, seek: int):
@@ -289,7 +312,7 @@ def azure_multi_part_upload(
289
312
  abort_event=abort_event,
290
313
  exception_class=exception_class,
291
314
  )
292
- if progress_bar:
315
+ if progress_bar is not None:
293
316
  progress_bar.update(
294
317
  multi_part_upload_progress,
295
318
  advance=multipart_info.part_size,
@@ -328,4 +351,6 @@ def azure_multi_part_upload(
328
351
  timeout=2 * 60,
329
352
  )
330
353
  response.raise_for_status()
354
+ if progress_bar is not None:
355
+ progress_bar.refresh()
331
356
  logger.debug("Multipart upload of %s completed", local_file)
@@ -52,7 +52,6 @@ from truefoundry.deploy.v2.lib.deployable_patched_models import (
52
52
  Workflow,
53
53
  )
54
54
  from truefoundry.deploy.v2.lib.patched_models import (
55
- UV,
56
55
  AMQPInputConfig,
57
56
  AMQPMetricConfig,
58
57
  AMQPOutputConfig,
@@ -103,8 +102,6 @@ from truefoundry.deploy.v2.lib.patched_models import (
103
102
  NvidiaTimeslicingGPU,
104
103
  OCIRepo,
105
104
  Param,
106
- Pip,
107
- Poetry,
108
105
  Port,
109
106
  PythonBuild,
110
107
  RemoteSource,
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: application.json
3
- # timestamp: 2025-09-09T14:09:56+00:00
3
+ # timestamp: 2025-09-09T12:09:08+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -603,37 +603,6 @@ class Param(BaseModel):
603
603
  param_type: ParamType = "string"
604
604
 
605
605
 
606
- class Pip(BaseModel):
607
- """
608
- Use pip to install requirements files and packages
609
- """
610
-
611
- type: Literal["pip"] = Field(..., description="")
612
- requirements_path: Optional[str] = Field(
613
- None,
614
- description="Path to `requirements.txt` relative to `Path to build context`",
615
- )
616
- pip_packages: Optional[List[str]] = Field(
617
- None,
618
- description='Define pip package requirements.\nIn Python/YAML E.g. ["fastapi>=0.90,<1.0", "uvicorn"]',
619
- )
620
-
621
-
622
- class Poetry(BaseModel):
623
- """
624
- Use `poetry` to setup environment and sync `poetry.lock` file
625
- Your build context root must contain a `poetry.lock` file
626
- """
627
-
628
- type: Literal["poetry"] = Field(..., description="")
629
- poetry_version: Union[
630
- Literal["latest"], constr(regex=r"^\d+(\.\d+){1,2}([\-\.a-z0-9]+)?$")
631
- ] = Field("latest", description="Poetry version to use")
632
- install_options: Optional[str] = Field(
633
- None, description="install options to pass to poetry command"
634
- )
635
-
636
-
637
606
  class Protocol(str, Enum):
638
607
  """
639
608
  Protocol for the port.
@@ -656,6 +625,47 @@ class AppProtocol(str, Enum):
656
625
  tcp = "tcp"
657
626
 
658
627
 
628
+ class PythonBuild(BaseModel):
629
+ """
630
+ Describes that we are using python to build a container image with a specific python version and pip packages installed.
631
+ """
632
+
633
+ type: Literal["tfy-python-buildpack"] = Field(..., description="")
634
+ python_version: Optional[constr(regex=r"^\d+(\.\d+){1,2}([\-\.a-z0-9]+)?$")] = (
635
+ Field(
636
+ None,
637
+ description="Python version to run your application. Should be one of the tags listed on [Official Python Docker Page](https://hub.docker.com/_/python)",
638
+ )
639
+ )
640
+ build_context_path: str = Field(
641
+ "./", description="Build path relative to project root path."
642
+ )
643
+ requirements_path: Optional[str] = Field(
644
+ None,
645
+ description="Path to `requirements.txt` relative to\n`Path to build context`",
646
+ )
647
+ pip_packages: Optional[List[str]] = Field(
648
+ None,
649
+ description='Define pip package requirements.\nIn Python/YAML E.g. ["fastapi>=0.90,<1.0", "uvicorn"]',
650
+ )
651
+ apt_packages: Optional[List[str]] = Field(
652
+ None,
653
+ description='Debian packages to install via `apt get`.\nIn Python/YAML E.g. ["git", "ffmpeg", "htop"]',
654
+ )
655
+ command: Union[str, List[str]] = Field(
656
+ ...,
657
+ description="Command to run when the container starts.\nCommand will be set as the Entrypoint of the generated image.\nWhen deploying a Job, the command can be templatized by defining `params` and referencing them in command\nE.g. `python main.py --learning_rate {{learning_rate}}`",
658
+ )
659
+ cuda_version: Optional[
660
+ constr(
661
+ regex=r"^((\d+\.\d+(\.\d+)?-cudnn\d+-(runtime|devel)-ubuntu\d+\.\d+)|11\.0-cudnn8|11\.1-cudnn8|11\.2-cudnn8|11\.3-cudnn8|11\.4-cudnn8|11\.5-cudnn8|11\.6-cudnn8|11\.7-cudnn8|11\.8-cudnn8|12\.0-cudnn8|12\.1-cudnn8|12\.2-cudnn8|12\.3-cudnn9|12\.4-cudnn9|12\.5-cudnn9|12\.6-cudnn9)$"
662
+ )
663
+ ] = Field(
664
+ None,
665
+ description="Version of CUDA Toolkit and CUDNN to install in the image\nThese combinations are based off of publically available docker images on docker hub\nYou can also specify a valid tag of the form {cuda_version_number}-cudnn{cudnn_version_number}-{runtime|devel}-ubuntu{ubuntu_version}\nRefer https://hub.docker.com/r/nvidia/cuda/tags for valid set of values\nNote: We use deadsnakes ubuntu ppa to add Python that currently supports only Ubuntu 18.04, 20.04 and 22.04",
666
+ )
667
+
668
+
659
669
  class RPSMetric(BaseModel):
660
670
  type: Literal["rps"] = Field(..., description="")
661
671
  value: PositiveFloat = Field(
@@ -1092,19 +1102,6 @@ class TrueFoundryInteractiveLogin(BaseModel):
1092
1102
  )
1093
1103
 
1094
1104
 
1095
- class UV(BaseModel):
1096
- """
1097
- Use `uv` to setup environment and sync `uv.lock` file
1098
- Your build context root must contain a `uv.lock` file
1099
- """
1100
-
1101
- type: Literal["uv"] = Field(..., description="")
1102
- uv_version: str = Field("latest", description="UV version to use")
1103
- sync_options: Optional[str] = Field(
1104
- None, description="Sync options to pass to uv command"
1105
- )
1106
-
1107
-
1108
1105
  class VolumeBrowser(BaseModel):
1109
1106
  username: Optional[constr(regex=r"^[a-z][a-z0-9]{1,8}[a-z0-9]$")] = Field(
1110
1107
  None, description="Username for logging in the volume browser."
@@ -1202,6 +1199,25 @@ class BaseWorkbenchInput(BaseModel):
1202
1199
  )
1203
1200
 
1204
1201
 
1202
+ class Build(BaseModel):
1203
+ """
1204
+ Describes how we build our code into a Docker image.
1205
+ """
1206
+
1207
+ type: Literal["build"] = Field(..., description="")
1208
+ docker_registry: Optional[constr(regex=r"^\S+$")] = Field(
1209
+ None,
1210
+ description="FQN of the container registry. If you can't find your registry here,\nadd it through the [Integrations](/integrations?tab=docker-registry) page",
1211
+ )
1212
+ build_source: Union[RemoteSource, GitSource, LocalSource] = Field(
1213
+ ..., description="Source code location."
1214
+ )
1215
+ build_spec: Union[DockerFileBuild, PythonBuild] = Field(
1216
+ ...,
1217
+ description="Instructions to build a container image out of the build source",
1218
+ )
1219
+
1220
+
1205
1221
  class Canary(BaseModel):
1206
1222
  """
1207
1223
  This strategy brings up the new release without bringing the older release down. Traffic is shifted from the older release to the newer release in a staged manner.
@@ -1224,6 +1240,23 @@ class Codeserver(BaseWorkbenchInput):
1224
1240
  image: WorkbenchImage
1225
1241
 
1226
1242
 
1243
+ class ContainerTaskConfig(BaseModel):
1244
+ type: Literal["container-task-config"] = Field(..., description="")
1245
+ image: Union[Build, Image] = Field(
1246
+ ...,
1247
+ description="Specify whether you want to deploy a Docker image or build and deploy from source code",
1248
+ )
1249
+ env: Optional[Dict[str, str]] = Field(
1250
+ None,
1251
+ description="Configure environment variables to be injected in the task either as plain text or secrets. [Docs](https://docs.truefoundry.com/docs/env-variables)",
1252
+ )
1253
+ resources: Optional[Resources] = None
1254
+ mounts: Optional[List[Union[SecretMount, StringDataMount, VolumeMount]]] = Field(
1255
+ None, description="Configure data to be mounted to Workflow pod(s) as a volume."
1256
+ )
1257
+ service_account: Optional[str] = Field(None, description="")
1258
+
1259
+
1227
1260
  class CoreNATSOutputConfig(BaseModel):
1228
1261
  """
1229
1262
  Describes the configuration for the output Core NATS worker
@@ -1412,50 +1445,6 @@ class Port(BaseModel):
1412
1445
  ] = Field(None, description="Authentication method for inbound traffic")
1413
1446
 
1414
1447
 
1415
- class PythonBuild(BaseModel):
1416
- """
1417
- Describes that we are using python to build a container image with a specific python version and pip packages installed.
1418
- """
1419
-
1420
- type: Literal["tfy-python-buildpack"] = Field(..., description="")
1421
- python_version: Optional[constr(regex=r"^\d+(\.\d+){1,2}([\-\.a-z0-9]+)?$")] = (
1422
- Field(
1423
- None,
1424
- description="Python version to run your application. Should be one of the tags listed on [Official Python Docker Page](https://hub.docker.com/_/python)",
1425
- )
1426
- )
1427
- build_context_path: str = Field(
1428
- "./", description="Build path relative to project root path."
1429
- )
1430
- requirements_path: Optional[str] = Field(
1431
- None,
1432
- description="Path to `requirements.txt` relative to\n`Path to build context`",
1433
- )
1434
- pip_packages: Optional[List[str]] = Field(
1435
- None,
1436
- description='Define pip package requirements.\nIn Python/YAML E.g. ["fastapi>=0.90,<1.0", "uvicorn"]',
1437
- )
1438
- python_dependencies: Optional[Union[Pip, UV, Poetry]] = Field(
1439
- None, description="Python dependencies to install"
1440
- )
1441
- apt_packages: Optional[List[str]] = Field(
1442
- None,
1443
- description='Debian packages to install via `apt get`.\nIn Python/YAML E.g. ["git", "ffmpeg", "htop"]',
1444
- )
1445
- command: Union[str, List[str]] = Field(
1446
- ...,
1447
- description="Command to run when the container starts.\nCommand will be set as the Entrypoint of the generated image.\nWhen deploying a Job, the command can be templatized by defining `params` and referencing them in command\nE.g. `python main.py --learning_rate {{learning_rate}}`",
1448
- )
1449
- cuda_version: Optional[
1450
- constr(
1451
- regex=r"^((\d+\.\d+(\.\d+)?-cudnn\d+-(runtime|devel)-ubuntu\d+\.\d+)|11\.0-cudnn8|11\.1-cudnn8|11\.2-cudnn8|11\.3-cudnn8|11\.4-cudnn8|11\.5-cudnn8|11\.6-cudnn8|11\.7-cudnn8|11\.8-cudnn8|12\.0-cudnn8|12\.1-cudnn8|12\.2-cudnn8|12\.3-cudnn9|12\.4-cudnn9|12\.5-cudnn9|12\.6-cudnn9)$"
1452
- )
1453
- ] = Field(
1454
- None,
1455
- description="Version of CUDA Toolkit and CUDNN to install in the image\nThese combinations are based off of publically available docker images on docker hub\nYou can also specify a valid tag of the form {cuda_version_number}-cudnn{cudnn_version_number}-{runtime|devel}-ubuntu{ubuntu_version}\nRefer https://hub.docker.com/r/nvidia/cuda/tags for valid set of values\nNote: We use deadsnakes ubuntu ppa to add Python that currently supports only Ubuntu 18.04, 20.04 and 22.04",
1456
- )
1457
-
1458
-
1459
1448
  class PythonTaskConfig(BaseModel):
1460
1449
  """
1461
1450
  Describes the configuration for the python function task
@@ -1591,40 +1580,38 @@ class WorkflowAlert(BaseModel):
1591
1580
  on_failure: bool = Field(True, description="Send an alert when the job fails")
1592
1581
 
1593
1582
 
1594
- class Build(BaseModel):
1595
- """
1596
- Describes how we build our code into a Docker image.
1597
- """
1598
-
1599
- type: Literal["build"] = Field(..., description="")
1600
- docker_registry: Optional[constr(regex=r"^\S+$")] = Field(
1601
- None,
1602
- description="FQN of the container registry. If you can't find your registry here,\nadd it through the [Integrations](/integrations?tab=docker-registry) page",
1603
- )
1604
- build_source: Union[RemoteSource, GitSource, LocalSource] = Field(
1605
- ..., description="Source code location."
1606
- )
1607
- build_spec: Union[DockerFileBuild, PythonBuild] = Field(
1583
+ class BaseService(BaseModel):
1584
+ name: constr(regex=r"^[a-z](?:[a-z0-9]|-(?!-)){1,30}[a-z0-9]$") = Field(
1608
1585
  ...,
1609
- description="Instructions to build a container image out of the build source",
1586
+ description="Name of the service. This uniquely identifies this service in the workspace.\n> Name can only contain alphanumeric characters and '-' and can be atmost 25 characters long",
1610
1587
  )
1611
-
1612
-
1613
- class ContainerTaskConfig(BaseModel):
1614
- type: Literal["container-task-config"] = Field(..., description="")
1615
1588
  image: Union[Build, Image] = Field(
1616
1589
  ...,
1617
1590
  description="Specify whether you want to deploy a Docker image or build and deploy from source code",
1618
1591
  )
1592
+ artifacts_download: Optional[ArtifactsDownload] = None
1593
+ resources: Optional[Resources] = None
1619
1594
  env: Optional[Dict[str, str]] = Field(
1620
1595
  None,
1621
- description="Configure environment variables to be injected in the task either as plain text or secrets. [Docs](https://docs.truefoundry.com/docs/env-variables)",
1596
+ description="Configure environment variables to be injected in the service either as plain text or secrets. [Docs](https://docs.truefoundry.com/docs/env-variables)",
1622
1597
  )
1623
- resources: Optional[Resources] = None
1598
+ ports: List[Port] = Field(
1599
+ ...,
1600
+ description="Expose the deployment to make it accessible over the internet or keep it private. Implement authentication to restrict access. [Docs](https://docs.truefoundry.com/docs/define-ports-and-domains)",
1601
+ )
1602
+ service_account: Optional[str] = None
1624
1603
  mounts: Optional[List[Union[SecretMount, StringDataMount, VolumeMount]]] = Field(
1625
- None, description="Configure data to be mounted to Workflow pod(s) as a volume."
1604
+ None,
1605
+ description="Configure data to be mounted to service pod(s) as a string, secret or volume. [Docs](https://docs.truefoundry.com/docs/mounting-volumes-service)",
1606
+ )
1607
+ labels: Optional[Dict[str, str]] = Field(None, description="")
1608
+ kustomize: Optional[Kustomize] = None
1609
+ liveness_probe: Optional[HealthProbe] = None
1610
+ readiness_probe: Optional[HealthProbe] = None
1611
+ startup_probe: Optional[HealthProbe] = None
1612
+ workspace_fqn: Optional[str] = Field(
1613
+ None, description="Fully qualified name of the workspace"
1626
1614
  )
1627
- service_account: Optional[str] = Field(None, description="")
1628
1615
 
1629
1616
 
1630
1617
  class FlyteLaunchPlan(BaseModel):
@@ -1670,38 +1657,40 @@ class PySparkTaskConfig(BaseModel):
1670
1657
  service_account: Optional[str] = Field(None, description="")
1671
1658
 
1672
1659
 
1673
- class BaseService(BaseModel):
1674
- name: constr(regex=r"^[a-z](?:[a-z0-9]|-(?!-)){1,30}[a-z0-9]$") = Field(
1675
- ...,
1676
- description="Name of the service. This uniquely identifies this service in the workspace.\n> Name can only contain alphanumeric characters and '-' and can be atmost 25 characters long",
1677
- )
1678
- image: Union[Build, Image] = Field(
1679
- ...,
1680
- description="Specify whether you want to deploy a Docker image or build and deploy from source code",
1681
- )
1682
- artifacts_download: Optional[ArtifactsDownload] = None
1683
- resources: Optional[Resources] = None
1684
- env: Optional[Dict[str, str]] = Field(
1685
- None,
1686
- description="Configure environment variables to be injected in the service either as plain text or secrets. [Docs](https://docs.truefoundry.com/docs/env-variables)",
1660
+ class Service(BaseService):
1661
+ """
1662
+ Describes the configuration for the service
1663
+ """
1664
+
1665
+ type: Literal["service"] = Field(..., description="")
1666
+ replicas: Union[confloat(ge=0.0, le=500.0), ServiceAutoscaling] = Field(
1667
+ 1,
1668
+ description="Deploy multiple instances of your pods to distribute incoming traffic across them, ensuring effective load balancing.",
1687
1669
  )
1688
- ports: List[Port] = Field(
1689
- ...,
1690
- description="Expose the deployment to make it accessible over the internet or keep it private. Implement authentication to restrict access. [Docs](https://docs.truefoundry.com/docs/define-ports-and-domains)",
1670
+ auto_shutdown: Optional[Autoshutdown] = None
1671
+ allow_interception: bool = Field(
1672
+ False,
1673
+ description="Whether to allow intercepts to be applied for this service.\nThis would inject an additional sidecar in each pod of the service. Not recommended on production",
1691
1674
  )
1692
- service_account: Optional[str] = None
1693
- mounts: Optional[List[Union[SecretMount, StringDataMount, VolumeMount]]] = Field(
1675
+ rollout_strategy: Optional[Union[Rolling, Canary, BlueGreen]] = Field(
1694
1676
  None,
1695
- description="Configure data to be mounted to service pod(s) as a string, secret or volume. [Docs](https://docs.truefoundry.com/docs/mounting-volumes-service)",
1677
+ description="Strategy to dictate how a rollout should happen when a new release for this service is made [Docs](https://docs.truefoundry.com/docs/rollout-strategy)",
1696
1678
  )
1697
- labels: Optional[Dict[str, str]] = Field(None, description="")
1698
- kustomize: Optional[Kustomize] = None
1699
- liveness_probe: Optional[HealthProbe] = None
1700
- readiness_probe: Optional[HealthProbe] = None
1701
- startup_probe: Optional[HealthProbe] = None
1702
- workspace_fqn: Optional[str] = Field(
1703
- None, description="Fully qualified name of the workspace"
1679
+
1680
+
1681
+ class AsyncService(BaseService):
1682
+ """
1683
+ Describes the configuration for the async-service
1684
+ """
1685
+
1686
+ type: Literal["async-service"] = Field(..., description="")
1687
+ replicas: Union[confloat(ge=0.0, le=500.0), AsyncServiceAutoscaling] = Field(
1688
+ 1,
1689
+ description="Deploy multiple instances of your pods to distribute incoming traffic across them, ensuring effective load balancing.",
1704
1690
  )
1691
+ rollout_strategy: Optional[Rolling] = None
1692
+ worker_config: WorkerConfig
1693
+ sidecar: Optional[AsyncProcessorSidecar] = None
1705
1694
 
1706
1695
 
1707
1696
  class FlyteTaskCustom(BaseModel):
@@ -1766,40 +1755,30 @@ class Job(BaseModel):
1766
1755
  )
1767
1756
 
1768
1757
 
1769
- class Service(BaseService):
1758
+ class ApplicationSet(BaseModel):
1770
1759
  """
1771
- Describes the configuration for the service
1760
+ Describes the configuration for the application set
1772
1761
  """
1773
1762
 
1774
- type: Literal["service"] = Field(..., description="")
1775
- replicas: Union[confloat(ge=0.0, le=500.0), ServiceAutoscaling] = Field(
1776
- 1,
1777
- description="Deploy multiple instances of your pods to distribute incoming traffic across them, ensuring effective load balancing.",
1763
+ type: Literal["application-set"] = Field(..., description="")
1764
+ name: str = Field(..., description="Name of the application set.")
1765
+ components: Optional[List[Union[Service, AsyncService, Job, Helm]]] = Field(
1766
+ None, description="Array of components with their specifications."
1778
1767
  )
1779
- auto_shutdown: Optional[Autoshutdown] = None
1780
- allow_interception: bool = Field(
1781
- False,
1782
- description="Whether to allow intercepts to be applied for this service.\nThis would inject an additional sidecar in each pod of the service. Not recommended on production",
1768
+ template: Optional[str] = Field(
1769
+ None, description="Template to be used for the application set."
1783
1770
  )
1784
- rollout_strategy: Optional[Union[Rolling, Canary, BlueGreen]] = Field(
1771
+ values: Optional[Dict[str, Any]] = Field(
1785
1772
  None,
1786
- description="Strategy to dictate how a rollout should happen when a new release for this service is made [Docs](https://docs.truefoundry.com/docs/rollout-strategy)",
1773
+ description="Values to be used to render components for the application set.",
1787
1774
  )
1788
-
1789
-
1790
- class AsyncService(BaseService):
1791
- """
1792
- Describes the configuration for the async-service
1793
- """
1794
-
1795
- type: Literal["async-service"] = Field(..., description="")
1796
- replicas: Union[confloat(ge=0.0, le=500.0), AsyncServiceAutoscaling] = Field(
1797
- 1,
1798
- description="Deploy multiple instances of your pods to distribute incoming traffic across them, ensuring effective load balancing.",
1775
+ workspace_fqn: Optional[str] = Field(
1776
+ None, description="Fully qualified name of the workspace"
1777
+ )
1778
+ convert_template_manifest: Optional[bool] = Field(
1779
+ None,
1780
+ description="Flag to indicate if the template manifest should be converted to TrueFoundry manifest",
1799
1781
  )
1800
- rollout_strategy: Optional[Rolling] = None
1801
- worker_config: WorkerConfig
1802
- sidecar: Optional[AsyncProcessorSidecar] = None
1803
1782
 
1804
1783
 
1805
1784
  class FlyteTask(BaseModel):
@@ -1828,32 +1807,6 @@ class Workflow(BaseModel):
1828
1807
  alerts: Optional[List[WorkflowAlert]] = Field(None, description="")
1829
1808
 
1830
1809
 
1831
- class ApplicationSet(BaseModel):
1832
- """
1833
- Describes the configuration for the application set
1834
- """
1835
-
1836
- type: Literal["application-set"] = Field(..., description="")
1837
- name: str = Field(..., description="Name of the application set.")
1838
- components: Optional[List[Union[Service, AsyncService, Job, Helm]]] = Field(
1839
- None, description="Array of components with their specifications."
1840
- )
1841
- template: Optional[str] = Field(
1842
- None, description="Template to be used for the application set."
1843
- )
1844
- values: Optional[Dict[str, Any]] = Field(
1845
- None,
1846
- description="Values to be used to render components for the application set.",
1847
- )
1848
- workspace_fqn: Optional[str] = Field(
1849
- None, description="Fully qualified name of the workspace"
1850
- )
1851
- convert_template_manifest: Optional[bool] = Field(
1852
- None,
1853
- description="Flag to indicate if the template manifest should be converted to TrueFoundry manifest",
1854
- )
1855
-
1856
-
1857
1810
  class Application(BaseModel):
1858
1811
  __root__: Union[
1859
1812
  Service,
@@ -2,7 +2,6 @@ from typing import Any, Dict, List, Optional, Union
2
2
 
3
3
  from truefoundry.deploy._autogen.models import (
4
4
  DockerFileBuild,
5
- Pip,
6
5
  PythonBuild,
7
6
  SparkBuild,
8
7
  TaskDockerFileBuild,
@@ -15,11 +15,11 @@ __all__ = ["generate_dockerfile_content", "build"]
15
15
  def _convert_to_dockerfile_build_config(
16
16
  build_configuration: PythonBuild,
17
17
  dockerfile_path: str,
18
- extra_opts: Optional[List[str]] = None,
18
+ mount_python_package_manager_conf_secret: bool = False,
19
19
  ) -> DockerFileBuild:
20
20
  dockerfile_content = generate_dockerfile_content(
21
21
  build_configuration=build_configuration,
22
- docker_build_extra_args=extra_opts,
22
+ mount_python_package_manager_conf_secret=mount_python_package_manager_conf_secret,
23
23
  )
24
24
  with open(dockerfile_path, "w", encoding="utf8") as fp:
25
25
  fp.write(dockerfile_content)
@@ -40,11 +40,14 @@ def build(
40
40
  raise ValueError(
41
41
  "`python_version` is required for `tfy-python-buildpack` builder"
42
42
  )
43
+ mount_python_package_manager_conf_secret = (
44
+ has_python_package_manager_conf_secret(extra_opts) if extra_opts else False
45
+ )
43
46
  with TemporaryDirectory() as local_dir:
44
47
  docker_build_configuration = _convert_to_dockerfile_build_config(
45
48
  build_configuration,
46
49
  dockerfile_path=os.path.join(local_dir, "Dockerfile"),
47
- extra_opts=extra_opts,
50
+ mount_python_package_manager_conf_secret=mount_python_package_manager_conf_secret,
48
51
  )
49
52
  dockerfile.build(
50
53
  tag=tag,