on: workflow_call: inputs: sha: description: "The commit SHA to use for artifact names" required: true type: string permissions: {} jobs: system-test-debian: timeout-minutes: 10 name: "python on debian" runs-on: ubuntu-latest container: debian:trixie@sha256:5cf544fad978371b3df255b61e209b373583cb88b733475c86e49faa15ac2104 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Install Python" run: apt-get update && apt-get install -y python3 python3-pip python3-venv python3-debian - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-linux-musl-${{ inputs.sha }} - name: "Prepare binary" run: chmod +x ./uv - name: "Print Python path" run: echo $(which python3) - name: "Validate global Python install" run: python3 scripts/check_system_python.py --uv ./uv --externally-managed - name: "Test `uv run` with system Python" run: | ./uv run --no-project -p python3 -v python -c "import debian" ./uv run --no-project -p python3 -v --with anyio python -c "import debian" system-test-fedora: timeout-minutes: 10 name: "python on fedora" runs-on: ubuntu-latest container: fedora:45@sha256:af8cdc432037f5e8e288bbc26c2b55b96000a911ec5b37959cd464d830f6cc5b steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Install Python" run: dnf install python3 which -y && python3 -m ensurepip - 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: "Print Python path" run: echo $(which python3) - name: "Validate global Python install" run: python3 scripts/check_system_python.py --uv ./uv system-test-ubuntu: timeout-minutes: 10 name: "python3.12 via setup-python" runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.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: "Print Python path" run: echo $(which python) - name: "Validate global Python install" run: python scripts/check_system_python.py --uv ./uv # Currently failing, see https://github.com/astral-sh/uv/issues/13811 # system-test-opensuse: # timeout-minutes: 5 # name: "python on opensuse" # runs-on: ubuntu-latest # container: opensuse/tumbleweed # steps: # - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # - name: "Install Python" # run: > # until # zypper install -y python310 which && python3.10 -m ensurepip && mv /usr/bin/python3.10 /usr/bin/python3; # do sleep 10; # done # # We retry because `zypper` can fail during remote repository updates # # The above will not sleep forever due to the job level timeout # - 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: "Print Python path" # run: echo $(which python3) # - name: "Validate global Python install" # run: python3 scripts/check_system_python.py --uv ./uv # Note: rockylinux is a 1-1 code compatible distro to rhel # rockylinux mimics centos but with added maintenance stability # and avoids issues with centos stream uptime concerns system-test-rocky-linux: timeout-minutes: 10 name: "python on rocky linux ${{ matrix.rocky-version }}" runs-on: ubuntu-latest container: rockylinux/rockylinux:${{ matrix.rocky-version }} strategy: fail-fast: false matrix: rocky-version: ["8", "9", "10"] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Install Python" if: matrix.rocky-version == '8' run: | for i in {1..5}; do dnf install python39 python39-pip which -y && break || { echo "Attempt $i failed, retrying in 10 seconds..."; sleep 10; } if [ $i -eq 5 ]; then echo "Failed to install Python after 5 attempts" exit 1 fi done - name: "Install Python" if: matrix.rocky-version == '9' run: | for i in {1..5}; do dnf install python3.9 python3.9-pip which -y && break || { echo "Attempt $i failed, retrying in 10 seconds..."; sleep 10; } if [ $i -eq 5 ]; then echo "Failed to install Python after 5 attempts" exit 1 fi done - name: "Install Python" if: matrix.rocky-version == '10' run: | dnf install python3 python3-pip which -y - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-linux-musl-${{ inputs.sha }} - name: "Prepare binary" run: chmod +x ./uv - name: "Print Python path" run: echo $(which python3) # Needed for building Pydantic - name: "Install build tools" run: dnf install -y gcc - name: "Validate global Python install" run: python3 scripts/check_system_python.py --uv ./uv system-test-graalpy: timeout-minutes: 10 name: "graalpy on linux" runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "graalpy24.1" - 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: "Print Python path" run: echo $(which graalpy) - name: "Validate global Python install" run: graalpy scripts/check_system_python.py --uv ./uv system-test-pypy: timeout-minutes: 10 name: "pypy on linux" runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "pypy3.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: "Print Python path" run: echo $(which pypy) - name: "Validate global Python install" run: pypy scripts/check_system_python.py --uv ./uv system-test-pyston: timeout-minutes: 10 name: "pyston on linux" runs-on: ubuntu-latest container: pyston/pyston:2.3.5 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-linux-musl-${{ inputs.sha }} - name: "Prepare binary" run: chmod +x ./uv - name: "Print Python path" run: echo $(which pyston) - name: "Validate global Python install" run: pyston scripts/check_system_python.py --uv ./uv system-test-alpine: timeout-minutes: 10 name: "python on alpine" runs-on: ubuntu-latest container: alpine:latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Install Python" run: apk add --update --no-cache python3 py3-pip - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-linux-musl-${{ inputs.sha }} - name: "Prepare binary" run: chmod +x ./uv - name: "Print Python path" run: echo $(which python3) - name: "Validate global Python install" run: python3 scripts/check_system_python.py --uv ./uv --externally-managed system-test-macos-aarch64: timeout-minutes: 10 name: "python on macos aarch64" runs-on: macos-14 # github-macos-14-aarch64-3 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 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: "Print Python path" run: echo $(which python3) - name: "Validate global Python install" run: python3 scripts/check_system_python.py --uv ./uv --externally-managed system-test-macos-aarch64-homebrew: timeout-minutes: 10 name: "homebrew python on macos aarch64" runs-on: macos-14 # github-macos-14-aarch64-3 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Install Python" run: brew install python3 - 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: "Print Python path" run: echo $(which python3) - name: "Validate global Python install" run: python3 scripts/check_system_python.py --uv ./uv --externally-managed system-test-macos-aarch64-emulated: timeout-minutes: 10 name: "x86-64 python on macos aarch64" runs-on: macos-14 # github-macos-14-aarch64-3 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: 3.13 architecture: x64 - 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: "Print Python path" run: echo $(which python3) - name: "Validate global Python install" run: python3 scripts/check_system_python.py --uv ./uv --externally-managed system-test-macos-x86_64: timeout-minutes: 10 name: "python on macos x86-64" runs-on: macos-15-intel # github-macos-15-x86_64-4 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false # We test with GitHub's Python as a regression test for # https://github.com/astral-sh/uv/issues/2450 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-macos-x86_64-${{ inputs.sha }} - name: "Prepare binary" run: chmod +x ./uv - name: "Print Python path" run: echo $(which python3) - name: "Validate global Python install" run: python3 scripts/check_system_python.py --uv ./uv --externally-managed system-test-windows-python-310: timeout-minutes: 10 name: "python3.10 on windows x86-64" runs-on: windows-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.10" - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-windows-x86_64-${{ inputs.sha }} - name: "Print Python path" run: echo $(which python) - name: "Validate global Python install" run: py -3.10 ./scripts/check_system_python.py --uv ./uv.exe system-test-windows-x86_64-python-310: timeout-minutes: 10 name: "python3.10 on windows x86" runs-on: windows-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.10" architecture: "x86" - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-windows-x86_64-${{ inputs.sha }} - name: "Print Python path" run: echo $(which python) - name: "Validate global Python install" run: python ./scripts/check_system_python.py --uv ./uv.exe system-test-windows-x86_64-python-313: timeout-minutes: 10 name: "python3.13 on windows x86-64" runs-on: windows-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" allow-prereleases: true - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-windows-x86_64-${{ inputs.sha }} - name: "Print Python path" run: echo $(which python) - name: "Validate global Python install" run: py -3.13 ./scripts/check_system_python.py --uv ./uv.exe system-test-windows-aarch64-x86-python-313: timeout-minutes: 10 name: "x86-64 python3.13 on windows aarch64" runs-on: windows-11-arm steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" architecture: "x64" allow-prereleases: true - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-windows-aarch64-${{ inputs.sha }} - name: "Validate global Python install" run: py -3.13 ./scripts/check_system_python.py --uv ./uv.exe system-test-windows-aarch64-aarch64-python-313: timeout-minutes: 10 name: "aarch64 python3.13 on windows aarch64" runs-on: windows-11-arm steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" architecture: "arm64" allow-prereleases: true - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-windows-aarch64-${{ inputs.sha }} - name: "Validate global Python install" run: py -3.13-arm64 ./scripts/check_system_python.py --uv ./uv.exe system-test-choco: timeout-minutes: 10 name: "python3.9 via chocolatey" runs-on: windows-latest env: TEST_PYTHON_VERSION: "3.9.13" steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Install Python" run: choco install python3 --verbose --version=$env:TEST_PYTHON_VERSION - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-windows-x86_64-${{ inputs.sha }} # Chocolatey updates the registry but doesn't update `GITHUB_PATH` and since figuring out what # it added would be more work than it's worth, it's simpler to just reload the values from the # registry. - name: "Validate global Python install" run: | $env:PATH = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") python ./scripts/check_system_python.py --uv ./uv.exe --check-python-version $env:TEST_PYTHON_VERSION --check-path system-test-pyenv: timeout-minutes: 10 name: "python3.9 via pyenv" runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Install pyenv" run: | # Install pyenv curl https://pyenv.run | bash # Set up environment variables for current step export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" # Install Python 3.9 pyenv install 3.9 pyenv global 3.9 # Make environment variables persist across steps echo "PYENV_ROOT=$HOME/.pyenv" >> $GITHUB_ENV echo "$HOME/.pyenv/bin" >> $GITHUB_PATH echo "$HOME/.pyenv/shims" >> $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: "Print Python path" run: echo $(which python3.9) - name: "Validate global Python install" run: python3.9 scripts/check_system_python.py --uv ./uv system-test-linux-313: timeout-minutes: 10 name: "python3.13 via setup-python" runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: 3.13 allow-prereleases: true - 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: "Print Python path" run: echo $(which python3.13) - name: "Validate global Python install" run: python3.13 scripts/check_system_python.py --uv ./uv system-test-conda: timeout-minutes: 10 name: "conda${{ matrix.python-version }} on ${{ matrix.os }} ${{ matrix.arch }}" runs-on: ${{ matrix.runner }} strategy: fail-fast: false matrix: os: ["linux", "windows", "macos"] python-version: ["3.8", "3.11"] include: - { os: "linux", target: "linux-libc", runner: "ubuntu-latest", arch: "x86-64", } - { os: "windows", target: "windows-x86_64", runner: "windows-latest", arch: "x86-64", } - { os: "macos", target: "macos-aarch64", runner: "macos-14", arch: "aarch64", } steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167 # v3.3.0 with: miniconda-version: "latest" activate-environment: uv python-version: ${{ matrix.python-version }} - name: Conda info shell: bash -el {0} run: conda info - name: Conda list shell: pwsh run: conda list - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-${{ matrix.target }}-${{ inputs.sha }} - name: "Prepare binary" if: ${{ matrix.os != 'windows' }} run: chmod +x ./uv - name: "Print Python path" shell: bash -el {0} run: echo $(which python) - name: "Validate global Python install" shell: bash -el {0} run: python ./scripts/check_system_python.py --uv ./uv system-test-amazonlinux: timeout-minutes: 10 name: "python on amazonlinux" runs-on: ubuntu-latest container: amazonlinux:2023 steps: - name: "Install base requirements" run: | # Needed for `actions/checkout` yum install tar gzip which -y - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Install Python" run: yum install python3 python3-pip -y - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-linux-musl-${{ inputs.sha }} - name: "Prepare binary" run: chmod +x ./uv - name: "Print Python path" run: echo $(which python3) - name: Install build tools run: yum install -y gcc - name: "Validate global Python install" run: python3 scripts/check_system_python.py --uv ./uv system-test-windows-embedded-python-310: timeout-minutes: 10 name: "embedded python3.10 on windows x86-64" runs-on: windows-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: "Download binary" uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: uv-windows-x86_64-${{ inputs.sha }} # Download embedded Python. - name: "Download embedded Python" run: curl -LsSf https://www.python.org/ftp/python/3.11.8/python-3.11.8-embed-amd64.zip -o python-3.11.8-embed-amd64.zip - name: "Unzip embedded Python" run: 7z x python-3.11.8-embed-amd64.zip -oembedded-python - name: "Show embedded Python contents" run: ls embedded-python - name: "Set PATH" run: echo "${{ github.workspace }}\embedded-python" >> $env:GITHUB_PATH - name: "Print Python path" run: echo $(which python) - name: "Validate embedded Python install" run: python ./scripts/check_embedded_python.py --uv ./uv.exe