Skip to content

Commit 426ec5a

Browse files
committed
Merge remote-tracking branch 'origin/main' into ajost/host-launch
2 parents e81a9ab + 94625c1 commit 426ec5a

6 files changed

Lines changed: 116 additions & 25 deletions

File tree

‎.github/workflows/test-wheel-linux.yml‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,22 @@ jobs:
146146
dependencies: "jq wget libgl1 libegl1 g++ util-linux yq"
147147
dependent_exes: "jq wget yq"
148148

149+
- name: Checkout driver install scripts (workflow revision)
150+
if: ${{ matrix.DRIVER != 'latest' && matrix.DRIVER != 'earliest' }}
151+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
152+
with:
153+
ref: ${{ github.sha }}
154+
path: .driver-tools
155+
sparse-checkout: ci/tools
156+
persist-credentials: false
157+
149158
- name: Install GPU driver
150159
if: ${{ matrix.DRIVER != 'latest' && matrix.DRIVER != 'earliest' }}
151160
env:
152161
DRIVER: ${{ matrix.DRIVER }}
162+
DRIVER_SHA256: ${{ matrix.DRIVER_SHA256 }}
153163
GPU_TYPE: ${{ matrix.GPU }}
154-
run: ./ci/tools/install_gpu_driver.sh
164+
run: ./.driver-tools/ci/tools/install_gpu_driver.sh
155165

156166
- name: Ensure GPU is working
157167
run: nvidia-smi

‎.github/workflows/test-wheel-windows.yml‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,23 @@ jobs:
119119
with:
120120
enable-apt: true
121121

122+
- name: Checkout driver install scripts (workflow revision)
123+
if: ${{ matrix.DRIVER != 'latest' && matrix.DRIVER != 'earliest' }}
124+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
125+
with:
126+
ref: ${{ github.sha }}
127+
path: .driver-tools
128+
sparse-checkout: ci/tools
129+
persist-credentials: false
130+
122131
- name: Install GPU driver
123132
if: ${{ matrix.DRIVER != 'latest' && matrix.DRIVER != 'earliest' }}
124133
env:
125134
DRIVER: ${{ matrix.DRIVER }}
135+
DRIVER_SHA256: ${{ matrix.DRIVER_SHA256 }}
126136
GPU_TYPE: ${{ matrix.GPU }}
127137
run: |
128-
ci/tools/install_gpu_driver.ps1
138+
.driver-tools/ci/tools/install_gpu_driver.ps1
129139
130140
- name: Configure driver mode
131141
env:

