|
| 1 | +name: Test Windows Installer |
| 2 | + |
| 3 | +# On-demand only. Nothing here runs on push or pull_request: every run downloads |
| 4 | +# uv (~34 MB) and a managed CPython interpreter (~30 MB) into fresh prefixes, which |
| 5 | +# is far too slow and too costly to attach to every PR. Dispatch it against the |
| 6 | +# branch or PR head you want to test: |
| 7 | +# |
| 8 | +# gh workflow run test-windows-installer.yml --ref <branch> -f arch=x64 |
| 9 | +# |
| 10 | +# The second install is the assertion that matters. Until PR #15 an install.ps1 |
| 11 | +# bug made the "already installed, skip the download" branch unreachable on |
| 12 | +# Windows, so every re-run silently re-downloaded uv. Nothing in CI could catch |
| 13 | +# that, which is why this job exists. |
| 14 | +on: |
| 15 | + workflow_dispatch: |
| 16 | + inputs: |
| 17 | + ref: |
| 18 | + description: 'Branch, tag or SHA to test. Leave empty to test the branch this workflow is dispatched from.' |
| 19 | + required: false |
| 20 | + type: string |
| 21 | + arch: |
| 22 | + description: 'Windows architecture to test. arm64 needs the windows-11-arm runner to be enabled for this repository.' |
| 23 | + required: false |
| 24 | + type: choice |
| 25 | + default: x64 |
| 26 | + options: |
| 27 | + - x64 |
| 28 | + - arm64 |
| 29 | + |
| 30 | +# Least privilege: this job reads the repository and nothing else. |
| 31 | +permissions: |
| 32 | + contents: read |
| 33 | + |
| 34 | +# No actions/cache here on purpose. The 30-second caching rule targets package |
| 35 | +# managers, and caching uv or the interpreter would defeat the point: this job |
| 36 | +# exists to prove a *fresh* install works and that the second run correctly skips. |
| 37 | +jobs: |
| 38 | + install: |
| 39 | + name: Install on Windows ${{ inputs.arch }} under ${{ matrix.shell }} |
| 40 | + # The self-hosted fleet is Alma Linux and Ubuntu only, so there is no Windows |
| 41 | + # runner to use, and this job is nothing but Windows-only behaviour: the arch |
| 42 | + # selection in install.ps1, the .zip release asset, and Windows PowerShell 5.1, |
| 43 | + # which is the shell install.bat invokes. |
| 44 | + # RUNNER-EXCEPTION: no Windows runner exists on the self-hosted fleet (cicd-github-actions 1.3) |
| 45 | + runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-latest' }} |
| 46 | + strategy: |
| 47 | + fail-fast: false |
| 48 | + matrix: |
| 49 | + shell: [powershell, pwsh] |
| 50 | + steps: |
| 51 | + - uses: actions/checkout@v6 |
| 52 | + with: |
| 53 | + ref: ${{ inputs.ref || github.ref }} |
| 54 | + |
| 55 | + - name: Report the interpreter and architecture under test |
| 56 | + shell: ${{ matrix.shell }} |
| 57 | + run: | |
| 58 | + Write-Host "PowerShell : $($PSVersionTable.PSVersion)" |
| 59 | + Write-Host "PSEdition : $($PSVersionTable.PSEdition)" |
| 60 | + Write-Host "PROCESSOR : $env:PROCESSOR_ARCHITECTURE" |
| 61 | +
|
| 62 | + - name: Read the pinned uv version from distro.toml |
| 63 | + shell: ${{ matrix.shell }} |
| 64 | + run: | |
| 65 | + $line = Select-String -Path distro.toml -Pattern '^uv_version\s*=\s*"([^"]+)"' | Select-Object -First 1 |
| 66 | + if ($null -eq $line) { throw "no uv_version line found in distro.toml" } |
| 67 | + $pin = $line.Matches[0].Groups[1].Value |
| 68 | + Write-Host "pinned uv: $pin" |
| 69 | + # Add-Content, not Out-File: Windows PowerShell 5.1 writes a BOM with |
| 70 | + # Out-File -Encoding utf8, and a BOM corrupts the GITHUB_ENV variable name. |
| 71 | + Add-Content -Path $env:GITHUB_ENV -Value "UV_PIN=$pin" |
| 72 | +
|
| 73 | + - name: First install |
| 74 | + shell: ${{ matrix.shell }} |
| 75 | + run: ./install.ps1 -Prefix "$env:RUNNER_TEMP\mp" -Python 3.14 -EnvPrefix MPWINTEST -Isolated |
| 76 | + |
| 77 | + - name: Assert the pinned uv and its uvx twin are installed |
| 78 | + shell: ${{ matrix.shell }} |
| 79 | + run: | |
| 80 | + $uv = "$env:RUNNER_TEMP\mp\uv.exe" |
| 81 | + if (-not (Test-Path $uv)) { throw "uv.exe was not installed" } |
| 82 | + if (-not (Test-Path "$env:RUNNER_TEMP\mp\uvx.exe")) { throw "uvx.exe was not installed" } |
| 83 | + $actual = (& $uv --version 2>$null) -replace '^uv\s+(\S+).*', '$1' |
| 84 | + if ($actual -ne $env:UV_PIN) { throw "uv reports '$actual' but distro.toml pins '$env:UV_PIN'" } |
| 85 | +
|
| 86 | + - name: Second install must skip rather than re-download |
| 87 | + shell: ${{ matrix.shell }} |
| 88 | + run: | |
| 89 | + $out = ./install.ps1 -Prefix "$env:RUNNER_TEMP\mp" -Python 3.14 -EnvPrefix MPWINTEST -Isolated 2>&1 | Out-String |
| 90 | + Write-Host $out |
| 91 | + if ($out -match 'Downloading uv') { throw "the second run re-downloaded uv: the skip branch did not fire" } |
| 92 | + if ($out -notmatch [regex]::Escape($env:UV_PIN)) { throw "the second run never reported the pinned uv version" } |
| 93 | + if ($out -notmatch 'venv already exists') { throw "the second run rebuilt the venv" } |
| 94 | +
|
| 95 | + - name: install.bat fallback path |
| 96 | + shell: cmd |
| 97 | + run: install.bat -Prefix "%RUNNER_TEMP%\mp-bat" -Python 3.14 -EnvPrefix MPWINTESTBAT -Isolated |
| 98 | + |
| 99 | + - name: Assert the install.bat fallback produced a working uv |
| 100 | + shell: ${{ matrix.shell }} |
| 101 | + run: | |
| 102 | + $uv = "$env:RUNNER_TEMP\mp-bat\uv.exe" |
| 103 | + if (-not (Test-Path $uv)) { throw "install.bat did not produce uv.exe" } |
| 104 | + $actual = (& $uv --version 2>$null) -replace '^uv\s+(\S+).*', '$1' |
| 105 | + if ($actual -ne $env:UV_PIN) { throw "install.bat produced uv '$actual' but distro.toml pins '$env:UV_PIN'" } |
0 commit comments