Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 0 additions & 23 deletions .github/workflows/draft-pdf.yml

This file was deleted.

197 changes: 184 additions & 13 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,199 @@
---
name: build

on: [push, pull_request]
on:

Check warning on line 4 in .github/workflows/workflow.yml

View workflow job for this annotation

GitHub Actions / pre-commit

4:1 [truthy] truthy value should be one of [false, true]

Check warning on line 4 in .github/workflows/workflow.yml

View workflow job for this annotation

GitHub Actions / pre-commit

4:1 [truthy] truthy value should be one of [false, true]
push:
branches: [main, master, 'release/**']
pull_request:
schedule:
# Weekly, Monday 06:00 UTC. Catches upstream dependency breakage before a
# user does, which is how the NumPy 2 and pandas 3 failures reached release.
- cron: '0 6 * * 1'
workflow_dispatch:

# Superseded runs on the same ref are pointless; cancel them.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
build:
name: Build (${{ matrix.os }}, Python ${{ matrix.python-version }})
test:
name: Test (${{ matrix.os }}, Python ${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
strategy:
# Report every platform failure, not just the first.
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.9", "3.10", "3.11"]
python-version: ['3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
# This repository carries a large history relative to its working
# tree; a blobless checkout avoids transferring it.
filter: blob:none
fetch-depth: 1

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
cache: pip
cache-dependency-path: requirements.txt

- name: Install
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

- name: Run offline test suite
# No network and no package data: capability-gated tests skip visibly.
run: python -m pytest tests -v --cov=stitches --cov-report=xml --cov-report=term

Check failure on line 54 in .github/workflows/workflow.yml

View workflow job for this annotation

GitHub Actions / pre-commit

54:81 [line-length] line too long (88 > 80 characters)

Check failure on line 54 in .github/workflows/workflow.yml

View workflow job for this annotation

GitHub Actions / pre-commit

54:81 [line-length] line too long (88 > 80 characters)

- name: Upload coverage
# Previously coverage.xml was generated and then discarded.
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
uses: codecov/codecov-action@v4
with:
files: ./coverage.xml
fail_ci_if_error: false

regression:
name: Output invariance
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
filter: blob:none
fetch-depth: 1

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: pip
cache-dependency-path: requirements.txt

- name: Install
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

- name: Assert outputs are unchanged
run: python -m pytest tests/regression -v -m regression

- name: Assert golden artifacts were not silently modified
# --update-golden must never run in CI. If the working tree is dirty
# after the suite, something rewrote a golden artifact, which would let
# an output change pass review unnoticed.
run: |
if ! git diff --quiet -- tests/regression/golden; then
echo "::error::Golden artifacts were modified during the test run."
git diff --stat -- tests/regression/golden
exit 1
fi

benchmark:
name: Performance
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
filter: blob:none
fetch-depth: 1

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: pip
cache-dependency-path: requirements.txt

- name: Install
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
python -m pip install pytest-benchmark

- name: Run benchmarks
# Informational: shared runners are far too noisy to gate a merge on.
# The saved JSON is what makes trends reviewable over time.
run: |
python -m pytest benchmarks --benchmark-only \
--benchmark-json=benchmark-results.json \
--benchmark-columns=mean,stddev,rounds \
--benchmark-sort=mean

- name: Upload benchmark results
uses: actions/upload-artifact@v4
with:
name: benchmark-results-${{ github.sha }}
path: benchmark-results.json
retention-days: 90

integration:
name: Network and package data
# Requires the Zenodo download and live Pangeo access, so it is too slow and
# too flaky on third-party availability to run on every push.
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'

Check failure on line 139 in .github/workflows/workflow.yml

View workflow job for this annotation

GitHub Actions / pre-commit

139:81 [line-length] line too long (83 > 80 characters)

Check failure on line 139 in .github/workflows/workflow.yml

View workflow job for this annotation

GitHub Actions / pre-commit

139:81 [line-length] line too long (83 > 80 characters)
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
with:
filter: blob:none
fetch-depth: 1

- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: pip
cache-dependency-path: requirements.txt

- name: Install
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install .
- name: Test and generate coverage report on Linux
python -m pip install -e ".[dev]"

- name: Cache Zenodo package data
uses: actions/cache@v4
with:
path: stitches/data
# Keyed on the Zenodo record so a data revision busts the cache.
key: stitches-pkgdata-8367628

- name: Run network and package-data tests
run: |
pip install pytest
pip install pytest-cov
pytest --cov=./ --cov-report=xml
python -m pytest tests -v --network --slow --package-data

latest-deps:
name: Latest dependencies
# Resolves dependencies without the repository pins to surface upstream
# breakage early. Allowed to fail so it warns rather than blocks.
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'

Check failure on line 174 in .github/workflows/workflow.yml

View workflow job for this annotation

GitHub Actions / pre-commit

174:81 [line-length] line too long (83 > 80 characters)

Check failure on line 174 in .github/workflows/workflow.yml

View workflow job for this annotation

GitHub Actions / pre-commit

174:81 [line-length] line too long (83 > 80 characters)
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
with:
filter: blob:none
fetch-depth: 1

- uses: actions/setup-python@v5
with:
python-version: '3.13'

- name: Install with newest resolvable dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade \
matplotlib xarray numpy pandas intake intake-esm nc_time_axis \
scikit-learn 'fsspec[gcs]' tqdm requests pytest pyarrow
python -m pip install -e . --no-deps

- name: Report resolved versions
run: python -m pip list

- name: Run offline suite against latest dependencies
run: python -m pytest tests -v
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ tests/.DS_Store
# pycharm
.idea

# vscode
.vscode

# local development virtualenvs
.venv/
venv/
env/

# pytest-benchmark results
.benchmarks/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
33 changes: 28 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,36 @@ repos:
rev: v3.8.0
hooks:
- id: pyupgrade
args: ['--py39-plus']
args: ['--py310-plus']
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: debug-statements
- id: check-merge-conflict
- id: check-yaml
- id: check-toml
# Repository history is ~140x the size of the working tree because large
# generated artifacts were committed and later deleted. This blocks the
# next one. See plans/repo-clone-performance.md.
# Golden regression artifacts are excluded: they are intentionally
# committed, small, and individually well under this limit.
- id: check-added-large-files
args: ['--maxkb=512']

# Jupyter notebooks are the single largest recurring contributor to repository
# growth: stitches-quickstart.ipynb alone accumulated 38.5 MB across 31
# revisions because base64-encoded PNG outputs are committed. Re-running a
# notebook rewrites every image byte-for-byte on one enormous JSON line, which
# git cannot delta-compress, so each commit stores a full new copy.
#
# Stripping outputs means GitHub's static renderer shows no figures; the
# executed notebooks are published through the nbsphinx docs build instead.
- repo: https://github.com/kynan/nbstripout
rev: 0.7.1
hooks:
- id: nbstripout
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
hooks:
Expand All @@ -25,7 +48,7 @@ repos:
rev: 23.3.0
hooks:
- id: black
args: ['--target-version=py39']
args: ['--target-version=py310']
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
Expand All @@ -40,11 +63,11 @@ repos:
rev: 1.7.0
hooks:
- id: nbqa-pyupgrade
args: ['--py39-plus']
args: ['--py310-plus']
additional_dependencies: ['pyupgrade==3.8.0']
- id: nbqa-black
additional_dependencies: ['black==23.3.0']
args: ['--line-length=88', '--target-version=py39']
args: ['--line-length=88', '--target-version=py310']
- id: nbqa-isort
additional_dependencies: ['isort==5.12.0']
args: ['--profile=black']
Expand All @@ -57,7 +80,7 @@ repos:
hooks:
- id: blackdoc
additional_dependencies: ['black==23.3.0']
args: ['--target-version=py39']
args: ['--target-version=py310']
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.32.0
hooks:
Expand Down
Loading
Loading