Test workflow #2223
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test workflow | |
| permissions: | |
| contents: read | |
| checks: write | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - "**" | |
| schedule: | |
| - cron: "23 3 * * 0" | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.ref }}-${{ github.workflow }} | |
| cancel-in-progress: true | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.13" | |
| - name: Run focused Ruff checks | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install "ruff>=0.8,<1.0" | |
| ruff check . | |
| minimal-install: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Install system build dependencies (when binary not available) | |
| run: | | |
| retry() { | |
| for attempt in 1 2 3; do | |
| "$@" && return 0 | |
| echo "Command failed on attempt ${attempt}; retrying..." | |
| sleep $((attempt * 20)) | |
| done | |
| "$@" | |
| } | |
| disable_unavailable_apt_sources() { | |
| sudo rm -f \ | |
| /etc/apt/sources.list.d/azure-cli.list \ | |
| /etc/apt/sources.list.d/azure-cli.sources \ | |
| /etc/apt/sources.list.d/microsoft-prod.list \ | |
| /etc/apt/sources.list.d/microsoft-prod.sources | |
| } | |
| disable_unavailable_apt_sources | |
| retry sudo apt-get update | |
| retry sudo apt-get install -y \ | |
| gfortran pkg-config ninja-build \ | |
| libopenblas-dev liblapack-dev \ | |
| libfftw3-dev libhealpix-cxx-dev | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.13" | |
| - name: Install default package and run public smoke check | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install . | |
| python - <<'PY' | |
| import pyrecest | |
| from pyrecest.backend import array, diag | |
| from pyrecest.filters import KalmanFilter | |
| kf = KalmanFilter((array([0.0, 1.0]), diag(array([1.0, 1.0])))) | |
| print(f"Imported pyrecest {pyrecest.__version__}; initial estimate={kf.get_point_estimate()}") | |
| PY | |
| docs: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.13" | |
| - name: Install documentation dependencies | |
| run: | | |
| retry() { | |
| for attempt in 1 2 3; do | |
| "$@" && return 0 | |
| echo "Command failed on attempt ${attempt}; retrying..." | |
| sleep $((attempt * 20)) | |
| done | |
| "$@" | |
| } | |
| python -m pip install --upgrade pip | |
| retry python -m pip install poetry | |
| poetry env use python | |
| retry poetry install --only docs --no-root | |
| - name: Build documentation | |
| run: poetry run mkdocs build --strict | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/src | |
| - name: Check backend API matrix documentation | |
| run: poetry run python scripts/check_backend_api_matrix.py | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/src | |
| package: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Install system build dependencies (when binary not available) | |
| run: | | |
| retry() { | |
| for attempt in 1 2 3; do | |
| "$@" && return 0 | |
| echo "Command failed on attempt ${attempt}; retrying..." | |
| sleep $((attempt * 20)) | |
| done | |
| "$@" | |
| } | |
| disable_unavailable_apt_sources() { | |
| sudo rm -f \ | |
| /etc/apt/sources.list.d/azure-cli.list \ | |
| /etc/apt/sources.list.d/azure-cli.sources \ | |
| /etc/apt/sources.list.d/microsoft-prod.list \ | |
| /etc/apt/sources.list.d/microsoft-prod.sources | |
| } | |
| disable_unavailable_apt_sources | |
| retry sudo apt-get update | |
| retry sudo apt-get install -y \ | |
| gfortran pkg-config ninja-build \ | |
| libopenblas-dev liblapack-dev \ | |
| libfftw3-dev libhealpix-cxx-dev | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.13" | |
| - name: Build distributions and validate local release metadata | |
| run: | | |
| retry() { | |
| for attempt in 1 2 3; do | |
| "$@" && return 0 | |
| echo "Command failed on attempt ${attempt}; retrying..." | |
| sleep $((attempt * 20)) | |
| done | |
| "$@" | |
| } | |
| python -m pip install --upgrade pip | |
| retry python -m pip install build twine | |
| python scripts/check_release_consistency.py --local-only | |
| python -m build | |
| python -m twine check dist/* | |
| - name: Smoke-test default wheel in a clean environment | |
| run: | | |
| python -m venv /tmp/pyrecest-default-wheel | |
| /tmp/pyrecest-default-wheel/bin/python -m pip install --upgrade pip | |
| /tmp/pyrecest-default-wheel/bin/python -m pip install dist/*.whl | |
| /tmp/pyrecest-default-wheel/bin/python - <<'PY' | |
| import pyrecest | |
| from pyrecest.filters import KalmanFilter | |
| print(f"Installed pyrecest {pyrecest.__version__}") | |
| print(f"Resolved baseline filter {KalmanFilter.__name__}") | |
| PY | |
| - name: Install built wheel and smoke-run public examples | |
| run: | | |
| python -m pip install dist/*.whl | |
| python - <<'PY' | |
| import pyrecest | |
| print(f"Installed pyrecest {pyrecest.__version__}") | |
| PY | |
| python scripts/check_minimal_imports.py | |
| python examples/basic/kalman_filter.py | |
| python examples/basic/gaussian_multiplication.py | |
| python scripts/run_scenario.py scenarios/linear_gaussian_cv_1d/config.toml --expected scenarios/linear_gaussian_cv_1d/expected.json | |
| python benchmarks/basic_regressions.py --output benchmark-results.json | |
| python scripts/check_benchmark_regression.py \ | |
| benchmark-results.json \ | |
| benchmarks/baselines/basic_regressions-linux-py313.json | |
| python scripts/check_benchmark_results.py benchmark-results.json --baseline benchmarks/baselines/basic_regressions.json | |
| - name: Upload benchmark result artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: package-benchmark-results | |
| path: benchmark-results.json | |
| test: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - backend: numpy | |
| python-version: "3.11" | |
| - backend: numpy | |
| python-version: "3.12" | |
| - backend: numpy | |
| python-version: "3.13" | |
| - backend: numpy | |
| python-version: "3.14" | |
| - backend: pytorch | |
| python-version: "3.11" | |
| - backend: pytorch | |
| python-version: "3.12" | |
| - backend: pytorch | |
| python-version: "3.13" | |
| - backend: jax | |
| python-version: "3.11" | |
| - backend: jax | |
| python-version: "3.12" | |
| - backend: jax | |
| python-version: "3.13" | |
| permissions: | |
| checks: write | |
| pull-requests: write | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Install system build dependencies (when binary not available) | |
| run: | | |
| retry() { | |
| for attempt in 1 2 3; do | |
| "$@" && return 0 | |
| echo "Command failed on attempt ${attempt}; retrying..." | |
| sleep $((attempt * 20)) | |
| done | |
| "$@" | |
| } | |
| disable_unavailable_apt_sources() { | |
| sudo rm -f \ | |
| /etc/apt/sources.list.d/azure-cli.list \ | |
| /etc/apt/sources.list.d/azure-cli.sources \ | |
| /etc/apt/sources.list.d/microsoft-prod.list \ | |
| /etc/apt/sources.list.d/microsoft-prod.sources | |
| } | |
| disable_unavailable_apt_sources | |
| retry sudo apt-get update | |
| retry sudo apt-get install -y \ | |
| gfortran pkg-config ninja-build \ | |
| libopenblas-dev liblapack-dev \ | |
| libfftw3-dev libhealpix-cxx-dev | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install dependencies | |
| run: | | |
| retry() { | |
| for attempt in 1 2 3; do | |
| "$@" && return 0 | |
| echo "Command failed on attempt ${attempt}; retrying..." | |
| sleep $((attempt * 20)) | |
| done | |
| "$@" | |
| } | |
| python -m pip install --upgrade pip | |
| retry python -m pip install poetry | |
| poetry env use python | |
| case "${{ matrix.backend }}" in | |
| numpy) | |
| retry poetry install --with dev --extras "healpy_support" | |
| ;; | |
| pytorch) | |
| retry poetry install --with dev --extras "healpy_support" | |
| retry poetry run python -m pip install \ | |
| --index-url https://download.pytorch.org/whl/cpu \ | |
| --extra-index-url https://pypi.org/simple \ | |
| "torch>=2.4,<3.0" | |
| ;; | |
| jax) | |
| retry poetry install --with dev --extras "healpy_support jax_support" | |
| ;; | |
| *) | |
| echo "Unsupported backend: ${{ matrix.backend }}" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| - name: Run tests | |
| run: | | |
| if [ "${{ matrix.backend }}" = "jax" ]; then | |
| export JAX_ENABLE_X64=True | |
| fi | |
| export PYRECEST_BACKEND=${{ matrix.backend }} | |
| poetry run python -m pytest \ | |
| --rootdir . \ | |
| -v \ | |
| --strict-config \ | |
| --junitxml=junit_test_results_${{ matrix.backend }}.xml \ | |
| --cov=pyrecest \ | |
| --cov-report=term-missing \ | |
| --cov-report=xml:coverage_${{ matrix.backend }}_${{ matrix.python-version }}.xml \ | |
| ./tests | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/src | |
| - name: Upload test result artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ${{ matrix.backend }}-${{ matrix.python-version }}-test-results | |
| path: junit_test_results_${{ matrix.backend }}.xml | |
| - name: Upload coverage artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ${{ matrix.backend }}-${{ matrix.python-version }}-coverage | |
| path: coverage_${{ matrix.backend }}_${{ matrix.python-version }}.xml | |
| full-test: | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| backend: [numpy, pytorch, jax] | |
| python-version: ["3.11", "3.12", "3.13", "3.14"] | |
| permissions: | |
| checks: write | |
| pull-requests: write | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Install system build dependencies (when binary not available) | |
| run: | | |
| retry() { | |
| for attempt in 1 2 3; do | |
| "$@" && return 0 | |
| echo "Command failed on attempt ${attempt}; retrying..." | |
| sleep $((attempt * 20)) | |
| done | |
| "$@" | |
| } | |
| disable_unavailable_apt_sources() { | |
| sudo rm -f \ | |
| /etc/apt/sources.list.d/azure-cli.list \ | |
| /etc/apt/sources.list.d/azure-cli.sources \ | |
| /etc/apt/sources.list.d/microsoft-prod.list \ | |
| /etc/apt/sources.list.d/microsoft-prod.sources | |
| } | |
| disable_unavailable_apt_sources | |
| retry sudo apt-get update | |
| retry sudo apt-get install -y \ | |
| gfortran pkg-config ninja-build \ | |
| libopenblas-dev liblapack-dev \ | |
| libfftw3-dev libhealpix-cxx-dev | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install dependencies | |
| run: | | |
| retry() { | |
| for attempt in 1 2 3; do | |
| "$@" && return 0 | |
| echo "Command failed on attempt ${attempt}; retrying..." | |
| sleep $((attempt * 20)) | |
| done | |
| "$@" | |
| } | |
| python -m pip install --upgrade pip | |
| retry python -m pip install poetry | |
| poetry env use python | |
| case "${{ matrix.backend }}" in | |
| numpy) | |
| retry poetry install --with dev --extras "healpy_support" | |
| ;; | |
| pytorch) | |
| retry poetry install --with dev --extras "healpy_support" | |
| retry poetry run python -m pip install \ | |
| --index-url https://download.pytorch.org/whl/cpu \ | |
| --extra-index-url https://pypi.org/simple \ | |
| "torch>=2.4,<3.0" | |
| ;; | |
| jax) | |
| retry poetry install --with dev --extras "healpy_support jax_support" | |
| ;; | |
| *) | |
| echo "Unsupported backend: ${{ matrix.backend }}" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| - name: Run full backend matrix | |
| run: | | |
| if [ "${{ matrix.backend }}" = "jax" ]; then | |
| export JAX_ENABLE_X64=True | |
| fi | |
| export PYRECEST_BACKEND=${{ matrix.backend }} | |
| poetry run python -m pytest --rootdir . -v --strict-config --junitxml=junit_test_results_${{ matrix.backend }}.xml ./tests | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/src | |
| - name: Upload test result artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: full-${{ matrix.backend }}-${{ matrix.python-version }}-test-results | |
| path: junit_test_results_${{ matrix.backend }}.xml | |
| publish-results: | |
| needs: [test, full-test] | |
| runs-on: ubuntu-latest | |
| if: always() && (needs.test.result != 'skipped' || needs.full-test.result != 'skipped') | |
| permissions: | |
| checks: write | |
| pull-requests: write | |
| steps: | |
| - name: Download all test result artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: test-results | |
| - name: Publish test results | |
| uses: EnricoMi/publish-unit-test-result-action@v2 | |
| with: | |
| comment_mode: off | |
| compare_to_earlier_commit: false | |
| github_token: ${{ github.token }} | |
| files: | | |
| test-results/*/junit_test_results_*.xml |