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
@@ -1,150 +1,67 @@
1
- from copy import deepcopy
2
- from typing import Dict, List, Optional, Set, Union
1
+ from typing import Dict
3
2
 
4
- from jinja2 import Template
3
+ from mako.template import Template
5
4
 
6
5
  from truefoundry.common.constants import ENV_VARS, PythonPackageManager
7
- from truefoundry.deploy._autogen.models import UV, Pip, Poetry
6
+ from truefoundry.deploy._autogen.models import PythonBuild
7
+ from truefoundry.deploy.builder.constants import (
8
+ PIP_CONF_BUILDKIT_SECRET_MOUNT,
9
+ UV_CONF_BUILDKIT_SECRET_MOUNT,
10
+ )
8
11
  from truefoundry.deploy.builder.utils import (
9
12
  generate_apt_install_command,
10
- generate_command_to_install_from_uv_lock,
11
13
  generate_pip_install_command,
12
- generate_poetry_install_command,
13
- generate_secret_mounts,
14
14
  generate_uv_pip_install_command,
15
- get_available_secrets,
16
15
  )
17
16
  from truefoundry.deploy.v2.lib.patched_models import (
18
17
  CUDAVersion,
19
- PythonBuild,
20
18
  _resolve_requirements_path,
21
- check_whether_poetry_toml_exists,
22
19
  )
23
- from truefoundry.pydantic_v1 import BaseModel
24
-
25
-
26
- class TemplateContext(BaseModel):
27
- """Pydantic model for template context used in Dockerfile generation."""
28
-
29
- # Common fields
30
- python_image_repo: str
31
- python_version: str
32
- apt_install_command: Optional[str] = None
33
- package_manager_config_secret_mount: str = ""
34
-
35
- # Pip-specific fields
36
- requirements_path: Optional[str] = None
37
- requirements_destination_path: Optional[str] = None
38
- python_packages_install_command: Optional[str] = None
39
-
40
- # UV-specific fields
41
- final_uv_sync_command: Optional[str] = None
42
-
43
- # Poetry-specific fields
44
- final_poetry_install_command: Optional[str] = None
45
- poetry_version_expression: Optional[str] = None
46
- poetry_toml_exists: bool = False
47
-
48
-
49
- CUDA_BASE_IMAGE_TEMPLATE = """\
50
- FROM nvidia/cuda:{{ cuda_image_tag }} AS base
51
- SHELL ["/bin/bash", "-o", "pipefail", "-e", "-u", "-c"]
52
-
53
- ENV PATH=/virtualenvs/venv/bin:$PATH
54
- ENV VIRTUAL_ENV=/virtualenvs/venv/
55
- RUN echo "deb https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu $(cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2) main" >> /etc/apt/sources.list && \\
56
- echo "deb-src https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu $(cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2) main" >> /etc/apt/sources.list && \\
57
- apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F23C5A6CF475977595C89F51BA6932366A755776 && \\
58
- apt update && \\
59
- DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends git python{{ python_version }}-dev python{{ python_version }}-venv && \\
60
- python{{ python_version }} -m venv /virtualenvs/venv/ && \\
61
- rm -rf /var/lib/apt/lists/* && \\
62
- python -m pip install -U pip setuptools wheel
63
- """
64
-
65
- STANDARD_BASE_IMAGE_TEMPLATE = """\
66
- FROM {{ python_image_repo }}:{{ python_version }} AS base
67
- SHELL ["/bin/bash", "-o", "pipefail", "-e", "-u", "-c"]
68
-
69
- ENV PATH=/virtualenvs/venv/bin:$PATH
70
- ENV VIRTUAL_ENV=/virtualenvs/venv/
71
- RUN apt update && \\
72
- DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends git && \\
73
- python -m venv /virtualenvs/venv/ && \\
74
- rm -rf /var/lib/apt/lists/* && \\
75
- python -m pip install -U pip setuptools wheel
76
- """
77
20
 
21
+ # TODO (chiragjn): Switch to a non-root user inside the container
78
22
 
