Prepare the 3.0.0b8 pre-release #1
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: CI | |
| on: | |
| push: | |
| branches: [main, master] | |
| pull_request: | |
| branches: [main, master] | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - run: pip install ruff | |
| - run: ruff check src/ tests/ | |
| - run: ruff format --check src/ tests/ | |
| test: | |
| runs-on: ${{ matrix.os }} | |
| # GUI tests use Qt; run it headless on the CI runners. | |
| env: | |
| QT_QPA_PLATFORM: offscreen | |
| # HDF5/netCDF4 segfaults under joblib-parallel writes on some runners | |
| # unless file locking is disabled (HDF5 is not fork-safe). | |
| HDF5_USE_FILE_LOCKING: "FALSE" | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| python-version: ["3.10", "3.11", "3.12"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| # Headless PySide6 on Linux needs the system EGL/GL/xkbcommon libraries | |
| # (libEGL.so.1 etc.); the macOS/Windows wheels bundle their own. | |
| - name: Install Qt system libraries for headless PySide6 (Linux) | |
| if: runner.os == 'Linux' | |
| run: sudo apt-get update && sudo apt-get install -y libegl1 libgl1 libxkbcommon0 libdbus-1-3 | |
| # gui (PySide6) + remote (paramiko) extras so the full test suite runs on CI. | |
| - run: pip install -e ".[dev,gui,remote]" | |
| # Coverage is reported (terminal + XML) but no hard threshold yet; | |
| # maintainers should set --cov-fail-under once a baseline is agreed. | |
| - run: pytest tests/ -v --tb=short --cov --cov-report=term-missing --cov-report=xml | |
| - name: Upload coverage report | |
| if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-xml | |
| path: coverage.xml | |
| if-no-files-found: warn | |
| wheel-zip-smoke: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - run: python -m pip install build | |
| - run: python -m build --wheel | |
| - run: python -m build --sdist | |
| - name: Check archive contents | |
| run: | | |
| python - <<'PY' | |
| import tarfile | |
| import zipfile | |
| from pathlib import Path | |
| expected_nc = { | |
| "openbench/dataset/IGBP.nc", | |
| "openbench/dataset/PFT.nc", | |
| "openbench/dataset/Climate_zone.nc", | |
| } | |
| wheel = next(Path("dist").glob("*.whl")) | |
| with zipfile.ZipFile(wheel) as zf: | |
| wheel_nc = {name for name in zf.namelist() if name.endswith(".nc")} | |
| if wheel_nc != expected_nc: | |
| raise SystemExit(f"unexpected wheel NetCDF members: {sorted(wheel_nc)}") | |
| sdist = next(Path("dist").glob("*.tar.gz")) | |
| with tarfile.open(sdist, "r:gz") as tf: | |
| sdist_nc = { | |
| "/".join(Path(name).parts[-4:]) | |
| for name in tf.getnames() | |
| if name.endswith(".nc") | |
| } | |
| expected_sdist_nc = {"src/" + name for name in expected_nc} | |
| if sdist_nc != expected_sdist_nc: | |
| raise SystemExit(f"unexpected sdist NetCDF members: {sorted(sdist_nc)}") | |
| PY | |
| - name: Install runtime dependencies without keeping extracted OpenBench | |
| run: | | |
| WHEEL=$(echo dist/*.whl) | |
| python -m pip install "$WHEEL" | |
| python -m pip uninstall -y colm-openbench | |
| - name: Smoke test built wheel through zipimport | |
| run: | | |
| WHEEL=$(echo dist/*.whl) | |
| PYTHONPATH="$WHEEL" python -m openbench --help | |
| PYTHONPATH="$WHEEL" python -m openbench model list | tee /tmp/openbench-model-list.txt | |
| grep -q "CoLM2024" /tmp/openbench-model-list.txt | |
| PYTHONPATH="$WHEEL" python - <<'PY' | |
| import tempfile | |
| from openbench.cli.init_cmd import ensure_user_registry_overlays | |
| from openbench.config.adapter import build_fig_nml | |
| from openbench.data.registry.scanner import _has_custom_station_filter, get_reference_profile | |
| from openbench.gui.app import _prepare_stylesheet | |
| from openbench.visualization import cmaps | |
| assert build_fig_nml() | |
| assert get_reference_profile("GLEAM_v4.2a") | |
| assert cmaps.N3gauss.name == "N3gauss" | |
| assert _has_custom_station_filter("GEBA") | |
| with tempfile.TemporaryDirectory() as tmpdir: | |
| overlay = ensure_user_registry_overlays(tmpdir) | |
| assert (overlay / "custom" / "GEBA_filter.py").is_file() | |
| stylesheet, stack = _prepare_stylesheet() | |
| try: | |
| assert "CHECKMARK_PATH" not in stylesheet | |
| assert "QWidget" in stylesheet | |
| finally: | |
| stack.close() | |
| PY | |
| - name: Verify built artifacts contain no scratch files | |
| run: | | |
| python -m pip install pytest | |
| python -m pytest tests/test_build_artifacts.py -q |