Skip to content

Workflow file for this run

name: CI
on:
workflow_call:
inputs:
id:
description: 'ID'
required: true
type: string
runner:
description: 'GitHub runner'
required: true
type: string
container:
description: 'Docker container'
required: false
type: string
default: ''
verset:
description: 'Dependency version set'
required: false
type: string
default: 'latest'
test_matrix:
description: 'Test matrix for `test_iguana` job (JSON)'
required: false
type: string
# test coverage and sanitizers
# FIXME: `b_sanitize=memory` is not used because `libc++` needs to be re-compiled with `-fsanitize=memory`, otherwise
# we are bothered by false positives (e.g., from `std::map` insertion)
default: >-
{
"include": [
{ "mode": "coverage", "CC": "gcc", "CXX": "g++", "buildtype": "release" },
{ "mode": "address sanitizer", "CC": "clang", "CXX": "clang++", "buildtype": "debug" },
{ "mode": "thread sanitizer", "CC": "clang", "CXX": "clang++", "buildtype": "debug" },
{ "mode": "undefined behavior sanitizer", "CC": "clang", "CXX": "clang++", "buildtype": "debug" },
{ "mode": "leak sanitizer", "CC": "clang", "CXX": "clang++", "buildtype": "debug" }
]
}
defaults:
run:
shell: bash
env:
hipo_version: f40da676bbd1745398e9fdf233ff213ff98798f1
num_events: 1000
# sanitizer options; NOTE: suppression path assumes the build directory is a subdirectory of the top-level repo directory
UBSAN_OPTIONS: halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1:suppressions=../.github/UBSAN.supp
ASAN_OPTIONS: halt_on_error=1:abort_on_error=1:print_summary=1
jobs:
# download test data
#########################################################
download_test_data:
runs-on: ubuntu-latest
env:
type: physics
steps:
- uses: actions/cache@v4
id: cache
with:
key: test_data
path: test_data.hipo
lookup-only: true
- name: download
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
run: |
wget -nv --no-check-certificate http://clasweb.jlab.org/clas12offline/distribution/clas12-timeline/validation_files_${{ env.type }}.tar.zst
tar xvf validation_files_${{ env.type }}.tar.zst
mv -v $(find validation_files -type f -name "*.hipo" | head -n1) test_data.hipo
# dependencies
#########################################################
build_hipo:
name: Build HIPO
runs-on: ${{ inputs.runner }}
container:
image: ${{ inputs.container }}
steps:
- uses: actions/cache/restore@v4
id: cache
with:
key: hipo-${{ inputs.id }}-${{ env.hipo_version }}
path: hipo.tar.zst
lookup-only: true
- name: checkout iguana for dependency installation script
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: actions/checkout@v4
with:
path: iguana_src
- name: checkout hipo
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: actions/checkout@v4
with:
repository: gavalian/hipo
ref: ${{ env.hipo_version }}
path: hipo_src
- name: build
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
run: |
iguana_src/.github/install-dependency-packages.sh ${{ inputs.runner }} ${{ inputs.verset }}
cmake -S hipo_src -B build -G Ninja --install-prefix $(pwd)/hipo -DCMAKE_POSITION_INDEPENDENT_CODE=ON # using PIE build, for sanitizer readibility
cmake --build build
cmake --install build
tar cavf hipo{.tar.zst,}
- uses: actions/cache/save@v4
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
id: cache_save
with:
key: hipo-${{ inputs.id }}-${{ env.hipo_version }}
path: hipo.tar.zst
test_root:
name: test ROOT
runs-on: ${{ inputs.runner }}
container:
image: ${{ inputs.container }}
steps:
- uses: cvmfs-contrib/github-action-cvmfs@v4
run: |
ls /cvmfs/sft.cern.ch
echo "==="
ls /cvmfs/sft.cern.ch/lcg/app/releases/ROOT/6.28.10/x86_64-ubuntu22-gcc114-opt
echo "==="
ls /cvmfs/sft.cern.ch/lcg/app/releases/ROOT/6.28.10/x86_64-mac127-clang140-opt
# build
#########################################################
build_iguana:
name: Build Iguana
needs:
- build_hipo
runs-on: ${{ inputs.runner }}
container:
image: ${{ inputs.container }}
strategy:
fail-fast: true
matrix:
include:
# build C++-only version with various compilers and buildtypes
- { id: cpp-gcc-release, CC: gcc, CXX: g++, buildtype: release, binding_opts: '' }
- { id: cpp-gcc-debug, CC: gcc, CXX: g++, buildtype: debug, binding_opts: '' }
- { id: cpp-clang-release, CC: clang, CXX: clang++, buildtype: release, binding_opts: '' }
- { id: cpp-clang-debug, CC: clang, CXX: clang++, buildtype: debug, binding_opts: '' }
# build with bindings
- { id: python, CC: gcc, CXX: g++, buildtype: release, binding_opts: '-Dbind_python=True' }
env:
CC: ${{ matrix.CC }}
CXX: ${{ matrix.CXX }}
steps:
### setup
- uses: actions/checkout@v4
with: # settings needed for version number detection
clean: false
fetch-tags: true
fetch-depth: 0
### dependencies
- name: install dependency packages
run: .github/install-dependency-packages.sh ${{ inputs.runner }} ${{ inputs.verset }}
- name: get local dependency `hipo`
uses: actions/cache/restore@v4
with:
key: hipo-${{ inputs.id }}-${{ env.hipo_version }}
path: hipo.tar.zst
- name: untar local dependencies
run: ls *.tar.zst | xargs -I{} tar xvf {}
- name: tree local dependencies
run: tree hipo
- name: summarize dependencies
if: ${{ matrix.id == 'cpp-gcc-release' }}
run: |
echo '### Dependencies' >> $GITHUB_STEP_SUMMARY
echo '| Dependency | Version |' >> $GITHUB_STEP_SUMMARY
echo '| --- | --- |' >> $GITHUB_STEP_SUMMARY
echo "| \`hipo\` | ${{ env.hipo_version }} |" >> $GITHUB_STEP_SUMMARY
cat pkg_summary.md >> $GITHUB_STEP_SUMMARY
- name: meson setup
run: meson setup build-iguana $(meson/resolve-dependencies.py --cli --hipo ./hipo)
- name: meson configure
run: |
meson configure \
--prefix=$(pwd)/iguana \
-Dbuildtype=${{ matrix.buildtype }} \
-Dexamples=True \
-Ddocumentation=False \
${{ matrix.binding_opts }} \
build-iguana
- name: dump build options
run: meson configure build-iguana | cat
- name: meson install
run: meson install -C build-iguana
### dump info about this build
- name: dump build log
if: always()
run: cat build-iguana/meson-logs/meson-log.txt
- name: readelf/otool iguana examples
if: ${{ matrix.id == 'cpp-gcc-release' || matrix.id == 'cpp-gcc-debug' || matrix.id == 'cpp-clang-release' || matrix.id == 'cpp-clang-debug' }}
run: |
binaries=$(find iguana/bin -type f -name "iguana-example-*")
libraries=$(find iguana -type f -name "*.so")
for obj in $binaries $libraries; do
echo "[+++] READ $obj"
if [ ${{ inputs.runner }} = "macos-latest" ]; then
otool -l $obj
else
readelf -d $obj
fi
done
- name: cat pkg-config pc files
run: |
pcfiles=$(find iguana -type f -name "*.pc")
for pcfile in $pcfiles; do
echo "[+++] cat $pcfile"
cat $pcfile
done
- run: tree iguana
### upload artifacts
- name: tar
run: |
tar cavf iguana{.tar.zst,}
tar cavf build-iguana{.tar.zst,}
- uses: actions/upload-artifact@v4
with:
name: install_iguana_${{ matrix.id }}
retention-days: 1
path: iguana.tar.zst
- uses: actions/upload-artifact@v4
if: ${{ matrix.id == 'cpp-gcc-release' || matrix.id == 'cpp-gcc-debug' || matrix.id == 'cpp-clang-release' || matrix.id == 'cpp-clang-debug' }}
with:
name: build_iguana_${{ matrix.id }}
retention-days: 1
path: build-iguana.tar.zst
# run tests
#########################################################
test_iguana:
name: Test Iguana
needs:
- build_hipo
- download_test_data
- build_iguana
runs-on: ${{ inputs.runner }}
container:
image: ${{ inputs.container }}
strategy:
fail-fast: false
matrix: ${{ fromJson(inputs.test_matrix) }}
env:
CC: ${{ matrix.CC }}
CXX: ${{ matrix.CXX }}
build_id: ${{ matrix.CC }}-${{ matrix.buildtype }}
steps:
### setup
- uses: actions/checkout@v4
with: # settings needed for version number detection
clean: false
fetch-tags: true
fetch-depth: 0
- name: get test data
uses: actions/cache/restore@v4
with:
key: test_data
path: test_data.hipo
- name: get iguana build dir
uses: actions/download-artifact@v4
with:
name: build_iguana_cpp-${{ env.build_id }}
### dependencies
- name: install dependency packages
run: .github/install-dependency-packages.sh ${{ inputs.runner }} ${{ inputs.verset }}
- name: get local dependency `hipo`
uses: actions/cache/restore@v4
with:
key: hipo-${{ inputs.id }}-${{ env.hipo_version }}
path: hipo.tar.zst
- name: untar local dependencies
run: ls *.tar.zst | xargs -I{} tar xvf {}
### rebuild iguana
- name: meson wipe builddir for macOS re-link # macOS Homebrew installation prefix varies among runners, so wipe the builddir to force re-linking
if: ${{ inputs.runner == 'macos-latest' }}
run: meson setup build-iguana --wipe
- name: meson configure
run: |
meson configure \
-Dtest_data_file=$(pwd)/test_data.hipo \
-Dtest_num_events=${{ env.num_events }} \
build-iguana
case "${{ matrix.mode }}" in
coverage)
meson configure \
-Db_coverage=true \
build-iguana
;;
*sanitizer)
san=$(echo ${{ matrix.mode }} | sed 's; .*;;g')
meson configure \
-Db_sanitize=$san \
-Db_lundef=false \
-Db_pie=true \
build-iguana
;;
esac
- name: dump build options
run: meson configure build-iguana | cat
- name: meson install
run: meson install -C build-iguana # must install, so the config files are in the expected location
### run tests
- name: TEST algorithms
run: |
echo -e "\e[1;35m[NOTE]: log files are found in artifact 'logs_build_iguana_${{ matrix.mode }}' \e[0m"
meson test --print-errorlogs -C build-iguana
- name: TEST coverage
if: ${{ matrix.mode == 'coverage' }}
run: |
ninja -C build-iguana coverage
mv build-iguana/meson-logs/coveragereport coverage-report
echo '### Coverage Report' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
cat build-iguana/meson-logs/coverage.txt >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo '' >> $GITHUB_STEP_SUMMARY
echo '- for details, see the `coverage-report` artifact' >> $GITHUB_STEP_SUMMARY
echo '- to compare to the report from the `main` branch, see <https://jeffersonlab.github.io/iguana/coverage-report>' >> $GITHUB_STEP_SUMMARY
### upload artifacts
- uses: actions/upload-artifact@v4
if: ${{ matrix.mode != 'coverage' }}
with:
name: logs_build_iguana_${{ matrix.mode }}
retention-days: 1
path: build-iguana/meson-logs
- uses: actions/upload-artifact@v4
if: ${{ matrix.mode == 'coverage' }}
with:
name: coverage-report
retention-days: 7
path: coverage-report
# run examples
# - a bit redundant, with `meson test` from `test_iguana`, but this ensures
# the _installation_ works (e.g., `rpath` handling)
#########################################################
test_examples:
name: Test Installed Examples
needs:
- download_test_data
- build_iguana
runs-on: ${{ inputs.runner }}
container:
image: ${{ inputs.container }}
strategy:
fail-fast: false
matrix:
include:
- { id: cpp-gcc-release, extension: '' }
- { id: python, extension: '.py' }
steps:
### dependencies and test data
- uses: actions/checkout@v4
with:
path: iguana_src # keep source code isolated
- name: install dependency packages
run: .github/install-dependency-packages.sh ${{ inputs.runner }} ${{ inputs.verset }}
working-directory: iguana_src
- name: get local dependency `hipo`
uses: actions/cache/restore@v4
with:
key: hipo-${{ inputs.id }}-${{ env.hipo_version }}
path: hipo.tar.zst
- name: get iguana build artifacts
uses: actions/download-artifact@v4
with:
name: install_iguana_${{ matrix.id }}
- name: get test data
uses: actions/cache/restore@v4
with:
key: test_data
path: test_data.hipo
- name: untar artifacts
run: |
ls *.tar.zst | xargs -I{} tar xvf {}
rm -v *.tar.zst
- name: tree artifacts
run: tree
### setup python virtaul environment (for python binding tests)
- name: install python binding runtime dependencies
if: ${{ matrix.id == 'python' }}
run: |
python -m venv .venv
source .venv/bin/activate
echo PATH=$PATH >> $GITHUB_ENV
python -m pip install -r iguana_src/bind/python/requirements.txt
### set env vars - depends on runner and binding
- name: source environment for Linux and python
if: ${{ inputs.runner == 'ubuntu-latest' && matrix.id == 'python' }}
run: |
source iguana/bin/this_iguana.sh verbose
echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH >> $GITHUB_ENV
echo PYTHONPATH=$PYTHONPATH >> $GITHUB_ENV
- name: source environment for macOS and python
if: ${{ inputs.runner == 'macos-latest' && matrix.id == 'python' }}
run: |
source iguana/bin/this_iguana.sh verbose ld
echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH >> $GITHUB_ENV
echo PYTHONPATH=$PYTHONPATH >> $GITHUB_ENV
echo DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH >> $GITHUB_ENV # for cppyy on macOS to be able to find dynamic libs
### run tests
- name: test 00
run: iguana/bin/iguana-example-00-basic${{ matrix.extension }} test_data.hipo ${{ env.num_events }}
- name: test 01
run: iguana/bin/iguana-example-01-bank-rows${{ matrix.extension }} test_data.hipo ${{ env.num_events }}
# test consumers
#########################################################
test_consumer_builds:
name: Test consumer builds
needs:
- download_test_data
- build_iguana
runs-on: ${{ inputs.runner }}
container:
image: ${{ inputs.container }}
strategy:
fail-fast: false
matrix:
tool: [ cmake, make, meson ]
env:
build_id: cpp-gcc-release
steps:
### dependencies and test data
- uses: actions/checkout@v4
- name: install dependency packages
run: .github/install-dependency-packages.sh ${{ inputs.runner }} ${{ inputs.verset }}
- name: get local dependency `hipo`
uses: actions/cache/restore@v4
with:
key: hipo-${{ inputs.id }}-${{ env.hipo_version }}
path: hipo.tar.zst
- name: get iguana build artifacts
uses: actions/download-artifact@v4
with:
name: install_iguana_${{ env.build_id }}
- name: get test data
uses: actions/cache/restore@v4
with:
key: test_data
path: test_data.hipo
- name: untar artifacts
run: |
ls *.tar.zst | xargs -I{} tar xvf {}
rm -v *.tar.zst
### set env vars
- name: set cmake prefix path
if: ${{ matrix.tool == 'cmake' }}
run: echo CMAKE_PREFIX_PATH=$(pwd)/hipo >> $GITHUB_ENV
### build test
- name: build
run: |
source iguana/bin/this_iguana.sh verbose
.github/test-consumer-build.sh ${{ matrix.tool }}
- name: readelf/otool executable
run: |
if [ ${{ inputs.runner }} = "macos-latest" ]; then
otool -l install-consumer/bin/iguana-example-00-basic
else
readelf -d install-consumer/bin/iguana-example-00-basic
fi
### run test
- name: run
run: |
install-consumer/bin/iguana-example-00-basic test_data.hipo 1
# documentation
#########################################################
doc_generate:
if: ${{ inputs.runner == 'ubuntu-latest' && inputs.verset == 'latest' }}
name: Generate documentation
runs-on: ${{ inputs.runner }}
steps:
- uses: actions/checkout@v4
- name: doxygen
uses: mattnotmitt/doxygen-action@v1
with:
doxyfile-path: doc/Doxyfile
- uses: actions/upload-artifact@v4
with:
name: doxygen
retention-days: 1
path: doc/api/
# deployment
#########################################################
collect_webpages:
if: ${{ (github.head_ref == 'main' || github.ref_name == 'main') && inputs.runner == 'ubuntu-latest' && inputs.verset == 'latest' }}
name: Collect webpages
needs:
- doc_generate
- test_iguana
runs-on: ${{ inputs.runner }}
steps:
- uses: actions/checkout@v4
with:
path: iguana_src
- name: download doxygen documentation
uses: actions/download-artifact@v4
with:
name: doxygen
path: doxygen
- name: download coverage report
uses: actions/download-artifact@v4
with:
name: coverage-report
path: coverage-report
- run: tree
- name: collect
run: |
mkdir pages
cp iguana_src/.github/pages-index.html pages/index.html
mv doxygen pages/
mv coverage-report pages/
- run: tree
- uses: actions/upload-pages-artifact@v3
with:
retention-days: 1
path: pages/
deploy_webpages:
if: ${{ (github.head_ref == 'main' || github.ref_name == 'main') && inputs.runner == 'ubuntu-latest' && inputs.verset == 'latest' }}
name: Deploy webpages
needs: collect_webpages
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ${{ inputs.runner }}
steps:
- name: deployment
id: deployment
uses: actions/deploy-pages@v4
# finalize
#########################################################
final:
name: Final
needs:
- test_iguana
- test_examples
- test_consumer_builds
runs-on: ${{ inputs.runner }}
steps:
- run: exit 0