79
- APT_PACKAGES_TEMPLATE = """
80
- {% if apt_install_command %}
81
- RUN {{ apt_install_command }}
82
- {% endif %}
83
- """
84
-
85
-
86
- PIP_DEPENDENCIES_TEMPLATE = """\
87
- {% if requirements_path %}
88
- COPY {{ requirements_path }} {{ requirements_destination_path }}
89
- {% endif %}
90
-
91
- {% if python_packages_install_command %}
92
- RUN {{ package_manager_config_secret_mount }} {{ python_packages_install_command }}
93
- {% endif %}
23
+ DEFAULT_PYTHON_IMAGE_REPO = "public.ecr.aws/docker/library/python"
94
24
 
25
+ _POST_PYTHON_INSTALL_TEMPLATE = """
26
+ % if apt_install_command is not None:
27
+ RUN ${apt_install_command}
28
+ % endif
29
+ % if requirements_path is not None:
30
+ COPY ${requirements_path} ${requirements_destination_path}
31
+ % endif
32
+ % if python_packages_install_command is not None:
33
+ RUN ${package_manager_config_secret_mount} ${python_packages_install_command}
34
+ % endif
95
35
  COPY . /app
96
36
  WORKDIR /app
97
37
  """
98
38
 
99
- UV_DEPENDENCIES_TEMPLATE = """\
100
- # Set up UV environment
101
- WORKDIR /app
102
- COPY pyproject.toml uv.lock .
103
- {% if python_packages_install_command %}
104
- RUN {{ package_manager_config_secret_mount }} {{ python_packages_install_command }}
105
- {% endif %}
106
-
107
- COPY ./ .
108
- {% if final_uv_sync_command %}
109
- RUN {{ package_manager_config_secret_mount }} {{ final_uv_sync_command }}
110
- {% endif %}
111
- """
112
-
113
- POETRY_DEPENDENCIES_TEMPLATE = """\
114
- RUN python -m venv /opt/poetry
115
- ENV PATH="/opt/poetry/bin:$PATH"
116
- RUN pip install -q --no-cache-dir -U "poetry{{ poetry_version_expression }}"
117
-
118
- WORKDIR /app
119
- COPY pyproject.toml poetry.lock .
120
- {% if poetry_toml_exists %}
121
- COPY poetry.toml .
122
- {%- endif %}
123
- RUN poetry config virtualenvs.create false --local \\
124
- && poetry config virtualenvs.in-project false --local
125
-
126
- ENV PATH="/virtualenvs/venv/bin:$PATH"
127
- ENV VIRTUAL_ENV="/virtualenvs/venv/"
128
-
129
- {% if python_packages_install_command %}
130
- RUN {{ package_manager_config_secret_mount }} {{ python_packages_install_command }}
131
- {% endif %}
132
-
133
- COPY ./ .
134
-
135
- {% if final_poetry_install_command %}
136
- RUN {{ package_manager_config_secret_mount }} {{ final_poetry_install_command }}
137
- {% endif %}
138
-
139
- RUN rm -rf /opt/poetry
39
+ DOCKERFILE_TEMPLATE = Template(
40
+ """
41
+ FROM ${python_image_repo}:${python_version}
42
+ ENV PATH=/virtualenvs/venv/bin:$PATH
43
+ RUN apt update && \
44
+ DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends git && \
45
+ python -m venv /virtualenvs/venv/ && \
46
+ rm -rf /var/lib/apt/lists/*
140
47
  """
48
+ + _POST_PYTHON_INSTALL_TEMPLATE
49
+ )
141
50
 
