Skip to content

Commit 3d617c6

Browse files
committed
Merge remote-tracking branch 'origin/move-to-uv' into move-to-uv
2 parents cf3f4be + 581aaba commit 3d617c6

9 files changed

Lines changed: 565 additions & 505 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,28 @@
88
"remoteEnv": {
99
// Allow X11 apps to run inside the container
1010
"DISPLAY": "${localEnv:DISPLAY}",
11-
"PATH": "${containerEnv:PATH}:/workspaces/${localWorkspaceFolderBasename}/.venv/bin"
11+
// We put venv on a different volume to cache so have to copy
12+
"UV_LINK_MODE": "copy",
13+
// Do the equivalent of "activate" the venv so we don't have to "uv run" everything
14+
"PATH": "/workspaces/${localWorkspaceFolderBasename}/.venv/bin:${containerEnv:PATH}"
1215
},
1316
"customizations": {
1417
"vscode": {
1518
// Set *default* container specific settings.json values on container create.
1619
"settings": {
17-
"python.defaultInterpreterPath": "/venv/bin/python"
20+
"python.defaultInterpreterPath": "/workspaces/${localWorkspaceFolderBasename}/.venv/bin/python",
21+
"python.terminal.activateEnvInCurrentTerminal": false,
22+
"python.terminal.activateEnvironment": false,
23+
"python.testing.unittestEnabled": false,
24+
"python.testing.pytestEnabled": true,
25+
"editor.formatOnSave": true,
26+
"editor.codeActionsOnSave": {
27+
"source.organizeImports": "explicit"
28+
},
29+
"remote.autoForwardPorts": false,
30+
"[python]": {
31+
"editor.defaultFormatter": "charliermarsh.ruff"
32+
}
1833
},
1934
// Add the IDs of extensions you want installed when the container is created.
2035
"extensions": [
@@ -28,26 +43,35 @@
2843
]
2944
}
3045
},
31-
"features": {
32-
// add in eternal history and other bash features
33-
"ghcr.io/diamondlightsource/devcontainer-features/bash-config:1": {}
34-
},
35-
// Create the config folder for the bash-config feature
36-
"initializeCommand": "mkdir -p ${localEnv:HOME}/.config/bash-config",
46+
// Create the config folder for the bash-config feature and uv cache
47+
"initializeCommand": "mkdir -p ${localEnv:HOME}/.config/terminal-config ${localEnv:HOME}/.cache/uv",
3748
"runArgs": [
3849
// Allow the container to access the host X11 display and EPICS CA
3950
"--net=host",
4051
// Make sure SELinux does not disable with access to host filesystems like tmp
4152
"--security-opt=label=disable"
4253
],
4354
"mounts": [
55+
// Mount in the user terminal config folder so it can be edited
56+
{
57+
"source": "${localEnv:HOME}/.config/terminal-config",
58+
"target": "/user-terminal-config",
59+
"type": "bind"
60+
},
61+
// Keep a persistent cross container cache for uv
62+
{
63+
"source": "${localEnv:HOME}/.cache/uv",
64+
"target": "/root/.cache/uv",
65+
"type": "bind"
66+
},
67+
// Use a volume mount for the uv venv so it is local to the container
4468
{
4569
"target": "/workspaces/${localWorkspaceFolderBasename}/.venv",
4670
"type": "volume"
4771
}
4872
],
4973
// Mount the parent as /workspaces so we can pip install peers as editable
5074
"workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind",
51-
// After the container is created, install the uv env
52-
"postCreateCommand": "uv venv --seed && uv sync --locked && pre-commit install"
75+
// After the container is created, install the python project in editable form
76+
"postCreateCommand": "uv sync && uv run pre-commit install"
5377
}
Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
name: Install requirements
2-
description: Install a version of python then call pip install and report what was installed
2+
description: Install uv, use it to install dependencies and report what was installed
33
inputs:
44
python-version:
55
description: Python version to install, default is from Dockerfile
66
default: "dev"
7-
pip-install:
8-
description: Parameters to pass to uv pip install
9-
default: "$([ -f dev-requirements.txt ] && echo '-c dev-requirements.txt') -e .[dev]"
7+
uv-sync:
8+
description: Parameters to pass to uv sync
9+
default: "--locked"
1010

1111
runs:
1212
using: composite
@@ -22,24 +22,17 @@ runs:
2222
shell: bash
2323

2424
- name: Install uv and set the python version
25-
uses: astral-sh/setup-uv@v5
25+
uses: astral-sh/setup-uv@v6
2626
with:
2727
python-version: ${{ env.PYTHON_VERSION }}
2828
enable-cache: true
2929
cache-dependency-glob: "uv.lock"
30+
activate-environment: true
3031

3132
- name: Install packages
32-
run: uv pip install ${{ inputs.pip-install }}
33+
run: uv sync ${{ inputs.uv-sync }}
3334
shell: bash
3435

3536
- name: Report what was installed
36-
run: uv pip list
37-
shell: bash
38-
39-
- name: Add venv path to Github environment
40-
run: echo "VENV_PATH=.venv" >> $GITHUB_ENV
41-
shell: bash
42-
43-
- name: Add venv path to Github Path
44-
run: echo "${{ env.VENV_PATH }}/bin:$PATH" >> $GITHUB_PATH
37+
run: uv pip freeze
4538
shell: bash

.github/workflows/_dist.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,22 @@ jobs:
1717
export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) &&
1818
pipx run build
1919
20+
- name: Install uv
21+
uses: astral-sh/setup-uv@v6
22+
23+
- name: Build sdist and wheel
24+
run: >
25+
export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) &&
26+
uvx --from build pyproject-build
27+
2028
- name: Upload sdist and wheel as artifacts
2129
uses: actions/upload-artifact@v4
2230
with:
2331
name: dist
2432
path: dist
2533

