Skip to content
Merged
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
56 changes: 45 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ jobs:
steps:

- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Setup uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
cache-dependency-glob: "**/pyproject.toml"

Expand All @@ -43,10 +43,10 @@ jobs:
shell: bash
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Setup uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
enable-cache: false

Expand All @@ -73,10 +73,10 @@ jobs:
shell: bash
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Setup uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
cache-dependency-glob: "**/pyproject.toml"
python-version: ${{ matrix.python-version }}
Expand All @@ -85,6 +85,17 @@ jobs:
run: uv sync --all-extras

- name: Install modflow executables
id: install_modflow
continue-on-error: true
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/autotest
repo: modflow6-nightly-build

# the download reaches out to github and occasionally has its
# connection reset, failing the job before any test runs
- name: Install modflow executables (retry)
if: steps.install_modflow.outcome == 'failure'
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/autotest
Expand Down Expand Up @@ -113,10 +124,10 @@ jobs:
shell: bash
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Setup uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
cache-dependency-glob: "**/pyproject.toml"
python-version: ${{ matrix.python-version }}
Expand All @@ -125,6 +136,18 @@ jobs:
run: uv sync --all-extras

- name: Install modflow executables
id: install_modflow
continue-on-error: true
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/autotest
repo: executables
tag: "14.0"

# the download reaches out to github and occasionally has its
# connection reset, failing the job before any test runs
- name: Install modflow executables (retry)
if: steps.install_modflow.outcome == 'failure'
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/autotest
Expand All @@ -138,7 +161,7 @@ jobs:
- name: Run autotests
working-directory: ./autotest
shell: bash -l {0}
run: pytest -v -n auto -m "not mf6"
run: uv run pytest -v -n auto -m "not mf6"

autotest_mf6_examples:
name: modflowapi mf6 examples autotests
Expand All @@ -154,10 +177,10 @@ jobs:
shell: bash
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Setup uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
cache-dependency-glob: "**/pyproject.toml"
python-version: ${{ matrix.python-version }}
Expand All @@ -166,6 +189,17 @@ jobs:
run: uv sync --all-extras

- name: Install modflow6 nightly build
id: install_modflow
continue-on-error: true
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/autotest
repo: modflow6-nightly-build

# the download reaches out to github and occasionally has its
# connection reset, failing the job before any test runs
- name: Install modflow6 nightly build (retry)
if: steps.install_modflow.outcome == 'failure'
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/autotest
Expand Down
43 changes: 43 additions & 0 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: pull request

on:
pull_request:
types: [opened, edited, reopened, synchronize]
branches: [develop]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:

title:
name: check title
# the release and reset pull requests are opened by a bot and are not
# squash merged, so their titles do not reach the changelog
if: github.event.pull_request.user.type != 'Bot'
runs-on: ubuntu-latest
defaults:
run:
shell: bash
steps:

- name: Check conventional commit format
env:
TITLE: ${{ github.event.pull_request.title }}
run: |
# pull requests are squash merged, so the title becomes the commit
# message in develop, and the changelog is generated from those
# messages. a title that is not a conventional commit is dropped
# from the release notes without warning.
types="build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test"
if [[ ! "$TITLE" =~ ^($types)(\([^\)]+\))?!?:\ .+ ]]; then
echo "::error::'$TITLE' is not a conventional commit header."
echo ""
echo "Use '<type>(<scope>): <subject>', for example:"
echo " feat(runner): support adaptive time step retries"
echo ""
echo "Type is one of: ${types//|/, }."
echo "Only feat, fix, perf and refactor reach the release notes;"
echo "see cliff.toml. A user facing change needs one of those."
exit 1
fi
echo "'$TITLE' is a conventional commit header"
37 changes: 24 additions & 13 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ jobs:
fi

- name: Checkout source branch
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || github.ref_name }}
fetch-depth: 0

- name: Setup uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
cache-dependency-glob: "**/pyproject.toml"

Expand Down Expand Up @@ -104,14 +104,25 @@ jobs:
uv run scripts/update_version.py -v "${{ steps.version.outputs.version }}"
uv run python -c "import modflowapi; print('Version: ', modflowapi.__version__)"

- name: Lint and format
- name: Check style
run: |
uvx ruff check --fix .
uvx ruff format .
uvx ruff check .
uvx ruff format --check .
uvx codespell

- name: Install modflow executables
if: ${{ github.event_name != 'workflow_dispatch' || inputs.run_tests }}
id: install_modflow
continue-on-error: true
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/autotest
repo: modflow6-nightly-build

# the download reaches out to github and occasionally has its
# connection reset, failing the job before any test runs
- name: Install modflow executables (retry)
if: ${{ (github.event_name != 'workflow_dispatch' || inputs.run_tests) && steps.install_modflow.outcome == 'failure' }}
uses: modflowpy/install-modflow-action@v1
with:
path: ${{ github.workspace }}/autotest
Expand Down Expand Up @@ -167,7 +178,7 @@ jobs:
git config core.sharedRepository true
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
git add version.txt modflowapi/version.py CITATION.cff HISTORY.md
git commit -m "ci(release): set version to $ver, update changelog"
git push origin "v$ver"

