Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |