2 Commits

Author SHA1 Message Date
Claude
eb9ec687cb 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>
2026-03-20 22:56:13 -07:00
Claude
d297540053 Skip setup-python on macOS, use system Python instead
setup-python's internal install script hardcodes /Users/runner which
fails on self-hosted runners without sudo. macOS ships with Python 3
so we use it directly and skip the action entirely.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 22:47:05 -07:00
2 changed files with 42 additions and 21 deletions

View File

@@ -32,19 +32,15 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Python - name: Install uv
uses: actions/setup-python@v5 uses: astral-sh/setup-uv@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
env:
AGENT_TOOLSDIRECTORY: ${{ runner.temp }}/toolcache
- name: Install Python build tools - name: Set up Python
run: python -m pip install --upgrade pip setuptools wheel run: uv python install ${{ env.PYTHON_VERSION }}
- name: Build sidecar - name: Build sidecar
working-directory: python working-directory: python
run: python 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)
print(f"[build] Creating venv at {venv_dir}") use_uv = _has_uv()
subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
# Determine python path inside venv — use `python -m pip` instead of if use_uv:
# calling pip directly to avoid permission errors on Windows 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}")
subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
# Determine python path inside venv
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:
subprocess.run([python, "-m", "pip", *args], check=True) if use_uv:
subprocess.run(["uv", "pip", "install", "--python", python, *args], check=True)
else:
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)