@@ -86,9 +86,9 @@ name: Build and Publish Python wheels to PyPI and TestPyPI
8686# - Both wheel sets deployed to PyPI together (production tags only)
8787# - UMEP builds use Python 3.12 only (aligned with QGIS 3.40 LTR bundled Python)
8888# - UMEP build triggers (runs on ALL events for continuous NumPy 1.x testing):
89- # * PRs: manylinux cp312 (NumPy 1.x validation before merge)
90- # * Master/manual: manylinux cp312 (continuous UMEP compatibility testing)
91- # * Nightly/dev tags: manylinux cp312 (daily testing, uses .dev1 to avoid version collision)
89+ # * PRs: win cp312 (NumPy 1.x validation before merge, Windows = QGIS primary platform )
90+ # * Master/manual: win cp312 (continuous UMEP compatibility testing)
91+ # * Nightly/dev tags: win cp312 (daily testing, uses .dev1 to avoid version collision)
9292# * Production tags: all platforms cp312 (complete distribution → PyPI, uses rc1 suffix)
9393#
9494# UMEP INTEGRATION:
@@ -178,39 +178,72 @@ jobs:
178178 # Only run for pull requests (push/tag/schedule always build)
179179 if : github.event_name == 'pull_request'
180180 outputs :
181- needs-build : ${{ steps.filter.outputs.code }}
181+ needs-build : ${{ steps.filter.outputs.core == 'true' || steps.filter.outputs.util == 'true' || steps.filter.outputs.cfg == 'true' || steps.filter.outputs.tests == 'true' }}
182+ core-changed : ${{ steps.filter.outputs.core }}
183+ util-changed : ${{ steps.filter.outputs.util }}
184+ cfg-changed : ${{ steps.filter.outputs.cfg }}
185+ tests-changed : ${{ steps.filter.outputs.tests }}
182186 steps :
183187 - uses : actions/checkout@v4
184188
185189 - uses : dorny/paths-filter@v3
186190 id : filter
187191 with :
188192 filters : |
189- code:
193+ core:
194+ # Fortran physics
195+ - 'src/suews/src/**'
196+ # Fortran driver interface
197+ - 'src/supy_driver/**'
198+ - 'src/supy/supy_driver/**'
199+ # Core Python files that affect scientific rigour
200+ - 'src/supy/_run.py'
201+ - 'src/supy/_supy_module.py'
202+ - 'src/supy/_load.py'
203+ - 'src/supy/_post.py'
204+ - 'src/supy/_check.py'
205+ - 'src/supy/_save.py'
206+ - 'src/supy/suews_sim.py'
207+ # Catch-all for core package changes
190208 - 'src/suews/**'
209+ util:
210+ # Utility modules (nice-to-have)
211+ - 'src/supy/util/**'
212+ # Default category for remaining supy changes
191213 - 'src/supy/**'
192- - 'src/supy_driver/**'
193- - '.github/workflows/build-publish_to_pypi.yml'
194- - '.github/actions/build-suews/**'
195- - 'test/**'
196- - 'scripts/**'
197- # NOTE: schemas/** excluded - JSON metadata files don't require builds
198- # Bot-created schema PRs use schema-pr-validation.yml instead
214+ cfg:
215+ # Config validation
216+ - 'src/supy/data_model/**'
217+ # CLI commands
218+ - 'src/supy/cmd/**'
219+ # JSON configs
220+ - 'src/supy/*.json'
221+ # Schemas
222+ - 'schemas/**'
223+ # Build system / infra
224+ - '.github/**'
199225 - 'pyproject.toml'
200226 - 'meson.build'
201227 - 'meson_options.txt'
202228 - 'Makefile'
203229 - 'get_ver_git.py'
230+ - 'scripts/**'
231+ tests:
232+ - 'test/**'
204233
205234 # Determine if we should run limited or full matrix
206235 determine_matrix :
207236 name : Determine build matrix
208237 runs-on : ubuntu-latest
238+ needs : [detect-changes]
239+ # Always run - detect-changes is skipped for non-PR events, but we still need matrix
240+ if : always() && (needs.detect-changes.result == 'success' || needs.detect-changes.result == 'skipped')
209241 outputs :
210242 buildplat : ${{ steps.set-matrix.outputs.buildplat }}
211243 python : ${{ steps.set-matrix.outputs.python }}
212244 umep_buildplat : ${{ steps.set-matrix.outputs.umep_buildplat }}
213245 umep_python : ${{ steps.set-matrix.outputs.umep_python }}
246+ test_tier : ${{ steps.set-matrix.outputs.test_tier }}
214247 steps :
215248 - name : Set matrix based on trigger type
216249 id : set-matrix
@@ -220,30 +253,67 @@ jobs:
220253 PR_PLATFORMS='[["ubuntu-latest", "manylinux", "x86_64"], ["macos-latest", "macosx", "arm64"], ["windows-2025", "win", "AMD64"]]'
221254 MINIMAL_PLATFORMS='[["ubuntu-latest", "manylinux", "x86_64"]]'
222255
256+ CORE_CHANGED="${{ needs.detect-changes.outputs.core-changed || 'false' }}"
257+ UTIL_CHANGED="${{ needs.detect-changes.outputs.util-changed || 'false' }}"
258+ CFG_CHANGED="${{ needs.detect-changes.outputs.cfg-changed || 'false' }}"
259+ TESTS_CHANGED="${{ needs.detect-changes.outputs.tests-changed || 'false' }}"
260+
223261 # Python version strategies:
224262 # - Draft PR: minimal (1 platform, bookend versions) for fastest feedback
225263 # - PR/Master: reduced (ARM Mac + Linux + Windows, bookend versions) for speed with good coverage
226264 # - Tags/Schedule/Manual: full (all platforms including x86_64 Mac, all Python versions) for comprehensive testing
227265
228266 if [[ "${{ github.event_name }}" == "pull_request" ]] && [[ "${{ github.event.pull_request.draft }}" == "true" ]]; then
229- echo "Running minimal matrix for draft PR (1 platform, bookend Python versions)"
230- echo "buildplat=$MINIMAL_PLATFORMS" >> $GITHUB_OUTPUT
231- echo 'python=["cp39", "cp314"]' >> $GITHUB_OUTPUT
232- elif [[ "${{ github.event_name }}" == "pull_request" ]] || [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/master" ]]; then
233- echo "Running reduced matrix for PR/master (ARM Mac + Linux + Windows, bookend Python versions)"
234- echo "buildplat=$PR_PLATFORMS" >> $GITHUB_OUTPUT
235- echo 'python=["cp39", "cp314"]' >> $GITHUB_OUTPUT
267+ if [[ "$CORE_CHANGED" == "true" ]]; then
268+ echo "Draft PR with core changes - reduced platforms, core tests"
269+ echo "buildplat=$PR_PLATFORMS" >> $GITHUB_OUTPUT
270+ echo 'python=["cp39", "cp314"]' >> $GITHUB_OUTPUT
271+ echo "test_tier=core" >> $GITHUB_OUTPUT
272+ elif [[ "$CFG_CHANGED" == "true" ]]; then
273+ echo "Draft PR with cfg changes - reduced platforms, cfg tests"
274+ echo "buildplat=$PR_PLATFORMS" >> $GITHUB_OUTPUT
275+ echo 'python=["cp39", "cp314"]' >> $GITHUB_OUTPUT
276+ echo "test_tier=cfg" >> $GITHUB_OUTPUT
277+ else
278+ echo "Draft PR with util/tests changes - minimal platform, smoke tests"
279+ echo "buildplat=$MINIMAL_PLATFORMS" >> $GITHUB_OUTPUT
280+ echo 'python=["cp39", "cp314"]' >> $GITHUB_OUTPUT
281+ echo "test_tier=smoke" >> $GITHUB_OUTPUT
282+ fi
283+ elif [[ "${{ github.event_name }}" == "pull_request" ]]; then
284+ if [[ "$CORE_CHANGED" == "true" ]]; then
285+ echo "Ready PR with core changes - reduced platforms, standard tests"
286+ echo "buildplat=$PR_PLATFORMS" >> $GITHUB_OUTPUT
287+ echo 'python=["cp39", "cp314"]' >> $GITHUB_OUTPUT
288+ echo "test_tier=standard" >> $GITHUB_OUTPUT
289+ elif [[ "$CFG_CHANGED" == "true" ]]; then
290+ echo "Ready PR with cfg changes - reduced platforms, standard tests"
291+ echo "buildplat=$PR_PLATFORMS" >> $GITHUB_OUTPUT
292+ echo 'python=["cp39", "cp314"]' >> $GITHUB_OUTPUT
293+ echo "test_tier=standard" >> $GITHUB_OUTPUT
294+ else
295+ echo "Ready PR with util/tests changes - reduced platforms, smoke tests"
296+ echo "buildplat=$PR_PLATFORMS" >> $GITHUB_OUTPUT
297+ echo 'python=["cp39", "cp314"]' >> $GITHUB_OUTPUT
298+ echo "test_tier=smoke" >> $GITHUB_OUTPUT
299+ fi
300+ elif [[ "${{ github.event_name }}" == "schedule" ]]; then
301+ echo "Running full matrix for nightly (all platforms, all Python versions, all tests)"
302+ echo "buildplat=$FULL_PLATFORMS" >> $GITHUB_OUTPUT
303+ echo 'python=["cp39", "cp310", "cp311", "cp312", "cp313", "cp314"]' >> $GITHUB_OUTPUT
304+ echo "test_tier=all" >> $GITHUB_OUTPUT
236305 else
237- echo "Running full matrix for tags/schedule/ manual (all platforms including x86_64 Mac , all Python versions)"
306+ echo "Running full matrix for tags/manual (all platforms, all Python versions, all tests )"
238307 echo "buildplat=$FULL_PLATFORMS" >> $GITHUB_OUTPUT
239308 echo 'python=["cp39", "cp310", "cp311", "cp312", "cp313", "cp314"]' >> $GITHUB_OUTPUT
309+ echo "test_tier=all" >> $GITHUB_OUTPUT
240310 fi
241311
242312 # UMEP builds: Python 3.12 only (aligned with QGIS 3.40 LTR bundled Python)
243- # PR: manylinux only for quick validation
313+ # PR/nightly: Windows only (QGIS primary platform) for quick validation
244314 # Production: all platforms for complete UMEP distribution
245315 echo "UMEP matrix: cp312 only (QGIS 3.40 LTR uses Python 3.12)"
246- echo 'umep_buildplat=[["ubuntu-latest ", "manylinux ", "x86_64 "]]' >> $GITHUB_OUTPUT
316+ echo 'umep_buildplat=[["windows-2025 ", "win ", "AMD64 "]]' >> $GITHUB_OUTPUT
247317 echo 'umep_python=["cp312"]' >> $GITHUB_OUTPUT
248318
249319 build_wheels :
@@ -280,6 +350,7 @@ jobs:
280350 python : ${{ matrix.python }}
281351 is_umep_variant : ' false'
282352 wheel_name_suffix : ' '
353+ test_tier : ${{ needs.determine_matrix.outputs.test_tier }}
283354
284355 build_umep :
285356 name : Build UMEP wheel (rc1/dev1) for ${{ matrix.python }}-${{ matrix.buildplat[1] }} ${{ matrix.buildplat[2] }}
@@ -321,6 +392,7 @@ jobs:
321392 python : ${{ matrix.python }}
322393 is_umep_variant : ' true'
323394 wheel_name_suffix : ' -umep'
395+ test_tier : ${{ needs.determine_matrix.outputs.test_tier }}
324396
325397 # PR gate: single consolidated check for branch protection
326398 # This job ALWAYS runs for PRs and reports pass/fail based on build results
@@ -467,7 +539,7 @@ jobs:
467539 needs :
468540 - deploy_pypi
469541 # Run whenever PyPI deployment succeeds (already ensures it's a production tag)
470- if : needs.deploy_pypi.result == 'success'
542+ if : always() && needs.deploy_pypi.result == 'success'
471543
472544 permissions :
473545 contents : write # Required to create releases
0 commit comments