Skip to content

Merge remote-tracking branch 'origin/main' into wip/pdb-open-regress #396

Merge remote-tracking branch 'origin/main' into wip/pdb-open-regress

Merge remote-tracking branch 'origin/main' into wip/pdb-open-regress #396

Workflow file for this run

name: Test
# Runs the three regression suites. Separate from build.yml on purpose:
# that workflow answers "does this compile and package on five platforms",
# which is a different question and a different failure mode from "does it
# still behave".
#
# The suites are deliberately tiered by what they need, and the first two
# need remarkably little -- no display, no ECCE services, no install, no
# build at all:
#
# parsers real chemistry-code output -> the real eccejobmonitor
# Begin/Skip/End algorithm -> the real scripts/parsers scripts.
# python3 + perl. ~1 min.
# dialogs the real scripts/codereg dialogs, run headless under
# broadwayd (GTK3's displayless backend -- no X server at all),
# diffed against what each ai.<code> generator recognises.
# + wxPython. ~2 min.
# apps every installed wx-linked C++ app started on Xvfb with
# software OpenGL, checked that it opens a window and stays up.
# Needs a build, an install, and a per-user data server; hence
# its own job. ~6 min.
#
# build.yml's header used to say running the GUI apps needed "a lot more
# complexity than a build-and-package health check warrants". That was a
# fair call when it was written; in practice it came down to `apt install
# xvfb` plus letting the app wrapper start its own services, so the apps
# job below exists now. The other two never needed any of that.
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch: {}
# One run per branch. Without this every push starts a full run and none
# of them cancel the older ones, so a run of quick pushes leaves a dozen
# stale runs competing for the same runners -- which is exactly what
# happened on 2026-09-23: nine pushes in a day, eleven jobs each, and CI
# stopped completing anything for six hours. A superseded run tells you
# nothing a newer one will not.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
scripts:
name: Parsers and dialogs (no build, no display)
runs-on: ubuntu-latest
# Bounded so a hung job cannot hold a runner slot for GitHub's
# 6-hour default; see the concurrency note above.
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
# perl: the parser scripts are Perl and are run for real.
# python3-wxgtk4.0: the codereg dialogs are wxPython and are run
# for real.
# libgtk-3-bin: provides broadwayd, which lets those dialogs run
# with no X server at all.
sudo apt-get install -y perl python3 python3-wxgtk4.0 libgtk-3-bin
- name: Parser / property pipeline suite
run: tests/parsers/run_tests.py
- name: Code-registration dialog suite
run: tests/dialogs/run_tests.py
# Added 2026-09-23: this suite existed but was never wired in, so
# the basis exporters were the one layer CI did not cover -- the
# layer a silent bug had just been found in twice (Gaussian being
# sent ECCE's own basis names, and Fortran D exponents read without
# their exponent). Needs nothing the other two do not.
- name: Basis set exporter suite
run: tests/basis/run_tests.py
# The input-deck checker: real decks through the real script. The
# cases that matter most are the WORKING decks, which must come
# back clean -- a checker that cries wolf gets ignored, including
# the time it is right.
- name: Input checker suite
run: tests/verify/run_tests.py
# The orbital and ESP maths. Deliberately compiles with plain g++
# against include/ alone -- SlaterExpansion, CoulombIntegrals and
# EspField have no wx, DAV or XML dependency by design -- so it
# belongs in this job rather than the one that builds. The one
# part that does need the build tree, the importConfig round
# trip, skips itself with a reason when there is none.
- name: Orbital and ESP maths suite
run: tests/slater/run_tests.py
# Character tables. Pure data checking, no build: a wrong sign in
# a hand-entered table would silently misassign an irrep, and the
# orthogonality theorem catches it for free.
- name: Character table suite
run: tests/symmetry/run_tests.py
e2e:
name: End-to-end (real code, real monitor, real parsers)
runs-on: ubuntu-latest
# Debian, not the runner's Ubuntu, and deliberately.
#
# This suite exists to notice when a CODE's behaviour changes, so
# running it against a different distribution's build of that code
# reports differences that have nothing to do with ECCE. It did:
# Ubuntu's quantum-espresso 6.7 aborts on this deck with a glibc
# FORTIFY buffer-overflow check inside pw.x, while Debian's build of
# the same upstream 6.7 runs it fine. The overflow is latent in QE
# either way -- Ubuntu's hardening is simply stricter and catches it
# -- and neither the bug nor the difference is ECCE's.
#
# ECCE targets Debian, so this is also the platform whose answers
# matter. Only this job moves: the others test our own Python,
# Perl and C++, where the distribution is not the variable.
container: debian:trixie
# Bounded so a hung job cannot hold a runner slot for GitHub's
# 6-hour default; see the concurrency note above. Roomier than the
# script suites because nwchem-openmpi is a large apt install; the
# jobs themselves are seconds on these molecules.
timeout-minutes: 30
steps:
# BEFORE the checkout, which is not the usual order: a bare Debian
# image has neither git nor ca-certificates, and actions/checkout
# needs both. Nothing here needs the repository.
#
# MOPAC is Debian-packaged and runs a small molecule in seconds,
# which is what makes this tier possible at all. ORCA and
# Gaussian cannot be installed here -- one is registration-walled,
# the other licensed -- so they stay a developer-box tier and the
# suite skips them by name rather than passing silently.
#
# No sudo: a container runs as root, and Debian's image has none.
- name: Install dependencies
run: |
apt-get update
apt-get install -y --no-install-recommends \
ca-certificates git perl python3 \
mopac nwchem nwchem-openmpi \
quantum-espresso quantum-espresso-data-sssp gromacs
- uses: actions/checkout@v4
# Declare what this job installed. Without this a code whose
# binary is not where the suite looks simply skips, and the job
# goes green with that coverage quietly gone -- which is exactly
# what happened to nwchem on its first run here.
- name: End-to-end suite
env:
ECCE_E2E_REQUIRE: mopac,nwchem,qe,gromacs
run: tests/e2e/run_tests.py -v
apps:
name: GUI apps (build, install, Xvfb)
runs-on: ubuntu-latest
# Bounded so a hung job cannot hold a runner slot for GitHub's
# 6-hour default; see the concurrency note above.
timeout-minutes: 40
steps:
- uses: actions/checkout@v4
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential gfortran cmake ninja-build \
libwxgtk3.2-dev libxerces-c-dev libgl-dev libglu1-mesa-dev \
libgtk-3-dev libx11-dev libice-dev libxt-dev libjpeg-dev \
libmosquitto-dev mosquitto-dev libaprutil1-dev mosquitto git dpkg-dev libssh-dev \
python3 libcoin-dev libegl-dev
- name: Install runtime dependencies
run: |
# apache2: the data server is a real per-user Apache instance
# (ecce-server depends on it; listed here so it is cached early).
# xvfb: headless X. These apps link GLX for the Open Inventor
# viewer, so broadwayd (used by the dialogs suite) is not an
# option -- it serves no GLX.
# libgl1-mesa-dri: llvmpipe, the software renderer that actually
# answers those GLX calls. Without it the apps get no GL and
# the suite says so on startup.
# x11-utils: xdpyinfo/xwininfo, used to see whether a window
# actually appeared. glxinfo is in mesa-utils, separately.
# mesa-utils: glxinfo, only to report whether GL is working.
# python3-wxgtk4.0: pulled in because the installed package's
# codereg dialogs need it at runtime.
sudo apt-get install -y \
apache2 apache2-utils xvfb libgl1-mesa-dri x11-utils \
mesa-utils mosquitto python3-wxgtk4.0
- name: Build
run: |
cmake -G Ninja -B build-cmake
cmake --build build-cmake
- name: Package and install
working-directory: build-cmake
run: |
cpack -G DEB
# Two packages since the client/server split (ecce-server depends
# on ecce-client, so one apt transaction takes both, in order).
# apt rather than dpkg -i so their dependencies are resolved;
# no recommends, to keep nwchem and friends out of the runner.
sudo apt-get install -y --no-install-recommends \
./ecce-client_*_amd64.deb ./ecce-server_*_amd64.deb
# ECCE_APPS_TRACE names each app before it starts. Without it a
# wedged suite leaves the last SUCCESSFUL app as the final log
# line and the culprit has to be inferred from the ordering.
# The symmetry operation checks, here rather than in the no-build
# job, because they need the symops binary this job has just
# built. Without this they skip everywhere and the 78 checks that
# tie PNNL's Fortran generator tables to the hand-entered
# character tables never actually run.
#
# Before the GUI suite, not after: it needs no display or
# services, and a failure of the apps suite should not hide it.
- name: Symmetry operation suite
run: tests/symmetry/run_tests.py
# ECCE_TEST_STATE names the private state directory this run
# isolates itself into -- see tests/apps/isolate.py: a run no longer
# touches ~/.ECCE, its ports or its services at all, so it cannot
# collide with a live session (#136). Named here rather than left
# to its default so the log collection below knows where to look.
- name: GUI application smoke suite
env:
ECCE_APPS_TRACE: '1'
ECCE_TEST_STATE: ${{ runner.temp }}/ecce-state
run: tests/apps/run_tests.py -v
- name: Collect service logs on failure
if: failure()
run: |
# These live in the run's own state dir and are the first thing
# anyone debugging a red run here will want.
STATE="${{ runner.temp }}/ecce-state/.ECCE"
for f in "$STATE"/*.log "$STATE"/dataserver/logs/error_log; do
[ -f "$f" ] && { echo "=== $f"; tail -50 "$f"; }
done || true