mirror of
https://github.com/astral-sh/uv
synced 2026-01-21 21:40:11 -05:00
This file is too big for an LLM context window and several contributors have complained about it being too scary to touch. This also gets us collapsible sections in the UI. I renamed some jobs for clarity in the meantime. And added a meta-job for required checks passing so we can avoid churn in our "Settings" when we change job names. Note this was entirely refactored by Claude. --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
952 lines
32 KiB
YAML
952 lines
32 KiB
YAML
on:
|
|
workflow_call:
|
|
inputs:
|
|
sha:
|
|
description: "The commit SHA to use for artifact names"
|
|
required: true
|
|
type: string
|
|
|
|
permissions: {}
|
|
|
|
env:
|
|
CARGO_INCREMENTAL: 0
|
|
CARGO_NET_RETRY: 10
|
|
CARGO_TERM_COLOR: always
|
|
PYTHON_VERSION: "3.12"
|
|
RUSTUP_MAX_RETRIES: 10
|
|
|
|
jobs:
|
|
integration-test-nushell:
|
|
name: "nushell"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Install nushell
|
|
env:
|
|
# This token only needs read access to the GitHub repository nushell/nushell.
|
|
# This token is used (via gh-cli) to avoid hitting GitHub REST API rate limits.
|
|
GITHUB_TOKEN: ${{ github.token }}
|
|
run: |-
|
|
# get latest nushell tag name
|
|
nu_latest=$(gh release list --repo nushell/nushell --limit 1 --exclude-pre-releases --exclude-drafts --json "tagName" --jq '.[0].tagName')
|
|
# trim any trailing whitespace from output
|
|
nu_tag=${nu_latest%%[[:space:]]*}
|
|
|
|
# download binary for x86_64-unknown-linux-gnu target
|
|
gh release download ${nu_tag} --repo nushell/nushell --pattern "nu-${nu_tag}-x86_64-unknown-linux-gnu.tar.gz"
|
|
|
|
# extract nu binary from tar.gz
|
|
tar -xf "nu-${nu_tag}-x86_64-unknown-linux-gnu.tar.gz"
|
|
# make the binary executable
|
|
chmod +x "./nu-${nu_tag}-x86_64-unknown-linux-gnu/nu"
|
|
# add it to PATH
|
|
echo "${{ github.workspace }}/nu-${nu_tag}-x86_64-unknown-linux-gnu" >> "${GITHUB_PATH}"
|
|
|
|
- name: Download binary
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: Prepare binary
|
|
run: chmod +x ./uv
|
|
|
|
- name: Create venv
|
|
# The python version is arbitrary for this test.
|
|
# We only want to ensure the activation script behaves properly
|
|
run: ./uv venv
|
|
|
|
- name: Activate venv
|
|
shell: nu {0}
|
|
run: overlay use ${{ github.workspace }}/.venv/bin/activate.nu
|
|
|
|
integration-test-conda:
|
|
name: "conda on linux"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- uses: conda-incubator/setup-miniconda@835234971496cad1653abb28a638a281cf32541f # v3.2.0
|
|
with:
|
|
miniconda-version: latest
|
|
activate-environment: uv
|
|
python-version: "3.12"
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: Conda info
|
|
shell: bash -el {0}
|
|
run: conda info
|
|
|
|
- name: "Install a package"
|
|
shell: bash -el {0}
|
|
run: |
|
|
echo "$CONDA_PREFIX"
|
|
./uv pip install anyio
|
|
|
|
integration-test-deadsnakes-39-linux:
|
|
name: "deadsnakes python3.9 on ubuntu"
|
|
timeout-minutes: 15
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: "Install python3.9"
|
|
run: |
|
|
for i in {1..5}; do
|
|
sudo add-apt-repository ppa:deadsnakes && break || { echo "Attempt $i failed, retrying in 10 seconds..."; sleep 10; }
|
|
if [ $i -eq 5 ]; then
|
|
echo "Failed to add repository after 5 attempts"
|
|
exit 1
|
|
fi
|
|
done
|
|
sudo apt-get update
|
|
sudo apt-get install python3.9
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: "Check missing distutils"
|
|
run: |
|
|
./uv venv -p 3.9 --python-preference only-system -v 2>&1 | tee log.txt || true
|
|
# We should report that distutils is missing
|
|
grep 'Python installation is missing `distutils`' log.txt
|
|
|
|
- name: "Install distutils"
|
|
run: |
|
|
sudo apt-get install python3.9-distutils
|
|
|
|
- name: "Create a virtualenv"
|
|
run: |
|
|
./uv venv -p 3.9 --python-preference only-system -v
|
|
|
|
- name: "Check version"
|
|
run: |
|
|
.venv/bin/python --version
|
|
|
|
- name: "Check install"
|
|
run: |
|
|
./uv pip install -v anyio
|
|
|
|
integration-test-free-threaded-windows-x86_64:
|
|
name: "free-threaded on windows"
|
|
timeout-minutes: 10
|
|
runs-on: windows-latest
|
|
|
|
steps:
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-windows-x86_64-${{ inputs.sha }}
|
|
|
|
- name: "Install free-threaded Python via uv"
|
|
run: |
|
|
./uv python install -v 3.13t
|
|
|
|
- name: "Create a virtual environment (stdlib)"
|
|
run: |
|
|
& (./uv python find 3.13t) -m venv .venv
|
|
|
|
- name: "Check version (stdlib)"
|
|
run: |
|
|
.venv/Scripts/python --version
|
|
|
|
- name: "Create a virtual environment (uv)"
|
|
run: |
|
|
./uv venv -c -p 3.13t --managed-python
|
|
|
|
- name: "Check version (uv)"
|
|
run: |
|
|
.venv/Scripts/python --version
|
|
|
|
- name: "Check is free-threaded"
|
|
run: |
|
|
.venv/Scripts/python -c "import sys; exit(1) if sys._is_gil_enabled() else exit(0)"
|
|
|
|
- name: "Check install"
|
|
run: |
|
|
./uv pip install -v anyio
|
|
|
|
- name: "Check uv run"
|
|
run: |
|
|
./uv run python -c ""
|
|
./uv run -p 3.13t python -c ""
|
|
|
|
integration-test-windows-aarch64-implicit:
|
|
name: "aarch64 windows implicit"
|
|
timeout-minutes: 10
|
|
runs-on: windows-11-arm
|
|
|
|
steps:
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-windows-aarch64-${{ inputs.sha }}
|
|
|
|
- name: "Install Python via uv (implicitly select x64)"
|
|
run: |
|
|
./uv python install -v 3.13
|
|
|
|
- name: "Create a virtual environment (stdlib)"
|
|
run: |
|
|
& (./uv python find 3.13) -m venv .venv
|
|
|
|
- name: "Check version (stdlib)"
|
|
run: |
|
|
.venv/Scripts/python --version
|
|
|
|
- name: "Create a virtual environment (uv)"
|
|
run: |
|
|
./uv venv -c -p 3.13 --managed-python
|
|
|
|
- name: "Check version (uv)"
|
|
run: |
|
|
.venv/Scripts/python --version
|
|
|
|
- name: "Check is x64"
|
|
run: |
|
|
.venv/Scripts/python -c "import sys; exit(1) if 'AMD64' not in sys.version else exit(0)"
|
|
|
|
- name: "Check install"
|
|
run: |
|
|
./uv pip install -v anyio
|
|
|
|
- name: "Check uv run"
|
|
run: |
|
|
./uv run python -c ""
|
|
./uv run -p 3.13 python -c ""
|
|
|
|
integration-test-windows-aarch64-explicit:
|
|
name: "aarch64 windows explicit"
|
|
timeout-minutes: 10
|
|
runs-on: windows-11-arm
|
|
|
|
steps:
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-windows-aarch64-${{ inputs.sha }}
|
|
|
|
- name: "Install Python via uv (explicitly select aarch64)"
|
|
run: |
|
|
./uv python install -v cpython-3.13-windows-aarch64-none
|
|
|
|
- name: "Create a virtual environment (stdlib)"
|
|
run: |
|
|
& (./uv python find 3.13) -m venv .venv
|
|
|
|
- name: "Check version (stdlib)"
|
|
run: |
|
|
.venv/Scripts/python --version
|
|
|
|
- name: "Create a virtual environment (uv)"
|
|
run: |
|
|
./uv venv -c -p 3.13 --managed-python
|
|
|
|
- name: "Check version (uv)"
|
|
run: |
|
|
.venv/Scripts/python --version
|
|
|
|
- name: "Check is NOT x64"
|
|
run: |
|
|
.venv/Scripts/python -c "import sys; exit(1) if 'AMD64' in sys.version else exit(0)"
|
|
|
|
- name: "Check install"
|
|
run: |
|
|
./uv pip install -v anyio
|
|
|
|
- name: "Check uv run"
|
|
run: |
|
|
./uv run python -c ""
|
|
./uv run -p 3.13 python -c ""
|
|
|
|
integration-test-windows-python-install-manager:
|
|
name: "windows python install manager"
|
|
timeout-minutes: 10
|
|
runs-on: windows-latest
|
|
|
|
steps:
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-windows-x86_64-${{ inputs.sha }}
|
|
|
|
- name: "Install Python via Python Install manager"
|
|
run: |
|
|
# https://www.python.org/downloads/release/pymanager-250/
|
|
winget install --accept-package-agreements --accept-source-agreements 9NQ7512CXL7T
|
|
# Call Python Install Manager's py.exe by full path to avoid legacy py.exe
|
|
& "$env:LOCALAPPDATA\Microsoft\WindowsApps\py.exe" install 3.14
|
|
|
|
# https://github.com/astral-sh/uv/issues/16204
|
|
- name: "Check temporary environment creation"
|
|
run: |
|
|
./uv run -p $env:LOCALAPPDATA\Python\pythoncore-3.14-64\python.exe --with numpy python -c "import sys; print(sys.executable)"
|
|
|
|
integration-test-pypy-linux:
|
|
name: "pypy on linux"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: "Install PyPy"
|
|
run: ./uv python install -v pypy3.9
|
|
|
|
- name: "Create a virtual environment"
|
|
run: |
|
|
./uv venv -p pypy3.9 --managed-python
|
|
|
|
- name: "Check for executables"
|
|
run: |
|
|
check_in_bin() {
|
|
local executable_name=$1
|
|
local bin_path=".venv/bin"
|
|
|
|
if [[ -x "$bin_path/$executable_name" ]]; then
|
|
return 0
|
|
else
|
|
echo "Executable '$executable_name' not found in folder '$bin_path'."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
executables=("pypy" "pypy3" "python")
|
|
|
|
all_found=true
|
|
for executable_name in "${executables[@]}"; do
|
|
check_in_bin "$executable_name" "$folder_path"
|
|
result=$?
|
|
|
|
if [[ $result -ne 0 ]]; then
|
|
all_found=false
|
|
fi
|
|
done
|
|
|
|
if ! $all_found; then
|
|
echo "One or more expected executables were not found."
|
|
exit 1
|
|
fi
|
|
|
|
- name: "Check version"
|
|
run: |
|
|
.venv/bin/pypy --version
|
|
.venv/bin/pypy3 --version
|
|
.venv/bin/python --version
|
|
|
|
- name: "Check install"
|
|
run: |
|
|
./uv pip install anyio
|
|
|
|
integration-test-pypy-windows-x86_64:
|
|
name: "pypy on windows"
|
|
timeout-minutes: 10
|
|
runs-on: windows-latest
|
|
|
|
steps:
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-windows-x86_64-${{ inputs.sha }}
|
|
|
|
- name: "Install PyPy"
|
|
run: .\uv.exe python install pypy3.9
|
|
|
|
- name: "Create a virtual environment"
|
|
run: |
|
|
.\uv.exe venv -p pypy3.9 --managed-python
|
|
|
|
- name: "Check for executables"
|
|
shell: python
|
|
run: |
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
def binary_exist(binary):
|
|
binaries_path = Path(".venv\\Scripts")
|
|
if (binaries_path / binary).exists():
|
|
return True
|
|
print(f"Executable '{binary}' not found in folder '{binaries_path}'.")
|
|
|
|
all_found = True
|
|
expected_binaries = [
|
|
"pypy3.9.exe",
|
|
"pypy3.9w.exe",
|
|
"pypy3.exe",
|
|
"pypyw.exe",
|
|
"python.exe",
|
|
"python3.9.exe",
|
|
"python3.exe",
|
|
"pythonw.exe",
|
|
]
|
|
for binary in expected_binaries:
|
|
if not binary_exist(binary):
|
|
all_found = False
|
|
|
|
if not all_found:
|
|
print("One or more expected executables were not found.")
|
|
sys.exit(1)
|
|
|
|
- name: "Check version"
|
|
run: |
|
|
& .venv\Scripts\pypy3.9.exe --version
|
|
& .venv\Scripts\pypy3.exe --version
|
|
& .venv\Scripts\python.exe --version
|
|
|
|
- name: "Check install"
|
|
run: |
|
|
.\uv.exe pip install anyio
|
|
|
|
integration-test-graalpy-linux:
|
|
name: "graalpy on linux"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: "Install GraalPy"
|
|
run: ./uv python install -v graalpy
|
|
|
|
- name: "Create a virtual environment"
|
|
run: |
|
|
./uv venv -p graalpy --managed-python
|
|
|
|
- name: "Check for executables"
|
|
run: |
|
|
check_in_bin() {
|
|
local executable_name=$1
|
|
local bin_path=".venv/bin"
|
|
|
|
if [[ -x "$bin_path/$executable_name" ]]; then
|
|
return 0
|
|
else
|
|
echo "Executable '$executable_name' not found in folder '$bin_path'."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
executables=("graalpy" "python3" "python")
|
|
|
|
all_found=true
|
|
for executable_name in "${executables[@]}"; do
|
|
check_in_bin "$executable_name" "$folder_path"
|
|
result=$?
|
|
|
|
if [[ $result -ne 0 ]]; then
|
|
all_found=false
|
|
fi
|
|
done
|
|
|
|
if ! $all_found; then
|
|
echo "One or more expected executables were not found."
|
|
exit 1
|
|
fi
|
|
|
|
- name: "Check version"
|
|
run: |
|
|
.venv/bin/graalpy --version
|
|
.venv/bin/python3 --version
|
|
.venv/bin/python --version
|
|
|
|
- name: "Check install"
|
|
run: |
|
|
./uv pip install anyio
|
|
|
|
- name: "Check a GraalPy dev version (different version parsing)"
|
|
run: |
|
|
curl -sLf https://github.com/graalvm/graal-languages-ea-builds/releases/download/graalpy-25.0.0-ea.31/graalpy-25.0.0-ea.31-linux-amd64.tar.gz | tar xz
|
|
./uv run -p ./graalpy-25.0.0-dev-linux-amd64/bin/python python --version
|
|
|
|
integration-test-graalpy-windows-x86_64:
|
|
name: "graalpy on windows"
|
|
timeout-minutes: 10
|
|
runs-on: windows-latest
|
|
|
|
steps:
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-windows-x86_64-${{ inputs.sha }}
|
|
|
|
- name: "Install GraalPy"
|
|
run: .\uv.exe python install graalpy
|
|
|
|
- name: "Create a virtual environment"
|
|
run: |
|
|
.\uv.exe venv -p graalpy --managed-python
|
|
|
|
- name: "Check for executables"
|
|
shell: python
|
|
run: |
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
def binary_exist(binary):
|
|
binaries_path = Path(".venv\\Scripts")
|
|
if (binaries_path / binary).exists():
|
|
return True
|
|
print(f"Executable '{binary}' not found in folder '{binaries_path}'.")
|
|
|
|
all_found = True
|
|
expected_binaries = [
|
|
"graalpy.exe",
|
|
"python.exe",
|
|
"python3.exe",
|
|
]
|
|
for binary in expected_binaries:
|
|
if not binary_exist(binary):
|
|
all_found = False
|
|
|
|
if not all_found:
|
|
print("One or more expected executables were not found.")
|
|
sys.exit(1)
|
|
|
|
- name: "Check version"
|
|
run: |
|
|
& .venv\Scripts\graalpy.exe --version
|
|
& .venv\Scripts\python3.exe --version
|
|
& .venv\Scripts\python.exe --version
|
|
|
|
- name: "Check install"
|
|
run: |
|
|
.\uv.exe pip install anyio
|
|
|
|
integration-test-pyodide-linux:
|
|
name: "pyodide on linux"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: "Create a native virtual environment"
|
|
run: |
|
|
./uv venv venv-native -p 3.12
|
|
# We use features added in 0.30.3 but there is no known breakage in
|
|
# newer versions.
|
|
./uv pip install -p venv-native/bin/python pyodide-build==0.30.7 pip
|
|
|
|
- name: "Install Pyodide interpreter"
|
|
run: |
|
|
source ./venv-native/bin/activate
|
|
pyodide xbuildenv install 0.27.5
|
|
PYODIDE_PYTHON=$(pyodide config get interpreter)
|
|
PYODIDE_INDEX=$(pyodide config get package_index)
|
|
echo "PYODIDE_PYTHON=$PYODIDE_PYTHON" >> $GITHUB_ENV
|
|
echo "PYODIDE_INDEX=$PYODIDE_INDEX" >> $GITHUB_ENV
|
|
|
|
- name: "Create Pyodide virtual environment"
|
|
run: |
|
|
./uv venv -p $PYODIDE_PYTHON venv-pyodide
|
|
source ./venv-pyodide/bin/activate
|
|
./uv pip install --extra-index-url=$PYODIDE_INDEX --no-build numpy
|
|
python -c 'import numpy'
|
|
|
|
- name: "Install Pyodide with uv python"
|
|
run: |
|
|
./uv python install cpython-3.13.2-emscripten-wasm32-musl
|
|
|
|
- name: "Create a Pyodide virtual environment using uv installed Python"
|
|
run: |
|
|
./uv venv -p cpython-3.13.2-emscripten-wasm32-musl venv-pyodide2
|
|
# TODO: be able to install Emscripten wheels here...
|
|
source ./venv-pyodide2/bin/activate
|
|
./uv pip install packaging
|
|
python -c 'import packaging'
|
|
|
|
integration-test-github-actions:
|
|
name: "github actions"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
|
with:
|
|
python-version: "3.12.7"
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: "Install a package without system opt-in"
|
|
run: |
|
|
./uv pip install anyio && exit 1 || echo "Failed as expected"
|
|
|
|
- name: "Install a package with system opt-in"
|
|
run: |
|
|
./uv pip install anyio --system
|
|
|
|
- name: Configure uv to use the system Python by default
|
|
run: echo "UV_SYSTEM_PYTHON=1" >> $GITHUB_ENV
|
|
|
|
- name: "Install a package with system opt-in via the environment"
|
|
run: |
|
|
./uv pip install anyio --reinstall
|
|
|
|
- name: "Create a project"
|
|
run: |
|
|
# Use Python 3.11 as the minimum required version
|
|
./uv init --python 3.11
|
|
./uv add anyio
|
|
|
|
- name: "Sync to the system Python"
|
|
run: ./uv sync -v --python 3.12
|
|
env:
|
|
UV_PROJECT_ENVIRONMENT: "/opt/hostedtoolcache/Python/3.12.7/x64"
|
|
|
|
- name: "Attempt to sync to the system Python with an incompatible version"
|
|
run: |
|
|
./uv sync -v --python 3.11 && { echo "ci: Error; should not succeed"; exit 1; } || { echo "ci: Ok; expected failure"; exit 0; }
|
|
env:
|
|
UV_PROJECT_ENVIRONMENT: "/opt/hostedtoolcache/Python/3.12.7/x64"
|
|
|
|
- name: "Attempt to sync to a non-Python environment directory"
|
|
run: |
|
|
mkdir -p /home/runner/example
|
|
touch /home/runner/example/some-file
|
|
./uv sync -v && { echo "ci: Error; should not succeed"; exit 1; } || { echo "ci: Ok; expected failure"; exit 0; }
|
|
env:
|
|
UV_PROJECT_ENVIRONMENT: "/home/runner/example"
|
|
|
|
integration-test-github-actions-freethreaded:
|
|
name: "free-threaded on github actions"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
|
with:
|
|
python-version: "3.13t"
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: "Install a package without system opt-in"
|
|
run: |
|
|
./uv pip install anyio && exit 1 || echo "Failed as expected"
|
|
|
|
- name: "Install a package with system opt-in but without free-threaded opt-in"
|
|
run: |
|
|
./uv pip install anyio --system --python 3.13 || echo "Failed as expected"
|
|
# (we need to request 3.13 or we'll discover 3.12 on the system)
|
|
|
|
- name: "Install a package with system and free-threaded opt-in"
|
|
run: |
|
|
./uv pip install anyio --system --python 3.13t
|
|
|
|
- name: "Create a virtual environment"
|
|
run: |
|
|
./uv venv -p 3.13t --python-preference only-system
|
|
|
|
- name: "Check is free-threaded"
|
|
run: |
|
|
.venv/bin/python -c "import sys; exit(1) if sys._is_gil_enabled() else exit(0)"
|
|
|
|
integration-test-wsl:
|
|
name: "pyenv on wsl"
|
|
timeout-minutes: 15
|
|
runs-on: windows-latest
|
|
if: ${{ github.event.pull_request.head.repo.fork != true }}
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-musl-${{ inputs.sha }}
|
|
|
|
- name: "Setup WSL"
|
|
uses: Vampire/setup-wsl@6a8db447be7ed35f2f499c02c6e60ff77ef11278 # v6.0.0
|
|
with:
|
|
distribution: Ubuntu-22.04
|
|
|
|
- name: "Install pyenv-win"
|
|
shell: pwsh
|
|
run: |
|
|
Write-Host "Installing pyenv-win..."
|
|
Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv-win/pyenv-win/master/pyenv-win/install-pyenv-win.ps1" -OutFile "./install-pyenv-win.ps1"
|
|
.\install-pyenv-win.ps1
|
|
|
|
# Add pyenv-win to PATH for this session
|
|
$env:PYENV = "$env:USERPROFILE\.pyenv\pyenv-win"
|
|
$env:PATH = "$env:PYENV\bin;$env:PYENV\shims;$env:PATH"
|
|
|
|
# Add to GITHUB_PATH so WSL can find the shims
|
|
echo "$env:PYENV\bin" | Out-File -FilePath $env:GITHUB_PATH -Append
|
|
echo "$env:PYENV\shims" | Out-File -FilePath $env:GITHUB_PATH -Append
|
|
|
|
Write-Host "Installing Python 3.11.9 via pyenv-win..."
|
|
& "$env:PYENV\bin\pyenv.bat" install 3.11.9
|
|
& "$env:PYENV\bin\pyenv.bat" global 3.11.9
|
|
|
|
Write-Host "Verifying pyenv-win installation..."
|
|
& "$env:PYENV\bin\pyenv.bat" versions
|
|
|
|
- name: "Test uv"
|
|
shell: wsl-bash {0}
|
|
run: |
|
|
set -x
|
|
chmod +x ./uv
|
|
|
|
# Check that we don't fail on `pyenv-win` shims
|
|
./uv python list -v
|
|
|
|
integration-test-registries:
|
|
name: "registries"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
if: ${{ github.event.pull_request.head.repo.fork != true }}
|
|
environment: uv-test-registries
|
|
env:
|
|
PYTHON_VERSION: 3.12
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
|
|
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
|
with:
|
|
python-version: "${{ env.PYTHON_VERSION }}"
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: "Configure AWS credentials"
|
|
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
|
|
with:
|
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
aws-region: us-east-1
|
|
|
|
- name: "Get AWS CodeArtifact token"
|
|
run: |
|
|
UV_TEST_AWS_TOKEN=$(aws codeartifact get-authorization-token \
|
|
--domain tests \
|
|
--domain-owner ${{ secrets.AWS_ACCOUNT_ID }} \
|
|
--region us-east-1 \
|
|
--query authorizationToken \
|
|
--output text)
|
|
echo "::add-mask::$UV_TEST_AWS_TOKEN"
|
|
echo "UV_TEST_AWS_TOKEN=$UV_TEST_AWS_TOKEN" >> $GITHUB_ENV
|
|
|
|
- name: "Authenticate with GCP"
|
|
id: "auth"
|
|
uses: "google-github-actions/auth@fc2174804b84f912b1f6d334e9463f484f1c552d"
|
|
with:
|
|
credentials_json: "${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}"
|
|
|
|
- name: "Set up GCP SDK"
|
|
uses: "google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db"
|
|
|
|
- name: "Get GCP Artifact Registry token"
|
|
id: get_token
|
|
run: |
|
|
UV_TEST_GCP_TOKEN=$(gcloud auth print-access-token)
|
|
echo "::add-mask::$UV_TEST_GCP_TOKEN"
|
|
echo "UV_TEST_GCP_TOKEN=$UV_TEST_GCP_TOKEN" >> $GITHUB_ENV
|
|
|
|
- name: "Run registry tests with environment variable backend"
|
|
run: ./uv run -p "${PYTHON_VERSION}" scripts/registries-test.py --uv ./uv --color always --all --auth-method env
|
|
env:
|
|
RUST_LOG: uv=debug
|
|
UV_TEST_ARTIFACTORY_TOKEN: ${{ secrets.UV_TEST_ARTIFACTORY_TOKEN }}
|
|
UV_TEST_ARTIFACTORY_URL: ${{ secrets.UV_TEST_ARTIFACTORY_URL }}
|
|
UV_TEST_ARTIFACTORY_USERNAME: ${{ secrets.UV_TEST_ARTIFACTORY_USERNAME }}
|
|
UV_TEST_AWS_URL: ${{ secrets.UV_TEST_AWS_URL }}
|
|
UV_TEST_AWS_USERNAME: aws
|
|
UV_TEST_AZURE_TOKEN: ${{ secrets.UV_TEST_AZURE_TOKEN }}
|
|
UV_TEST_AZURE_URL: ${{ secrets.UV_TEST_AZURE_URL }}
|
|
UV_TEST_AZURE_USERNAME: dummy
|
|
UV_TEST_CLOUDSMITH_TOKEN: ${{ secrets.UV_TEST_CLOUDSMITH_TOKEN }}
|
|
UV_TEST_CLOUDSMITH_URL: ${{ secrets.UV_TEST_CLOUDSMITH_URL }}
|
|
UV_TEST_CLOUDSMITH_USERNAME: ${{ secrets.UV_TEST_CLOUDSMITH_USERNAME }}
|
|
UV_TEST_GCP_URL: ${{ secrets.UV_TEST_GCP_URL }}
|
|
UV_TEST_GCP_USERNAME: oauth2accesstoken
|
|
UV_TEST_GEMFURY_TOKEN: ${{ secrets.UV_TEST_GEMFURY_TOKEN }}
|
|
UV_TEST_GEMFURY_URL: ${{ secrets.UV_TEST_GEMFURY_URL }}
|
|
UV_TEST_GEMFURY_USERNAME: ${{ secrets.UV_TEST_GEMFURY_USERNAME }}
|
|
UV_TEST_GITLAB_TOKEN: ${{ secrets.UV_TEST_GITLAB_TOKEN }}
|
|
UV_TEST_GITLAB_URL: ${{ secrets.UV_TEST_GITLAB_URL }}
|
|
UV_TEST_GITLAB_USERNAME: token
|
|
|
|
- name: "Run registry tests with text store backend"
|
|
run: ./uv run -p "${PYTHON_VERSION}" scripts/registries-test.py --uv ./uv --color always --all --auth-method text-store
|
|
env:
|
|
RUST_LOG: uv=debug
|
|
UV_TEST_ARTIFACTORY_TOKEN: ${{ secrets.UV_TEST_ARTIFACTORY_TOKEN }}
|
|
UV_TEST_ARTIFACTORY_URL: ${{ secrets.UV_TEST_ARTIFACTORY_URL }}
|
|
UV_TEST_ARTIFACTORY_USERNAME: ${{ secrets.UV_TEST_ARTIFACTORY_USERNAME }}
|
|
UV_TEST_AWS_URL: ${{ secrets.UV_TEST_AWS_URL }}
|
|
UV_TEST_AWS_USERNAME: aws
|
|
UV_TEST_AZURE_TOKEN: ${{ secrets.UV_TEST_AZURE_TOKEN }}
|
|
UV_TEST_AZURE_URL: ${{ secrets.UV_TEST_AZURE_URL }}
|
|
UV_TEST_AZURE_USERNAME: dummy
|
|
UV_TEST_CLOUDSMITH_TOKEN: ${{ secrets.UV_TEST_CLOUDSMITH_TOKEN }}
|
|
UV_TEST_CLOUDSMITH_URL: ${{ secrets.UV_TEST_CLOUDSMITH_URL }}
|
|
UV_TEST_CLOUDSMITH_USERNAME: ${{ secrets.UV_TEST_CLOUDSMITH_USERNAME }}
|
|
UV_TEST_GCP_URL: ${{ secrets.UV_TEST_GCP_URL }}
|
|
UV_TEST_GCP_USERNAME: oauth2accesstoken
|
|
UV_TEST_GEMFURY_TOKEN: ${{ secrets.UV_TEST_GEMFURY_TOKEN }}
|
|
UV_TEST_GEMFURY_URL: ${{ secrets.UV_TEST_GEMFURY_URL }}
|
|
UV_TEST_GEMFURY_USERNAME: ${{ secrets.UV_TEST_GEMFURY_USERNAME }}
|
|
UV_TEST_GITLAB_TOKEN: ${{ secrets.UV_TEST_GITLAB_TOKEN }}
|
|
UV_TEST_GITLAB_URL: ${{ secrets.UV_TEST_GITLAB_URL }}
|
|
UV_TEST_GITLAB_USERNAME: token
|
|
|
|
integration-uv-build-backend:
|
|
name: "uv_build"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
|
with:
|
|
python-version: "${{ env.PYTHON_VERSION }}"
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: |
|
|
chmod +x ./uv
|
|
chmod +x ./uvx
|
|
|
|
- name: "Test uv_build package"
|
|
run: |
|
|
# Build the Python package, which is not covered by uv's integration tests since they can't depend on having
|
|
# a Python package (only the binary itself is built before running Rust's tests)
|
|
./uv build -v crates/uv-build
|
|
|
|
# Test the main path (`build_wheel`) through pip
|
|
./uv venv -v --seed
|
|
./uv run --no-project python -m pip install -v test/packages/built-by-uv --find-links crates/uv-build/dist --no-index --no-deps
|
|
./uv run --no-project python -c "from built_by_uv import greet; print(greet())"
|
|
|
|
# Test both `build_wheel` and `build_sdist` through uv
|
|
./uv venv -c -v
|
|
./uv build -v --force-pep517 test/packages/built-by-uv --find-links crates/uv-build/dist --offline
|
|
./uv pip install -v test/packages/built-by-uv/dist/*.tar.gz --find-links crates/uv-build/dist --offline --no-deps
|
|
./uv run --no-project python -c "from built_by_uv import greet; print(greet())"
|
|
|
|
# Test both `build_wheel` and `build_sdist` through the official `build`
|
|
rm -rf test/packages/built-by-uv/dist/
|
|
./uv venv -c -v
|
|
./uv pip install build
|
|
# Add the uv binary to PATH for `build` to find
|
|
PATH="$(pwd):$PATH" UV_OFFLINE=1 UV_FIND_LINKS=crates/uv-build/dist ./uv run --no-project python -m build -v --installer uv test/packages/built-by-uv
|
|
./uv pip install -v test/packages/built-by-uv/dist/*.tar.gz --find-links crates/uv-build/dist --offline --no-deps
|
|
./uv run --no-project python -c "from built_by_uv import greet; print(greet())"
|
|
|
|
cache-test-ubuntu:
|
|
name: "cache on linux"
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-linux-libc-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: "Download binary for last version"
|
|
run: curl -LsSf "https://github.com/astral-sh/uv/releases/latest/download/uv-x86_64-unknown-linux-gnu.tar.gz" | tar -xvz
|
|
|
|
- name: "Check cache compatibility"
|
|
run: python scripts/check_cache_compat.py --uv-current ./uv --uv-previous ./uv-x86_64-unknown-linux-gnu/uv
|
|
|
|
cache-test-macos-aarch64:
|
|
name: "cache on macos aarch64"
|
|
timeout-minutes: 10
|
|
runs-on: macos-14
|
|
steps:
|
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: "Download binary"
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
with:
|
|
name: uv-macos-aarch64-${{ inputs.sha }}
|
|
|
|
- name: "Prepare binary"
|
|
run: chmod +x ./uv
|
|
|
|
- name: "Download binary for last version"
|
|
run: curl -LsSf "https://github.com/astral-sh/uv/releases/latest/download/uv-aarch64-apple-darwin.tar.gz" | tar -xvz
|
|
|
|
- name: "Check cache compatibility"
|
|
run: python scripts/check_cache_compat.py --uv-current ./uv --uv-previous ./uv-aarch64-apple-darwin/uv
|