1- name : CI
1+ name : Tests and Coverage
22
33on :
44 # allows us to run workflows manually
2121 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
2222
2323jobs :
24+ filter-changes :
25+ runs-on : ubuntu-latest
26+ outputs :
27+ source_changed : ${{ steps.filter.outputs.source_changed }}
28+ steps :
29+ - name : Check out the repository
30+ uses : actions/checkout@v4
31+ - name : Examine changed files
32+ id : filter
33+ uses : dorny/paths-filter@668c092af3649c4b664c54e4b704aa46782f6f7c # latest master commit, not released yet
34+ with :
35+ filters : |
36+ source_changed:
37+ - '!docs/**'
38+ - '!**/*.md'
39+ predicate-quantifier : ' every'
2440 main :
41+ needs : filter-changes
42+ if : ${{ needs.filter-changes.outputs.source_changed == 'true' }}
2543 runs-on : ubuntu-22.04
2644 strategy :
2745 matrix :
28- python-version : ["3.11 "]
46+ python-version : ["3.12 "]
2947 mpi : [n, y]
3048 omp : [n, y]
3149 dagmc : [n]
3250 libmesh : [n]
3351 event : [n]
34- vectfit : [n]
3552
3653 include :
37- - python-version : " 3.12 "
54+ - python-version : " 3.13 "
3855 omp : n
3956 mpi : n
40- - python-version : " 3.13"
57+ - python-version : " 3.14"
58+ omp : n
59+ mpi : n
60+ - python-version : " 3.14t"
4161 omp : n
4262 mpi : n
4363 - dagmc : y
44- python-version : " 3.11 "
64+ python-version : " 3.12 "
4565 mpi : y
4666 omp : y
4767 - libmesh : y
48- python-version : " 3.11 "
68+ python-version : " 3.12 "
4969 mpi : y
5070 omp : y
5171 - libmesh : y
52- python-version : " 3.11 "
72+ python-version : " 3.12 "
5373 mpi : n
5474 omp : y
5575 - event : y
56- python-version : " 3.11 "
76+ python-version : " 3.12 "
5777 omp : y
5878 mpi : n
59- - vectfit : y
60- python-version : " 3.11"
61- omp : n
62- mpi : y
6379 name : " Python ${{ matrix.python-version }} (omp=${{ matrix.omp }},
6480 mpi=${{ matrix.mpi }}, dagmc=${{ matrix.dagmc }},
65- libmesh=${{ matrix.libmesh }}, event=${{ matrix.event }}
66- vectfit=${{ matrix.vectfit }})"
81+ libmesh=${{ matrix.libmesh }}, event=${{ matrix.event }}"
6782
6883 env :
6984 MPI : ${{ matrix.mpi }}
7085 PHDF5 : ${{ matrix.mpi }}
7186 OMP : ${{ matrix.omp }}
7287 DAGMC : ${{ matrix.dagmc }}
7388 EVENT : ${{ matrix.event }}
74- VECTFIT : ${{ matrix.vectfit }}
7589 LIBMESH : ${{ matrix.libmesh }}
7690 NPY_DISABLE_CPU_FEATURES : " AVX512F AVX512_SKX"
7791 OPENBLAS_NUM_THREADS : 1
92+ PYTEST_ADDOPTS : --cov=openmc --cov-report=lcov:coverage-python.lcov
7893 # libfabric complains about fork() as a result of using Python multiprocessing.
7994 # We can work around it with RDMAV_FORK_SAFE=1 in libfabric < 1.13 and with
8095 # FI_EFA_FORK_SAFE=1 in more recent versions.
@@ -131,11 +146,6 @@ jobs:
131146 sudo update-alternatives --set mpirun /usr/bin/mpirun.mpich
132147 sudo update-alternatives --set mpi-x86_64-linux-gnu /usr/include/x86_64-linux-gnu/mpich
133148
134- - name : Optional apt dependencies for vectfit
135- shell : bash
136- if : ${{ matrix.vectfit == 'y' }}
137- run : sudo apt install -y libblas-dev liblapack-dev
138-
139149 - name : install
140150 shell : bash
141151 run : |
@@ -153,7 +163,7 @@ jobs:
153163 path : |
154164 ~/nndc_hdf5
155165 ~/endf-b-vii.1
156- key : ${{ runner.os }}-build-xs-cache
166+ key : ${{ runner.os }}-build-xs-cache-${{ hashFiles(format('{0}/tools/ci/download-xs.sh', github.workspace)) }}
157167
158168 - name : before
159169 shell : bash
@@ -171,18 +181,68 @@ jobs:
171181 uses : mxschmitt/action-tmate@v3
172182 timeout-minutes : 10
173183
174- - name : after_success
184+ - name : Generate C++ coverage (gcovr)
185+ shell : bash
186+ run : |
187+ # Produce LCOV directly from gcov data in the build tree
188+ gcovr \
189+ --root "$GITHUB_WORKSPACE" \
190+ --object-directory "$GITHUB_WORKSPACE/build" \
191+ --filter "$GITHUB_WORKSPACE/src" \
192+ --filter "$GITHUB_WORKSPACE/include" \
193+ --exclude "$GITHUB_WORKSPACE/src/external/.*" \
194+ --exclude "$GITHUB_WORKSPACE/src/include/openmc/external/.*" \
195+ --gcov-ignore-errors source_not_found \
196+ --gcov-ignore-errors output_error \
197+ --gcov-ignore-parse-errors suspicious_hits.warn \
198+ --merge-mode-functions=separate \
199+ --print-summary \
200+ --lcov -o coverage-cpp.lcov || true
201+
202+ - name : Merge C++ and Python coverage
175203 shell : bash
176204 run : |
177- cpp-coveralls -i src -i include -e src/external --exclude-pattern "/usr/*" --dump cpp_cov.json
178- coveralls --merge=cpp_cov.json --service=github
205+ # Merge C++ and Python LCOV into a single file for upload
206+ cat coverage-cpp.lcov coverage-python.lcov > coverage.lcov
179207
180- finish :
181- needs : main
208+ - name : Upload coverage to Coveralls
209+ if : ${{ hashFiles('coverage.lcov') != '' }}
210+ uses : coverallsapp/github-action@v2
211+ with :
212+ github-token : ${{ secrets.GITHUB_TOKEN }}
213+ parallel : true
214+ flag-name : C++ and Python
215+ path-to-lcov : coverage.lcov
216+ fail-on-error : false
217+
218+ coverage :
219+ needs : [filter-changes, main]
220+ if : ${{ always() }}
182221 runs-on : ubuntu-latest
183222 steps :
184223 - name : Coveralls Finished
224+ if : ${{ needs.filter-changes.outputs.source_changed == 'true' }}
185225 uses : coverallsapp/github-action@v2
186226 with :
187- github-token : ${{ secrets.github_token }}
227+ github-token : ${{ secrets.GITHUB_TOKEN }}
188228 parallel-finished : true
229+ fail-on-error : false
230+
231+ ci-pass :
232+ needs : [filter-changes, main, coverage]
233+ name : Check CI status
234+ if : ${{ always() }}
235+ runs-on : ubuntu-latest
236+ steps :
237+ - name : Check CI status
238+ run : |
239+ if [[ "${{ needs.filter-changes.outputs.source_changed }}" == "false" ]]; then
240+ echo "Documentation-only change - CI skipped successfully"
241+ exit 0
242+ fi
243+ if [[ "${{ needs.main.result }}" == "success" && "${{ needs.coverage.result }}" == "success" ]]; then
244+ echo "CI passed"
245+ exit 0
246+ fi
247+ echo "CI failed"
248+ exit 1
0 commit comments