Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions helm/blueapi/config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,12 @@
"description": "Revision (branch or tag) to check out when cloning - defaults to remote's HEAD. If a tag is used, the repo will be left in a 'detached head' state.",
"title": "Target Revision",
"type": "string"
},
"use_uv_lock": {
"default": false,
"description": "Whether to install the repository using uv.lock",
"title": "Use Uv Lock",
"type": "boolean"
}
},
"title": "ScratchRepository",
Expand Down
6 changes: 6 additions & 0 deletions helm/blueapi/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,12 @@
"title": "Target Revision",
"description": "Revision (branch or tag) to check out when cloning - defaults to remote's HEAD. If a tag is used, the repo will be left in a 'detached head' state.",
"type": "string"
},
"use_uv_lock": {
"title": "Use Uv Lock",
"description": "Whether to install the repository using uv.lock",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
Expand Down
23 changes: 19 additions & 4 deletions src/blueapi/cli/scratch.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def setup_scratch(

scratch_install(
*(config.root / repo.name for repo in config.repositories),
use_uv_lock=[repo.use_uv_lock for repo in config.repositories],
timeout=install_timeout,
)

Expand Down Expand Up @@ -116,7 +117,11 @@ def ensure_repo(
)


def scratch_install(*paths: Path, timeout: float = _DEFAULT_INSTALL_TIMEOUT) -> None:
def scratch_install(
*paths: Path,
use_uv_lock: list[bool] | None = None,
timeout: float = _DEFAULT_INSTALL_TIMEOUT,
) -> None:
"""
Install scratch packages. Make blueapi aware of repositories checked out in
the scratch area. Make it automatically follow code changes to those repositories
Expand All @@ -125,15 +130,25 @@ def scratch_install(*paths: Path, timeout: float = _DEFAULT_INSTALL_TIMEOUT) ->

Args:
paths: List of Paths to the checked out repositories
use_uv_lock: Optional list of booleans indicating whether to install
using uv.lock
timeout: Time to wait for installation subprocess
"""
if not paths:
return

use_uv_lock_list = use_uv_lock or [False] * len(paths)

LOGGER.info("Installing packages")
for path in paths:
for path, uv_lock in zip(paths, use_uv_lock_list, strict=True):
_validate_directory(path)
args = ["uv", "pip", "install", "-e", str(path)]
process = Popen(args)
if uv_lock:
args = ["uv", "sync", "--inexact"]
process = Popen(args, cwd=path)
else:
args = ["uv", "pip", "install", "-e", str(path)]
process = Popen(args)

process.wait(timeout=timeout)
if process.returncode != 0:
raise RuntimeError(
Expand Down
4 changes: 4 additions & 0 deletions src/blueapi/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ class ScratchRepository(BlueapiBaseModel):
# include an invalid value
default_factory=lambda: None,
)
use_uv_lock: bool = Field(
description="Whether to install the repository using uv.lock",
default=False,
)

@field_validator("remote_url")
@classmethod
Expand Down
17 changes: 17 additions & 0 deletions tests/unit_tests/cli/test_scratch.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,22 @@ def test_scratch_install_installs_path(
)


@patch("blueapi.cli.scratch.Popen")
def test_scratch_install_with_uv_lock(
mock_popen: Mock,
directory_path_with_sgid: Path,
):
mock_process = Mock()
mock_process.returncode = 0
mock_popen.return_value = mock_process

scratch_install(directory_path_with_sgid, use_uv_lock=[True], timeout=1.0)

mock_popen.assert_called_once_with(
["uv", "sync", "--inexact"], cwd=directory_path_with_sgid
)


def test_scratch_install_fails_on_file(file_path: Path):
with pytest.raises(KeyError):
scratch_install(file_path, timeout=1.0)
Expand Down Expand Up @@ -348,6 +364,7 @@ def test_setup_scratch_iterates_repos(
call(
directory_path_with_sgid / "foo",
directory_path_with_sgid / "bar",
use_uv_lock=[False, False],
timeout=120.0,
),
]
Expand Down
2 changes: 2 additions & 0 deletions tests/unit_tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ def test_config_yaml_parsed(temp_yaml_config_file):
{
"name": "dodal",
"remote_url": "https://github.com/DiamondLightSource/dodal.git",
"use_uv_lock": False,
}
],
},
Expand Down Expand Up @@ -396,6 +397,7 @@ def test_config_yaml_parsed(temp_yaml_config_file):
{
"name": "dodal",
"remote_url": "https://github.com/DiamondLightSource/dodal.git",
"use_uv_lock": False,
}
],
},
Expand Down
Loading