‎ci/test-matrix.yml‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,16 @@
2020
# - install that version via ci/tools/install_gpu_driver.sh (Linux)
2121
# or ci/tools/install_gpu_driver.ps1 (Windows) at the start of the
2222
# job. The matrix row is routed to the 'latest' runner image (the
23-
# install scripts swap the driver themselves).
23+
# install scripts swap the driver themselves). A version-string
24+
# row must also set DRIVER_SHA256: the SHA-256 of the exact
25+
# installer the script downloads (see the URL construction in
26+
# install_gpu_driver.sh / .ps1; Windows data-center and desktop
27+
# installers differ). Whoever changes DRIVER owns this value:
28+
# compute it on a machine with an up-to-date trust store, e.g.
29+
# `curl -fsSL <installer-url> | sha256sum`, and state in the PR
30+
# how it was obtained; reviewers should recompute it. Treat a
31+
# CI hash mismatch as possible tampering -- never copy the
32+
# "got" value from a job log into this file.
2433
# - DRIVER: 'earliest' does not work with CUDA 12.9.1
2534
# - DRIVER: a custom version is not supported with FLAVOR=wsl on Linux.
2635
# - ENV: optional map of extra environment variables to inject into the test
@@ -50,10 +59,10 @@ linux:
5059
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.4.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest' }
5160
- { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '12.9.1', LOCAL_CTK: '0', GPU: 'v100', GPU_COUNT: '1', DRIVER: 'latest' }
5261
- { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '13.0.2', LOCAL_CTK: '1', GPU: 'rtxpro6000', GPU_COUNT: '1', DRIVER: 'latest' }
53-
- { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '13.4.2', LOCAL_CTK: '1', GPU: 'rtxpro6000', GPU_COUNT: '1', DRIVER: '610.43.02' }
62+
- { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '13.4.2', LOCAL_CTK: '1', GPU: 'rtxpro6000', GPU_COUNT: '1', DRIVER: '610.43.02', DRIVER_SHA256: '3034a054bb4cdf7752ff8dc272564cb105513804bff53538945901b16ca77463' }
5463
- { ARCH: 'amd64', PY_VER: '3.14', CUDA_VER: '12.9.1', LOCAL_CTK: '0', GPU: 't4', GPU_COUNT: '1', DRIVER: 'latest' }
5564
- { ARCH: 'amd64', PY_VER: '3.14', CUDA_VER: '13.0.2', LOCAL_CTK: '1', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest' }
56-
- { ARCH: 'amd64', PY_VER: '3.14', CUDA_VER: '13.4.2', LOCAL_CTK: '1', GPU: 'l4', GPU_COUNT: '1', DRIVER: '610.43.02' }
65+
- { ARCH: 'amd64', PY_VER: '3.14', CUDA_VER: '13.4.2', LOCAL_CTK: '1', GPU: 'l4', GPU_COUNT: '1', DRIVER: '610.43.02', DRIVER_SHA256: '3034a054bb4cdf7752ff8dc272564cb105513804bff53538945901b16ca77463' }
5766
- { ARCH: 'amd64', PY_VER: '3.14t', CUDA_VER: '12.9.1', LOCAL_CTK: '1', GPU: 't4', GPU_COUNT: '1', DRIVER: 'latest' }
5867
- { ARCH: 'amd64', PY_VER: '3.14t', CUDA_VER: '13.0.2', LOCAL_CTK: '1', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest' }
5968
- { ARCH: 'amd64', PY_VER: '3.14t', CUDA_VER: '13.4.2', LOCAL_CTK: '1', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest' }
@@ -101,7 +110,7 @@ linux:
101110
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '13.0.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.9.1', TORCH_CUDA: 'cu130' } }
102111
# nightly-numba-cuda
103112
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '12.9.1', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-numba-cuda' } }
104-
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.4.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: '580.65.06', ENV: { MODE: 'nightly-numba-cuda' } }
113+
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.4.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: '580.65.06', DRIVER_SHA256: '04b10867af585e765cfbfdcf39ed5f4bd112375bebab0172eaa187c6aa5024ff', ENV: { MODE: 'nightly-numba-cuda' } }
105114
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '12.9.1', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-numba-cuda' } }
106115
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '13.4.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-numba-cuda' } }
107116
# nightly-numba-cuda-mlir (MLIR backend, linux-64 only)
@@ -150,7 +159,7 @@ windows:
150159
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.0.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.9.1', TORCH_CUDA: 'cu130' } }
151160
# nightly-numba-cuda
152161
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '12.9.1', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-numba-cuda' } }
153-
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.4.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: '596.36', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-numba-cuda' } }
162+
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.4.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: '596.36', DRIVER_SHA256: '99182c2fdf3f23c503c74608945d84be99f036b5ec969f2945062069a15acd2e', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-numba-cuda' } }
154163
# nightly-numba-cuda-mlir (MLIR backend, win-64)
155164
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '12.9.1', LOCAL_CTK: '0', GPU: 'rtxpro6000', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'MCDM', ENV: { MODE: 'nightly-numba-cuda-mlir' } }
156165
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.4.2', LOCAL_CTK: '0', GPU: 'rtxpro6000', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'MCDM', ENV: { MODE: 'nightly-numba-cuda-mlir' } }

‎ci/tools/install_gpu_driver.ps1‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
# right driver).
1111
#
1212
# Inputs (env):
13-
# DRIVER Driver version, e.g. "610.47". Must NOT be 'latest' or
14-
# 'earliest' -- those are runner-pre-installed and the
15-
# workflow is expected to skip this script for them.
16-
# GPU_TYPE Lower-case GPU label from the matrix (e.g. "l4", "rtx4090").
17-
# Selects the data-center vs desktop installer variant.
13+
# DRIVER Driver version, e.g. "610.47". Must NOT be 'latest' or
14+
# 'earliest' -- those are runner-pre-installed and the
15+
# workflow is expected to skip this script for them.
16+
# DRIVER_SHA256 Expected SHA-256 hex digest of the downloaded driver
17+
# installer.
18+
# GPU_TYPE Lower-case GPU label from the matrix (e.g. "l4", "rtx4090").
19+
# Selects the data-center vs desktop installer variant.
1820

