dagster-cloud-cli 1.13.7__tar.gz → 1.13.8__tar.gz

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 (88) hide show
  1. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/PKG-INFO +2 -2
  2. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/ci/__init__.py +6 -2
  3. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/serverless/__init__.py +11 -4
  4. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/deps.py +2 -6
  5. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/source.py +8 -13
  6. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/docker_utils.py +26 -6
  7. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/gql.py +2 -0
  8. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/types.py +1 -4
  9. dagster_cloud_cli-1.13.8/dagster_cloud_cli/version.py +1 -0
  10. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/test_pyproject_toml_support.py +39 -2
  11. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/pyproject.toml +2 -2
  12. dagster_cloud_cli-1.13.7/dagster_cloud_cli/version.py +0 -1
  13. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/.gitignore +0 -0
  14. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/LICENSE +0 -0
  15. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/__init__.py +0 -0
  16. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/__init__.py +0 -0
  17. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/branch_deployment/__init__.py +0 -0
  18. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/ci/checks.py +0 -0
  19. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/ci/report.py +0 -0
  20. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/ci/state.py +0 -0
  21. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/ci/utils.py +0 -0
  22. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/config.py +0 -0
  23. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/deployment/__init__.py +0 -0
  24. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/deployment/alert_policies/__init__.py +0 -0
  25. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/deployment/alert_policies/commands.py +0 -0
  26. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/integration/__init__.py +0 -0
  27. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/integration/atlan/__init__.py +0 -0
  28. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/job/__init__.py +0 -0
  29. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/metrics.py +0 -0
  30. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/organization/__init__.py +0 -0
  31. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/organization/saml/__init__.py +0 -0
  32. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/organization/saml/commands.py +0 -0
  33. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/run/__init__.py +0 -0
  34. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/serverless/Dockerfile +0 -0
  35. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/serverless/Dockerfile.dagster-cloud-cli +0 -0
  36. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/commands/workspace/__init__.py +0 -0
  37. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/config/__init__.py +0 -0
  38. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/config/jinja_template_loader.py +0 -0
  39. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/config/list_merge_strategies.py +0 -0
  40. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/config/loader.py +0 -0
  41. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/config/merger.py +0 -0
  42. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/config/models.py +0 -0
  43. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/config_utils.py +0 -0
  44. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/__init__.py +0 -0
  45. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/agent_queue.py +0 -0
  46. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/alert_types.py +0 -0
  47. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/artifacts.py +0 -0
  48. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/docker_runner.py +0 -0
  49. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/errors.py +0 -0
  50. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/graphql_client.py +0 -0
  51. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/headers/__init__.py +0 -0
  52. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/headers/auth.py +0 -0
  53. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/headers/impl.py +0 -0
  54. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/headers/versioning/__init__.py +0 -0
  55. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/headers/versioning/constants.py +0 -0
  56. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/__init__.py +0 -0
  57. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/code_location.py +0 -0
  58. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/deploy.py +0 -0
  59. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/git_context.py +0 -0
  60. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/github_context.py +0 -0
  61. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/gitlab_context.py +0 -0
  62. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/parse_workspace.py +0 -0
  63. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/pex_registry.py +0 -0
  64. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/platforms.py +0 -0
  65. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/selftest.py +0 -0
  66. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/pex_builder/util.py +0 -0
  67. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/core/workspace.py +0 -0
  68. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/entrypoint.py +0 -0
  69. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/pex_utils.py +0 -0
  70. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/py.typed +0 -0
  71. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/ui.py +0 -0
  72. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli/utils.py +0 -0
  73. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/__init__.py +0 -0
  74. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/commands/ci/integration/__init__.py +0 -0
  75. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/commands/ci/test_ci_template.py +0 -0
  76. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/commands/integration/test_atlan_integration_cli.py +0 -0
  77. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/config/test_config_loader.py +0 -0
  78. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/config/test_defaults_merging.py +0 -0
  79. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/config/test_template_loader.py +0 -0
  80. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/conftest.py +0 -0
  81. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/test_artifacts.py +0 -0
  82. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/test_check.py +0 -0
  83. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/test_ci_commands.py +0 -0
  84. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/test_gql.py +0 -0
  85. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/test_metrics.py +0 -0
  86. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/dagster_cloud_cli_tests/test_utils.py +0 -0
  87. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/tox.ini +0 -0
  88. {dagster_cloud_cli-1.13.7 → dagster_cloud_cli-1.13.8}/uv.lock +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dagster-cloud-cli
