Continuous Integration¶
The NeoN project uses a two-level Continuous Integration (CI) system to ensure correct builds, GPU compatibility, and automated benchmarking.
The main repository is hosted on GitHub, and GPU-based workflows are delegated to LRZ GitLab, where jobs are executed on both NVIDIA and AMD GPUs. The CI architecture for NeoN is illustrated below.
Continuous Integration on GitHub¶
GitHub CI is responsible for managing the overall NeoN CI workflow.
Responsibilities:
Build and test NeoN on CPU across different platforms (Linux, macOS, Windows).
Push the source code and commit metadata to LRZ GitLab.
Cancel outdated pipelines on LRZ GitLab for the same branch.
Trigger new LRZ GitLab pipelines for GPU builds and benchmarks.
Note
The GitHub CI acts as the control layer for all NeoN CI operations. Developers interact only with GitHub — all LRZ GitLab pipelines are triggered automatically.
Python Wheel CI/CD¶
In addition to the build-and-test workflows, NeoN provides a dedicated GitHub Actions workflow for
building and distributing Python wheels. This workflow is defined in
.github/workflows/python_wheels.yaml and is responsible for release packaging rather than for
ordinary pull-request testing.
Release builds are managed by GitHub Actions and cibuildwheel. The workflow creates Python
wheels inside controlled CI environments and uploads or publishes the resulting artifacts.
The workflow supports both stable and development versions. For a tag such as v0.1.2, the
package version is derived from the tag and treated as a stable release. For manually triggered
builds, the workflow generates a development version with a .dev suffix so that test artifacts
do not conflict with stable releases.
CPU wheels are built for Linux x86-64, Linux ARM64, Windows AMD64, macOS Apple Silicon, and macOS Intel. The matrix covers CPython 3.9 through 3.13. MPI and optional dependencies such as PETSc, ADIOS2, and SUNDIALS are disabled for these wheels, and CUDA/HIP support is disabled. This keeps the default PyPI package installable without requiring those external HPC libraries.
After each CPU wheel is built and repaired, cibuildwheel installs it into an isolated test
environment. The current installed-wheel check verifies that the package imports, its distribution
and module versions agree, its backend feature indicators are valid, and serial execution support is
present. The complete Python binding test suite is not currently executed against every repaired
wheel.
CUDA wheels are handled separately. The Linux wheel job installs the CUDA toolkit inside the
manylinux container before running cibuildwheel. CUDA wheels are built with Kokkos CUDA
support enabled and receive a local version suffix such as +cuda128. The NVIDIA driver library
libcuda.so.1 is explicitly excluded from wheel repair, because it is provided by the user’s
installed NVIDIA driver and must not be bundled into the wheel.
Note
GitHub-hosted runners provide CPU machines only. They can compile CUDA wheels if the CUDA toolkit is installed in the build container, but they cannot run or import the CUDA extension as a full runtime test because no NVIDIA driver or GPU is available. CUDA wheels must therefore be validated on a machine with a compatible NVIDIA driver and GPU.
Publishing is separated by wheel type:
CPU wheels are published to PyPI through PyPI Trusted Publishing. This uses GitHub’s OpenID Connect identity instead of storing a long-lived PyPI API token.
CUDA wheels are uploaded as GitHub Actions artifacts and can be attached to GitHub Releases. This keeps GPU-specific, large, driver-dependent wheels separate from the default PyPI package.
To rehearse the publish flow before a real release, dispatch the workflow manually with
build_wheels, build_cpu and publish_repository=testpypi. This builds a unique .dev
version and uploads it to TestPyPI, so Trusted Publishing configuration and package metadata can be
validated without touching the production index. TestPyPI needs its own trusted-publisher entry and a
GitHub testpypi environment; publish_repository=pypi targets the production index instead.
The workflow also includes recovery paths for already-built artifacts. If a build succeeds but a publish or release-upload step fails, existing wheel artifacts can be reused by providing the original GitHub Actions run ID. This avoids rebuilding expensive CPU or CUDA wheels only to repeat an upload step.
At the time of writing, the CUDA wheel path is intentionally narrow while it is being validated: it builds the CUDA 12.8 variant for CPython 3.12 on Linux x86-64. Runtime wheel testing is skipped in that build job because the GitHub-hosted runner has no GPU. The same structure can be extended to additional Python versions, CUDA versions, and GPU architectures after the packaged wheel is validated on production hardware.
Continuous Integration on LRZ GitLab¶
The LRZ GitLab CI handles GPU-related operations.
Responsibilities:
Build and test NeoN on NVIDIA and AMD GPU on Linux.
Run benchmark jobs after successful build and test stages.
Report the status and results back to GitHub for unified monitoring.
Development Workflow¶
The development workflow for NeoN proceeds as follows:
A developer opens a pull request (PR) or pushes a commit to an existing PR on GitHub.
GitHub CI builds and tests NeoN on CPUs, and pushes the same branch to LRZ GitLab.
GitHub CI cancels all pending or running LRZ GitLab pipelines for that branch.
GitHub CI triggers a new LRZ GitLab pipeline.
LRZ GitLab CI builds and tests NeoN on GPUs.
If the tests pass, GitHub CI triggers integration tests with the NeoFOAM on GPUs (see below).
(Optional) Benchmark jobs are executed after successful testing, including integration testing.
The developer monitors all results directly on GitHub.
Tip
Use the benchmark label on a NeoN pull request to trigger benchmarking jobs.
Integration Tests¶
NeoN is a CFD library that can be integrated into other frameworks. An option is to use the GitHub repository NeoFOAM, which provides an adapter to integrate NeoN with OpenFOAM.
To ensure the correctness of this integration, the CI system includes jobs that build and run NeoFOAM with NeoN. The integration tests are executed on CPUs by GitHub CI, while the integration tests on GPUs are executed by LRZ GitLab CI as illustrated below.
flowchart TD
A[GitHub CI] --> B[NeoN LRZ GitLab Pipeline]
B -->|Build & Test NeoN| C{Pipeline Success?}
C -->|Yes| D[NeoFOAM LRZ GitLab Pipeline]
D -->|Build & Test NeoFOAM using same NeoN version| E[End]
C -->|No| F[Stop]
GitHub CI triggers a pipeline on NeoN LRZ GitLab which builds and tests NeoN.
If the pipeline succeeds, GitHub CI triggers a pipeline on NeoFOAM LRZ GitLab.
The NeoFOAM pipeline builds and tests NeoFOAM with the NeoN version triggering the pipeline.
This ensures that any changes in NeoN do not break the integration with NeoFOAM.
Branch Handling Rules: When triggering the NeoFOAM pipeline, the following rules apply to determine which NeoFOAM branch to use:
If a branch with the same name as the NeoN branch exists on LRZ GitLab, it is used directly.
Otherwise, the main branch is used as a fallback.
Pull Request Labels¶
NeoN’s GitHub repository uses labels to control the CI behavior.
Relevant Labels:
skip-build— Skip all build-and-test jobs on both GitHub and LRZ GitLab.benchmark— Enable GPU benchmarking jobs after successful build-and-test jobs and integration tests.
These labels allow developers to customize the CI process according to their needs.
Summary¶
The NeoN CI system provides:
Unified GitHub-driven CI management.
Transparent CPU and GPU build workflows.
Automatic synchronization between GitHub and LRZ GitLab.
Branch-aware pipeline handling and cancellation.
On-demand GPU benchmarking via PR labels.