From 0fb441d589836349c70aeed538d81109dfeed1e1 Mon Sep 17 00:00:00 2001 From: Trent Nelson Date: Thu, 15 Oct 2026 14:52:49 -0700 Subject: [PATCH] Reduce duplicate CI package image downloads Run native wheel qualification on vetted pushes alongside GPU checks. Share one pinned image between separate installation and runtime containers, with bounded retries for image pulls only. Signed-off-by: Trent Nelson --- .github/workflows/ci.yml | 12 +++++--- .github/workflows/wheels.yml | 59 ++++++++++++++---------------------- CONTRIBUTING.md | 14 ++++++--- 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index baee1975..5c7966cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -210,6 +210,8 @@ jobs: package: name: native distributions + # Qualify packages once, on the same vetted source as the GPU checks. + if: github.event_name == 'push' && github.repository == 'NVIDIA/cuPhoton' uses: ./.github/workflows/wheels.yml conda: @@ -217,7 +219,7 @@ jobs: uses: ./.github/workflows/conda.yml ci-required: - # PR checks do not satisfy the merge gate before GPU qualification. + # PR checks do not satisfy the merge gate before package and GPU qualification. name: ${{ github.event_name == 'pull_request' && 'ci-pr-checks' || 'ci-required' }} needs: [lint, test-cpu, test-gpu, package, conda] if: ${{ always() }} @@ -229,15 +231,17 @@ jobs: LINT_RESULT: ${{ needs.lint.result }} CPU_RESULT: ${{ needs.test-cpu.result }} GPU_RESULT: ${{ needs.test-gpu.result }} - REQUIRE_GPU: ${{ github.event_name == 'push' && github.repository == 'NVIDIA/cuPhoton' }} + REQUIRE_FULL_CI: ${{ github.event_name == 'push' && github.repository == 'NVIDIA/cuPhoton' }} PACKAGE_RESULT: ${{ needs.package.result }} CONDA_RESULT: ${{ needs.conda.result }} run: | - for result in "${LINT_RESULT}" "${CPU_RESULT}" "${PACKAGE_RESULT}" "${CONDA_RESULT}"; do + for result in "${LINT_RESULT}" "${CPU_RESULT}" "${CONDA_RESULT}"; do test "${result}" = success || exit 1 done - if [ "${REQUIRE_GPU}" = true ]; then + if [ "${REQUIRE_FULL_CI}" = true ]; then test "${GPU_RESULT}" = success || exit 1 + test "${PACKAGE_RESULT}" = success || exit 1 else test "${GPU_RESULT}" = skipped || exit 1 + test "${PACKAGE_RESULT}" = skipped || exit 1 fi diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 2513c329..32f08929 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -89,23 +89,27 @@ jobs: if-no-files-found: error install: - name: installed wheel / py${{ matrix.python.version }} / ${{ matrix.platform.arch }} + name: installed wheel and runtimes / py${{ matrix.python.version }} / ${{ matrix.platform.arch }} needs: wheels strategy: fail-fast: false matrix: python: - version: "3.12" + dragon: true image: public.ecr.aws/docker/library/python:3.12-slim-bookworm@sha256:392307d22300de8b5986851a12d9176dfc0fc073e65bf6523ebd7dcbeb23564e - version: "3.13" + dragon: true image: public.ecr.aws/docker/library/python:3.13-slim-bookworm@sha256:2325bb286ec344af3e5898cc224b5844e2707ac6e26b1632516fd3edc84a5e26 + # Dragon 0.14.2 has no Python 3.14 wheel or source distribution. - version: "3.14" + dragon: false image: public.ecr.aws/docker/library/python:3.14-slim-bookworm@sha256:82bc3c539b8813ada9d68c63b40158fa002f7f33de9bf3312a3dfdc0620dff56 platform: - {runner: ubuntu-24.04, arch: x86_64} - {runner: ubuntu-24.04-arm, arch: aarch64} runs-on: ${{ matrix.platform.runner }} - timeout-minutes: 20 + timeout-minutes: 45 steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: @@ -115,12 +119,26 @@ jobs: with: name: cuphoton-wheels-${{ matrix.platform.arch }} path: wheelhouse + - name: Pull the pinned Python image + timeout-minutes: 8 + env: + PYTHON_IMAGE: ${{ matrix.python.image }} + run: | + # Retry image delivery only; installation and test failures are final. + for delay in 0 15 30; do + sleep "$delay" + if timeout --kill-after=10s 120s docker pull "$PYTHON_IMAGE"; then + exit 0 + fi + done + echo "Unable to pull the pinned Python image after three attempts" >&2 + exit 1 - name: Install without a compiler, toolkit, or system CFITSIO env: PYTHON_VERSION: ${{ matrix.python.version }} PYTHON_IMAGE: ${{ matrix.python.image }} run: | - docker run --rm \ + docker run --pull=never --rm \ -e WHEEL_ABI="cp${PYTHON_VERSION/./}" \ -v "$PWD/wheelhouse:/wheels:ro" \ -v "$PWD/scripts/wheels:/checks:ro" \ @@ -135,37 +153,6 @@ jobs: python -I /checks/test_installed.py --mode native ' - runtimes: - name: installed runtimes / py${{ matrix.python.version }} / ${{ matrix.platform.arch }} - needs: wheels - strategy: - fail-fast: false - matrix: - python: - - version: "3.12" - dragon: true - image: public.ecr.aws/docker/library/python:3.12-slim-bookworm@sha256:392307d22300de8b5986851a12d9176dfc0fc073e65bf6523ebd7dcbeb23564e - - version: "3.13" - dragon: true - image: public.ecr.aws/docker/library/python:3.13-slim-bookworm@sha256:2325bb286ec344af3e5898cc224b5844e2707ac6e26b1632516fd3edc84a5e26 - # Dragon 0.14.2 has no Python 3.14 wheel or source distribution. - - version: "3.14" - dragon: false - image: public.ecr.aws/docker/library/python:3.14-slim-bookworm@sha256:82bc3c539b8813ada9d68c63b40158fa002f7f33de9bf3312a3dfdc0620dff56 - platform: - - {runner: ubuntu-24.04, arch: x86_64} - - {runner: ubuntu-24.04-arm, arch: aarch64} - runs-on: ${{ matrix.platform.runner }} - timeout-minutes: 25 - steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - with: - persist-credentials: false - ref: ${{ inputs.source-ref || github.sha }} - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: cuphoton-wheels-${{ matrix.platform.arch }} - path: wheelhouse - name: Exercise installed cuTile imports and distributed CPU runtimes env: PYTHON_VERSION: ${{ matrix.python.version }} @@ -173,7 +160,7 @@ jobs: WITH_DRAGON: ${{ matrix.python.dragon }} run: | mkdir -p stack-reports - docker run --rm --shm-size=2g \ + docker run --pull=never --rm --shm-size=2g \ -e WHEEL_ABI="cp${PYTHON_VERSION/./}" \ -e WITH_DRAGON \ -e OMPI_ALLOW_RUN_AS_ROOT=1 \ @@ -223,7 +210,7 @@ jobs: if-no-files-found: error distributions: - needs: [sdist, wheels, install, runtimes] + needs: [sdist, wheels, install] runs-on: ubuntu-24.04 timeout-minutes: 10 steps: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 57767921..1e597343 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -106,10 +106,11 @@ Use `make format` for Python fixes and `make ci-lint` for the complete checks. Validation logs should be clean. If warnings are expected, describe them in the pull request. -### GPU CI +### Package and GPU CI -Pull requests first run CPU and package checks on GitHub-hosted runners. -GPU CI starts when `copy-pr-bot` copies a vetted revision to +Pull requests first run lint, CPU, and conda checks on GitHub-hosted runners. +Native wheel builds, installed-wheel/runtime checks, and GPU CI start when +`copy-pr-bot` copies a vetted revision to `pull-request/` in this repository. Ready PRs from verified NVIDIA contributors with signed commits sync automatically. Draft PRs need an explicit maintainer trigger; each new external contribution revision needs @@ -123,7 +124,12 @@ not qualify new changes. The required `ci-required` check combines CPU, package, and GPU results for that revision. The initial `ci-pr-checks` result does not satisfy the merge -gate. Pushes to `main` and `0.1.x` also run the GPU checks. +gate. Pushes to `main` and `0.1.x` also run the full package and GPU checks. + +Installed-wheel and runtime checks cover Python 3.12–3.14 on x86-64 and +arm64. Each matrix job pulls its pinned Python image once and runs both +checks in separate fresh containers. Image pulls have bounded retries; +installation and test failures fail the job without retrying. The GPU job uses one L40G with Python 3.12 and the locked CUDA 13 dependencies. It checks CuPy/PyTorch execution, runs six xFit GPU parity cases, and runs