Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: CI

on:
push:
branches:
- master
pull_request:

env:
IMAGE_PREFIX: ghcr.io/fairrootgroup/odc-ci

jobs:
build-and-test:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read

strategy:
fail-fast: false
matrix:
include:
- fedora: fedora39
label: fedora-39-x86_64-gcc-13
- fedora: fedora40
label: fedora-40-x86_64-gcc-14
- fedora: fedora41
label: fedora-41-x86_64-gcc-14
- fedora: fedora42
label: fedora-42-x86_64-gcc-15
- fedora: fedora42-boost190
label: fedora-42-x86_64-gcc-15-boost-1.90
- fedora: fedora42
label: sanitizers
extra: -DENABLE_SANITIZERS=ON

container:
image: ${{ format('{0}:{1}', 'ghcr.io/fairrootgroup/odc-ci', matrix.fedora) }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Build and test
env:
LABEL: ${{ matrix.label }}
run: ctest -S ODCTest.cmake -VV --output-on-failure ${{ matrix.extra }}

- name: Collect logs on failure
if: failure()
run: |
mkdir -p build/logs
cp -r ~/.ODC/ build/logs/ODC 2>/dev/null || true
cp -r ~/.DDS/ build/logs/DDS 2>/dev/null || true

- name: Upload logs on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: logs-${{ matrix.label }}
path: |
build/logs/
build/tmp/
if-no-files-found: ignore
retention-days: 7

slurm-integration:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- uses: GSI-HPC/sind-action@v1
with:
clusters: |
- kind: Cluster
name: odc
image: ${{ env.IMAGE_PREFIX }}:fedora42-sind
nodes:
- controller
- worker: 2

- name: Build and test
run: |
sind exec odc -- bash -lc '\
cd /data && \
ctest -S ODCTest.cmake -VV --output-on-failure \
-DLABEL=slurm-integration \
-DDDS_RMS="<rms>slurm</rms><configFile>/data/tests/slurm.cfg</configFile><agents>2</agents><slots>18</slots>" \
'

- name: Collect logs on failure
if: failure()
run: |
mkdir -p build/logs
sind exec odc -- bash -c 'cp -r ~/.ODC/ /data/build/logs/ODC 2>/dev/null; cp -r ~/.DDS/ /data/build/logs/DDS 2>/dev/null' || true

- name: Upload logs on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: logs-slurm-integration
path: |
build/logs/
build/tmp/
if-no-files-found: ignore
retention-days: 7

- uses: GSI-HPC/sind-action/cleanup@v1
if: always()
74 changes: 74 additions & 0 deletions .github/workflows/docker-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Docker Images

on:
push:
branches:
- master
paths:
- 'utils/ci/Dockerfile.*'
pull_request:
paths:
- 'utils/ci/Dockerfile.*'
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_PREFIX: ghcr.io/fairrootgroup/odc-ci

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

strategy:
fail-fast: false
matrix:
include:
- image: fedora39
build-args: FEDORA_VERSION=39
target: odc
- image: fedora40
build-args: FEDORA_VERSION=40
target: odc
- image: fedora41
build-args: FEDORA_VERSION=41
target: odc
- image: fedora42
build-args: FEDORA_VERSION=42
target: odc
- image: fedora42-boost190
target: odc
build-args: |
FEDORA_VERSION=42
BOOST_VERSION=90
- image: fedora42-sind
build-args: FEDORA_VERSION=42
target: sind-node

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
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:
context: utils/ci
file: utils/ci/Dockerfile.fedora
target: ${{ matrix.target }}
build-args: ${{ matrix.build-args }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ env.IMAGE_PREFIX }}:${{ matrix.image }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}:${{ matrix.image }}-cache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}:${{ matrix.image }}-cache,mode=max
3 changes: 3 additions & 0 deletions ODCTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ endif()

if(NOT TEST_ONLY)
list(APPEND options "-DCMAKE_INSTALL_PREFIX=install")
if(DDS_RMS)
list(APPEND options "-DDDS_RMS=${DDS_RMS}")
endif()
if(ENABLE_SANITIZERS)
list(APPEND options "-DCMAKE_CXX_FLAGS='-O1 -fsanitize=address,leak,undefined -fno-omit-frame-pointer -fno-var-tracking-assignments'")
endif()
Expand Down
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/tmp")
list(APPEND TEST_ENV "TMPDIR=${CMAKE_BINARY_DIR}/tmp")

set(ODC_DATADIR "${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_DATADIR}")