1921
# Install the driver
2022
function Install-Driver {
@@ -26,6 +28,11 @@ function Install-Driver {
2628
exit 1
2729
}
2830

31+
if (-not $env:DRIVER_SHA256) {
32+
Write-Error "DRIVER_SHA256 env var is required to verify the driver installer."
33+
exit 1
34+
}
35+
2936
# Get GPU type from environment variable
3037
$gpu_type = $env:GPU_TYPE
3138

@@ -68,6 +75,13 @@ function Install-Driver {
6875
$ProgressPreference = $ProgressPreference_tmp
6976
Write-Output 'Download complete!'
7077

78+
$actual_sha256 = (Get-FileHash -Algorithm SHA256 -Path $filepath).Hash
79+
if ($actual_sha256 -ne $env:DRIVER_SHA256) {
80+
Write-Error "SHA256 mismatch for ${filepath}: expected $($env:DRIVER_SHA256), got $actual_sha256"
81+
exit 1
82+
}
83+
Write-Output "SHA256 verified: $actual_sha256"
84+
7185
# Install the file with the specified path from earlier
7286
Write-Output 'Running the driver installer...'
7387
Start-Process -FilePath $filepath -ArgumentList $install_args -Wait

‎ci/tools/install_gpu_driver.sh‎

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
# bind-mount refresh) and may cause issues.
1414
#
1515
# Inputs (env):
16-
# DRIVER Driver version, e.g. "580.65.06". Must NOT be 'latest' or
17-
# 'earliest' -- those are runner-pre-installed and the
18-
# workflow is expected to skip this script for them.
19-
# GPU_TYPE Lower-case GPU label from the matrix (e.g. "v100", "l4",
20-
# "h100"). Used only to pick the kernel module flavor
21-
# (Volta needs the proprietary/legacy module; everything
22-
# newer can use the open module).
16+
# DRIVER Driver version, e.g. "580.65.06". Must NOT be 'latest' or
17+
# 'earliest' -- those are runner-pre-installed and the
18+
# workflow is expected to skip this script for them.
19+
# DRIVER_SHA256 Expected lowercase SHA-256 hex digest of the downloaded
20+
# driver installer.
21+
# GPU_TYPE Lower-case GPU label from the matrix (e.g. "v100", "l4",
22+
# "h100"). Used only to pick the kernel module flavor
23+
# (Volta needs the proprietary/legacy module; everything
24+
# newer can use the open module).
2325
#
2426
# Arch is detected from `uname -m`.
2527
#
@@ -32,6 +34,7 @@
3234
set -euo pipefail
3335

3436
: "${DRIVER:?DRIVER env var is required (e.g. 580.65.06)}"
37+
: "${DRIVER_SHA256:?DRIVER_SHA256 env var is required (64-char sha256 of the installer)}"
3538
: "${GPU_TYPE:?GPU_TYPE env var is required (e.g. l4)}"
3639

3740
case "$DRIVER" in
@@ -70,7 +73,7 @@ URL="https://us.download.nvidia.com/XFree86/${ARCH_DIR}/${VERSION}/NVIDIA-Linux-
7073

7174
# Re-elevate to root if needed (sudo is preinstalled on the runner image).
7275
if [ "$(id -u)" != 0 ]; then
73-
exec sudo -E DRIVER="$DRIVER" GPU_TYPE="$GPU_TYPE" "$0" "$@"
76+
exec sudo -E DRIVER="$DRIVER" DRIVER_SHA256="$DRIVER_SHA256" GPU_TYPE="$GPU_TYPE" "$0" "$@"
7477
fi
7578

7679
echo "install_gpu_driver.sh is ALPHA -- it performs live modifications to the host driver stack and may cause issues" >&2
@@ -89,6 +92,15 @@ in_container() {
8992
host_install() {
9093
apt-get -y install build-essential dkms "linux-headers-$(uname -r)" psmisc kmod
9194

95+
# Download and verify the installer before tearing down the existing
96+
# host driver so a download failure or SHA-256 mismatch leaves the
97+
# runner's current driver intact.
98+
local d
99+
d=$(mktemp -d)
100+
( cd "$d" \
101+
&& wget -q -O installer.run "$URL" \
102+
&& echo "${DRIVER_SHA256} installer.run" | sha256sum --check --strict - )
103+
92104
systemctl stop nvidia-persistenced dcgm-exporter || true
93105
# if-test instead of `fuser ... || true` so a kill failure surfaces
94106
# (fuser exits 1 when nothing holds the device, which is the happy path).
@@ -107,10 +119,7 @@ host_install() {
107119
| awk -v re="$KEEP_RE" '$0 !~ re' \
108120
| xargs -r apt-get -y remove --purge || true
109121

110-
local d
111-
d=$(mktemp -d)
112122
( cd "$d" \
113-
&& wget -q -O installer.run "$URL" \
114123
&& sh installer.run --silent --dkms --no-questions \
115124
--accept-license --ui=none --no-cc-version-check --kernel-module-type="$KMT" )
116125
modprobe nvidia nvidia_uvm nvidia_modeset
@@ -193,9 +202,10 @@ if [ -z "${_NVDRV_NSENTERED:-}" ] && in_container; then
193202
# ours lives in the GH workspace mount (container-only), so we pipe the
194203
# script body in via stdin instead -- the `< "$0"` fd is opened before
195204
# nsenter and stays valid across the namespace switch. Env vars (DRIVER,
196-
# GPU_TYPE, _NVDRV_NSENTERED) are inherited by the host-side bash.
205+
# DRIVER_SHA256, GPU_TYPE, _NVDRV_NSENTERED) are inherited by the
206+
# host-side bash.
197207
_NVDRV_NSENTERED=1 nsenter -t 1 -m -p -n -i -u -- bash -s < "$0" \
198-
|| { echo "::error::container needs 'options: --privileged --pid=host'" >&2; exit 1; }
208+
|| { echo "::error::host-side driver install failed (see output above; also check container has 'options: --privileged --pid=host')" >&2; exit 1; }
199209
refresh_container_libs
200210

201211
# Re-bind /run/nvidia-persistenced from the host. The container's
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
"""Ensure custom DRIVER entries in ci/test-matrix.yml carry valid, consistent SHA-256 hashes."""
5+
6+
from __future__ import annotations
7+
8+
import re
9+
from pathlib import Path
10+
11+
import pytest
12+
import yaml
13+
14+
MATRIX_PATH = Path(__file__).resolve().parents[2] / "test-matrix.yml"
15+
SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
16+
PREINSTALLED_DRIVERS = {"latest", "earliest"}
17+
18+
19+
@pytest.mark.agent_authored(model="gemini-4-argon")
20+
def test_test_matrix_custom_drivers_have_valid_consistent_sha256() -> None:
21+
matrix = yaml.safe_load(MATRIX_PATH.read_text(encoding="utf-8"))
22+
seen_hashes: dict[tuple[str, str, str, str], str] = {}
23+
custom_rows = 0
24+
25+
for platform in ("linux", "windows"):
26+
for section_name, rows in matrix[platform].items():
27+
for index, row in enumerate(rows):
28+
driver = row["DRIVER"]
29+
if driver in PREINSTALLED_DRIVERS:
30+
assert "DRIVER_SHA256" not in row, f"{platform}.{section_name}[{index}] sets DRIVER_SHA256"
31+
continue
32+
custom_rows += 1
33+
sha256 = row.get("DRIVER_SHA256", "")
34+
assert SHA256_RE.fullmatch(sha256), f"{platform}.{section_name}[{index}] has invalid DRIVER_SHA256"
35+
key = (platform, str(row["ARCH"]), "" if platform == "linux" else str(row["GPU"]), str(driver))
36+
assert seen_hashes.setdefault(key, sha256) == sha256, f"Conflicting DRIVER_SHA256 for {key}"
37+
38+
assert custom_rows > 0

0 commit comments

Comments
 (0)