Skip to content

ci: move ubuntu-latest jobs onto linux-amd64-cpu4 - #1377

Draft
roivanov wants to merge 6 commits into
mainfrom
ci/codeql-cpu8
Draft

roivanov wants to merge 6 commits into
mainfrom
ci/codeql-cpu8

Conversation

@roivanov

@roivanov roivanov commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fixes #1518. Move the GitHub-hosted ubuntu-latest jobs onto linux-amd64-cpu4 (m7i.xlarge, 4 vCPU / 16 GiB), the same size as ubuntu-latest. Tile test jobs in cutile-rs.yml already run on linux-amd64-cpu16 and stay there. book.yml's deploy job stays on ubuntu-latest, because actions/deploy-pages publishes GitHub Pages from a GitHub-hosted runner.

Problem

ubuntu-latest is 4 vCPU / 16 GB. On this public repository those minutes are free, and that size is the whole free pool. A larger GitHub-hosted runner is billed here too. nv-cpu-general is the same class of machine at the EC2 rate, and this repository already has that group for Tile CI.

Rust CodeQL is the long job. On main push 6d47ae4 it took 38m 31s (run); the baseline on ubuntu-latest was 42m 51s (job). On that same push, examples-compile took 9m 39s and clippy 5m 1s. An 8-core run left the Rust extract at about 35 minutes: the extractor loads each Cargo workspace through rust-analyzer with one worker thread. This pull request keeps every moved job on linux-amd64-cpu4.

Security

ubuntu-latest runs a pull_request workflow on its own, including one opened from outside NVIDIA. nv-cpu-general does not. Only an NVIDIA employee can start a job on these runners. An outside pull request runs only after an employee has checked that it is legitimate and approved it through copy-pr-bot.

Each job gets its own VM, destroyed when the job ends. Inbound network access is blocked. The moved workflows trigger on push to main and to pull-request/[0-9]+, which is what cutile-rs.yml already does. copy-pr-bot is already enabled (.github/copy-pr-bot.yaml). Draft pull requests do not auto-sync.

Cost

NVIDIA/cuda-rust is public. Standard ubuntu-latest minutes are free. GitHub larger runners are billed on public repositories too. nv-cpu-general is self-hosted EC2: GitHub does not meter it. The bill is the instance.

Rates are list price. GitHub rounds each job up to the next minute. EC2 is us-east-1 Linux on-demand; the runner group's region and any enterprise discount are not in the runner docs. The 150 GiB volume on these labels is extra and small next to the instance.

6d47ae4 ran every ubuntu-latest job this move takes: 53 jobs, 93.1 minutes of runner time, 125 billed minutes. book.yml deploy is left out of that total.

Runner Machine $/min This push
ubuntu-latest (this repo, public) 4 vCPU / 16 GB $0 $0
GitHub larger Linux 4-core 4 vCPU / 16 GB $0.012 $1.50
linux-amd64-cpu4 (this PR) m7i.xlarge, 4 vCPU / 16 GiB $0.00336 $0.42

The Rust CodeQL job, measured in rust:1.98.0-bookworm on linux-amd64-cpu8, was 36 billed minutes (run): about $0.24 on cpu8, about $0.12 on cpu4 if that duration holds. Installing rustup on the 8-core VM took 35m 12s (run). The container run took the same 35 minutes.

Changes

  • runs-on: linux-amd64-cpu4 for the jobs that were on ubuntu-latest: CI's callees (fmt, clippy, unit-tests, cargo-deny), docs, examples-compile, codeql, book build, status-guard, naming-guard, ci-status, and the changes job in cutile-rs.yml.
  • Drop pull_request. Trigger on push to main and pull-request/[0-9]+.
  • Jobs that call cargo, rustfmt, or the CodeQL Rust extractor run in rust:1.98.0-bookworm. That matches the root rust-toolchain.toml pin. The Oxide nightly still comes from cuda-oxide/rust-toolchain.toml when the job enters that tree. The nv-cpu-general image has no rustup, and a missing rustup makes the Rust extractor exit 0 with an empty database. The Rust leg fails if rustup show active-toolchain cannot see the root pin.
  • Mark the mounted workspace as a safe git directory. The container otherwise reports dubious ownership when a step calls git.
  • book.yml deploy stays on ubuntu-latest and runs only for refs/heads/main, so a mirror push cannot publish the site.
  • CUDA, LLVM, and cargo-deny stay workflow install steps. The image already has git, gh, python3, and docker for the jobs that run on the VM directly.

Result

Container run on linux-amd64-cpu8: Rust analysis 35m 1s. rustc 1.98.0 (88d9e12ae 2026-08-18), active toolchain overridden by the root rust-toolchain.toml. 1,391 files extracted without error, 190 with errors, 1,580 scanned. Analyze (actions) passed in the same image.

Testing

Workflow-only change. just check and example smoketests do not apply.

Post-PR TODOs

  • Reorganize the workflows so we build the container image once, push it to ephemeral storage, and reuse it across jobs.

Checklist

  • All commits signed off (git commit -s)
  • SPDX headers on new source files

Questions about the review? Ping us in #contributors on Discord.

@NVIDIA NVIDIA deleted a comment from copy-pr-bot Bot Oct 2, 2026
@copy-pr-bot

copy-pr-bot Bot commented Oct 2, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@roivanov

roivanov commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

8-core timing

