Skip to content

ci: harden fetch_ctk with manifest/archive verification and optional redist-base-url - #3347

Merged
juenglin merged 5 commits into
NVIDIA:mainfrom
juenglin:juenglin/fetch-ctk-harden-and-redist-url
Nov 4, 2026
Merged

juenglin merged 5 commits into
NVIDIA:mainfrom
juenglin:juenglin/fetch-ctk-harden-and-redist-url

Conversation

@juenglin

@juenglin juenglin commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

After this lands, both public and private repositories use identical files for fetch_ctk/action.yml, install_windows_deps/action.yml, ci/tools/fetch_ctk_redistrib.py, and ci/tools/tests/test_fetch_ctk_redistrib.py.

Changes

.github/actions/fetch_ctk/action.yml

  • Add optional redist-base-url input (default: public NVIDIA developer server). The action is now parameterizable for any redistrib-shaped server without changing the action itself.
  • Split the single Install dependencies step into two OS-gated steps: Install Unix dependencies (Linux) and Install Windows dependencies (Windows, via the new install_windows_deps action). This makes the action usable on Windows runners.
  • Download the redistrib manifest once in Set up CTK cache variable and reuse it in Get CUDA components, eliminating a redundant network round-trip.
  • Verify the manifest hash before trusting it (verify-metadata). Public-server manifests are checked against KNOWN_REDISTRIB_SHA256; alternate servers warn only. Per-archive verification is only trustworthy if the JSON carrying those hashes is itself trusted, so this step must come first.
  • Include the first 8 hex digits of the manifest sha256 in the cache key (-m<sha8>). Alternate servers can publish different manifests under the same CUDA version; without this they would restore each other's cached toolkit. For the public server this is a one-time cache miss on the first run with the new key format.
  • Verify each downloaded component archive against the sha256 in the (now trusted) manifest before extracting (component-sha256 + sha256sum --check). The old code extracted without any archive integrity check.

.github/actions/install_windows_deps/action.yml (new)

  • Composite action that installs a pinned portable Git for Windows bundle (ARM64 or x64) when curl, unzip, tar, sha256sum, or cygpath are not already on PATH. Checks the archive hash before extracting. Caches the result under RUNNER_TOOL_CACHE.

ci/tools/fetch_ctk_redistrib.py

  • Add KNOWN_REDISTRIB_SHA256: pinned public manifest hashes for 12.6.3, 12.9.1, 13.0.2, and 13.4.2. Extend as new CUDA versions enter the matrix (the regeneration command is in the dict comment).
  • Add get_component_subdir_info, get_component_sha256, compute_file_sha256, verify_metadata_sha256.
  • Add component-sha256 and verify-metadata CLI subcommands. verify-metadata accepts --metadata-source {public,custom}; custom sources only warn and never fail closed.
  • Remove --metadata-url from filter-components and component-relative-path. Callers must download the manifest and pass --metadata-path. This removes the urllib dependency and prevents the action from downloading the manifest twice.
  • Simplify load_metadata to read from a local path only.

ci/tools/tests/test_fetch_ctk_redistrib.py (new)

  • 13 agent-authored unit tests covering get_component_sha256 (hash lookup, alias resolution, missing field, unavailable platform), verify_metadata_sha256 (match, mismatch, unpinned warning, custom source), and the component-sha256 and verify-metadata CLI subcommands.
  • Run with python -m pytest ci/tools/tests/test_fetch_ctk_redistrib.py.

Compatibility

Removing --metadata-url from filter-components and component-relative-path is a breaking change for any direct caller using the URL form. Within this repository, only fetch_ctk/action.yml calls the script, and it is updated here. The URL form is not part of any public API.

The new -m<sha8> suffix in the cache key causes a one-time cache miss for all existing public-server cached toolkits on the first run. Subsequent runs hit the new key.

Testing

All 13 new tests pass locally (python -m pytest ci/tools/tests/test_fetch_ctk_redistrib.py -v). The action changes will be exercised by CI on this PR.

…se-url

Brings the public fetch_ctk action and redistrib helper into parity with
the private ctk-next branch.

fetch_ctk/action.yml
- Add optional redist-base-url input (default: public NVIDIA developer
  server). Callers can override to install from an alternate redistrib
  server without changing the action itself.