2634
- name: Check for packaging errors
27-
run: pipx run twine check --strict dist/*
35+
run: uvx twine check --strict dist/*
2836

2937
- name: Install produced wheel
3038
run: python -m pip install dist/*.whl

Dockerfile

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
# The devcontainer should use the developer target and run as root with podman
2-
# or docker with user namespaces.
3-
ARG PYTHON_VERSION=3.11
4-
FROM python:${PYTHON_VERSION} AS developer
5-
6-
# Use this version of uv
7-
ARG UV_VERSION=0.7.4
8-
9-
# Install uv using the official image
10-
# See https://docs.astral.sh/uv/guides/integration/docker/#installing-uv
11-
COPY --from=ghcr.io/astral-sh/uv:${UV_VERSION} /uv /uvx /bin/
1+
# The developer stage is used as a devcontainer including dev versions
2+
# of the build dependencies
3+
FROM ghcr.io/diamondlightsource/ubuntu-devcontainer:noble AS developer

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ dev = [
1818
"sphinx-autobuild",
1919
"sphinx-copybutton",
2020
"sphinx-design",
21-
"tox-uv",
21+
"tox-direct",
2222
"twine>=6.1.0",
2323
]
2424

template/Dockerfile.jinja

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,22 @@ COPY . /workspaces/{{ repo_name }}
3232
WORKDIR /workspaces/{{ repo_name }}
3333
RUN chmod o+wrX . && touch dev-requirements.txt && pip install -c dev-requirements.txt .
3434

35-
{% if docker_debug %}
36-
FROM build AS debug
37-
38-
{% if git_platform=="github.com" %}
39-
# Set origin to use ssh
40-
RUN git remote set-url origin git@github.com:{{github_org}}/{{repo_name}}.git
41-
{% endif %}
42-
43-
# For this pod to understand finding user information from LDAP
44-
RUN apt update
45-
RUN DEBIAN_FRONTEND=noninteractive apt install libnss-ldapd -y
46-
RUN sed -i 's/files/ldap files/g' /etc/nsswitch.conf
35+
# Install the project's dependencies using the lockfile and settings
36+
RUN --mount=type=cache,target=/root/.cache/uv \
37+
--mount=type=bind,source=uv.lock,target=uv.lock \
38+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
39+
uv sync --locked --no-install-project --no-dev
4740

48-
# Make editable and debuggable
49-
RUN pip install debugpy
50-
RUN pip install -e .
41+
# Then, add the rest of the project source code and install it
42+
# Installing separately from its dependencies allows optimal layer caching
43+
COPY . /assets/
44+
RUN --mount=type=cache,target=/root/.cache/uv \
45+
uv sync --locked --no-dev
5146

52-
# Alternate entrypoint to allow devcontainer to attach
53-
ENTRYPOINT [ "/bin/bash", "-c", "--" ]
54-
CMD [ "while true; do sleep 30; done;" ]
47+
# The runtime stage installs runtime deps then copies in built assets
48+
# This time we remove the apt lists to save disk space
49+
FROM ubuntu:noble as runtime
5550

56-
{% endif %}
57-
# The runtime stage copies the built venv into a slim runtime container
58-
FROM python:${PYTHON_VERSION}-slim AS runtime
5951
# Add apt-get system dependecies for runtime here if needed
6052

6153
# We need to keep the venv at the same absolute path as in the build stage

template/pyproject.toml.jinja

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ dev = [
3737
{% endif %}"tox-direct",
3838
"twine",
3939
"types-mock",
40+
"uv~=0.7.0",
4041
]
4142

4243
[project.scripts]
@@ -49,9 +50,6 @@ GitHub = "{{ repo_url }}"
4950
email = "{{ author_email }}"
5051
name = "{{ author_name }}"
5152

52-
[tool.uv]
53-
default-groups = []
54-
5553
[tool.setuptools_scm]
5654
version_file = "src/{{ package_name }}/_version.py"
5755
{% if type_checker=="pyright" %}

tests/test_example.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,16 @@ def run_pipe(cmd: str, cwd=None):
3838

3939
def make_venv(project_path: Path) -> callable:
4040
venv_path = project_path / ".venv"
41-
run_pipe(f"uv venv {venv_path}")
4241
run = functools.partial(run_pipe, cwd=str(project_path))
43-
# install to this env (hence the -p)
44-
run(f"uv pip install -e .[dev] -p {venv_path}/bin/python")
45-
# run("ls -la .venv/bin >&2")
42+
run("uv sync") # Create a lockfile and install packages
43+
44+
for exe_path in [
45+
venv_path / "bin" / "tox",
46+
venv_path / "bin" / "python",
47+
venv_path / "bin" / "uv",
48+
]:
49+
assert exe_path.exists(), f"UV created a venv but did not install {exe_path}"
50+
4651
return run
4752

4853

@@ -60,8 +65,8 @@ def test_template_defaults(tmp_path: Path):
6065
# Only run linkcheck if not on a tag, as the CI might not have pushed
6166
# the docs for this tag yet, so we will fail
6267
run(".venv/bin/tox -p -e docs -- -b linkcheck")
63-
run(".venv/bin/uv pip install build twine")
64-
run(".venv/bin/python -m build")
68+
run(".venv/bin/uv pip install twine")
69+
run(".venv/bin/uv build")
6570
run(".venv/bin/twine check --strict dist/*")
6671

6772

0 commit comments

Comments
 (0)