A real Rust analysis on linux-amd64-cpu8 (m7i.2xlarge, 8 vCPU / 32 GiB) finished in 35m 12s, about 8 minutes under the 42m 51s ubuntu-latest baseline (4 vCPU / 16 GiB). Same result: 1,391 files extracted cleanly, 189 with errors.

Earlier green runs on this branch (~1m 30s) were empty extracts. The nv-cpu-general image has no rustup, and the Rust extractor logs a warning and exits 0. The 35-minute run is the one after installing rustup.

Phase 4 vCPU 8 vCPU
Extract 30m 55s 28m 07s
LoadSource 18m 24s 17m 07s
LoadManifest 7m 22s 6m 21s
Finalize 1m 07s 39s
Queries 9m 32s 5m 44s

More CPUs do not move the extract

--threads is passed only to database finalize and database run-queries. The Rust extractor never sees it. CodeQL 2.27.1 (and current main) loads each Cargo workspace through rust-analyzer with num_worker_threads: 1 and proc_macro_processes: 1 hardcoded. Workspaces are loaded one at a time, then files one by one. That is the 28-minute extract. The extra cores show up in queries (9m 32s → 5m 44s) and almost nowhere else.

Narrowing the scan is the only other lever, and we are not taking it

Of the 28-minute extract, per-file gaps land about here:

Tree Time
cutile-rs/cutile-benchmarks 8.7 min
cuda-oxide examples 7.7 min
cuda-oxide/crates/fuzzer 4.0 min
Everything else 7.7 min

paths-ignore would drop those files before extraction (build-mode: none supports it for Rust). A workspace is still loaded if any of its files remain, so this removes the per-file rust-analyzer work, not the Cargo load of cutile-rs or cuda-oxide.

Analyzing only changed files is not available for this job:

  • Diff-informed analysis still extracts the whole tree and only hides alerts outside the diff. The action enables it for pull_request. This run logged Not performing diff-informed analysis because we are not analyzing a pull request. Self-hosted runners reject pull_request, which is why the workflow triggers on push.
  • Overlay analysis reuses a default-branch database and extracts changed files. codeql-action v4 enables it for C/C++, C#, Go, Java, JavaScript, Python, and Ruby. Rust is not in that list. This run logged Using overlay database mode: none without caching.

Not moving to a larger runner, and not narrowing the file set, based on this.

Self-hosted runners reject pull_request, so the workflow triggers on the
copy-pr-bot mirror push. The nv-cpu-general image has no rustup; the
rust:1.98.0-bookworm container supplies it.

Signed-off-by: Roman Ivanov <rivanov@nvidia.com>
@roivanov
roivanov marked this pull request as ready for review October 15, 2026 21:36
linux-amd64-cpu4 matches ubuntu-latest. The 8-core run did not shorten the Rust extract.

Signed-off-by: Roman Ivanov <rivanov@nvidia.com>
@roivanov roivanov changed the title ci: run CodeQL on an 8-core runner ci: run CodeQL on a 4-core runner Oct 15, 2026
@roivanov
roivanov marked this pull request as draft October 15, 2026 22:32
Self-hosted runners reject pull_request, so these workflows trigger on the
copy-pr-bot mirror push. Jobs that call cargo use the rust:1.98.0-bookworm
container. The Pages deploy job stays on ubuntu-latest.

Signed-off-by: Roman Ivanov <rivanov@nvidia.com>
@roivanov
roivanov marked this pull request as ready for review October 15, 2026 22:49
@roivanov roivanov changed the title ci: run CodeQL on a 4-core runner ci: move ubuntu-latest jobs onto linux-amd64-cpu4 Oct 15, 2026
@roivanov roivanov added the ci GitHub Actions workflows, runners, and CI configuration label Oct 15, 2026
The toolkit install needs lsb_release and an Ubuntu apt repo, so it fails
in rust:bookworm. Container steps were also running under dash, which
rejects set -o pipefail.

Signed-off-by: Roman Ivanov <rivanov@nvidia.com>
A local action is resolved from the workspace, so the setup action
cannot be the first step. Install git, then checkout, then rustup.

Signed-off-by: Roman Ivanov <rivanov@nvidia.com>
@roivanov

Copy link
Copy Markdown
Collaborator Author

😮 nvidia/cuda:13.1.1-devel-ubuntu24.04 does not include git.

The image layers install the CUDA toolkit packages, plus gnupg2, curl, and ca-certificates. curl is then removed. Nothing installs git, and the Ubuntu 24.04 base does not include it.

The same thing shows up on the Tile jobs. Checkout on nvidia/cuda:13.3.0-devel-ubuntu24.04 logs that Git 2.18 is not on PATH and downloads a tarball instead of cloning. The Tile setup step installs git for that reason.

The install step stays. Without it, actions/checkout does not create a repository, and the later git config call has no git binary.

sync-example-locks.sh --check runs under python3. The CUDA devel image
does not include it.

Signed-off-by: Roman Ivanov <rivanov@nvidia.com>
@roivanov
roivanov marked this pull request as draft October 16, 2026 01:11
run: |
apt-get update -qq
apt-get install -y -qq --no-install-recommends \
build-essential ca-certificates curl git pkg-config libclang-dev wget

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It seems like every place this is called installs ca-certificates and git beforehand anyway due to this being in the repo that needs to be checked out. Same with the mark as a safe git repository (maybe I missed some). I think that the duplication should be removed from here as you state it cannot be called until after the checkotu.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci GitHub Actions workflows, runners, and CI configuration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci: move ubuntu-latest jobs onto linux-amd64-cpu4 or larger runners

3 participants