diff --git a/.github/workflows/ubuntu24-mpich-image.yml b/.github/workflows/ubuntu24-mpich-image.yml new file mode 100644 index 00000000..4ce5936c --- /dev/null +++ b/.github/workflows/ubuntu24-mpich-image.yml @@ -0,0 +1,74 @@ +name: Ubuntu 24.04 MPICH CI image + +# Builds the ubuntu-24.04 + source-MPICH image (ci/ubuntu24-mpich/Dockerfile) used by +# build.yml's ubuntu-24.04 x mpich legs (build matrix, sanitizers, coverage) and +# publishes it to GHCR. Ubuntu 24.04's apt mpich is broken on the runners +# (ch4:ucx -> MPI_Init abort on the verbs device + singleton launches); this +# image ships a source mpich built --with-device=ch4:ofi that forms a real +# multi-rank world. See ci/ubuntu24-mpich/Dockerfile for the full rationale. +# +# Deliberately NOT triggered on every PR: the image only needs rebuilding when +# its recipe changes. It runs on: +# * pushes to master that touch the Dockerfile or this workflow, +# * a weekly schedule (so ubuntu:24.04 base + libfabric security updates get +# picked up), and +# * manual dispatch — the BOOTSTRAP path: run this once (from any branch) to +# publish :latest, then make the GHCR package PUBLIC, before build.yml's +# ubuntu-24.04 mpich legs can pull it. +# +# Published as ghcr.io/codes-org/codes-ci-ubuntu24-mpich — :latest plus a : tag so +# a build.yml change can pin a specific image if a Dockerfile bump regresses. +on: + push: + branches: + - master + paths: + - 'ci/ubuntu24-mpich/Dockerfile' + - '.github/workflows/ubuntu24-mpich-image.yml' + schedule: + # Weekly, Monday 08:00 UTC — refresh the ubuntu:24.04 base + apt packages. + - cron: "0 8 * * 1" + workflow_dispatch: + +permissions: + contents: read + packages: write + +jobs: + build-and-push: + name: build + push codes-ci-ubuntu24-mpich + runs-on: ubuntu-24.04 + steps: + - name: Checkout CODES + uses: actions/checkout@v4 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push + uses: docker/build-push-action@v6 + with: + # The Dockerfile COPYs nothing from the build context (mpich is fetched + # inside the build), so the context is just the directory holding it. + # `file` defaults to {context}/Dockerfile = ci/ubuntu24-mpich/Dockerfile. + context: ci/ubuntu24-mpich + # CI builds amd64 (the runner arch that build.yml's 24.04 legs run on). + platforms: linux/amd64 + # Don't publish from PR builds (a PR can't be trusted with + # packages:write and shouldn't move :latest); push only on + # master / schedule / dispatch. + push: ${{ github.event_name != 'pull_request' }} + tags: | + ghcr.io/codes-org/codes-ci-ubuntu24-mpich:latest + ghcr.io/codes-org/codes-ci-ubuntu24-mpich:${{ github.sha }} + # Persist layer cache so an unchanged Dockerfile is a fast no-op and a + # version bump only rebuilds the mpich layer onward. + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/ci/ubuntu24-mpich/Dockerfile b/ci/ubuntu24-mpich/Dockerfile new file mode 100644 index 00000000..6fa27408 --- /dev/null +++ b/ci/ubuntu24-mpich/Dockerfile @@ -0,0 +1,58 @@ +# ubuntu-24.04 CI image with a source-built MPICH, for the build.yml jobs that +# run ctest with MPICH on ubuntu-24.04: the build matrix's 24.04 x mpich legs, +# the ASan/UBSan sanitizer lanes, and the coverage job. +# +# Why this image exists +# --------------------- +# Ubuntu 24.04's apt mpich (4.2.0-5build3) is built --with-device=ch4:ucx and is +# broken on the GitHub-hosted runners in TWO independent ways: +# 1. UCX probes the runner's InfiniBand-verbs device and tries the RDMA (rc) +# transport, aborting MPI_Init with "ibv_create_srq() failed: Operation not +# supported" -- every MPI-initializing test dies. +# 2. Even past that, mpiexec starts every rank as its own size-1 singleton, so +# optimistic (--sync=3) tests silently run sequential. +# There is no fixed mpich in the noble apt archive. So we build MPICH from source +# with --with-device=ch4:ofi (libfabric, sockets/TCP -- no UCX, no verbs), which +# forms a real multi-rank world on the runners. The mpi-multirank-sanity ctest is +# the tripwire: it fails if the launcher ever regresses to singletons again. +# +# The base stays ubuntu:24.04 so these legs keep exercising the modern toolchain +# (gcc-13 / clang) they exist for -- only the MPI is swapped for our own build. +# +# Published as ghcr.io/codes-org/codes-ci-ubuntu24-mpich by +# .github/workflows/ubuntu24-mpich-image.yml. Like codes-ci-full, make the GHCR package +# PUBLIC after the first publish so build.yml (including fork PRs) can pull it +# anonymously. +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive + +# Toolchain + CODES build deps (cmake/ninja/pkg-config/flex/bison), BOTH compilers +# the matrix drives (gcc via build-essential + clang), lcov for the coverage job, +# and the tools to fetch/build MPICH. Deliberately NO apt mpich -- we build our +# own below and put it ahead of everything on PATH. +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential clang \ + cmake ninja-build pkg-config \ + flex bison \ + lcov \ + git ca-certificates wget \ + && rm -rf /var/lib/apt/lists/* + +# --- MPICH from source, ch4:ofi device (embedded libfabric, sockets/TCP). No UCX +# and no verbs probing, reliable PMI wire-up -> mpiexec forms a real multi- +# rank world on the CI runners. Installed to /opt/mpich and put on PATH so +# find_package(MPI) discovers mpicc/mpicxx/mpiexec with no CODES/ROSS config +# change. Bump MPICH_VERSION to update -- that's the whole maintenance story. +ARG MPICH_VERSION=4.2.3 +RUN wget -q "https://www.mpich.org/static/downloads/${MPICH_VERSION}/mpich-${MPICH_VERSION}.tar.gz" \ + && tar xzf "mpich-${MPICH_VERSION}.tar.gz" \ + && cd "mpich-${MPICH_VERSION}" \ + && ./configure --prefix=/opt/mpich --with-device=ch4:ofi --disable-fortran \ + && make -j"$(nproc)" \ + && make install \ + && cd / \ + && rm -rf "mpich-${MPICH_VERSION}" "mpich-${MPICH_VERSION}.tar.gz" + +# Put our mpich first so find_package(MPI) picks it over anything else. +ENV PATH=/opt/mpich/bin:$PATH