-
Notifications
You must be signed in to change notification settings - Fork 79
[CI][refator]: migrate GPU workflow #309
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,67 +15,39 @@ on: | |
| - '.github/workflows/gpu-ci.yml' | ||
| types: [ opened, synchronize, reopened, labeled ] | ||
|
|
||
| concurrency: | ||
| group: gpu-ci-serial | ||
| cancel-in-progress: false | ||
|
|
||
| # The orchestrator is checked out from the base branch, then run against the PR | ||
| # revision in an isolated temporary worktree. Do not grant repository-write or | ||
| # cloud credentials to this job: it executes untrusted PR test code. | ||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| gpu-tests: | ||
| if: contains(github.event.pull_request.labels.*.name, 'needs-gpu-ci') | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
|
|
||
| strategy: | ||
| fail-fast: false | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we avoid running PR-controlled code directly on a persistent self-hosted runner? A worktree, venv, and CUDA_VISIBLE_DEVICES don't sandbox the process, so PR code can still access the host, other jobs, and other GPUs. This should use a disposable runner/VM with real OS-level isolation.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. A worktree, venv, and CUDA_VISIBLE_DEVICES do not provide host isolation. We will not run PR-controlled code directly on the persistent H100 runner. Until a disposable VM/runner is available, the persistent runner will be restricted to post-merge main validation. |
||
| matrix: | ||
| include: | ||
| - { gpu_id: "NVIDIA RTX A4000", target_sm: "8.6" } # SM86 | ||
| - { gpu_id: "NVIDIA H100 80GB HBM3", target_sm: "9.0", force_sm90: "1" } # SM90 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like this new workflow hasn't actually run in GitHub Actions yet. The current GPU checks still use the old RunPod matrix and deleted RunPod steps.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct. Since this uses pull_request_target, this PR is still using the workflow from the base branch, so the existing runs are the old RunPod workflow and do not validate this change. After the isolated runner setup is in place, we will validate the new workflow with a controlled test PR. |
||
| # This label must be attached to the local eight-H100-SXM runner fleet. | ||
| # Multiple runner agents may share one host; ci/run_gpu_ci.sh arbitrates | ||
| # the four physical two-GPU pairs on that host. | ||
| runs-on: [self-hosted, linux, x64, h100-sxm-8x] | ||
|
Comment on lines
26
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Inspect triggers, gating and any environment/approval settings in the GPU CI workflow.
fd -t f 'gpu-ci.yml' .github/workflows --exec sed -n '1,60p'
# Look for other workflows that run on pull_request_target or self-hosted runners.
rg -n 'pull_request_target|self-hosted|environment:' .github/workflowsRepository: RL-Align/RL-Kernel Length of output: 2237 🏁 Script executed: #!/bin/bash
# Inspect the trusted orchestrator and workflow configuration to determine whether
# PR-controlled code executes on the persistent runner and whether any approval
# mechanism already exists.
printf '%s\n' '--- workflow ---'
sed -n '1,80p' .github/workflows/gpu-ci.yml
printf '%s\n' '--- orchestrator outline ---'
ast-grep outline ci/run_gpu_ci.sh --lang bash
printf '%s\n' '--- orchestrator references to PR code and execution ---'
rg -n -C 3 'PR_(REPO_URL|SHA)|clone|fetch|checkout|worktree|pip install|pytest|python|bash|exec|docker|sudo|GPU_CI_' ci/run_gpu_ci.sh
printf '%s\n' '--- workflow approval and label handling ---'
rg -n -C 3 'environment:|required_reviewers|needs-gpu-ci|labeled|synchronize|pull_request_target' .github/workflows ciRepository: RL-Align/RL-Kernel Length of output: 9106 Require approval for every pull request revision.
Add a required-reviewer 🧰 Tools🪛 actionlint (1.7.12)[error] 30-30: label "h100-sxm-8x" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2025-vs2026", "windows-2022", "windows-11-arm", "ubuntu-slim", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-latest", "macos-latest-xlarge", "macos-latest-large", "macos-26-intel", "macos-26-xlarge", "macos-26-large", "macos-26", "macos-15-intel", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xlarge", "macos-14-large", "macos-14", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file (runner-label) 🤖 Prompt for AI Agents |
||
| timeout-minutes: 180 | ||
|
|
||
| steps: | ||
| - name: Checkout secure orchestrator script from base branch | ||
| - name: Checkout trusted GPU CI orchestrator from base branch | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ github.event.pull_request.base.sha }} | ||
| fetch-depth: 1 | ||
| persist-credentials: false | ||
|
|
||
| - name: Install runpodctl | ||
| run: | | ||
| wget -qO runpodctl https://github.com/runpod/runpodctl/releases/latest/download/runpodctl-linux-amd64 | ||
| chmod +x runpodctl | ||
| sudo mv runpodctl /usr/local/bin/runpodctl | ||
| runpodctl version | ||
|
|
||
| - name: Configure runpodctl | ||
| run: runpodctl config --apiKey "${{ secrets.RUNPOD_API_KEY }}" | ||
|
|
||
| - name: Setup SSH key | ||
| run: | | ||
| mkdir -p ~/.ssh && chmod 700 ~/.ssh | ||
| printf '%s\n' "${{ secrets.RUNPOD_SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519 | ||
| chmod 600 ~/.ssh/id_ed25519 | ||
| ssh-keygen -y -f ~/.ssh/id_ed25519 > /dev/null && echo "key OK" || echo "key BROKEN" | ||
|
|
||
| # Follow-up (#191): to test multiple architectures, add a matrix and pass | ||
| # GPU_ID + TARGET_SM (+ KERNEL_ALIGN_FORCE_SM90 for Hopper) through to the script. | ||
| # run_gpu_ci.sh reads all three, normalizes TARGET_SM, asserts the pod matches it, | ||
| # and forwards KERNEL_ALIGN_FORCE_SM90 into the remote build: | ||
| # strategy: | ||
| # matrix: | ||
| # include: | ||
| # - { gpu_id: "NVIDIA RTX A4000", target_sm: "8.6" } # Ampere | ||
| # - { gpu_id: "NVIDIA A100 80GB PCIe", target_sm: "8.0" } | ||
| # - { gpu_id: "NVIDIA H100 PCIe", target_sm: "9.0", force_sm90: "1" } # build Hopper TMA/WGMMA kernels | ||
| # - { gpu_id: "NVIDIA B200", target_sm: "10.0" } | ||
| # Per-arch jobs must NOT fall back to a different-capability GPU: the script | ||
| # fails fast when the pod arch != requested TARGET_SM, so keep fallback within | ||
| # the same compute capability (or unset it for these jobs). | ||
| - name: Run GPU tests on RunPod | ||
| - name: Run GPU tests on the local H100 SXM server | ||
| env: | ||
| RUNPOD_API_KEY: ${{ secrets.RUNPOD_API_KEY }} | ||
| # These directories must be shared by every Actions runner process | ||
| # on the same physical server and writable by the runner account. | ||
| GPU_CI_LOCK_DIR: /var/tmp/rl-kernel-gpu-ci/locks | ||
| GPU_CI_WORK_ROOT: /var/tmp/rl-kernel-gpu-ci/workspaces | ||
| PR_REPO_URL: ${{ github.event.pull_request.head.repo.clone_url }} | ||
| PR_SHA: ${{ github.event.pull_request.head.sha }} | ||
| GPU_ID: ${{ matrix.gpu_id }} | ||
| TARGET_SM: ${{ matrix.target_sm }} | ||
| KERNEL_ALIGN_FORCE_SM90: ${{ matrix.force_sm90 }} | ||
| EXPECTED_GPU_NAME: H100 | ||
| EXPECTED_GPU_COUNT: "8" | ||
| TARGET_SM: "9.0" | ||
| KERNEL_ALIGN_FORCE_SM90: "1" | ||
| run: bash ci/run_gpu_ci.sh | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This label survives synchronize events. Once a PR is labeled, the author can push another commit and have unreviewed code run on the self-hosted runner. Can we clear the label on every synchronize event and require approval again for the new SHA?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. The label must approve a specific PR SHA, not the PR indefinitely. We will clear needs-gpu-ci on every synchronize event and run the GPU job only when the label is explicitly reapplied, requiring approval for each new commit.