|
| 1 | +name: Windows Virtual HID Device Test (manual) |
| 2 | + |
| 3 | +# Builds and self-signs a modified vhidmini2 UMDF2 driver, installs it on a |
| 4 | +# hosted runner, then runs the backend-agnostic device-I/O test against that |
| 5 | +# real virtual HID device (winapi backend). It installs a driver, so it is not |
| 6 | +# part of the per-push CI matrix; run it on demand from the Actions tab, or by |
| 7 | +# adding the 'ci-virtual-device' label to a pull request. |
| 8 | +# |
| 9 | +# The work is split across two runners because no single hosted image can do |
| 10 | +# both today: |
| 11 | +# - build-driver runs on windows-2022: the cached WDK (10.0.26100.6584) |
| 12 | +# ships DriverKit build tasks only up to MSBuild 17 (VS2022), which the |
| 13 | +# windows-2025* images no longer carry (VS2026 / MSBuild 18 -> MSB4062). |
| 14 | +# - win-vhid runs on windows-latest (Server 2025): the driver package's INF |
| 15 | +# depends on MsHidUmdf.inf semantics introduced in build 22000, so it does |
| 16 | +# not install on Server 2022 (build 20348). |
| 17 | +# Revisit once a WDK with 18.0 build tasks is cached here - then both jobs can |
| 18 | +# run on windows-latest again (and could be merged back into one). |
| 19 | + |
| 20 | +on: |
| 21 | + workflow_dispatch: |
| 22 | + # Also runs automatically on a pull request that carries the |
| 23 | + # 'ci-virtual-device' label (the build-driver job is gated on that label; |
| 24 | + # win-vhid follows via needs:). |
| 25 | + pull_request: |
| 26 | + types: [opened, reopened, labeled, synchronize] |
| 27 | + |
| 28 | +jobs: |
| 29 | + build-driver: |
| 30 | + # workflow_dispatch always runs; on a PR, only when the label is present. |
| 31 | + if: github.event_name == 'workflow_dispatch' || contains(github.event.pull_request.labels.*.name, 'ci-virtual-device') |
| 32 | + runs-on: windows-2022 |
| 33 | + steps: |
| 34 | + - uses: actions/checkout@v4 |
| 35 | + |
| 36 | + # Sets up the MSVC developer environment (cl/msbuild on PATH) by locating |
| 37 | + # the installed Visual Studio (no hard-coded path or edition). |
| 38 | + - name: Set up MSVC developer environment |
| 39 | + uses: TheMrMilchmann/setup-msvc-dev@v4 |
| 40 | + with: |
| 41 | + arch: x64 |
| 42 | + |
| 43 | + # The hosted runner ships the Windows SDK but not the WDK (no UMDF headers), |
| 44 | + # so the WDK must be obtained. Cache a self-contained offline installer |
| 45 | + # layout (the components, not just the bootstrapper) so it is downloaded only |
| 46 | + # once; later runs restore it from the cache and install offline. |
| 47 | + - name: Cache the WDK installer layout |
| 48 | + id: wdk-cache |
| 49 | + uses: actions/cache@v4 |
| 50 | + with: |
| 51 | + path: wdk-layout |
| 52 | + key: wdk-layout-26100.6584 |
| 53 | + |
| 54 | + - name: Download WDK installer layout (cache miss only) |
| 55 | + if: steps.wdk-cache.outputs.cache-hit != 'true' |
| 56 | + shell: pwsh |
| 57 | + run: | |
| 58 | + Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/?linkid=2335869" -OutFile "$env:RUNNER_TEMP\wdksetup.exe" |
| 59 | + # /layout downloads a complete offline copy into wdk-layout (cached). |
| 60 | + Start-Process -FilePath "$env:RUNNER_TEMP\wdksetup.exe" -ArgumentList '/layout', "$PWD\wdk-layout", '/quiet', '/ceip', 'off' -Wait |
| 61 | +
|
| 62 | + - name: Build vhidmini2 (UMDF2) |
| 63 | + shell: pwsh |
| 64 | + run: | |
| 65 | + $proj = "src\tests\windows\driver\VhidminiUm.vcxproj" |
| 66 | + $inc = "C:\Program Files (x86)\Windows Kits\10\Include" |
| 67 | + # Use a preinstalled WDK if a future image ships one (kit with UMDF |
| 68 | + # headers); otherwise install from the cached offline layout. |
| 69 | + $ver = Get-ChildItem $inc -Directory -ErrorAction SilentlyContinue | |
| 70 | + Where-Object { Test-Path (Join-Path $_.FullName 'wdf\umdf') } | |
| 71 | + Sort-Object Name -Descending | Select-Object -First 1 -ExpandProperty Name |
| 72 | + if ($ver) { |
| 73 | + Write-Host "Using preinstalled WDK ($ver)." |
| 74 | + } else { |
| 75 | + Write-Host "Installing WDK from the cached offline layout ..." |
| 76 | + Start-Process -FilePath "wdk-layout\wdksetup.exe" -ArgumentList '/quiet', '/norestart', '/ceip', 'off' -Wait |
| 77 | + $ver = "10.0.26100.0" |
| 78 | + } |
| 79 | + # msbuild comes from the MSVC developer environment set up above. |
| 80 | + msbuild $proj /p:Configuration=Release /p:Platform=x64 /p:WindowsTargetPlatformVersion=$ver /v:minimal |
| 81 | + if ($LASTEXITCODE -ne 0) { throw "vhidmini2 build failed (exit $LASTEXITCODE)." } |
| 82 | +
|
| 83 | + - name: Stage driver package (+ devcon) for the test job |
| 84 | + shell: pwsh |
| 85 | + run: | |
| 86 | + $out = "src/tests/windows/driver/x64/Release" |
| 87 | + # devcon.exe ships with the WDK just installed; the test runner has no |
| 88 | + # WDK, so carry the tool along with the driver package. |
| 89 | + $devcon = Get-ChildItem "C:\Program Files (x86)\Windows Kits\10" -Recurse -Filter devcon.exe -ErrorAction SilentlyContinue | |
| 90 | + Where-Object { $_.FullName -match '\\x64\\' } | Select-Object -First 1 -ExpandProperty FullName |
| 91 | + if (-not $devcon) { throw "devcon.exe not found in the installed WDK." } |
| 92 | + Copy-Item $devcon $out\ |
| 93 | + Get-ChildItem -Recurse $out | Select-Object FullName |
| 94 | +
|
| 95 | + - uses: actions/upload-artifact@v4 |
| 96 | + with: |
| 97 | + name: vhidmini-driver |
| 98 | + path: src/tests/windows/driver/x64/Release/ |
| 99 | + if-no-files-found: error |
| 100 | + |
| 101 | + win-vhid: |
| 102 | + needs: build-driver |
| 103 | + runs-on: windows-latest |
| 104 | + steps: |
| 105 | + - uses: actions/checkout@v4 |
| 106 | + |
| 107 | + - uses: actions/download-artifact@v4 |
| 108 | + with: |
| 109 | + name: vhidmini-driver |
| 110 | + path: driver-pkg |
| 111 | + |
| 112 | + - name: Trust the driver's test certificate |
| 113 | + shell: pwsh |
| 114 | + run: | |
| 115 | + $cer = "driver-pkg/VhidminiUm.cer" |
| 116 | + Import-Certificate -FilePath $cer -CertStoreLocation Cert:\LocalMachine\Root | Out-Null |
| 117 | + Import-Certificate -FilePath $cer -CertStoreLocation Cert:\LocalMachine\TrustedPublisher | Out-Null |
| 118 | + Write-Host "Imported test cert into Root and TrustedPublisher." |
| 119 | +
|
| 120 | + - name: Install virtual HID device (devcon, root-enumerated) |
| 121 | + shell: pwsh |
| 122 | + run: | |
| 123 | + $devcon = (Resolve-Path "driver-pkg/devcon.exe").Path |
| 124 | + $inf = (Resolve-Path "driver-pkg/VhidminiUm/VhidminiUm.inf").Path |
| 125 | + Write-Host "devcon: $devcon" |
| 126 | + Write-Host "inf: $inf" |
| 127 | + & $devcon install $inf "root\VhidminiUm" |
| 128 | + Write-Host "devcon exit: $LASTEXITCODE" |
| 129 | + if ($LASTEXITCODE -ne 0) { throw "devcon install failed (exit $LASTEXITCODE)." } |
| 130 | +
|
| 131 | + - name: HID devices present (diagnostic) |
| 132 | + shell: pwsh |
| 133 | + run: | |
| 134 | + Start-Sleep -Seconds 3 |
| 135 | + Get-PnpDevice -Class HIDClass -ErrorAction SilentlyContinue | |
| 136 | + Select-Object Status, FriendlyName, InstanceId | Format-Table -AutoSize |
| 137 | +
|
| 138 | + - name: Build HIDAPI + tests |
| 139 | + shell: pwsh |
| 140 | + run: | |
| 141 | + cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DHIDAPI_WITH_TESTS=ON |
| 142 | + cmake --build build --config Release |
| 143 | +
|
| 144 | + - name: Run device-I/O test against the virtual device |
| 145 | + shell: pwsh |
| 146 | + working-directory: build |
| 147 | + run: | |
| 148 | + ctest -C Release -R DeviceIO_winapi --output-on-failure |
| 149 | +
|
| 150 | + - name: Cleanup virtual device |
| 151 | + if: always() |
| 152 | + shell: pwsh |
| 153 | + run: | |
| 154 | + $devcon = "driver-pkg/devcon.exe" |
| 155 | + if (Test-Path $devcon) { & $devcon remove "root\VhidminiUm" 2>$null } |
| 156 | + Write-Host "cleanup done" |
0 commit comments