Skip to content

PowderN fix potential edge cases #6074

PowderN fix potential edge cases

PowderN fix potential edge cases #6074

name: mcxtrace-basictest
on:
push:
pull_request:
schedule:
- cron: '55 23 * * 0' # 23:55 every Sunday
workflow_dispatch:
inputs:
manual-debugging:
type: boolean
description: Launch manual debugging tmate for inspection (automatic in case of errors)
default: false
plots:
type: boolean
description: Generate test plots (mctest without --noplots) and run mxviewtest comparison tables
default: false
# Plots and mxviewtest are off by default (push/PR/schedule); request them via
# the "plots" tickbox when running the workflow manually
env:
NOPLOTS: ${{ inputs.plots && '' || '--noplots' }}
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
# --- built from source via cmake ---
- { method: source, os: ubuntu-24.04, CC: gcc-13, CXX: g++-13, python: '3.13', mpi: 'openmpi', nmpi: 'auto', cogen: 'classic'}
- { method: source, os: ubuntu-24.04, CC: clang, CXX: clang++, python: '3.13', mpi: 'openmpi', nmpi: 'auto', cogen: 'classic'}
# --- mccode.org-style .deb packages (buildscripts/build_debs_mcxtrace), apt-installed
# in /usr, no $MCXTRACE set - as for users of the mccode.org apt repo ---
- { method: debian, os: ubuntu-24.04, CC: gcc, CXX: g++, python: '3.12', mpi: 'openmpi', nmpi: 'auto', cogen: 'classic'}
# --- built via conda ---
- { method: conda, os: ubuntu-latest, CC: gcc, CXX: g++, python: '3.13', mpi: 'openmpi', nmpi: 'auto', cogen: 'classic'}
# - { method: conda, os: ubuntu-latest, CC: gcc, CXX: g++, python: '3.13', mpi: 'openmpi', nmpi: 'auto', cogen: 'antlr'}
- { method: conda, os: macos-latest, CC: clang, CXX: clang++, python: '3.13', mpi: 'openmpi', nmpi: '2', cogen: 'classic'}
- { method: conda, os: windows-latest, CC: CL, CXX: CL, python: "3.13", mpi: 'msmpi', nmpi: 'auto', cogen: 'classic'}
name: ${{ matrix.os }}.${{ matrix.method }}.${{ matrix.cogen }}.${{ matrix.CC || 'default' }}.${{ matrix.mpi }}
runs-on: ${{ matrix.os }}
env:
CC: ${{ matrix.CC }}
CXX: ${{ matrix.CXX }}
defaults:
run:
shell: bash -el {0}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
path: src
# Full history (rather than the old fetch-depth: 2) is needed so the
# "Check for modified instruments" step below can diff against the
# actual merge-base with main / the pre-push SHA, rather than just
# the single most recent commit - see that step for why.
fetch-depth: 0
- name: Setup python
uses: actions/setup-python@v6
if: matrix.method == 'source'
with:
python-version: ${{ matrix.python }}
- name: Setup VS in shell Intel
if: runner.os == 'Windows' && matrix.os != 'windows-11-arm'
uses: egor-tensin/vs-shell@v2
- name: Setup VS in shell arm64
if: runner.os == 'Windows' && matrix.os == 'windows-11-arm'
uses: egor-tensin/vs-shell@v2
with:
arch: arm64
- name: Setup MPI
uses: mpi4py/setup-mpi@v1
if: matrix.method == 'source'
with:
mpi: ${{ matrix.mpi }}
- name: Setup (Linux, source build)
id: setup-linux
if: matrix.method == 'source' && runner.os == 'Linux'
run: |
sudo apt -y install libgsl-dev libxrl-dev libnexus-dev
- name: Setup (macOS, source build)
id: setup-macos
if: matrix.method == 'source' && runner.os == 'macOS'
# Temporarily disable xraylib runs on macOS, upstream seems to
# cause build-issues. Will soon port basictest scripts to conda
# for Windows/Linux
run: |
brew install bison flex gfortran gsl
#if [ "${{ matrix.os }}" != "macos-15" ];
#then
# brew tap tschoonj/tap
# brew install xraylib
#fi
- name: Setup (Windows, source build)
id: setup-Windows
if: matrix.method == 'source' && runner.os == 'Windows'
shell: bash
run: |
cygpath -sm "$MSMPI_INC" > includepath.txt
cygpath -sm "$MSMPI_LIB64" > libpath.txt
choco install winflexbison3
choco install wget
if [ "$CC" == "gcc.exe" ]; then choco install mingw; fi
pip install mslex PyYAML ply mcpl mcpl-extra kdsource psutil jinja2
gcc.exe --version
- name: Setup (Windows Intel, source build)
id: setup-Windows-intel
if: matrix.method == 'source' && runner.os == 'Windows' && matrix.os != 'windows-11-arm'
shell: bash
run: |
pip install McStasscript ncrystal
- name: Setup MPI cygpath...
id: setup-Windows-paths
if: matrix.method == 'source' && runner.os == 'Windows'
run: |
set /p MPIINCVAR=<includepath.txt
set /p MPILIBVAR=<libpath.txt
echo MPIINCVAR=%MPIINCVAR% >> %GITHUB_ENV%
echo MPILIBVAR=%MPILIBVAR% >> %GITHUB_ENV%
- name: Check versions and set worker label
id: version-checks
run: |
which python3
python3 --version
which cmake
cmake --version
MYWORKERID=`echo ${RUNNER_TRACKING_ID} | md5sum | cut -c1-12`
echo MYWORKERID=${MYWORKERID} >> "$GITHUB_ENV"
- name: Get conda dependency list
id: conda-deps
if: matrix.method == 'conda'
run: |
./src/devel/bin/mccode-create-conda-yml -m mcxtrace -n mcxtrace -o dependencies.yml
cat dependencies.yml
- uses: mamba-org/setup-micromamba@v3
if: matrix.method == 'conda'
with:
environment-name: mcxtrace
environment-file: dependencies.yml
- name: Configure build and install mcxtrace (source)
id: mcxtrace-install
if: ${{ matrix.method == 'source' && matrix.CC != 'CL' }}
run: |
if [ "$RUNNER_OS" == "macOS" ]; then mkdir ${HOME}/tmp; fi
if [ "$RUNNER_OS" == "macOS" ]; then export SDKROOT=$(xcrun --sdk macosx --show-sdk-path); fi
set -e
set -u
set -x
mkdir build_mcxtrace
cd build_mcxtrace
export EXTRA_ARGS_FOR_CMAKE=""
if [ "$RUNNER_OS" == "macOS" ] && [ -f "/opt/homebrew/opt/flex/bin/flex" ]; then export HOMEBRW="/opt/homebrew/opt"; export GSLFLAGS="-lgsl -lgslcblas -L/opt/homebrew/lib -I/opt/homebrew/include"; export XRLFLAGS="-lxrl -L/opt/homebrew/lib -I/opt/homebrew/include"; fi
if [ "$RUNNER_OS" == "macOS" ] && [ -f "/usr/local/opt/flex/bin/flex" ]; then export HOMEBRW="/usr/local/opt"; export GSLFLAGS="-lgsl -lgslcblas -L/usr/local/lib -I/usr/local/include"; export XRLFLAGS="-lxrl -L/usr/local/lib -I/usr/local/include"; fi
if [ "$RUNNER_OS" == "macOS" ]; then export EXTRA_ARGS_FOR_CMAKE="-DBISON_EXECUTABLE=${HOMEBRW}/bison/bin/bison -DFLEX_EXECUTABLE=${HOMEBRW}/flex/bin/flex -DCMAKE_Fortran_COMPILER=${HOMEBRW}/gfortran/bin/gfortran"; fi
if [ "$RUNNER_OS" == "Linux" ]; then export EXTRA_ARGS_FOR_CMAKE="-DNEXUSLIB=/usr/lib -DNEXUSINCLUDE=/usr/include/nexus"; fi
if [ "$RUNNER_OS" == "Windows" ]; then export MPIINC=`cygpath -m -s "${MSMPI_INC}"`; export MPILIB=`cygpath -m -s "${MSMPI_LIB64}"`; export EXTRA_ARGS_FOR_CMAKE="-DMPILIBDIR=${MPILIB} -DMPIINCLUDEDIR=${MPIINC}"; fi
cmake \
-DCMAKE_INSTALL_PREFIX=../install_mcxtrace \
-S ../src \
-G "Unix Makefiles" \
-DMCVERSION="3.99.99" \
-DMCCODE_BUILD_CONDA_PKG=OFF \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_INSTALL_LIBDIR=lib \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_MCXTRACE=ON \
-DMCCODE_USE_LEGACY_DESTINATIONS=OFF \
-DBUILD_TOOLS=ON \
-DENABLE_COMPONENTS=ON \
-DENSURE_MCPL=OFF \
-DENSURE_NCRYSTAL=OFF \
-DENABLE_CIF2HKL=ON \
-DENABLE_NEUTRONICS=OFF \
${EXTRA_ARGS_FOR_CMAKE}
cmake --build . --config Release
cmake --build . --target install --config Release
export MCXTRACE_EXECUTABLE="mcxtrace"
export MXRUN_EXECUTABLE="mxrun"
if [ "$RUNNER_OS" == "Windows" ];
then
export MCXTRACE_EXECUTABLE="mcxtrace.exe"
export MXRUN_EXECUTABLE="mxrun.bat"
fi
test -f "../install_mcxtrace/bin/${MCXTRACE_EXECUTABLE}"
test -f "../install_mcxtrace/bin/${MXRUN_EXECUTABLE}"
test -f "../install_mcxtrace/share/mcxtrace/tools/Python/mccodelib/__init__.py"
test -d "../install_mcxtrace/share/mcxtrace/resources/data"
if [ "${{ matrix.mpi }}" == "openmpi" ]; then sed -i.bak 's/mpirun/mpirun\ --mca\ btl\ self,vader,tcp/g' ../install_mcxtrace/share/mcxtrace/tools/Python/mccodelib/mccode_config.json ; fi
if [ "$RUNNER_OS" == "macOS" ]; then sed -i.bak "s+-lgsl\ -lgslcblas+${GSLFLAGS}+g" ../install_mcxtrace/share/mcxtrace/tools/Python/mccodelib/mccode_config.json ; fi
if [ "$RUNNER_OS" == "macOS" ]; then sed -i.bak "s+-lxrl+${XRLFLAGS}+g" ../install_mcxtrace/share/mcxtrace/tools/Python/mccodelib/mccode_config.json ; fi
echo *******************************************************************************
echo Resulting mccode_config.json:
echo *******************************************************************************
cat ../install_mcxtrace/share/mcxtrace/tools/Python/mccodelib/mccode_config.json
echo *******************************************************************************
- name: Configure build and install mcxtrace on Windows-MSVC (source)
id: mcxtrace-install-windows-msvc
if: ${{ matrix.method == 'source' && matrix.CC != 'gcc.exe' && runner.os == 'Windows' }}
shell: cmd
run: >
cmake -B build -S src
"-DCMAKE_INSTALL_PREFIX=./install_mcxtrace"
-DMCVERSION="3.99.99"
-DMCCODE_BUILD_CONDA_PKG=OFF
-DMCCODE_CONFIG_MCPL2=ON
-DCMAKE_INSTALL_LIBDIR=lib
-DBUILD_MCXTRACE=ON
-DMCCODE_USE_LEGACY_DESTINATIONS=OFF
-DBUILD_TOOLS=ON
-DENABLE_COMPONENTS=ON
-DENABLE_CIF2HKL=OFF
-DENABLE_NEUTRONICS=OFF
-DMPIINCLUDEDIR=%MPIINCVAR%
-DMPILIBDIR=%MPILIBVAR%
- name: CMake build (source, Windows-MSVC)
if: ${{ matrix.method == 'source' && matrix.CC != 'gcc.exe' && runner.os == 'Windows' }}
shell: cmd
run: cmake --build build --config Release -j 2
- name: CMake install (source, Windows-MSVC)
if: ${{ matrix.method == 'source' && matrix.CC != 'gcc.exe' && runner.os == 'Windows' }}
run: cmake --install build --config Release
- name: set MCXTRACE env var (source, Windows)
if: matrix.method == 'source' && runner.os == 'Windows'
run: echo MCXTRACE=%CD%\install_mcxtrace\share\mcxtrace\resources >> %GITHUB_ENV%
- name: check MCXTRACE env var (source, Windows)
if: matrix.method == 'source' && runner.os == 'Windows'
run: echo %MCXTRACE%
- name: Various Windows debugging - McXtrace (source)
if: matrix.method == 'source' && runner.os == 'Windows'
shell: cmd
run: |
type .\install_mcxtrace\share\mcxtrace\tools\Python\mccodelib\mccode_config.json
.\install_mcxtrace\bin\mxrun -h
.\install_mcxtrace\bin\mcxtrace -v
if [ "${{ matrix.CC }}" != "CL" ];
then
mcpl-config -s
fi
- name: Various Windows debugging - MCPL (source)
if: matrix.method == 'source' && runner.os == 'Windows'
run: |
mcpl-config -s
- name: Pip install Unix (source)
id: pip-install
if: matrix.method == 'source' && runner.os != 'Windows'
run: |
set -e
set -u
set -x
if [ "$RUNNER_OS" == "macOS" ];
then
python3 -mpip install PyYAML pyaml ply McStasScript mcpl mcpl-extra kdsource jinja2 psutil --break-system-packages
fi
if [ "$RUNNER_OS" == "Linux" ];
then
python3 -mpip install PyYAML ply McStasscript mcpl mcpl-extra kdsource jinja2 psutil
fi
- name: Configure build and install mcxtrace (conda)
id: mcxtrace-install-conda
if: matrix.method == 'conda'
run: |
./src/devel/bin/mccode-build-conda -m mcxtrace -s $PWD/src -b $PWD/build_mcxtrace
- name: Setup mcxtrace-antlr
id: setup-mcxtrace-antlr
if: matrix.cogen == 'antlr'
continue-on-error: true
run: |
# Cache checkout src/ with mccode-antlr
if [ "${{ matrix.cogen }}" == "antlr" ];
then
# Set up config file to use mcxtrace-antlr
MCCODE_CONFIG=`mxrun --write-user-config | cut -f4 -d\ `
sed -i.bak s+\"MCCOGEN\"\:\ \"mcxtrace\",+\"MCCOGEN\"\:\ \"mcxtrace-antlr\ -I\$\{CONDA_PREFIX\}/share/mcxtrace/resources\",+g ${MCCODE_CONFIG}
grep -H COGEN ${MCCODE_CONFIG}
MCCODEANTLR_FLAGS__NEXUS=`grep NEXUSFLAGS ${MCCODE_CONFIG} |cut -f4 -d\"`
echo "MCCODEANTLR_FLAGS__NEXUS=${MCCODEANTLR_FLAGS__NEXUS}" >> "$GITHUB_ENV"
# Pre-poulate mccode-antlr cache
mccode-antlr cache populate --from-path src/ --flavor mcxtrace --no-strict --check-hashes
fi
- name: Validate build output (conda)
id: build-validation
if: always() && matrix.method == 'conda'
run: |
set -e
set -u
set -x
if [ "$RUNNER_OS" == "Windows" ];
then
echo "Validating Windows build output..."
echo "CONDA_PREFIX: $CONDA_PREFIX"
echo "Checking for mcxtrace executable..."
test -f ${CONDA_PREFIX}/bin/mcxtrace || test -f ${CONDA_PREFIX}/bin/mcxtrace.bat || { echo "ERROR: mcxtrace not found"; exit 1; }
echo "Checking for mxtest executable..."
test -f ${CONDA_PREFIX}/bin/mxtest.bat || { echo "ERROR: mxtest.bat not found"; ls -la ${CONDA_PREFIX}/bin/ | grep -i mxtest || echo "No mxtest found"; exit 1; }
else
echo "Validating Unix build output..."
test -f ${CONDA_PREFIX}/bin/mcxtrace || { echo "ERROR: mcxtrace not found"; exit 1; }
test -f ${CONDA_PREFIX}/bin/mxtest || { echo "ERROR: mxtest not found"; exit 1; }
fi
- name: Post install openmpi hacks macOS (conda)
id: post-install-openmpi-hacks-macOS
if: matrix.method == 'conda' && runner.os == 'macOS'
run: |
if [ "${{ matrix.mpi }}" == "openmpi" ]; then
sed -i.bak 's+mpirun+mpirun\ -mca\ regx\ naive\ --verbose\ --mca\ btl_tcp_if_include\ lo0+g' ${CONDA_PREFIX}/share/mcxtrace/tools/Python/mccodelib/mccode_config.json
fi
- name: Build and install mccode.org-style .deb packages (debian)
id: mcxtrace-install-debian
if: matrix.method == 'debian'
run: |
set -e
set -u
set -x
sudo apt-get update
# Build dependencies, as in dependency-scripts/getdeps_debian (minus LaTeX/equivs:
# the manuals package and the suite metapackage are not needed for testing)
sudo apt-get -y install git cmake gcc g++ gfortran flex bison build-essential rsync libopenmpi-dev openmpi-bin
cd src
./buildscripts/build_debs_mcxtrace 3.99.99
ls -l dist
# Install everything that was built, except the manuals package. apt resolves the
# runtime dependencies declared by the packages themselves (python3-*, libxrl-dev, ...)
sudo apt-get -y install $(ls $PWD/dist/*.deb | grep -v -- '-manuals')
# Same openmpi transport settings as for the source builds
sudo sed -i.bak 's/"mpirun/"mpirun --mca btl self,vader,tcp/g' /usr/share/mcxtrace/tools/Python/mccodelib/mccode_config.json
test -x /usr/bin/mcxtrace
test -x /usr/bin/mxtest
test -d /usr/share/mcxtrace/resources/data
# The point of this leg: resources must be found without the environment variable
test -z "${MCXTRACE:-}"
- name: Normalize PATH to installed McXtrace tools
id: normalize-path
run: |
# For source builds, put the freshly-installed bin/ on PATH so the
# shared test steps below can invoke bare `mcxtrace`/`mxtest`/etc,
# exactly like the conda builds already can (conda's own
# environment activation, via `shell: bash -el`, already puts
# $CONDA_PREFIX/bin on PATH every step - nothing extra needed there).
if [ "${{ matrix.method }}" == "source" ]; then
echo "$PWD/install_mcxtrace/bin" >> "$GITHUB_PATH"
fi
# If compiler is clang, set up mpicc to use clang
if [ "${{ matrix.CC }}" == "clang" ]; then
echo "OMPI_CC=clang" >> "$GITHUB_ENV"
echo "OMPI_CXX=clang++" >> "$GITHUB_ENV"
fi
# Start of tests (shared across all 5 matrix legs)
- name: Launch RNG test instrument
id: RNG-test
run: |
set -e
set -u
set -x
export MD5SUM="md5sum"
if [ "$RUNNER_OS" == "macOS" ];
then
export MD5SUM="md5"
fi
if [ "$RUNNER_OS" == "Windows" ];
then
export SUFFIX=".bat"
export EXESUFFIX=".exe"
else
export SUFFIX=""
export EXESUFFIX=""
fi
test -n "$(command -v mcxtrace${EXESUFFIX})"
mcxtrace${EXESUFFIX} --version
mxtest${SUFFIX} --verbose ${NOPLOTS} --instr=Test_RNG_rand01 --testdir=run_rngtest --suffix=${{ matrix.cogen }}_${{ matrix.method }} --uid=${MYWORKERID}
export SUM=`find run_rngtest -name rngout.dat | xargs -n1 grep -v \# | ${MD5SUM} | cut -f1 -d\ `
export EXPECTED="f192ce4609e2225bf9d42ce9c5fa5a86"
if [ "${EXPECTED}" == "${SUM}" ];
then
echo RNG test success!
true
else
echo RNG test failure!
false
fi
- name: Launch Basic tests
id: basictests
run: |
set -e
set -u
set -x
if [ "$RUNNER_OS" == "Windows" ];
then
export SUFFIX=".bat"
export EXESUFFIX=".exe"
else
export SUFFIX=""
export EXESUFFIX=""
fi
test -n "$(command -v mcxtrace${EXESUFFIX})"
mcxtrace${EXESUFFIX} --version
if [ "${{ matrix.nmpi }}" != "0" ];
then
mxtest${SUFFIX} --verbose ${NOPLOTS} --mpi=${{ matrix.nmpi }} --instr=JJ_SAXS,ESRF_BM29,Test_MCPL_input,Test_MCPL_output,Test_Absorption --testdir=run_basictests --suffix=${{ matrix.cogen }}_${{ matrix.method }}_${{ matrix.CC || 'default' }}_${{ matrix.mpi }} --uid=${MYWORKERID}
fi
- name: Direct binary run without $MCXTRACE (compiled-in resource dir, issue #2759)
id: direct-binary-resourcedir
# Re-uses the Test_Absorption binary built by the basic tests above. Running it
# directly (not via mxrun, which always exports $MCXTRACE), with $MCXTRACE
# removed and from an unrelated folder, so its material file (data/Mn.txt) can only be
# found via the resource dir baked into the binary by the code generator -
# the situation on mccode.org-style .deb installs, where $MCXTRACE is unset.
# classic only: the antlr code generator embeds a released runtime
if: matrix.cogen == 'classic' && matrix.nmpi != '0'
run: |
set -e
set -u
set -x
EXE=$(ls run_basictests/*/Test_Absorption/Test_Absorption.out run_basictests/*/Test_Absorption/Test_Absorption.exe 2>/dev/null | head -1 || true)
test -n "$EXE" || { echo "No Test_Absorption binary found below run_basictests"; exit 1; }
EXE="$(cd "$(dirname "$EXE")" && pwd)/$(basename "$EXE")"
# Unrelated folder in the workspace (mktemp -d is not usable on the Windows
# runners: the conda/Git-bash /tmp mappings disagree)
mkdir -p direct_binary_run
cd direct_binary_run
RC=0
env -u MCXTRACE "$EXE" --yes -n 1000 -d direct_run > direct_run.log 2>&1 || RC=$?
cat direct_run.log
test "$RC" == "0" || { echo "Test_Absorption binary failed (exit code $RC) without \$MCXTRACE"; exit 1; }
if grep -qi "could not" direct_run.log; then
echo "Test_Absorption binary could not locate installed resources without \$MCXTRACE"
exit 1
fi
# Positive check: the file was really picked up from the installed resources
grep -E "Opening input file '.*resources.*Mn\.txt'" direct_run.log
- name: MPI event-list output regression test
id: mpilisttest
# classic only: the antlr code generator embeds a released runtime
if: matrix.cogen == 'classic' && matrix.nmpi != '0'
run: |
set -e
set -u
set -x
if [ "$RUNNER_OS" == "Windows" ];
then
export SUFFIX=".bat"
else
export SUFFIX=""
fi
PY=$(command -v python3 || command -v python)
# h5py is needed to check NeXus output; NeXus is skipped (and reported) without it
${PY} -m pip install h5py || ${PY} -m pip install h5py --break-system-packages || true
${PY} src/mcxtrace-comps/examples/Tests/Test_Monitor_nD_list_MPI/test_mpi_lists.py --np 2 --mcrun mxrun${SUFFIX} --workdir run_mpilists
- name: Check for modified instruments
id: instr-test
run: |
set -e
set -u
set -x
export MXTEST_EXECUTABLE="mxtest"
export MXVIEWTEST_EXECUTABLE="mxviewtest"
if [ "$RUNNER_OS" == "Windows" ];
then
export MXTEST_EXECUTABLE="mxtest.bat"
export MXVIEWTEST_EXECUTABLE="mxviewtest.bat"
fi
export PERMISSIVE=" "
# Determine which base commit to diff against, robustly - this
# replaces the old `git diff --name-only HEAD HEAD~1`, which only
# ever considers the single most recent commit. That silently
# misses changes whenever a PR or push contains more than one
# commit (verified: a 3-commit PR touching 3 different files was
# only detected as a 1-file change under the old logic).
#
# - pull_request / pushes to non-main branches: diff against the
# merge-base with origin/main, so every commit since branching
# off main is considered, however many there are and regardless
# of rebases/force-pushes on the branch itself.
# - direct pushes to main: origin/main already includes this very
# push by the time we fetch it, so merge-base against it would
# wrongly show zero changes. Diff against the pre-push SHA
# (github.event.before) instead, so a multi-commit push to main
# still gets its full set of changes considered.
cd src
git fetch origin main --quiet || true
if [ "${{ github.ref }}" == "refs/heads/main" ] && [ "${{ github.event_name }}" == "push" ]; then
export DIFFBASE="${{ github.event.before }}"
if [ -z "$DIFFBASE" ] || [ "$DIFFBASE" == "0000000000000000000000000000000000000000" ]; then
export DIFFBASE=$(git rev-parse HEAD~1)
fi
else
export DIFFBASE=$(git merge-base origin/main HEAD)
fi
echo "Diffing against: $DIFFBASE"
PY=$(command -v python3 || command -v python)
# Changed components and instruments, in one pass (doc-header-only and
# whitespace-only edits are skipped, see devel/bin/mccode-git-diff-code)
CHANGED=$(${PY} devel/bin/mccode-git-diff-code $DIFFBASE HEAD | grep -E '^mcxtrace-comps/.*\.(comp|instr)$' || true)
CHANGEDCOMPS=$(echo "$CHANGED" | grep '\.comp$' | sed -e 's#.*/##' -e 's#\.comp$##' | sort -u | tr '\n' ',' | sed 's/,$//' || true)
CHANGEDINSTR=$(echo "$CHANGED" | grep '\.instr$' | sed -e 's#.*/##' -e 's#\.instr$##' | sort -u | tr '\n' ',' | sed 's/,$//' || true)
cd -
echo ----
echo "Changed components: ${CHANGEDCOMPS:-none}"
echo "Changed instruments: ${CHANGEDINSTR:-none}"
echo ----
# Single mctest run: --instr and --comp together select instruments
# matching either (changed instruments + users of changed components)
SCOPE=""
if [ -n "$CHANGEDINSTR" ]; then SCOPE="--instr=$CHANGEDINSTR"; fi
if [ -n "$CHANGEDCOMPS" ]; then SCOPE="$SCOPE --comp=$CHANGEDCOMPS"; fi
if [ "${#SCOPE}" -gt "6000" ]; then
# Keep within the Windows .bat command-line limit: test everything
echo "Very many changes - testing all instruments"
SCOPE=" "
fi
if [ -n "$SCOPE" ]; then
mkdir -p run_mxtest && cd run_mxtest
${MXTEST_EXECUTABLE} --verbose ${NOPLOTS} --mpi=${{ matrix.nmpi }} --testdir $PWD $SCOPE --suffix=CHANGES_${{ matrix.cogen }}_${{ matrix.method }}_${{ matrix.CC || 'default' }}_${{ matrix.mpi }} $PERMISSIVE --uid=${MYWORKERID} || { echo "${MXTEST_EXECUTABLE} failed with exit code $?"; exit 1; }
if [ -z "${NOPLOTS}" ]; then ${MXVIEWTEST_EXECUTABLE} --nobrowse $PWD; fi
else
echo "No component or instrument code changes - nothing to test"
fi
- name: 'Tar output files'
id: tar-package
if: always()
run: |
set -e
set -u
set -x
# Clear out binaries from sim dir and tar up artifact
ls | grep run_ | xargs -n1 ./src/devel/bin/mccode-simdir-cleanfiles -d
tar cvfz mcxtrace-${{ matrix.cogen }}.${{ matrix.method }}.${{ matrix.os }}.${{ matrix.CC }}.${{ matrix.mpi }}.python-${{ matrix.python }}_output.tgz run_*
- name: 'Upload Artifact'
id: tar-upload
uses: actions/upload-artifact@v6
if: always()
with:
name: mcxtrace-artefacts-${{ matrix.cogen }}.${{ matrix.method }}.${{ matrix.os }}.${{ matrix.CC }}.${{ matrix.mpi }}.python-${{ matrix.python }}
path: "mcxtrace-${{ matrix.cogen }}.${{ matrix.method }}.${{ matrix.os }}.${{ matrix.CC }}.${{ matrix.mpi }}.python-${{ matrix.python }}_output.tgz"
- name: Setup tmate session for manual debugging
uses: mxschmitt/action-tmate@v3
if: always() && (inputs.manual-debugging == true)
with:
limit-access-to-actor: true
compare:
name: mcxtrace-basictest-comparison
needs: build
# Only when plots are requested (manual runs with the "plots" tickbox)
if: always() && inputs.plots
runs-on: ubuntu-latest
defaults:
run:
shell: bash -el {0}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
path: src
- name: Get conda dependency list
id: conda-deps
run: |
./src/devel/bin/mccode-create-conda-yml -m mcxtrace -n mcxtrace -o dependencies.yml
- uses: mamba-org/setup-micromamba@v3
with:
environment-name: mcxtrace
environment-file: dependencies.yml
- name: Configure build and install mcxtrace
id: mcxtrace-install
run: |
# Only the Python tooling (mxviewtest, mxplotdiff-html, mxplot-html) is
# actually needed here - the diff/report generation is platform-agnostic
# regardless of which OS originally produced the monitor data - but we
# reuse the exact same install path as the build job for consistency,
# rather than maintaining a second, lighter-weight install mechanism.
./src/devel/bin/mccode-build-conda -m mcxtrace -s $PWD/src -b $PWD/build_mcxtrace
- name: 'Download all platform test artifacts'
id: download
uses: actions/download-artifact@v6
with:
pattern: mcxtrace-artefacts-*
path: downloaded_artifacts
- name: 'Merge changed-instrument columns into one shared testdir'
id: merge
# Plain (non-login) shell here deliberately: this step is pure
# tar/mv/mkdir, no conda activation needed, and a login shell's
# ~/.bash_logout (standard on Debian/Ubuntu images) runs
# `clear_console -q` on exit, which can fail in a non-interactive
# runner and override our own explicit `exit 0`/`exit 1` below,
# making a successful "nothing changed" run report as a failure.
shell: bash {0}
run: |
set -e
set -u
set -x
mkdir basictests
REFLABEL=""
FOUND_ANY="0"
for tgz in downloaded_artifacts/*/*.tgz; do
work=$(mktemp -d)
tar xzf "$tgz" -C "$work"
FOUND_ANY="1"
artifact_name=$(basename "$(dirname "$tgz")")
if [ -d "$work"/run_mxtest/ ]; then
mkdir -p changes
for labeldir in "$work"/run_mxtest/*/; do
if [[ "$artifact_name" == *"ubuntu-latest"* ]]; then
REFLABEL=$(basename "$labeldir")
fi
mv $labeldir changes/
done
fi
for labeldir in "$work"/run_basictests/*/; do
mv $labeldir basictests/
done
rm -rf "$work"
done
echo "FOUND_ANY=$FOUND_ANY" >> "$GITHUB_ENV"
if [ "$FOUND_ANY" == "0" ]; then
echo "No instrument/component changes detected on any platform"
fi
if [ -z "$REFLABEL" ]; then
echo "WARNING: could not identify the ubuntu-latest/conda reference column"
else
echo "REFLABEL=$REFLABEL" >> "$GITHUB_ENV"
echo "Reference column: $REFLABEL"
fi
- name: 'Run mxviewtest across all platform columns'
id: viewtest
run: |
set -e
set -u
set -x
if [ -d changes/ ]; then
cd changes
if [ -z "$REFLABEL" ]; then
mxviewtest --reflabel "$REFLABEL" --nobrowse
else
mxviewtest --nobrowse
fi
cd -
fi
if [ -d basictests/ ]; then
cd basictests && mxviewtest --nobrowse && ls -l $PWD && cd -
fi
- name: 'Tar output (all platform folders + comparison tables)'
id: tar-package
run: |
if [ -d changes/ ]; then
tar cvfz mcxtrace-basictest-comparison.tgz changes basictests
else
tar cvfz mcxtrace-basictest-comparison.tgz basictests
fi
- name: 'Upload comparison artifact'
id: comparison-upload
uses: actions/upload-artifact@v6
with:
name: mcxtrace-basictest-comparison
path: mcxtrace-basictest-comparison.tgz
- name: Setup tmate session for manual debugging
uses: mxschmitt/action-tmate@v3
if: always() && (inputs.manual-debugging == true)
with:
limit-access-to-actor: true