diff --git a/.github/actions/setup-diffbio/action.yml b/.github/actions/setup-diffbio/action.yml index 6cf799f..58cb7bf 100644 --- a/.github/actions/setup-diffbio/action.yml +++ b/.github/actions/setup-diffbio/action.yml @@ -43,6 +43,14 @@ runs: shell: bash env: UV_CONCURRENT_DOWNLOADS: "4" + # uv sync is a project command and selects its own interpreter; it does not + # inherit the one `uv venv --python` just created. Without these it resolved + # against CPython 3.14 and refused the lock, because tensorflow 2.20.0 has no + # cp314 wheel. The same three variables are exported for later steps further + # down; they are needed here too, before the first uv sync runs. + UV_PYTHON: ${{ inputs.python-version }} + UV_PYTHON_DOWNLOADS: never + UV_PYTHON_PREFERENCE: only-system run: | set -euo pipefail @@ -51,18 +59,31 @@ runs: editable_target="${{ inputs.macos-editable-target }}" fi + # Resolve from uv.lock rather than from the pyproject floors. Installing + # unpinned let every tool drift to its newest release between runs, so a + # run could fail on a dependency change no commit had made. + sync_args=(--locked) + if [[ "$editable_target" == *"["* ]]; then + extras="${editable_target#*[}" + extras="${extras%]}" + IFS=',' read -ra extra_names <<< "$extras" + for extra in "${extra_names[@]}"; do + sync_args+=(--extra "${extra// /}") + done + fi + for attempt in 1 2 3 4 5; do - if uv pip install -e "$editable_target"; then + if uv sync "${sync_args[@]}"; then break fi if [[ "$attempt" -eq 5 ]]; then - echo "Failed to install $editable_target after 5 attempts" >&2 + echo "Failed to sync $editable_target after 5 attempts" >&2 exit 1 fi delay=$((attempt * 10)) - echo "Install attempt $attempt failed, retrying in ${delay} seconds..." >&2 + echo "Sync attempt $attempt failed, retrying in ${delay} seconds..." >&2 sleep "$delay" done