ci-gpu workflow (graphistry/pygraphistry)
The ci-gpu workflow from graphistry/pygraphistry, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get caching, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the ci-gpu workflow from the graphistry/pygraphistry repository, a real project running GitHub Actions. It is shown here with attribution under its BSD-3-Clause license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: ci-gpu
on:
pull_request:
types:
- labeled
workflow_dispatch:
repository_dispatch:
types:
- trigger-ci-gpu
permissions:
contents: read
concurrency:
# Cancel previous runs of the same workflow/PR/ref. On non-PR events
# (workflow_dispatch, repository_dispatch) `pull_request.labels` is null;
# `contains(null, _)` returns false -> `!contains(...)` evaluates true,
# so cancellation defaults on. The `skip-cancel` PR label opts out on PRs.
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-cancel') }}
env:
UV_EXCLUDE_NEWER: "6 days"
jobs:
stub_mt:
name: Always-succeed step to prevent appearing as a failure
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Do nothing
run: echo "Do nothing"
gpu-disabled-guard:
name: GPU lane temporarily disabled
if: |
github.event_name == 'workflow_dispatch' ||
github.event_name == 'repository_dispatch' ||
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'gpu-ci'))
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Fail with re-enable guidance
run: |
echo "::error::ci-gpu is temporarily disabled while gpu_public is unavailable and PR-D hardening is pending."
echo "::error::Re-enable only after issue #1130 acceptance criteria are satisfied."
exit 1
gpu-permission:
# Temporarily disabled while gpu_public is unavailable and PR-D hardening is pending.
# Re-enable only after issue #1130 criteria are met.
if: ${{ vars.GRAPHISTRY_ENABLE_GPU_PUBLIC == 'true' }} # see #1130; disabled by default
runs-on: ubuntu-latest
steps:
- name: Do nothing
run: echo "Do nothing"
test-full-ai:
# Temporarily disabled while gpu_public is unavailable and PR-D hardening is pending.
# Re-enable only after issue #1130 criteria are met.
if: ${{ vars.GRAPHISTRY_ENABLE_GPU_PUBLIC == 'true' }} # see #1130; disabled by default
runs-on: gpu_public
strategy:
matrix:
# RAPIDS GPU images currently support <= 3.13
python-version: ['3.10', 3.11, 3.12, '3.13']
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: nvidia-smi
run: nvidia-smi
- name: Install test dependencies
run: |
python -m venv pygraphistry
source pygraphistry/bin/activate
python -m pip install --upgrade pip uv
uv pip install --extra-index-url=https://pypi.nvidia.com -e .[test,testai,ai,rapids]
echo "skrub: `pip show skrub | grep Version`"
echo "pandas: `pip show pandas | grep Version`"
echo "numpy: `pip show numpy | grep Version`"
echo "scikit-learn: `pip show scikit-learn | grep Version`"
echo "scipy: `pip show scipy | grep Version`"
echo "umap-learn: `pip show umap-learn | grep Version`"
- name: Test RAPIDS
shell: 'script -q -e -c "bash {0}"' # tty
run: |
source pygraphistry/bin/activate
python -c 'import cudf; v = cudf.DataFrame({\"x\": [1,2,3]}).x.sum(); print(\"got\", v); assert v == 6'
- name: Type check
env:
PYTHON_VERSION: ${{ matrix.python-version }}
run: |
source pygraphistry/bin/activate
./bin/typecheck.sh
- name: Run all tests
run: |
source pygraphistry/bin/activate
python -m pytest --version
python -B -m pytest -vv -n auto --dist loadfile
The same workflow, on Latchkey
Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.
name: ci-gpu on: pull_request: types: - labeled workflow_dispatch: repository_dispatch: types: - trigger-ci-gpu permissions: contents: read concurrency: # Cancel previous runs of the same workflow/PR/ref. On non-PR events # (workflow_dispatch, repository_dispatch) `pull_request.labels` is null; # `contains(null, _)` returns false -> `!contains(...)` evaluates true, # so cancellation defaults on. The `skip-cancel` PR label opts out on PRs. group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-cancel') }} env: UV_EXCLUDE_NEWER: "6 days" jobs: stub_mt: name: Always-succeed step to prevent appearing as a failure runs-on: latchkey-small timeout-minutes: 10 steps: - name: Do nothing run: echo "Do nothing" gpu-disabled-guard: name: GPU lane temporarily disabled if: | github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'gpu-ci')) runs-on: latchkey-small timeout-minutes: 10 steps: - name: Fail with re-enable guidance run: | echo "::error::ci-gpu is temporarily disabled while gpu_public is unavailable and PR-D hardening is pending." echo "::error::Re-enable only after issue #1130 acceptance criteria are satisfied." exit 1 gpu-permission: timeout-minutes: 30 # Temporarily disabled while gpu_public is unavailable and PR-D hardening is pending. # Re-enable only after issue #1130 criteria are met. if: ${{ vars.GRAPHISTRY_ENABLE_GPU_PUBLIC == 'true' }} # see #1130; disabled by default runs-on: latchkey-small steps: - name: Do nothing run: echo "Do nothing" test-full-ai: timeout-minutes: 30 # Temporarily disabled while gpu_public is unavailable and PR-D hardening is pending. # Re-enable only after issue #1130 criteria are met. if: ${{ vars.GRAPHISTRY_ENABLE_GPU_PUBLIC == 'true' }} # see #1130; disabled by default runs-on: gpu_public strategy: matrix: # RAPIDS GPU images currently support <= 3.13 python-version: ['3.10', 3.11, 3.12, '3.13'] steps: - name: Checkout repo uses: actions/checkout@v4 with: persist-credentials: false - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: cache: 'pip' python-version: ${{ matrix.python-version }} - name: nvidia-smi run: nvidia-smi - name: Install test dependencies run: | python -m venv pygraphistry source pygraphistry/bin/activate python -m pip install --upgrade pip uv uv pip install --extra-index-url=https://pypi.nvidia.com -e .[test,testai,ai,rapids] echo "skrub: `pip show skrub | grep Version`" echo "pandas: `pip show pandas | grep Version`" echo "numpy: `pip show numpy | grep Version`" echo "scikit-learn: `pip show scikit-learn | grep Version`" echo "scipy: `pip show scipy | grep Version`" echo "umap-learn: `pip show umap-learn | grep Version`" - name: Test RAPIDS shell: 'script -q -e -c "bash {0}"' # tty run: | source pygraphistry/bin/activate python -c 'import cudf; v = cudf.DataFrame({\"x\": [1,2,3]}).x.sum(); print(\"got\", v); assert v == 6' - name: Type check env: PYTHON_VERSION: ${{ matrix.python-version }} run: | source pygraphistry/bin/activate ./bin/typecheck.sh - name: Run all tests run: | source pygraphistry/bin/activate python -m pytest --version python -B -m pytest -vv -n auto --dist loadfile
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cache dependency installs on the setup step so they are served from cache.
- Add a job timeout so a hung step cannot burn hours of runner time.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Dependency installs
This workflow runs 4 jobs (7 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.