- Split the single 'Install dependencies' step into two OS-gated steps:
  'Install Unix dependencies' (Linux) and 'Install Windows dependencies'
  (Windows, via the new install_windows_deps action). This makes the
  action usable on Windows runners.
- Download the redistrib manifest once in 'Set up CTK cache variable'
  and reuse it in 'Get CUDA components', eliminating a redundant
  network round-trip.
- Verify the manifest hash before trusting it (verify-metadata). Public-
  server manifests are checked against KNOWN_REDISTRIB_SHA256; alternate
  servers warn only.
- Include the first 8 hex digits of the manifest sha256 in the cache
  key (-m<sha8>). Alternate servers can publish different manifests
  under the same CUDA version; without this they would restore each
  other's cached toolkit.
- Verify each downloaded component archive against the sha256 in the
  (now trusted) manifest before extracting (component-sha256 +
  sha256sum --check). The old code extracted without any archive check.

install_windows_deps/action.yml (new)
- Installs a pinned portable Git for Windows bundle (ARM64 or x64) when
  curl, unzip, tar, sha256sum, or cygpath are not already on PATH.
  Checks the archive hash before extracting.

ci/tools/fetch_ctk_redistrib.py
- Add KNOWN_REDISTRIB_SHA256: pinned public manifest hashes for 12.6.3,
  12.9.1, 13.0.2, and 13.4.2. Extend as new versions enter the matrix.
- Add get_component_subdir_info, get_component_sha256,
  compute_file_sha256, verify_metadata_sha256.
- Add component-sha256 and verify-metadata subcommands.
  verify-metadata accepts --metadata-source {public,custom}; custom
  sources only warn (never fail closed on a hash mismatch).
- Remove --metadata-url from filter-components and component-relative-
  path; callers must download the manifest themselves and pass
  --metadata-path. Removes the urllib dependency.
- Simplify load_metadata to read from a local path only.

ci/tools/tests/test_fetch_ctk_redistrib.py (new)
- 13 agent-authored unit tests covering get_component_sha256 (hash
  lookup, alias resolution, missing field, unavailable platform),
  verify_metadata_sha256 (match, mismatch, unpinned warning, custom
  source), component-sha256 and verify-metadata CLI subcommands.
@copy-pr-bot

copy-pr-bot Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the CI/CD CI/CD infrastructure label Nov 3, 2026
@juenglin
juenglin requested a review from rwgk November 3, 2026 22:02
@juenglin

juenglin commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test e4765dd

@juenglin
juenglin marked this pull request as ready for review November 3, 2026 22:16
On Windows, RUNNER_TEMP contains backslashes, and Git for Windows'
sha256sum prefixes its output line with a backslash for such file
names. The first 8 characters then included the backslash, producing an
invalid cache key and breaking 'tar -czvf' on the cache filename. Read
the manifest from stdin so no file name is printed.
@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Summary

Summary by CodeRabbit

  • New Features
    • CUDA toolkit downloads support a configurable redistribution server, with NVIDIA’s public server as the default.
    • Windows CI runners can set up required command-line tools when they are unavailable.
  • Reliability
    • Downloaded components are verified against manifest-provided SHA-256 checksums before extraction. Cache entries account for both manifest and component-list hashes.
    • Selected public metadata versions are checked against pinned SHA-256 values; custom or unpinned metadata may produce a warning.
  • Tests
    • Added coverage for metadata verification, component checksums, and custom download sources.

The CTK fetch action accepts a configurable redistributable base URL. It downloads and verifies a local manifest, filters components, and checks archive hashes before extraction. The CLI verifies pinned metadata and reports component hashes. A Windows action checks for required executables and installs Portable Git when needed.

Changes: CTK Fetch and Verification

Layer / File(s) Summary
Metadata verification and component hashes
ci/tools/fetch_ctk_redistrib.py, ci/tools/tests/test_fetch_ctk_redistrib.py
The CLI loads metadata from a local path, verifies pinned metadata hashes, and reports component archive hashes. Tests cover pinned and unpinned metadata, custom sources, component lookup, and CLI results.
Windows dependency installation
.github/actions/install_windows_deps/action.yml
The composite action checks required executables and installs a checksum-verified Portable Git bundle when they are unavailable. It adds the bundle’s directories to PATH.
Manifest-driven CTK fetch
.github/actions/fetch_ctk/action.yml
The action selects dependencies by runner OS, downloads and verifies the selected manifest, and uses it to filter components. It includes the manifest hash in the cache key and checks each component archive hash before extraction.