if(NOT DDS_RMS)
set(DDS_RMS "<rms>localhost</rms><agents>1</agents><slots>36</slots>")
endif()
string(RANDOM LENGTH 8 TEST_SESSION1)
string(RANDOM LENGTH 8 TEST_SESSION2)

Expand Down
4 changes: 2 additions & 2 deletions tests/cmd_set_1.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
.init --id @TEST_SESSION1@
.init --id @TEST_SESSION2@
.status
.submit --id @TEST_SESSION1@ --plugin odc-rp-same -r "<rms>localhost</rms><agents>1</agents><slots>36</slots>"
.submit --id @TEST_SESSION2@ --plugin odc-rp-same -r "<rms>localhost</rms><agents>1</agents><slots>36</slots>"
.submit --id @TEST_SESSION1@ --plugin odc-rp-same -r "@DDS_RMS@"
.submit --id @TEST_SESSION2@ --plugin odc-rp-same -r "@DDS_RMS@"
.activate --id @TEST_SESSION1@ --topo @ODC_DATADIR@/ex-topo-infinite.xml
.activate --id @TEST_SESSION2@ --topo @ODC_DATADIR@/ex-topo-infinite.xml
.prop --id @TEST_SESSION1@ --prop key1:value1 key2:value2
Expand Down
4 changes: 2 additions & 2 deletions tests/cmd_set_1_run.cfg.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.status
.run --id @TEST_SESSION1@ --plugin odc-rp-same -r "<rms>localhost</rms><agents>1</agents><slots>36</slots>" --topo @ODC_DATADIR@/ex-topo-infinite.xml
.run --id @TEST_SESSION2@ --plugin odc-rp-same -r "<rms>localhost</rms><agents>1</agents><slots>36</slots>" --topo @ODC_DATADIR@/ex-topo-infinite.xml
.run --id @TEST_SESSION1@ --plugin odc-rp-same -r "@DDS_RMS@" --topo @ODC_DATADIR@/ex-topo-infinite.xml
.run --id @TEST_SESSION2@ --plugin odc-rp-same -r "@DDS_RMS@" --topo @ODC_DATADIR@/ex-topo-infinite.xml
.prop --id @TEST_SESSION1@ --prop key1:value1 key2:value2
.prop --id @TEST_SESSION2@ --prop key1:value1 key2:value2
.config --id @TEST_SESSION1@
Expand Down
2 changes: 1 addition & 1 deletion tests/cmd_set_2.cfg.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.init --id @TEST_SESSION@
.submit --id @TEST_SESSION@ --plugin odc-rp-same -r "<rms>localhost</rms><agents>1</agents><slots>36</slots>"
.submit --id @TEST_SESSION@ --plugin odc-rp-same -r "@DDS_RMS@"
.activate --id @TEST_SESSION@ --topo @ODC_DATADIR@/ex-topo-infinite.xml
.prop --id @TEST_SESSION@ --prop key1:value1 key2:value2
.state --id @TEST_SESSION@
Expand Down
2 changes: 1 addition & 1 deletion tests/cmd_set_3_with_script.cfg.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.init --id @TEST_SESSION@
.submit --id @TEST_SESSION@ --plugin odc-rp-same -r "<rms>localhost</rms><agents>1</agents><slots>36</slots>"
.submit --id @TEST_SESSION@ --plugin odc-rp-same -r "@DDS_RMS@"
.activate --id @TEST_SESSION@ --script "cat @ODC_DATADIR@/ex-topo-infinite.xml"
.prop --id @TEST_SESSION@ --prop key1:value1 key2:value2
.config --id @TEST_SESSION@
Expand Down
5 changes: 4 additions & 1 deletion tests/odc-fixtures.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@ struct TopologyFixture
path.erase(pos);
}
mSession.mCollectionDetails.emplace(res.m_collectionID, CollectionDetails{res.m_agentID, res.m_collectionID, path, res.m_host, res.m_wrkDir, "unknown_job_id"});
mSession.mRuntimeCollectionIndex.at(res.m_collectionID)->mRuntimeCollectionAgents[res.m_collectionID] = res.m_agentID;
auto it = mSession.mRuntimeCollectionIndex.find(res.m_collectionID);
if (it != mSession.mRuntimeCollectionIndex.end()) {
it->second->mRuntimeCollectionAgents[res.m_collectionID] = res.m_agentID;
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/slurm.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#SBATCH --time=00:10:00
114 changes: 114 additions & 0 deletions utils/ci/Dockerfile.fedora
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Usage:
# docker build -f Dockerfile.fedora .
# docker build -f Dockerfile.fedora --build-arg FEDORA_VERSION=41 --build-arg DDS_VERSION=3.17 .
# docker build -f Dockerfile.fedora --build-arg BOOST_VERSION=90 .

# Stage 1: Common build environment with shared dnf packages.
ARG FEDORA_VERSION=42
FROM fedora:${FEDORA_VERSION} AS buildenv

RUN dnf -y update && \
dnf -y install abseil-cpp-devel \
asio-devel \
ca-certificates \
cmake \
flatbuffers-devel \
flatbuffers-compiler \
fmt-devel \
gcc-c++ \
git \
grpc-devel \
grpc-plugins \
libxml2 \
ninja-build \
patch \
wget \
zeromq-devel

# Stage 2: Build custom dependencies from source into /usr/local.
# Source and build trees are discarded with this stage.
FROM buildenv AS build

ARG BOOST_VERSION=
ARG FAIRCMAKEMODULES_VERSION=v1.0.0
ARG FAIRLOGGER_VERSION=v2.3.1
ARG FAIRMQ_VERSION=v1.10.1
ARG DDS_VERSION=3.18

RUN if [ -n "${BOOST_VERSION}" ]; then \
wget -O /boost.tar.gz "https://archives.boost.io/release/1.${BOOST_VERSION}.0/source/boost_1_${BOOST_VERSION}_0.tar.gz" && \
tar xzf /boost.tar.gz && \
cd /boost_1_${BOOST_VERSION}_0 && \
./bootstrap.sh --prefix=/usr/local && \
./b2 install -j$(nproc) --without-python --without-mpi && \
cd / && rm -rf /boost.tar.gz /boost_1_${BOOST_VERSION}_0; \
else \
dnf -y install boost-devel; \
fi

ADD --keep-git-dir=true https://github.com/FairRootGroup/FairCMakeModules.git#${FAIRCMAKEMODULES_VERSION} /FairCMakeModules
RUN cmake -GNinja -S FairCMakeModules -B FairCMakeModules_build -DCMAKE_INSTALL_PREFIX=/usr/local && \
cmake --build FairCMakeModules_build --target install

ADD --keep-git-dir=true https://github.com/FairRootGroup/FairLogger.git#${FAIRLOGGER_VERSION} /FairLogger
RUN cmake -GNinja -S FairLogger -B FairLogger_build -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release && \
cmake --build FairLogger_build --target install

ADD --keep-git-dir=true https://github.com/FairRootGroup/FairMQ.git#${FAIRMQ_VERSION} /FairMQ
RUN cmake -GNinja -S FairMQ -B FairMQ_build -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release && \
cmake --build FairMQ_build --target install

ADD https://github.com/FairRootGroup/DDS.git#${DDS_VERSION} /DDS
RUN echo "${DDS_VERSION}" > /DDS/version && \
cmake -GNinja -S DDS -B DDS_build -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release -DBUILD_dds-tutorials=OFF && \
cmake --build DDS_build --target wn_bin && \
cmake --build DDS_build --target install

# Stage 3: Final image with ODC-specific build dependencies
# and the install trees of the custom-built dependencies from stage 2.
FROM buildenv AS odc

ARG BOOST_VERSION=
RUN if [ -z "${BOOST_VERSION}" ]; then dnf -y install boost-devel; fi && \
dnf -y install clang-tools-extra \
libasan \
liblsan \
libubsan && \
dnf -y clean all

COPY --from=build /usr/local /usr/local

# Stage 4: sind-compatible Slurm node image for integration testing.
# Adds systemd, sshd, munge, and Slurm on top of the ODC build environment.
FROM odc AS sind-node

RUN dnf -y install \
systemd \
openssh-server \
munge \
slurm \
slurm-slurmctld \
slurm-slurmd \
&& dnf -y clean all

RUN systemctl enable sshd munge

RUN systemctl mask \
dev-hugepages.mount \
sys-fs-fuse-connections.mount \
systemd-logind.service \
getty.target \
console-getty.service

RUN mkdir -p /etc/munge /var/lib/munge /var/log/munge /run/munge \
&& chown -R munge:munge /etc/munge /var/lib/munge /var/log/munge /run/munge \
&& chmod 700 /etc/munge /var/lib/munge /var/log/munge /run/munge

RUN ssh-keygen -A \
&& sed -i 's/#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config \
&& sed -i 's/#PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config \
&& mkdir -p /root/.ssh && chmod 700 /root/.ssh

VOLUME ["/etc/slurm", "/etc/munge", "/data"]
STOPSIGNAL SIGRTMIN+3
CMD ["/sbin/init"]
Loading
Loading