142
- DOCKERFILE_TEMPLATE = """\
143
- {{ base_image_setup }}
144
- {{ apt_packages_section }}
145
- {{ python_dependencies_section }}
51
+ CUDA_DOCKERFILE_TEMPLATE = Template(
52
+ """
53
+ FROM nvidia/cuda:${nvidia_cuda_image_tag}
54
+ ENV PATH=/virtualenvs/venv/bin:$PATH
55
+ RUN echo "deb https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu $(cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2) main" >> /etc/apt/sources.list && \
56
+ echo "deb-src https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu $(cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2) main" >> /etc/apt/sources.list && \
57
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F23C5A6CF475977595C89F51BA6932366A755776 && \
58
+ apt update && \
59
+ DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends git python${python_version}-dev python${python_version}-venv && \
60
+ python${python_version} -m venv /virtualenvs/venv/ && \
61
+ rm -rf /var/lib/apt/lists/*
146
62
  """
147
-
63
+ + _POST_PYTHON_INSTALL_TEMPLATE
64
+ )
148
65
 
149
66
  CUDA_VERSION_TO_IMAGE_TAG: Dict[str, str] = {
150
67
  CUDAVersion.CUDA_11_0_CUDNN8.value: "11.0.3-cudnn8-runtime-ubuntu20.04",
@@ -172,248 +89,68 @@ CUDA_VERSION_TO_IMAGE_TAG: Dict[str, str] = {
172
89
  def generate_dockerfile_content(
173
90
  build_configuration: PythonBuild,
174
91
  package_manager: str = ENV_VARS.TFY_PYTHON_BUILD_PACKAGE_MANAGER,
175
- docker_build_extra_args: Optional[List[str]] = None,
92
+ mount_python_package_manager_conf_secret: bool = False,
176
93
  ) -> str:
177
- if isinstance(build_configuration, dict):
178
- build_configuration = PythonBuild(**build_configuration)
179
- if not build_configuration.python_version:
180
- raise ValueError(
181
- "`python_version` is required for `tfy-python-buildpack` builder"
182
- )
183
-
184
- # Set up Python dependencies
185
- python_dependencies = deepcopy(build_configuration.python_dependencies)
186
- if not python_dependencies:
187
- python_dependencies = Pip(
188
- type="pip",
189
- requirements_path=build_configuration.requirements_path,
190
- pip_packages=build_configuration.pip_packages,
191
- )
192
-
193
- # Get available secrets from docker build extra args
194
- available_secrets = set()
195
- if docker_build_extra_args:
196
- available_secrets = get_available_secrets(docker_build_extra_args)
197
-
198
- # Prepare template context
199
- context = _build_template_context(
200
- build_configuration=build_configuration,
201
- python_dependencies=python_dependencies,
202
- package_manager=package_manager,
203
- available_secrets=available_secrets,
204
- )
205
-
206
- # Build sections
207
- base_image_setup = _build_base_image_section(build_configuration)
208
- apt_packages_section = _build_apt_packages_section(context.apt_install_command)
209
- python_dependencies_section = _build_python_dependencies_section(
210
- python_dependencies.type, context
211
- )
212
-
213
- template = Template(DOCKERFILE_TEMPLATE)
214
- return template.render(
215
- base_image_setup=base_image_setup,
216
- apt_packages_section=apt_packages_section,
217
- python_dependencies_section=python_dependencies_section,
218
- )
219
-
220
-
221
- def _build_template_context(
222
- build_configuration: PythonBuild,
223
- python_dependencies: Union[Pip, UV, Poetry],
224
- package_manager: str,
225
- available_secrets: Set[str],
226
- ) -> TemplateContext:
227
- # Set up package manager config secret mount
228
- python_dependencies_type = python_dependencies.type
229
- package_manager_config_secret_mount = ""
230
- if available_secrets:
231
- package_manager_config_secret_mount = generate_secret_mounts(
232
- available_secrets=available_secrets,
233
- python_dependencies_type=python_dependencies_type,
234
- package_manager=package_manager,
235
- )
236
-
237
- # Configure dependencies based on type
238
- if python_dependencies_type == "uv":
239
- uv_context = _build_uv_context(
240
- python_dependencies,
241
- available_secrets,
242
- )
243
- return TemplateContext(
244
- python_image_repo=ENV_VARS.TFY_PYTHONBUILD_PYTHON_IMAGE_REPO,
245
- python_version=build_configuration.python_version,
246
- apt_install_command=generate_apt_install_command(
247
- apt_packages=build_configuration.apt_packages
248
- ),
249
- package_manager_config_secret_mount=package_manager_config_secret_mount,
250
- python_packages_install_command=uv_context[
251
- "python_packages_install_command"
252
- ],
253
- final_uv_sync_command=uv_context["final_uv_sync_command"],
254
- )
255
- elif python_dependencies_type == "poetry":
256
- poetry_toml_exists = check_whether_poetry_toml_exists(
257
- build_context_path=build_configuration.build_context_path,
258
- )
259
- poetry_context = _build_poetry_context(python_dependencies, available_secrets)
260
- return TemplateContext(
261
- python_image_repo=ENV_VARS.TFY_PYTHONBUILD_PYTHON_IMAGE_REPO,
262
- python_version=build_configuration.python_version,
263
- apt_install_command=generate_apt_install_command(
264
- apt_packages=build_configuration.apt_packages
265
- ),
266
- package_manager_config_secret_mount=package_manager_config_secret_mount,
267
- python_packages_install_command=poetry_context[
268
- "python_packages_install_command"
269
- ],
270
- final_poetry_install_command=poetry_context["final_poetry_install_command"],
271
- poetry_version_expression=poetry_context["poetry_version_expression"],
272
- poetry_toml_exists=poetry_toml_exists,
273
- )
274
- elif python_dependencies_type == "pip":
275
- pip_context = _build_pip_context(
276
- build_configuration,
277
- python_dependencies,
278
- package_manager,
279
- available_secrets,
280
- )
281
- return TemplateContext(
282
- python_image_repo=ENV_VARS.TFY_PYTHONBUILD_PYTHON_IMAGE_REPO,
283
- python_version=build_configuration.python_version,
284
- apt_install_command=generate_apt_install_command(
285
- apt_packages=build_configuration.apt_packages
286
- ),
287
- package_manager_config_secret_mount=package_manager_config_secret_mount,
288
- requirements_path=pip_context["requirements_path"],
289
- requirements_destination_path=pip_context["requirements_destination_path"],
290
- python_packages_install_command=pip_context[
291
- "python_packages_install_command"
292
- ],
293
- )
294
- else:
295
- raise ValueError(f"Unsupported dependency type: {python_dependencies_type}")
296
-
297
-
298
- def _build_base_image_section(build_configuration: PythonBuild) -> str:
299
- if build_configuration.cuda_version:
300
- cuda_image_tag = CUDA_VERSION_TO_IMAGE_TAG.get(
301
- build_configuration.cuda_version, build_configuration.cuda_version
302
- )
303
- template = Template(CUDA_BASE_IMAGE_TEMPLATE)
304
- return template.render(
305
- cuda_image_tag=cuda_image_tag,
306
- python_version=build_configuration.python_version,
307
- )
308
- else:
309
- template = Template(STANDARD_BASE_IMAGE_TEMPLATE)
310
- return template.render(
311
- python_image_repo=ENV_VARS.TFY_PYTHONBUILD_PYTHON_IMAGE_REPO,
312
- python_version=build_configuration.python_version,
313
- )
314
-
315
-
316
- def _build_apt_packages_section(apt_install_command: Optional[str]) -> str:
317
- template = Template(APT_PACKAGES_TEMPLATE)
318
- return template.render(apt_install_command=apt_install_command)
319
-
320
-
321
- def _build_python_dependencies_section(
322
- python_dependencies_type: str, context: TemplateContext
323
- ) -> str:
324
- if python_dependencies_type == "pip":
325
- template = Template(PIP_DEPENDENCIES_TEMPLATE)
326
- return template.render(**context.dict())
327
- elif python_dependencies_type == "uv":
328
- template = Template(UV_DEPENDENCIES_TEMPLATE)
329
- return template.render(**context.dict())
330
- elif python_dependencies_type == "poetry":
331
- template = Template(POETRY_DEPENDENCIES_TEMPLATE)
332
- return template.render(**context.dict())
333
- else:
334
- raise ValueError(f"Unsupported dependency type: {python_dependencies_type}")
335
-
336
-
337
- def _build_uv_context(python_dependencies: UV, available_secrets: Set[str]) -> Dict:
338
- python_packages_install_command = generate_command_to_install_from_uv_lock(
339
- sync_options=python_dependencies.sync_options,
340
- uv_version=python_dependencies.uv_version,
341
- available_secrets=available_secrets,
342
- )
343
- final_uv_sync_command = generate_command_to_install_from_uv_lock(
344
- sync_options=python_dependencies.sync_options,
345
- uv_version=python_dependencies.uv_version,
346
- install_project=True,
347
- available_secrets=available_secrets,
348
- )
349
-
350
- return {
351
- "python_packages_install_command": python_packages_install_command,
352
- "final_uv_sync_command": final_uv_sync_command,
353
- }
354
-
355
-
356
- def _build_poetry_context(
357
- python_dependencies: Poetry, available_secrets: Set[str]
358
- ) -> Dict:
359
- python_packages_install_command = generate_poetry_install_command(
360
- install_options=python_dependencies.install_options,
361
- available_secrets=available_secrets,
362
- )
363
- final_poetry_install_command = generate_poetry_install_command(
364
- install_options=python_dependencies.install_options,
365
- install_project=True,
366
- available_secrets=available_secrets,
367
- )
368
-
369
- poetry_version = python_dependencies.poetry_version
370
- # Handle "latest" poetry version by using major version constraint
371
- if poetry_version == "latest":
372
- major_version = ENV_VARS.TFY_PYTHON_BUILD_LATEST_POETRY_MAJOR_VERSION
373
- poetry_version_expression = f">={major_version},<{major_version + 1}"
374
- else:
375
- # For regular versions, use ~= operator for compatibility
376
- poetry_version_expression = f"~={poetry_version}"
377
-
378
- return {
379
- "python_packages_install_command": python_packages_install_command,
380
- "final_poetry_install_command": final_poetry_install_command,
381
- "poetry_version_expression": poetry_version_expression,
382
- }
383
-
384
-
385
- def _build_pip_context(
386
- build_configuration: PythonBuild,
387
- python_dependencies: Pip,
388
- package_manager: str,
389
- available_secrets: Set[str],
390
- ) -> Dict:
391
94
  # TODO (chiragjn): Handle recursive references to other requirements files e.g. `-r requirements-gpu.txt`
392
95
  requirements_path = _resolve_requirements_path(
393
96
  build_context_path=build_configuration.build_context_path,
394
- requirements_path=python_dependencies.requirements_path,
97
+ requirements_path=build_configuration.requirements_path,
395
98
  )
396
99
  requirements_destination_path = (
397
100
  "/tmp/requirements.txt" if requirements_path else None
398
101
  )
399
-
102
+ if not build_configuration.python_version:
103
+ raise ValueError(
104
+ "`python_version` is required for `tfy-python-buildpack` builder"
105
+ )
400
106
  if package_manager == PythonPackageManager.PIP.value:
401
107
  python_packages_install_command = generate_pip_install_command(
402
108
  requirements_path=requirements_destination_path,
403
- pip_packages=python_dependencies.pip_packages,
404
- available_secrets=available_secrets,
109
+ pip_packages=build_configuration.pip_packages,
110
+ mount_pip_conf_secret=mount_python_package_manager_conf_secret,
405
111
  )
406
112
  elif package_manager == PythonPackageManager.UV.value:
407
113
  python_packages_install_command = generate_uv_pip_install_command(
408
114
  requirements_path=requirements_destination_path,
409
- pip_packages=python_dependencies.pip_packages,
410
- available_secrets=available_secrets,
115
+ pip_packages=build_configuration.pip_packages,
116
+ mount_uv_conf_secret=mount_python_package_manager_conf_secret,
411
117
  )
412
118
  else:
413
119
  raise ValueError(f"Unsupported package manager: {package_manager}")
414
120
 
415
- return {
121
+ apt_install_command = generate_apt_install_command(
122
+ apt_packages=build_configuration.apt_packages
123
+ )
124
+ template_args = {
125
+ "python_image_repo": ENV_VARS.TFY_PYTHONBUILD_PYTHON_IMAGE_REPO,
126
+ "python_version": build_configuration.python_version,
127
+ "apt_install_command": apt_install_command,
416
128
  "requirements_path": requirements_path,
417
129
  "requirements_destination_path": requirements_destination_path,
418
130
  "python_packages_install_command": python_packages_install_command,
419
131
  }
132
+
133
+ if mount_python_package_manager_conf_secret:
134
+ if package_manager == PythonPackageManager.PIP.value:
135
+ template_args["package_manager_config_secret_mount"] = (
136
+ PIP_CONF_BUILDKIT_SECRET_MOUNT
137
+ )
138
+ elif package_manager == PythonPackageManager.UV.value:
139
+ template_args["package_manager_config_secret_mount"] = (
140
+ UV_CONF_BUILDKIT_SECRET_MOUNT
141
+ )
142
+ else:
143
+ raise ValueError(f"Unsupported package manager: {package_manager}")
144
+ else:
145
+ template_args["package_manager_config_secret_mount"] = ""
146
+
147
+ if build_configuration.cuda_version:
148
+ template = CUDA_DOCKERFILE_TEMPLATE
149
+ template_args["nvidia_cuda_image_tag"] = CUDA_VERSION_TO_IMAGE_TAG.get(
150
+ build_configuration.cuda_version, build_configuration.cuda_version
151
+ )
152
+ else:
153
+ template = DOCKERFILE_TEMPLATE
154
+
155
+ dockerfile_content = template.render(**template_args)
156
+ return dockerfile_content
@@ -17,12 +17,12 @@ __all__ = ["generate_dockerfile_content", "build"]
17
17
  def _convert_to_dockerfile_build_config(
18
18
  build_configuration: SparkBuild,
19
19
  dockerfile_path: str,
20
- extra_opts: Optional[List[str]] = None,
20
+ mount_python_package_manager_conf_secret: bool = False,
21
21
  ) -> DockerFileBuild:
22
22
  dockerfile_content = generate_dockerfile_content(
23
23
  build_configuration=build_configuration,
24
+ mount_python_package_manager_conf_secret=mount_python_package_manager_conf_secret,
24
25
  package_manager=PythonPackageManager.PIP.value,
25
- docker_build_extra_args=extra_opts,
26
26
  )
27
27
  with open(dockerfile_path, "w", encoding="utf8") as fp:
28
28
  fp.write(dockerfile_content)
@@ -39,6 +39,10 @@ def build(
39
39
  build_configuration: SparkBuild,
40
40
  extra_opts: Optional[List[str]] = None,
41
41
  ):
42
+ mount_python_package_manager_conf_secret = (
43
+ has_python_package_manager_conf_secret(extra_opts) if extra_opts else False
44
+ )
45
+
42
46
  # Copy tfy_execute_notebook.py to the build context
43
47
  execute_notebook_src = os.path.join(
44
48
  os.path.dirname(__file__), "tfy_execute_notebook.py"
@@ -59,7 +63,7 @@ def build(
59
63
  docker_build_configuration = _convert_to_dockerfile_build_config(
60
64
  build_configuration,
61
65
  dockerfile_path=os.path.join(local_dir, "Dockerfile"),
62
- extra_opts=extra_opts,
66
+ mount_python_package_manager_conf_secret=mount_python_package_manager_conf_secret,
63
67
  )
64
68
  dockerfile.build(
65
69
  tag=tag,
@@ -1,14 +1,14 @@
1
- from typing import List, Optional
2
-
3
1
  from mako.template import Template
4
2
 
5
3
  from truefoundry.common.constants import ENV_VARS, PythonPackageManager
6
4
  from truefoundry.deploy._autogen.models import SparkBuild
5
+ from truefoundry.deploy.builder.constants import (
6
+ PIP_CONF_BUILDKIT_SECRET_MOUNT,
7
+ UV_CONF_BUILDKIT_SECRET_MOUNT,
8
+ )
7
9
  from truefoundry.deploy.builder.utils import (
8
10
  generate_pip_install_command,
9
- generate_secret_mounts,
10
11
  generate_uv_pip_install_command,
11
- get_available_secrets,
12
12
  )
13
13
  from truefoundry.deploy.v2.lib.patched_models import (
14
14
  _resolve_requirements_path,
@@ -71,13 +71,8 @@ ADDITIONAL_PIP_PACKAGES = [
71
71
  def generate_dockerfile_content(
72
72
  build_configuration: SparkBuild,
73
73
  package_manager: str = ENV_VARS.TFY_PYTHON_BUILD_PACKAGE_MANAGER,
74
- docker_build_extra_args: Optional[List[str]] = None,
74
+ mount_python_package_manager_conf_secret: bool = False,
75
75
  ) -> str:
76
- # Get available secrets from docker build extra args
77
- available_secrets = set()
78
- if docker_build_extra_args:
79
- available_secrets = get_available_secrets(docker_build_extra_args)
80
-
81
76
  # TODO (chiragjn): Handle recursive references to other requirements files e.g. `-r requirements-gpu.txt`
82
77
  requirements_path = _resolve_requirements_path(
83
78
  build_context_path=build_configuration.build_context_path,
@@ -95,13 +90,13 @@ def generate_dockerfile_content(
95
90
  python_packages_install_command = generate_pip_install_command(
96
91
  requirements_path=requirements_destination_path,
97
92
  pip_packages=ADDITIONAL_PIP_PACKAGES,
98
- available_secrets=available_secrets,
93
+ mount_pip_conf_secret=mount_python_package_manager_conf_secret,
99
94
  )
100
95
  elif package_manager == PythonPackageManager.UV.value:
101
96
  python_packages_install_command = generate_uv_pip_install_command(
102
97
  requirements_path=requirements_destination_path,
103
98
  pip_packages=ADDITIONAL_PIP_PACKAGES,
104
- available_secrets=available_secrets,
99
+ mount_uv_conf_secret=mount_python_package_manager_conf_secret,
105
100
  )
106
101
  else:
107
102
  raise ValueError(f"Unsupported package manager: {package_manager}")
@@ -114,12 +109,17 @@ def generate_dockerfile_content(
114
109
  "python_packages_install_command": python_packages_install_command,
115
110
  }
116
111
 
117
- if available_secrets:
118
- template_args["package_manager_config_secret_mount"] = generate_secret_mounts(
119
- available_secrets=available_secrets,
120
- python_dependencies_type="pip",
121
- package_manager=package_manager,
122
- )
112
+ if mount_python_package_manager_conf_secret:
113
+ if package_manager == PythonPackageManager.PIP.value:
114
+ template_args["package_manager_config_secret_mount"] = (
115
+ PIP_CONF_BUILDKIT_SECRET_MOUNT
116
+ )
117
+ elif package_manager == PythonPackageManager.UV.value:
118
+ template_args["package_manager_config_secret_mount"] = (
119
+ UV_CONF_BUILDKIT_SECRET_MOUNT
120
+ )
121
+ else:
122
+ raise ValueError(f"Unsupported package manager: {package_manager}")
123
123
  else:
124
124
  template_args["package_manager_config_secret_mount"] = ""
125
125
 
@@ -15,11 +15,11 @@ __all__ = ["generate_dockerfile_content", "build"]
15
15
  def _convert_to_dockerfile_build_config(
16
16
  build_configuration: TaskPySparkBuild,
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)
@@ -35,11 +35,15 @@ def build(
35
35
  build_configuration: TaskPySparkBuild,
36
36
  extra_opts: Optional[List[str]] = None,
37
37
  ):
38
+ mount_python_package_manager_conf_secret = (
39
+ has_python_package_manager_conf_secret(extra_opts) if extra_opts else False
40
+ )
41
+
38
42
  with TemporaryDirectory() as local_dir:
39
43
  docker_build_configuration = _convert_to_dockerfile_build_config(
40
44
  build_configuration,
41
45
  dockerfile_path=os.path.join(local_dir, "Dockerfile"),
42
- extra_opts=extra_opts,
46
+ mount_python_package_manager_conf_secret=mount_python_package_manager_conf_secret,
43
47
  )
44
48
  dockerfile.build(
45
49
  tag=tag,