Expand Down Expand Up @@ -200,7 +211,7 @@ jobs:
steps:

- name: Checkout main branch
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
ref: main
fetch-depth: 0
Expand Down Expand Up @@ -251,12 +262,12 @@ jobs:
steps:

- name: Checkout main branch
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
ref: main

- name: Setup uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
enable-cache: false

Expand All @@ -267,7 +278,7 @@ jobs:
run: uvx twine check --strict dist/*

- name: Upload package
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: dist
path: dist
Expand All @@ -290,13 +301,13 @@ jobs:
steps:

- name: Checkout main branch
uses: actions/checkout@v4
uses: actions/checkout@v7
with:
ref: main
fetch-depth: 0

- name: Setup uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
cache-dependency-glob: "**/pyproject.toml"

Expand All @@ -317,7 +328,7 @@ jobs:
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git switch -c "$branch"
git add -A
git add version.txt modflowapi/version.py CITATION.cff
git commit -m "ci(release): update version to $next"
git push origin "$branch"

Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ uv.lock
# temporary test folders
autotest/temp/**

# modflow executables installed for testing
autotest/mf6
autotest/mf5to6
autotest/zbud6
autotest/libmf6.*
autotest/mf6.exe
autotest/mf5to6.exe
autotest/zbud6.exe

# notebooks
docs/examples/notebooks/*.ipynb

Expand Down
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ message: If you use this software, please cite both the article from preferred-c
and the software itself.
type: software
title: MODFLOW API
version: 1.0.0
date-released: '2026-09-05'
version: 1.0.1
date-released: '2026-09-06'
abstract: An extension to xmipy for the MODFLOW API.
repository-artifact: https://pypi.org/project/modflowapi
repository-code: https://github.com/MODFLOW-ORG/modflowapi
Expand Down
6 changes: 6 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# Changelog
### Version 1.0.1

#### Bug fixes

* [fix(dependencies)](https://github.com/MODFLOW-ORG/modflowapi/commit/adbfd151b14861360fbb9fb67f48bcff87f7d43f): Require a pandas that supports numpy 2 (#118). Committed by Joseph Hughes on 2026-09-06.

### Version 1.0.0

This is the first stable release. modflowapi now follows semantic versioning, so a breaking change to the `modflowapi` or `modflowapi.extensions` interface will increment the major version. The Python interface is unchanged from 0.2.0, but Python 3.9 and 3.10 are no longer supported; Python 3.11 or later is required.
Expand Down
Binary file removed autotest/mf5to6
Binary file not shown.
Binary file removed autotest/mf6
Binary file not shown.
Binary file removed autotest/zbud6
Binary file not shown.
23 changes: 20 additions & 3 deletions guide-to-publish.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ Releases are automated by [`.github/workflows/release.yml`](.github/workflows/re
Publishing to PyPI uses [trusted publishing](https://docs.pypi.org/trusted-publishers/), so no
API token is needed, but the repository must have a `release` environment configured.

> [!IMPORTANT]
> PyPI matches a trusted publisher on the organisation name, the repository name, the workflow
> filename and the environment name. Renaming any of them silently invalidates the publisher, and
> nothing reports it until the next release fails with `invalid-publisher`. This happened when the
> organisation was renamed from `MODFLOW-USGS` to `MODFLOW-ORG`, and went unnoticed for the
> eighteen months until the next release. After any such rename, update the publisher at
> https://pypi.org/manage/project/modflowapi/settings/publishing/ to match.

## 1. Start the release

From the [Actions tab](https://github.com/MODFLOW-ORG/modflowapi/actions/workflows/release.yml),
Expand Down Expand Up @@ -46,7 +54,16 @@ Merge the reset pull request to finish the release.

## Changelog conventions

Release notes are generated from commit messages, so commits merged to `develop` should follow the
Release notes are generated from commit messages, so commits merged to `develop` must follow the
[conventional commits](https://www.conventionalcommits.org/) format (`feat:`, `fix:`, `refactor:`,
etc.). Commits that do not follow the convention are omitted from the changelog. See
[`cliff.toml`](cliff.toml) for the commit groups and which ones are skipped.
etc.). Commits that do not follow the convention are omitted from the changelog without warning.
See [`cliff.toml`](cliff.toml) for the commit groups and which ones are skipped.

Pull requests are squash merged, so the title becomes the commit message the notes are generated
from. [`.github/workflows/pull_request.yml`](.github/workflows/pull_request.yml) rejects a title
that is not a conventional commit header, but it cannot tell whether the type is the right one: a
user facing change titled `chore:` still passes the check and is still dropped from the notes.

Read the generated changelog on the release pull request before merging it. Anything missing is
added there, into the section for the version being cut, not to `develop`; the section does not
exist until the release workflow generates it.
4 changes: 2 additions & 2 deletions modflowapi/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# modflowapi version file automatically created using...update_version.py
# created on...September 05, 2026 12:54:22
__version__ = "1.0.0"
# created on...September 06, 2026 12:36:39
__version__ = "1.0.1"
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ classifiers = [
requires-python = ">=3.11"
dependencies = [
"numpy>=1.23",
"pandas>=1.5",
"pandas>=2.2.2",
"xmipy>=1.5.0",
]

Expand Down
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.0
1.0.1