From d78f6ec50a3a73eb49e246eb55c4cc601e96d935 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 3 Oct 2025 15:49:04 +0200 Subject: [PATCH 1/9] Add pixi.toml configuration for environment management - Define workspace with VirtualShip name and pixi-build preview - Configure multiple test environments (py310, py311, py312) - Set up feature environments for docs, typing, and pre-commit - Define pixi tasks for tests, docs, linting, and type checking - Align dependencies with existing pyproject.toml --- pixi.toml | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 pixi.toml diff --git a/pixi.toml b/pixi.toml new file mode 100644 index 000000000..e6d86f158 --- /dev/null +++ b/pixi.toml @@ -0,0 +1,93 @@ +[workspace] +name = "VirtualShip" +preview = ["pixi-build"] +channels = ["conda-forge"] +platforms = ["win-64", "linux-64", "osx-64", "osx-arm64"] + +[package] +name = "virtualship" +version = "dynamic" + +[package.build] +backend = { name = "pixi-build-python", version = "==0.3.2" } + +[package.host-dependencies] +setuptools = "*" +setuptools_scm = "*" + +[environments] +test-latest = { features = ["test"], solve-group = "test" } +test-py310 = { features = ["test", "py310"] } +test-py311 = { features = ["test", "py311"] } +test-py312 = { features = ["test", "py312"] } +test-notebooks = { features = ["test", "notebooks"], solve-group = "test" } +docs = { features = ["docs"], solve-group = "docs" } +typing = { features = ["typing"], solve-group = "typing" } +pre-commit = { features = ["pre-commit"], no-default-feature = true } + +[dependencies] # keep section in sync with pyproject.toml dependencies +python = ">=3.10" +click = "*" +parcels = ">3.1.0" +pyproj = ">=3,<4" +sortedcontainers = "==2.4.0" +opensimplex = "==0.4.5" +numpy = ">=1,<2" +pydantic = ">=2,<3" +pyyaml = "*" +copernicusmarine = ">=2.2.2" +yaspin = "*" +textual = "*" + +[feature.py310.dependencies] +python = "3.10.*" + +[feature.py311.dependencies] +python = "3.11.*" + +[feature.py312.dependencies] +python = "3.12.*" + +[feature.test.dependencies] +pytest = "*" +pytest-cov = "*" +pytest-asyncio = "*" +seabird = "*" +openpyxl = "*" + +[feature.test.tasks] +tests = "pytest -ra --cov --cov-report=xml --cov-report=term --durations=20" + +[feature.notebooks.dependencies] +nbval = "*" +ipykernel = "*" + +[feature.notebooks.tasks] +tests-notebooks = "pytest --nbval-lax docs/" + +[feature.docs.dependencies] +sphinx = ">=7.0" +myst-parser = ">=0.13" +nbsphinx = "*" +ipykernel = "*" +pandoc = "*" +sphinx-copybutton = "*" +pydata-sphinx-theme = "*" +sphinx-autobuild = "*" + +[feature.docs.tasks] +docs = "sphinx-build docs docs/_build" +docs-watch = "sphinx-autobuild docs docs/_build" + +[feature.pre-commit.dependencies] +pre_commit = "*" + +[feature.pre-commit.tasks] +lint = "pre-commit run --all-files" + +[feature.typing.dependencies] +mypy = "*" +lxml = "*" + +[feature.typing.tasks] +typing = "mypy src/virtualship --install-types" From 00dc6f5f498ce16d35610f6b58009ec482b7e62d Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 3 Oct 2025 15:50:36 +0200 Subject: [PATCH 2/9] Update CI workflows to use Pixi - Replace mamba-org/setup-micromamba with prefix-dev/setup-pixi - Update test job to use pixi environments (test-py310, test-py312) - Update typechecking job to use pixi run typing - Enable pixi caching for faster CI runs - Simplify workflow by removing manual dependency installation --- .github/workflows/ci.yml | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ee289de0..bc994fd3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,55 +22,43 @@ env: jobs: tests: - name: tests (${{ matrix.runs-on }} | Python ${{ matrix.python-version }}) + name: "Unit tests: ${{ matrix.runs-on }} | pixi run -e ${{ matrix.pixi-environment }} tests" runs-on: ${{ matrix.runs-on }} strategy: fail-fast: false matrix: - python-version: ["3.10", "3.12"] + pixi-environment: ["test-py310", "test-py312"] runs-on: [ubuntu-latest, windows-latest, macos-14] steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: mamba-org/setup-micromamba@v2 + - uses: prefix-dev/setup-pixi@v0.9.0 with: - environment-name: ship - environment-file: environment.yml - create-args: >- - python=${{matrix.python-version}} - - - run: pip install . --no-deps + cache: true + cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }} - name: Test package - run: >- - python -m pytest -ra --cov --cov-report=xml --cov-report=term - --durations=20 + run: pixi run -e ${{ matrix.pixi-environment }} tests - name: Upload coverage report uses: codecov/codecov-action@v5.4.0 with: token: ${{ secrets.CODECOV_TOKEN }} typechecking: - name: mypy + name: "TypeChecking: pixi run typing" runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: mamba-org/setup-micromamba@v2 + - uses: prefix-dev/setup-pixi@v0.9.0 with: - environment-name: ship - environment-file: environment.yml - create-args: >- - python=3.12 - - - run: pip install . --no-deps - - run: conda install lxml # dep for report generation + cache: true + cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }} - name: Typechecking - run: | - mypy --install-types --non-interactive src/virtualship --html-report mypy-report + run: pixi run typing --non-interactive --html-report mypy-report - name: Upload test results if: ${{ always() }} # Upload even on mypy error uses: actions/upload-artifact@v4 From 65edf75f0f0fe47a8c814a0a175b1c2b5003a53a Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 3 Oct 2025 15:51:23 +0200 Subject: [PATCH 3/9] Update contributing guidelines for Pixi - Replace Conda-based development setup with Pixi - Add comprehensive Pixi workflows section with examples - Document testing, docs, and code quality commands - Include tips for environment management and CI reproduction - Update dependency management instructions to reference pixi.toml --- docs/contributing/index.md | 72 +++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/docs/contributing/index.md b/docs/contributing/index.md index 27d6d40c3..171d714e9 100644 --- a/docs/contributing/index.md +++ b/docs/contributing/index.md @@ -8,36 +8,66 @@ We have a design document providing a conceptual overview of VirtualShip. This d ### Development installation -We use `conda` to manage our development installation. Make sure you have `conda` installed by following [the instructions here](https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html) and then run the following commands: +```{note} +VirtualShip uses [Pixi](https://pixi.sh) to manage environments and run developer tooling. Pixi is a modern alternative to Conda and also includes other powerful tooling useful for a project like VirtualShip. It is our sole development workflow - we do not offer a Conda development workflow. Give Pixi a try, you won't regret it! +``` + +To get started contributing to VirtualShip: + +**Step 1:** [Install Pixi](https://pixi.sh/latest/). + +**Step 2:** [Fork the repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo#forking-a-repository) + +**Step 3:** Clone your fork and `cd` into the repository. + +**Step 4:** Install the Pixi environment ```bash -conda create -n ship python=3.10 -conda activate ship -conda env update --file environment.yml -pip install -e . --no-deps --no-build-isolation +pixi install ``` -This creates an environment, and installs all the dependencies that you need for development, including: +Now you have a development installation of VirtualShip, as well as a bunch of developer tooling to run tests, check code quality, and build the documentation! Simple as that. + +### Pixi workflows + +You can use the following Pixi commands to run common development tasks. -- core dependencies -- development dependencies (e.g., for testing) -- documentation dependencies +**Testing** -then installs the package in editable mode. +- `pixi run tests` - Run the full test suite using pytest with coverage reporting +- `pixi run tests-notebooks` - Run notebook tests -### Useful commands +**Documentation** -The following commands are useful for local development: +- `pixi run docs` - Build the documentation using Sphinx +- `pixi run docs-watch` - Build and auto-rebuild documentation when files change (useful for live editing) -- `pytest` to run tests -- `pre-commit run --all-files` to run pre-commit checks -- `pre-commit install` (optional) to install pre-commit hooks - - this means that every time you commit, pre-commit checks will run on the files you changed -- `sphinx-autobuild docs docs/_build` to build and serve the documentation -- `sphinx-apidoc -o docs/api/ --module-first --no-toc --force src/virtualship` (optional) to generate the API documentation -- `sphinx-build -b linkcheck docs/ _build/linkcheck` to check for broken links in the documentation +**Code quality** -The running of these commands is useful for local development and quick iteration, but not _vital_ as they will be run automatically in the CI pipeline (`pre-commit` by pre-commit.ci, `pytest` by GitHub Actions, and `sphinx` by ReadTheDocs). +- `pixi run lint` - Run pre-commit hooks on all files (includes formatting, linting, and other code quality checks) +- `pixi run typing` - Run mypy type checking on the codebase + +**Different environments** + +VirtualShip supports testing against different environments (e.g., different Python versions) with different feature sets. In CI we test against these environments, and you can too locally. For example: + +- `pixi run -e test-py310 tests` - Run tests using Python 3.10 +- `pixi run -e test-py311 tests` - Run tests using Python 3.11 +- `pixi run -e test-py312 tests` - Run tests using Python 3.12 + +The name of the workflow on GitHub contains the command you have to run locally to recreate the workflow - making it super easy to reproduce CI failures locally. + +**Typical development workflow** + +1. Make your code changes +2. Run `pixi run lint` to ensure code formatting and style compliance +3. Run `pixi run tests` to verify your changes don't break existing functionality +4. If you've added new features, run `pixi run typing` to check type annotations +5. If you've modified documentation, run `pixi run docs` to build and verify the docs + +```{tip} +You can run `pixi info` to see all available environments and `pixi task list` to see all available tasks across environments. +``` ## For maintainers @@ -52,5 +82,5 @@ The running of these commands is useful for local development and quick iteratio When adding a dependency, make sure to modify the following files where relevant: -- `environment.yml` for core and development dependencies (important for the development environment, and CI) +- `pixi.toml` for core and development dependencies (important for the development environment, and CI) - `pyproject.toml` for core dependencies (important for the pypi package, this should propagate through automatically to `recipe/meta.yml` in the conda-forge feedstock) From 66085c9705b8f77abc87bbf40264f333915e6c6f Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 3 Oct 2025 15:51:45 +0200 Subject: [PATCH 4/9] Add Pixi badge to README Add Pixi badge to indicate project uses Pixi for environment management --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b9a59e706..2444bc700 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ +[![Pixi Badge](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json)](https://pixi.sh) [![Anaconda-release](https://anaconda.org/conda-forge/virtualship/badges/version.svg)](https://anaconda.org/conda-forge/virtualship/) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/virtualship) [![DOI](https://zenodo.org/badge/682478059.svg)](https://doi.org/10.5281/zenodo.14013931) From b074772a6f1a164c77b2858e4cf21478e54499b1 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Fri, 3 Oct 2025 15:52:39 +0200 Subject: [PATCH 5/9] Remove environment.yml Environment management is now handled by pixi.toml. The environment.yml file is no longer needed as all dependencies are defined in pixi.toml. --- environment.yml | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 environment.yml diff --git a/environment.yml b/environment.yml deleted file mode 100644 index e15b21d0f..000000000 --- a/environment.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: ship -channels: - - conda-forge -dependencies: - - click - - parcels >3.1.0 - - pyproj >= 3, < 4 - - sortedcontainers == 2.4.0 - - opensimplex == 0.4.5 - - numpy >=1, < 2 - - pydantic >=2, <3 - - pip - - pyyaml - - copernicusmarine >= 2.2.2 - - openpyxl - - yaspin - - textual - - # linting - - pre-commit - - mypy - - # Testing - - pytest - - pytest-cov - - pytest-asyncio - - codecov - - seabird - - setuptools - - # Docs - - sphinx>=7.0 - - myst-parser>=0.13 - - nbsphinx - - ipykernel - - pandoc - - sphinx-copybutton - # - sphinx-autodoc-typehints # https://github.com/OceanParcels/virtualship/pull/125#issuecomment-2668766302 - - pydata-sphinx-theme - - sphinx-autobuild From 7b6b74ccf50f13cb96b47057174e6095c68f8d5b Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Mon, 6 Oct 2025 14:20:49 +0200 Subject: [PATCH 6/9] Add virtualship source dependency --- pixi.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pixi.toml b/pixi.toml index e6d86f158..4b755b408 100644 --- a/pixi.toml +++ b/pixi.toml @@ -6,10 +6,11 @@ platforms = ["win-64", "linux-64", "osx-64", "osx-arm64"] [package] name = "virtualship" -version = "dynamic" +version = "dynamic" # dynamic versioning needs better support in pixi https://github.com/prefix-dev/pixi/issues/2923#issuecomment-2598460666 . Putting `version = "dynamic"` here for now until pixi recommends something else. +license = "MIT" # can remove this once https://github.com/prefix-dev/pixi-build-backends/issues/397 is resolved [package.build] -backend = { name = "pixi-build-python", version = "==0.3.2" } +backend = { name = "pixi-build-python", version = "==0.4.0" } [package.host-dependencies] setuptools = "*" @@ -38,6 +39,7 @@ pyyaml = "*" copernicusmarine = ">=2.2.2" yaspin = "*" textual = "*" +virtualship = { path = "." } [feature.py310.dependencies] python = "3.10.*" From e4d39360061f51cdfee23a016582cc3e62ceb87b Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Mon, 6 Oct 2025 14:44:57 +0200 Subject: [PATCH 7/9] Move pytest args to CI call --- .github/workflows/ci.yml | 4 +++- pixi.toml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc994fd3d..ac6720f58 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,9 @@ jobs: cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }} - name: Test package - run: pixi run -e ${{ matrix.pixi-environment }} tests + run: + pixi run -e ${{ matrix.pixi-environment }} tests -ra --cov --cov-report=xml --cov-report=term + --durations=20 - name: Upload coverage report uses: codecov/codecov-action@v5.4.0 diff --git a/pixi.toml b/pixi.toml index 4b755b408..8164d2d47 100644 --- a/pixi.toml +++ b/pixi.toml @@ -58,7 +58,7 @@ seabird = "*" openpyxl = "*" [feature.test.tasks] -tests = "pytest -ra --cov --cov-report=xml --cov-report=term --durations=20" +tests = "pytest" [feature.notebooks.dependencies] nbval = "*" From 7c95aa5bb4d6c698a31bd486abb9ae584d8f0182 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Mon, 6 Oct 2025 14:46:43 +0200 Subject: [PATCH 8/9] Update RTD config --- .readthedocs.yaml | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 1c13b28aa..a8b751be8 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,18 +1,17 @@ -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - version: 2 -sphinx: - configuration: docs/conf.py build: - os: ubuntu-22.04 + os: ubuntu-lts-latest tools: - python: mambaforge-22.9 + python: "latest" # just so RTD stops complaining jobs: - pre_build: - - pip install . - - sphinx-build -b linkcheck docs/ _build/linkcheck - - sphinx-apidoc -o docs/api/ --module-first --no-toc --force src/virtualship - -conda: - environment: environment.yml + create_environment: + - asdf plugin add pixi + - asdf install pixi latest + - asdf global pixi latest + install: + - pixi install -e docs + build: + html: + - pixi run -e docs sphinx-build -T -b html docs $READTHEDOCS_OUTPUT/html +sphinx: + configuration: docs/conf.py From 00ec92978f082872d283e2224fcd5df6b8d78653 Mon Sep 17 00:00:00 2001 From: Vecko <36369090+VeckoTheGecko@users.noreply.github.com> Date: Thu, 23 Oct 2025 10:12:34 +0200 Subject: [PATCH 9/9] Add caching of Pixi lock --- .github/workflows/ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac6720f58..fe5ee154a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,9 +21,13 @@ env: FORCE_COLOR: 3 jobs: + cache-pixi-lock: + uses: Parcels-code/Parcels/.github/workflows/cache-pixi-lock.yml@58cdd6185b3af03785c567914a070288ffd804e0 + tests: name: "Unit tests: ${{ matrix.runs-on }} | pixi run -e ${{ matrix.pixi-environment }} tests" runs-on: ${{ matrix.runs-on }} + needs: cache-pixi-lock strategy: fail-fast: false matrix: @@ -34,6 +38,10 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + - uses: actions/cache/restore@v4 + with: + path: pixi.lock + key: ${{ needs.cache-pixi-lock.outputs.cache-id }} - uses: prefix-dev/setup-pixi@v0.9.0 with: cache: true @@ -51,10 +59,15 @@ jobs: typechecking: name: "TypeChecking: pixi run typing" runs-on: ubuntu-latest + needs: cache-pixi-lock steps: - uses: actions/checkout@v4 with: fetch-depth: 0 + - uses: actions/cache/restore@v4 + with: + path: pixi.lock + key: ${{ needs.cache-pixi-lock.outputs.cache-id }} - uses: prefix-dev/setup-pixi@v0.9.0 with: cache: true