3
- Version: 1.13.7
3
+ Version: 1.13.8
4
4
  Project-URL: Homepage, https://github.com/dagster-io/dagster/tree/master/python_modules/libraries/dagster-cloud-cli
5
5
  Author-email: Dagster Labs <hello@dagsterlabs.com>
6
6
  License-Expression: Apache-2.0
7
7
  License-File: LICENSE
8
8
  Requires-Python: <3.15,>=3.10
9
9
  Requires-Dist: click
10
- Requires-Dist: dagster-shared==1.13.7
10
+ Requires-Dist: dagster-shared==1.13.8
11
11
  Requires-Dist: github3-py
12
12
  Requires-Dist: jinja2
13
13
  Requires-Dist: packaging>=20.9
@@ -832,6 +832,7 @@ def _build_docker(
832
832
  name = location_state.location_name
833
833
  docker_utils.verify_docker()
834
834
  registry_info = utils.get_registry_info(url)
835
+ repo_location = name if registry_info.get("is_harbor") else None
835
836
 
836
837
  docker_image_tag = docker_utils.default_image_tag(
837
838
  location_state.deployment_name, name, location_state.build.commit_hash
@@ -853,15 +854,18 @@ def _build_docker(
853
854
  base_image=docker_base_image,
854
855
  dockerfile_path=dockerfile_path,
855
856
  use_editable_dagster=use_editable_dagster,
857
+ location_name=repo_location,
856
858
  )
857
859
  if retval != 0:
858
860
  raise ui.error(f"Failed to build docker image for location {name}")
859
861
 
860
- retval = docker_utils.upload_image(docker_image_tag, registry_info)
862
+ retval = docker_utils.upload_image(docker_image_tag, registry_info, location_name=repo_location)
861
863
  if retval != 0:
862
864
  raise ui.error(f"Failed to upload docker image for location {name}")
863
865
 
864
- image = f"{registry_info['registry_url']}:{docker_image_tag}"
866
+ image = docker_utils.full_image_ref(
867
+ registry_info["registry_url"], repo_location, docker_image_tag
868
+ )
865
869
  ui.print(f"Built and uploaded image {image} for location {name}")
866
870
 
867
871
  return state.DockerBuildOutput(image=image)
@@ -212,7 +212,6 @@ def deploy_command(
212
212
  if not source_directory:
213
213
  raise ui.error("No source directory provided.")
214
214
 
215
- _check_source_directory(source_directory)
216
215
  docker_utils.verify_docker()
217
216
 
218
217
  env_vars = kwargs.get("env", [])
@@ -221,21 +220,29 @@ def deploy_command(
221
220
  with gql.graphql_client_from_url(url, api_token, deployment_name=deployment) as client:
222
221
  ecr_info = gql.get_ecr_info(client)
223
222
  registry = ecr_info["registry_url"]
223
+ repo_location = location_name if ecr_info.get("is_harbor") else None
224
224
 
225
225
  image_tag = kwargs.get("image") or docker_utils.default_image_tag(
226
226
  deployment, location_name, kwargs.get("commit_hash")
227
227
  )
228
228
  retval = docker_utils.build_image(
229
- source_directory, image_tag, ecr_info, env_vars, base_image, use_editable_dagster=False
229
+ source_directory,
230
+ image_tag,
231
+ ecr_info,
232
+ env_vars,
233
+ base_image,
234
+ use_editable_dagster=False,
235
+ location_name=repo_location,
230
236
  )
231
237
  if retval != 0:
232
238
  return
233
239
 
234
- retval = docker_utils.upload_image(image_tag, ecr_info)
240
+ retval = docker_utils.upload_image(image_tag, ecr_info, location_name=repo_location)
235
241
  if retval != 0:
236
242
  return
237
243
 
238
- location_args = {**kwargs, "image": f"{registry}:{image_tag}"}
244
+ full_image = docker_utils.full_image_ref(registry, repo_location, image_tag)
245
+ location_args = {**kwargs, "image": full_image}
239
246
  location_document = get_location_document(location_name, location_args)
240
247
  gql.add_or_update_code_location(client, location_document)
241
248
 
@@ -419,19 +419,15 @@ def get_pyproject_toml_deps(code_directory: str) -> list[str]:
419
419
  except Exception as e:
420
420
  raise ValueError(f"Error parsing pyproject.toml: {e}")
421
421
 
422
- lines = []
423
-
424
422
  # Handle dependencies in [project] section (PEP 621)
425
423
  project_section = pyproject_data.get("project", {})
426
424
  dependencies = project_section.get("dependencies", [])
427
- for dep in dependencies:
428
- lines.append(str(dep))
425
+ lines = [str(dep) for dep in dependencies]
429
426
 
430
427
  # Handle optional dependencies in [project.optional-dependencies]
431
428
  optional_deps = project_section.get("optional-dependencies", {})
432
429
  for group_deps in optional_deps.values():
433
- for dep in group_deps:
434
- lines.append(str(dep))
430
+ lines.extend(str(dep) for dep in group_deps)
435
431
 
436
432
  # Handle legacy [tool.poetry.dependencies] for Poetry projects
437
433
  poetry_section = pyproject_data.get("tool", {}).get("poetry", {})
@@ -58,19 +58,14 @@ def _build_local_package(local_dir: str, build_dir: str, python_interpreter: str
58
58
  ]
59
59
  subprocess.run(command, check=True, cwd=local_dir)
60
60
  elif os.path.exists(os.path.join(local_dir, "pyproject.toml")):
61
- ui.print(f"Building package at {local_dir!r} using {python_interpreter} -m pip install")
62
- # Use pip install with --target to build and install the package to the build directory
63
- # This handles pyproject.toml files properly using modern Python build standards
64
- command = [
65
- python_interpreter,
66
- "-m",
67
- "pip",
68
- "install",
69
- "--target",
70
- build_dir,
71
- "--no-deps", # Don't install dependencies, just the package itself
72
- ".",
73
- ]
61
+ install_args = ["--target", build_dir, "--no-deps", "."]
62
+ uv_path = shutil.which("uv")
63
+ if uv_path:
64
+ ui.print(f"Building package at {local_dir!r} using uv pip install")
65
+ command = [uv_path, "pip", "install", "--python", python_interpreter, *install_args]
66
+ else:
67
+ ui.print(f"Building package at {local_dir!r} using {python_interpreter} -m pip install")
68
+ command = [python_interpreter, "-m", "pip", "install", *install_args]
74
69
  subprocess.run(command, check=True, cwd=local_dir)
75
70
  else:
76
71
  ui.warn(f"No setup.py or pyproject.toml found in {local_dir!r} - will not build.")
@@ -34,6 +34,26 @@ def _template_dockerfile(env_vars, custom_base_image=None) -> Generator[bytes, N
34
34
  yield bytes(dockerfile_content, "utf-8")
35
35
 
36
36
 
37
+ def full_image_ref(
38
+ registry_url: str,
39
+ location_name: str | None,
40
+ image_tag: str,
41
+ ) -> str:
42
+ """Build the full Docker image reference.
43
+
44
+ For Harbor-backed registries the registry URL already contains a
45
+ deployment-scoped prefix (``host/project/depl-prefix``). Each code
46
+ location gets its own repository nested under that prefix, so the
47
+ reference becomes ``host/project/depl-prefix/location:tag``.
48
+
49
+ For legacy ECR registries (or when *location_name* is ``None``) the
50
+ reference falls back to the previous ``registry:tag`` format.
51
+ """
52
+ if location_name:
53
+ return f"{registry_url}/{location_name}:{image_tag}"
54
+ return f"{registry_url}:{image_tag}"
55
+
56
+
37
57
  def build_image(
38
58
  source_directory,
39
59
  image: str,
@@ -42,8 +62,9 @@ def build_image(
42
62
  base_image: str | None,
43
63
  use_editable_dagster: bool,
44
64
  dockerfile_path: str | None = None,
65
+ location_name: str | None = None,
45
66
  ) -> int:
46
- registry = registry_info["registry_url"]
67
+ full_ref = full_image_ref(registry_info["registry_url"], location_name, image)
47
68
 
48
69
  with ExitStack() as stack:
49
70
  if dockerfile_path:
@@ -58,7 +79,7 @@ def build_image(
58
79
  "build",
59
80
  source_directory,
60
81
  "-t",
61
- f"{registry}:{image}",
82
+ full_ref,
62
83
  "-f",
63
84
  file_path,
64
85
  "--platform",
@@ -74,7 +95,7 @@ def build_image(
74
95
  return subprocess.run(cmd, input=build_input, check=True).returncode
75
96
 
76
97
 
77
- def upload_image(image, registry_info) -> int:
98
+ def upload_image(image, registry_info, location_name: str | None = None) -> int:
78
99
  registry = registry_info["registry_url"]
79
100
  aws_token = registry_info["aws_auth_token"]
80
101
  if not registry or not aws_token:
@@ -89,9 +110,8 @@ def upload_image(image, registry_info) -> int:
89
110
  input=password.encode(),
90
111
  check=True,
91
112
  )
92
- return subprocess.call(
93
- ["docker", "push", f"{registry}:{image}"], stderr=sys.stderr, stdout=sys.stdout
94
- )
113
+ full_ref = full_image_ref(registry, location_name, image)
114
+ return subprocess.call(["docker", "push", full_ref], stderr=sys.stderr, stdout=sys.stdout)
95
115
 
96
116
 
97
117
  def default_image_tag(deployment: str, location_name: str, commit_hash: str | None) -> str:
@@ -715,6 +715,7 @@ query CliGetEcrInfo {
715
715
  awsRegion
716
716
  awsAuthToken
717
717
  registryAllowCustomBase
718
+ registryIsHarbor
718
719
  registryUrl
719
720
  }
720
721
  }
@@ -728,6 +729,7 @@ def get_ecr_info(client: DagsterCloudGraphQLClient) -> Any:
728
729
  "aws_region": data["serverless"]["awsRegion"],
729
730
  "aws_auth_token": data["serverless"]["awsAuthToken"],
730
731
  "allow_custom_base": data["serverless"]["registryAllowCustomBase"],
732
+ "is_harbor": data["serverless"].get("registryIsHarbor", False),
731
733
  }
732
734
 
733
735
 
@@ -43,10 +43,7 @@ SubcommandTags = Enum(
43
43
  class CliEventTags:
44
44
  @classmethod
45
45
  def enums(cls):
46
- attrs = []
47
- for attr in cls.__dict__.values():
48
- if isinstance(attr, EnumMeta):
49
- attrs.append(attr)
46
+ attrs = [attr for attr in cls.__dict__.values() if isinstance(attr, EnumMeta)]
50
47
  return attrs
51
48
 
52
49
  @classmethod
@@ -0,0 +1 @@
1
+ __version__ = "1.13.8"
@@ -163,8 +163,9 @@ dependencies = ["requests>=2.25.0"]
163
163
 
164
164
 
165
165
  @patch("subprocess.run")
166
- def test_build_local_package_with_pyproject_toml(mock_run, temp_dir):
167
- """Test building a package with pyproject.toml."""
166
+ @patch("shutil.which", return_value=None)
167
+ def test_build_local_package_with_pyproject_toml(mock_which, mock_run, temp_dir):
168
+ """Test building a package with pyproject.toml falls back to pip when uv is not available."""
168
169
  mock_run.return_value = None
169
170
 
170
171
  pyproject_path = Path(temp_dir) / "pyproject.toml"
@@ -196,6 +197,42 @@ version = "0.1.0"
196
197
  assert command == expected_command
197
198
 
198
199
 
200
+ @patch("subprocess.run")
201
+ @patch("shutil.which", return_value="/usr/bin/uv")
202
+ def test_build_local_package_with_pyproject_toml_uses_uv(mock_which, mock_run, temp_dir):
203
+ """Test building a package with pyproject.toml uses uv when available."""
204
+ mock_run.return_value = None
205
+
206
+ pyproject_path = Path(temp_dir) / "pyproject.toml"
207
+ pyproject_path.write_text("""
208
+ [project]
209
+ name = "test-package"
210
+ version = "0.1.0"
211
+ """)
212
+
213
+ build_dir = Path(temp_dir) / "build"
214
+ build_dir.mkdir()
215
+
216
+ source._build_local_package(temp_dir, str(build_dir), "python") # noqa: SLF001
217
+
218
+ mock_run.assert_called_once()
219
+ args, _kwargs = mock_run.call_args
220
+ command = args[0]
221
+
222
+ expected_command = [
223
+ "/usr/bin/uv",
224
+ "pip",
225
+ "install",
226
+ "--python",
227
+ "python",
228
+ "--target",
229
+ str(build_dir),
230
+ "--no-deps",
231
+ ".",
232
+ ]
233
+ assert command == expected_command
234
+
235
+
199
236
  @patch("subprocess.run")
200
237
  def test_build_local_package_prefers_setup_py(mock_run, temp_dir):
201
238
  """Test that setup.py is preferred over pyproject.toml when both exist."""
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "dagster-cloud-cli"
9
- version = "1.13.7"
9
+ version = "1.13.8"
10
10
  requires-python = ">=3.10,<3.15"
11
11
  description = ""
12
12
  authors = [
@@ -14,7 +14,7 @@ authors = [
14
14
  ]
15
15
  license = "Apache-2.0"
16
16
  dependencies = [
17
- "dagster-shared==1.13.7",
17
+ "dagster-shared==1.13.8",
18
18
  "packaging>=20.9",
19
19
  "questionary",
20
20
  "requests",
@@ -1 +0,0 @@
1
- __version__ = "1.13.7"