Files
punktfunk/scripts/ci/provision-windows-wdk.ps1
enricobuehler 0bfc7fe913
apple / swift (pull_request) Successful in 1m43s
apple / distribute (pull_request) Skipped
apple / screenshots (pull_request) Skipped
windows-drivers / probe-and-proto (pull_request) Successful in 30s
windows-drivers / driver-build (pull_request) Successful in 1m49s
ci / docs-site (pull_request) Successful in 1m21s
ci / bun-nix (pull_request) Successful in 31s
ci / web (pull_request) Successful in 3m50s
ci / rust-arm64 (pull_request) Successful in 8m32s
android / android (pull_request) Successful in 7m22s
ci / rust (pull_request) Successful in 14m7s
windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (pull_request) Successful in 3m6s
windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (pull_request) Successful in 8m7s
ci: fold release.yml into apple.yml and the two Windows client workflows into one
Two merges, both of which exist to express an ordering Gitea cannot express across
files, and both of which delete a duplicated build.

release.yml -> apple.yml (as the `distribute` job)
  The name described neither what it did (Apple only — every other platform's release
  is its own packaging workflow attaching to the same Gitea release on a v* tag, with
  announce.yml as the manual "go") nor anything a reader would guess. The name was the
  smaller problem. Gitea has no cross-workflow `needs`, so nothing sequenced it against
  apple.yml's tests: a canary main push uploaded iOS, macOS and tvOS builds to
  TestFlight even when `swift test` had just failed on that same commit. It is now
  `needs: swift`, which is only expressible in one file.

  The two files' paths: filters had also drifted — apple.yml watched crates/**,
  release.yml watched crates/punktfunk-core/**. The merged filter takes the NARROW one,
  because that is the correct one: everything on this runner is built from
  punktfunk-core via build-xcframework.sh, and punktfunk-core's only path dependency is
  its own vendored fec-rs. That is checkable in one command, and the header says so, and
  says to widen it if that ever stops being true. Net effect on the shared mac mini:
  pushes that touch host-side crates no longer build or upload anything Apple.

windows.yml + windows-msix.yml -> windows-client.yml
  The pair built the same three crates FOUR times per client push on ONE runner: debug
  x64 + arm64 for lint/test, release x64 + arm64 for packaging. windows-host.yml already
  records why a second (debug) dep tree on this machine is a liability rather than a
  cost — it re-runs openh264-sys2's vendored C++ through cc-rs's cl.exe fan-out and tips
  the runner into C1069, which is disk exhaustion wearing a compiler error's clothes. So
  there is one release build per arch now and clippy/fmt/test run against it, exactly as
  windows-host.yml does. The paths list went from three copies to one; PRs get the
  build/lint/test signal and stop before packaging.

The rename is safe, and this is worth recording because the GitHub instinct is wrong
here: `github.run_number` is REPO-WIDE in Gitea, not per-workflow — consecutive runs of
DIFFERENT workflows get consecutive numbers (verified against the API: android 13226,
apple 13227, arch 13228, ci 13229, deb 13230). The canary MSIX version <minor>.<run>.0
and Apple's CURRENT_PROJECT_VERSION therefore keep climbing across a rename. On GitHub
the same rename would reset both to 1, sorting every new canary below the published ones
and getting the TestFlight uploads rejected outright.

25 workflows, down from 27, and every `name:` now matches its filename. Cross-references
in windows-host.yml, windows-drivers.yml, android.yml, flatpak.yml, sbom.yml, the
provisioning scripts, gitea-release.sh and clients/windows/packaging/README.md updated.
2026-08-13 12:10:36 +02:00

92 lines
5.5 KiB
PowerShell

# Provision the Windows Driver Kit (WDK) + cargo-wdk on the self-hosted windows-amd64 runner, so the
# all-Rust UMDF drivers (pf-vdisplay + the gamepad drivers, unified on microsoft/windows-drivers-rs)
# can build there. See design/windows-host-rewrite.md (M0).
#
# The runner already has the base Windows SDK 10.0.26100 (um/ headers) + MSVC + LLVM + Rust, but NOT the
# WDK — no km/ + wdf/ + um/iddcx headers, no inf2cat/stampinf/devgen. wdk-sys's bindgen needs those.
# Idempotent: skips the WDK install if the km/wdf headers are already present, and cargo-wdk if already
# installed. Safe to run repeatedly. Runs non-interactively (/q /norestart) — never auto-reboots.
#
# Invoked by scripts/ci/ensure-windows-toolchain.ps1, the shared self-provision step every Windows
# CI workflow runs at job start (windows-drivers.yml, windows-client.yml,
# windows-host.yml), on top of the generic runner unom/infra provisions (windows-runner/) and
# provision-windows-punktfunk-extras.ps1's FFmpeg/Inno Setup/ARM64-target layer. Run as the
# runner's account (SYSTEM) with admin rights.
[CmdletBinding()]
param(
# WDK 26100 standalone bootstrapper. Source: https://learn.microsoft.com/windows-hardware/drivers/download-the-wdk
# (bump this when the runner's base SDK version changes; must match an installed Windows SDK version).
[string]$WdkSetupUrl = 'https://download.microsoft.com/download/41fb59c2-1723-45f9-a270-96b73ad58233/KIT_BUNDLE_WDK_MEDIACREATION/wdksetup.exe',
[string]$SdkVersion = '10.0.26100.0'
)
$ErrorActionPreference = 'Stop'
function info($m) { Write-Host "[provision-wdk] $m" }
$kitRoot = 'C:\Program Files (x86)\Windows Kits\10'
$iddcxInc = Join-Path $kitRoot "Include\$SdkVersion\um\iddcx" # iddcx ships ONLY with the WDK -> reliable "installed" signal
$kmDir = Join-Path $kitRoot "Include\$SdkVersion\km" # kernel-mode SDK headers (ntddk/wdm) — also WDK-only
# ---- 1. WDK ---- (iddcx presence is the reliable "WDK installed" signal)
if (Test-Path $iddcxInc) {
info "WDK already present (iddcx headers at $iddcxInc) — skipping install."
} else {
$tmp = Join-Path $env:TEMP 'wdksetup.exe'
info "Downloading WDK bootstrapper -> $tmp"
Invoke-WebRequest -Uri $WdkSetupUrl -OutFile $tmp -UseBasicParsing
info ("downloaded {0:N1} MB" -f ((Get-Item $tmp).Length / 1MB))
info "Installing WDK silently (/q /norestart) — this can take several minutes..."
$p = Start-Process -FilePath $tmp -ArgumentList '/q','/norestart' -Wait -PassThru
info "wdksetup exit code = $($p.ExitCode)"
if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) {
# 3010 = success, reboot required (acceptable for headers/libs/tools; no reboot done).
throw "WDK install failed (exit $($p.ExitCode))"
}
}
# ---- 2. cargo-wdk (the windows-drivers-rs build+package tool: cargo build -> stampinf/inf2cat/signtool) ----
$haveCargoWdk = $false
try { & cargo wdk --version *> $null; if ($LASTEXITCODE -eq 0) { $haveCargoWdk = $true } } catch {}
if ($haveCargoWdk) {
info "cargo-wdk already installed."
} else {
info "Installing cargo-wdk (cargo install --locked cargo-wdk)..."
& cargo install --locked cargo-wdk
if ($LASTEXITCODE -ne 0) { throw "cargo install cargo-wdk failed ($LASTEXITCODE)" }
}
# ---- 2b. (LLVM is NOT pinned) ----
# The runner's default clang (C:\Program Files\LLVM) builds the driver workspace clean now that the
# vendored bindgen is 0.72 (the shipping pack proves it). LLVM 21.1.2 was briefly installed here to dodge
# a bindgen-0.71 layout-test overflow on clang 22; the 0.72 bump retired that pin. No LLVM install needed.
# ---- 3. Verify (enumerate the REAL layout; fail only on build-essential absences) ----
Write-Host ""
Write-Host "===== post-provision verification ====="
function found($label, $val) { Write-Host ("{0,-26} {1}" -f $label, $val) }
# WDF UMDF headers live under Include\wdf\umdf\<ver>\ (NOT under the SDK-version dir).
$umdfRoot = Join-Path $kitRoot 'Include\wdf\umdf'
$umdfVers = (Get-ChildItem $umdfRoot -Directory -ErrorAction SilentlyContinue | ForEach-Object { $_.Name }) -join ','
$umdfHdr = Get-ChildItem -Path $umdfRoot -Filter 'wdf.h' -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName
$iddcxVers = (Get-ChildItem $iddcxInc -Directory -ErrorAction SilentlyContinue | ForEach-Object { $_.Name }) -join ','
found 'Include\wdf\umdf vers' "[$umdfVers]"
found 'wdf.h' ($(if ($umdfHdr) { $umdfHdr } else { 'MISSING' }))
found 'km SDK headers' ($(if (Test-Path $kmDir) { $kmDir } else { 'MISSING' }))
found 'um/iddcx versions' "[$iddcxVers]"
foreach ($t in 'inf2cat.exe','stampinf.exe','signtool.exe','makecat.exe','InfVerif.exe') {
$hit = Get-ChildItem -Path $kitRoot -Filter $t -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName
found $t ($(if ($hit) { $hit } else { 'MISSING' }))
}
try { $cw = (& cargo wdk --version 2>&1) -join ' ' } catch { $cw = '' }
found 'cargo-wdk' $cw
$defClang = 'C:\Program Files\LLVM\bin\libclang.dll'
found 'default libclang' ($(if (Test-Path $defClang) { $defClang } else { 'MISSING (clang not on the runner?)' }))
# Block only on the genuinely build-essential pieces (headers + iddcx + cargo-wdk).
# inf2cat arch quirks are non-fatal — cargo-wdk locates the WDK tools itself.
$essential = ($null -ne $umdfHdr) -and (Test-Path $kmDir) -and ($iddcxVers -ne '') -and ($cw -match 'wdk')
if (-not $essential) { throw "provisioning incomplete: need wdf.h + km headers + iddcx + cargo-wdk (see above)" }
info "WDK + cargo-wdk provisioned OK. Driver builds use Version_Number=$SdkVersion + the runner-default clang (bindgen 0.72)."