mirror of
https://github.com/astral-sh/uv
synced 2026-01-22 14:00:11 -05:00
The Windows registry test (PEP 514 integration) tests Python installation registration functionality rather than system Python detection like the other tests in test-system, so it fits better in test-integration. Co-authored-by: Claude <noreply@anthropic.com>
970 lines
33 KiB
YAML
970 lines
33 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)"
|
|
|
|
# Test PEP 514 integration that installs Python into the Windows registry.
|
|
integration-test-windows-registry:
|
|
name: "windows registry"
|
|
timeout-minutes: 10
|
|
runs-on: windows-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-windows-x86_64-${{ inputs.sha }}
|
|
|
|
- name: "Test PEP 514 registration"
|
|
run: python ./scripts/check_registry.py --uv ./uv.exe
|
|
|
|
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
|