From f2e990e0929d929ff84ccd21ad5bf2af92f9181e Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Wed, 29 Jul 2026 13:18:14 +0100 Subject: [PATCH] ci: align Python floor matrix --- .github/workflows/python_matrix.yml | 89 +++++++++++++++++++++++----- bin/autohands | 5 +- tests/test_python_matrix_workflow.py | 63 ++++++++++++++++++++ 3 files changed, 139 insertions(+), 18 deletions(-) create mode 100644 tests/test_python_matrix_workflow.py diff --git a/.github/workflows/python_matrix.yml b/.github/workflows/python_matrix.yml index 622b8e7e..64c7d745 100644 --- a/.github/workflows/python_matrix.yml +++ b/.github/workflows/python_matrix.yml @@ -22,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] + python-version: ['3.12', '3.13'] project: - { name: PyAutoNerves, tests: test_autonerves } - { name: PyAutoArray, tests: test_autoarray } @@ -71,15 +71,74 @@ jobs: cd ${{ matrix.project.name }} python -m pytest ${{ matrix.project.tests }}/ --tb=short + # Python 3.14 is deliberately unit-suite evidence only. The known PyAutoFit + # workspace-level factor-graph regression is tracked separately and is not + # exercised by this job. Every project gets an isolated cell, but a failure + # cannot weaken or mask the required 3.12/3.13 matrix above. + experimental_python_314: + runs-on: ubuntu-latest + continue-on-error: true + strategy: + fail-fast: false + matrix: + python-version: ['3.14'] + project: + - { name: PyAutoNerves, tests: test_autonerves } + - { name: PyAutoArray, tests: test_autoarray } + - { name: PyAutoFit, tests: test_autofit } + - { name: PyAutoGalaxy, tests: test_autogalaxy } + - { name: PyAutoLens, tests: test_autolens } + steps: + - uses: actions/checkout@v4 + with: { repository: PyAutoLabs/PyAutoNerves, path: PyAutoNerves } + - uses: actions/checkout@v4 + with: { repository: PyAutoLabs/PyAutoArray, path: PyAutoArray } + - uses: actions/checkout@v4 + with: { repository: PyAutoLabs/PyAutoFit, path: PyAutoFit } + - uses: actions/checkout@v4 + with: { repository: PyAutoLabs/PyAutoGalaxy, path: PyAutoGalaxy } + - uses: actions/checkout@v4 + with: { repository: PyAutoLabs/PyAutoLens, path: PyAutoLens } + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + allow-prereleases: true + - name: Install libraries (experimental 3.14 evidence) + run: | + python -m pip install --upgrade pip wheel + pip install \ + -e ./PyAutoNerves \ + -e "./PyAutoArray[optional]" \ + -e ./PyAutoFit \ + -e ./PyAutoGalaxy \ + -e "./PyAutoLens[optional]" + pip install pytest pytest-cov + pip list | grep -iE "^(autonerves|autoarray|autofit|autogalaxy|autolens|jax|numpy|scipy|nautilus)" + - name: Run experimental tests + env: + NUMBA_CACHE_DIR: /tmp/numba_cache + MPLCONFIGDIR: /tmp/matplotlib + JAX_ENABLE_X64: "True" + run: | + cd ${{ matrix.project.name }} + python -m pytest ${{ matrix.project.tests }}/ --tb=short + - name: Record experimental cell result + if: always() + run: | + { + echo "### Python 3.14 experimental unit evidence" + echo "" + echo "- Project: ${{ matrix.project.name }}" + echo "- Cell status before continue-on-error: ${{ job.status }}" + echo "- This cell is non-required and does not cover workspace scripts." + } >> "$GITHUB_STEP_SUMMARY" + smoke_tests: runs-on: ubuntu-latest strategy: fail-fast: false matrix: - # 3.11+ only: the smoke set includes JAX/optax demos (e.g. autofit - # searches/mle.py MultiStartAdam), and autonerves[jax] is gated to - # Python >= 3.11. Unit tests below still cover 3.9/3.10 (numpy-only). - python-version: ['3.11', '3.12', '3.13'] + python-version: ['3.12', '3.13'] workspace: - { repo: PyAutoLabs/autofit_workspace, path: autofit_workspace } - { repo: PyAutoLabs/autogalaxy_workspace, path: autogalaxy_workspace } @@ -90,6 +149,7 @@ jobs: PYAUTO_FAST_PLOTS: "1" NUMBA_CACHE_DIR: /tmp/numba_cache MPLCONFIGDIR: /tmp/matplotlib + JAX_ENABLE_X64: "True" steps: - uses: actions/checkout@v4 with: { repository: PyAutoLabs/PyAutoNerves, path: PyAutoNerves } @@ -118,11 +178,6 @@ jobs: -e "./PyAutoLens[optional]" pip install numba pip list | grep -iE "^(autonerves|autoarray|autofit|autogalaxy|autolens|jax|numpy|scipy|nautilus)" - - name: Enable JAX_ENABLE_X64 on 3.11+ - run: | - if python -c "import sys; sys.exit(0 if sys.version_info >= (3, 11) else 1)"; then - echo "JAX_ENABLE_X64=True" >> $GITHUB_ENV - fi - name: Run smoke tests run: | cd ${{ matrix.workspace.path }} @@ -150,7 +205,7 @@ jobs: summary: runs-on: ubuntu-latest - needs: [unit_tests, smoke_tests] + needs: [unit_tests, smoke_tests, experimental_python_314] if: always() steps: - name: Post summary @@ -162,11 +217,13 @@ jobs: echo "|--------------|---------------------------------|" echo "| unit_tests | ${{ needs.unit_tests.result }} |" echo "| smoke_tests | ${{ needs.smoke_tests.result }} |" + echo "| python_314 (non-required job conclusion) | ${{ needs.experimental_python_314.result }} |" echo "" - echo "Per-cell pass/fail (Python version × project) is visible in" - echo "the matrix job logs above." + echo "Each 3.14 matrix cell records its pre-continue-on-error status" + echo "in that cell's summary; the aggregate conclusion may be coerced" + echo "to success by GitHub's job-level continue-on-error semantics." echo "" - echo "**Recommended:** 3.12, 3.13 (first-class)." - echo "**Supported with warning:** 3.9, 3.10, 3.11, 3.14." - echo "**JAX features:** 3.11+ only." + echo "**Required and supported:** 3.12, 3.13." + echo "**Experimental evidence (non-required):** 3.14." + echo "**Current source metadata rejects:** Python 3.11 and older." } >> "$GITHUB_STEP_SUMMARY" diff --git a/bin/autohands b/bin/autohands index 300aa116..86860488 100755 --- a/bin/autohands +++ b/bin/autohands @@ -116,11 +116,12 @@ cmd_pre_build() { help_verify_install() { cat <<'EOF' -autohands verify_install [CHECKS...] [--version VERSION] [--keep] +autohands verify_install [CHECKS...] [--version VERSION] [--testpypi] + [--find-links DIR] [--keep] Shim → `pyauto-heart verify_install`. Release-readiness checking is Heart's job now (PyAutoHands is a pure executor), so this delegates to PyAutoHeart, -which owns the install-path checks (pip & conda, A–E) and writes the JSON +which owns the install-path checks (pip, conda & Colab, A–F) and writes the JSON sidecar that `pyauto-heart readiness` consumes. See `pyauto-heart help verify_install` for full docs. diff --git a/tests/test_python_matrix_workflow.py b/tests/test_python_matrix_workflow.py new file mode 100644 index 00000000..8b02e474 --- /dev/null +++ b/tests/test_python_matrix_workflow.py @@ -0,0 +1,63 @@ +from pathlib import Path + +import yaml + + +WORKFLOW = ( + Path(__file__).resolve().parents[1] / ".github" / "workflows" / "python_matrix.yml" +) +AUTOHANDS = Path(__file__).resolve().parents[1] / "bin" / "autohands" + + +def load_workflow(): + return yaml.safe_load(WORKFLOW.read_text()) + + +def test_required_matrices_cover_only_supported_python_versions(): + jobs = load_workflow()["jobs"] + + assert jobs["unit_tests"]["strategy"]["matrix"]["python-version"] == [ + "3.12", + "3.13", + ] + assert jobs["smoke_tests"]["strategy"]["matrix"]["python-version"] == [ + "3.12", + "3.13", + ] + + +def test_python_314_is_isolated_and_non_required(): + jobs = load_workflow()["jobs"] + experimental = jobs["experimental_python_314"] + + assert experimental["continue-on-error"] is True + assert experimental["strategy"]["matrix"]["python-version"] == ["3.14"] + assert len(experimental["strategy"]["matrix"]["project"]) == 5 + assert "experimental_python_314" in jobs["summary"]["needs"] + assert "continue-on-error" not in jobs["unit_tests"] + assert "continue-on-error" not in jobs["smoke_tests"] + + record_step = next( + step for step in experimental["steps"] + if step.get("name") == "Record experimental cell result" + ) + assert record_step["if"] == "always()" + assert "job.status" in record_step["run"] + assert "does not cover workspace scripts" in record_step["run"] + + +def test_no_below_floor_success_or_banner_contract_remains(): + text = WORKFLOW.read_text() + + assert "Supported with warning" not in text + assert "JAX features" not in text + assert "Current source metadata rejects:** Python 3.11 and older" in text + + +def test_legacy_verify_install_shim_describes_the_heart_contract(): + text = AUTOHANDS.read_text() + + assert "[--testpypi]" in text + assert "[--find-links DIR]" in text + assert "pip, conda & Colab, A–F" in text + assert "A–E" not in text