Use uv for Python management in CI and build script

- CI: install uv via astral-sh/setup-uv, use uv to install Python
  and run the build script (replaces setup-python which fails on
  self-hosted macOS runners)
- build_sidecar.py: auto-detects uv and uses it for venv creation
  and package installation (much faster), falls back to standard
  venv + pip when uv is not available

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude
2026-03-20 22:56:13 -07:00
parent d297540053
commit eb9ec687cb
2 changed files with 42 additions and 26 deletions

View File

@@ -32,24 +32,15 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Set up Python - name: Set up Python
if: matrix.platform != 'macos' run: uv python install ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Verify Python (macOS)
if: matrix.platform == 'macos'
run: |
python3 --version
python3 -m pip --version
- name: Install Python build tools
run: python3 -m pip install --upgrade pip setuptools wheel
- name: Build sidecar - name: Build sidecar
working-directory: python working-directory: python
run: python3 build_sidecar.py --cpu-only run: uv run --python ${{ env.PYTHON_VERSION }} python build_sidecar.py --cpu-only
- name: Upload sidecar artifact - name: Upload sidecar artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3

View File

@@ -59,42 +59,67 @@ def get_target_triple() -> str:
return f"{arch}-unknown-{system}" return f"{arch}-unknown-{system}"
def _has_uv() -> bool:
"""Check if uv is available."""
try:
subprocess.run(["uv", "--version"], capture_output=True, check=True)
return True
except (FileNotFoundError, subprocess.CalledProcessError):
return False
def create_venv_and_install(cpu_only: bool) -> Path: def create_venv_and_install(cpu_only: bool) -> Path:
"""Create a fresh venv and install dependencies.""" """Create a fresh venv and install dependencies.
Uses uv if available (much faster), falls back to standard venv + pip.
"""
venv_dir = BUILD_DIR / "sidecar-venv" venv_dir = BUILD_DIR / "sidecar-venv"
if venv_dir.exists(): if venv_dir.exists():
shutil.rmtree(venv_dir) shutil.rmtree(venv_dir)
use_uv = _has_uv()
if use_uv:
print(f"[build] Creating venv with uv at {venv_dir}")
subprocess.run(
["uv", "venv", "--python", f"{sys.version_info.major}.{sys.version_info.minor}",
str(venv_dir)],
check=True,
)
else:
print(f"[build] Creating venv at {venv_dir}") print(f"[build] Creating venv at {venv_dir}")
subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True) subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
# Determine python path inside venv — use `python -m pip` instead of # Determine python path inside venv
# calling pip directly to avoid permission errors on Windows
if sys.platform == "win32": if sys.platform == "win32":
python = str(venv_dir / "Scripts" / "python") python = str(venv_dir / "Scripts" / "python")
else: else:
python = str(venv_dir / "bin" / "python") python = str(venv_dir / "bin" / "python")
def pip_install(*args: str) -> None: def pkg_install(*args: str) -> None:
if use_uv:
subprocess.run(["uv", "pip", "install", "--python", python, *args], check=True)
else:
subprocess.run([python, "-m", "pip", *args], check=True) subprocess.run([python, "-m", "pip", *args], check=True)
# Upgrade pip if not use_uv:
pip_install("install", "--upgrade", "pip", "setuptools", "wheel") # Upgrade pip (uv doesn't need this)
pkg_install("install", "--upgrade", "pip", "setuptools", "wheel")
# Install torch (CPU-only to avoid bundling ~2GB of CUDA libs) # Install torch (CPU-only to avoid bundling ~2GB of CUDA libs)
if cpu_only: if cpu_only:
print("[build] Installing PyTorch (CPU-only)") print("[build] Installing PyTorch (CPU-only)")
pip_install( pkg_install(
"install", "torch", "torchaudio", "install", "torch", "torchaudio",
"--index-url", "https://download.pytorch.org/whl/cpu", "--index-url", "https://download.pytorch.org/whl/cpu",
) )
else: else:
print("[build] Installing PyTorch (default, may include CUDA)") print("[build] Installing PyTorch (default, may include CUDA)")
pip_install("install", "torch", "torchaudio") pkg_install("install", "torch", "torchaudio")
# Install project and dev deps (includes pyinstaller) # Install project and dev deps (includes pyinstaller)
print("[build] Installing project dependencies") print("[build] Installing project dependencies")
pip_install("install", "-e", f"{SCRIPT_DIR}[dev]") pkg_install("install", "-e", f"{SCRIPT_DIR}[dev]")
return Path(python) return Path(python)