Suggested reviewers: leofang

Change: Bug fix

Merge Risk: Minimal · up to 794c0

No supported current-head defect remains established; the change is mergeable with normal CI validation.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between aa4689f and 794c0f2.

Files selected for processing: 1
  • .github/actions/install_windows_deps/action.yml

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up Comments

Nitpick suggestion: Normalize CTKBASEURL before the public-server comparison at Line 59. A trailing slash, …

51-51: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

suggestion: Normalize CTK_BASE_URL before the public-server comparison at Line 59. A trailing slash, such as .../redist/, fails the exact string match, so the pinned-hash check is skipped. The action treats the public server as custom and only warns. The same value also produces // in the manifest and archive URLs. Strip the slash first.

Also pass inputs.redist-base-url through env: instead of interpolating it into the script body. This follows the GitHub Actions guidance on script injection.

-        CTK_BASE_URL="${{ inputs.redist-base-url }}"
+        CTK_BASE_URL="${REDIST_BASE_URL%/}"

Add this to the step:

      env:
        REDIST_BASE_URL: ${{ inputs.redist-base-url }}

Source: Path instructions

Open the source location

Nitpick suggestion: curl -LSs has no --fail and no retry. An HTTP error page is written to $CTKJSONFILE and…

54-54: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

suggestion: curl -LSs has no --fail and no retry. An HTTP error page is written to $CTK_JSON_FILE and exits with status 0. A transient 5xx on the public server then fails with a metadata hash mismatch, which hides the real cause. For a custom server, the failure shows up later as a JSON parse error. Add --fail and a retry to make the failure clear and the step less flaky.

-        curl -LSs "${CTK_BASE_URL}/redistrib_${{ inputs.cuda-version }}.json" -o "$CTK_JSON_FILE"
+        curl -LSs --fail --retry 3 --retry-delay 2 "${CTK_BASE_URL}/redistrib_${{ inputs.cuda-version }}.json" -o "$CTK_JSON_FILE"

Source: Path instructions

Open the source location

@juenglin juenglin self-assigned this Nov 3, 2026
@juenglin juenglin added the github_actions Pull requests that update GitHub Actions code label Nov 3, 2026
- install_windows_deps: skip the WSL launcher (System32/SysWOW64/
  WindowsApps bash) when choosing the shell for the dependency check, and
  fail the check if DEPENDENT_EXES did not reach Bash. A WSL bash does not
  receive the Windows environment, so its empty loop reported success and
  skipped installing portable Git.
- fetch_ctk: strip a trailing slash from redist-base-url so the public
  server is still recognized (and its metadata pin enforced), and add
  --fail --retry 3 --retry-delay 2 to the manifest download so HTTP errors
  surface clearly instead of as a later hash or JSON error.
@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

@rwgk rwgk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (based on prior review of internal change).

@rwgk rwgk added this to the CI milestone Nov 3, 2026
@rwgk rwgk added CI/CD CI/CD infrastructure and removed CI/CD CI/CD infrastructure labels Nov 3, 2026
Comment thread .github/actions/fetch_ctk/action.yml Resolved
@NVIDIA NVIDIA deleted a comment from copy-pr-bot Bot Nov 3, 2026
…t on PATH

- fetch_ctk: use the full SHA-256 of the manifest in the cache key and
  filename instead of 8 hex digits, so an alternate server cannot share a
  key with the public server by colliding a truncated hash.
- install_windows_deps: when the validated Git Bash is not the first bash
  on PATH (for example the WSL launcher comes first), prepend its directory
  to PATH and GITHUB_PATH so later 'shell: bash' steps use Git Bash.
@juenglin

juenglin commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test aa4689f

Windows PowerShell 5.1 strips embedded double quotes when passing arguments
to native commands, so `[ -n "$DEPENDENT_EXES" ]` reached bash as
`[ -n curl unzip ... ]` and failed with "too many arguments", even with every
tool present. Count the words with `set --` instead.
@juenglin

juenglin commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test 794c0f2

@juenglin
juenglin enabled auto-merge (squash) November 3, 2026 23:55
@juenglin
juenglin merged commit 677fb9a into NVIDIA:main Nov 4, 2026
321 of 326 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI/CD CI/CD infrastructure github_actions Pull requests that update GitHub Actions code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants