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
10 changes: 10 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
.dockerignore
.venv
.git
.github
.history
.pytest_cache
__pycache__
*.pyc
*.log
dist
docs/build
docs/source/_build
32 changes: 16 additions & 16 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
version:
description: New semantic version (for example, 2.3.1)
description: New semantic version (for example, 2.3.2)
required: true

permissions:
Expand All @@ -17,7 +17,7 @@ jobs:
VERSION: ${{ inputs.version }}
steps:
- name: Check out the repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0

Expand All @@ -34,7 +34,7 @@ jobs:
fi

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.12"

Expand All @@ -48,27 +48,17 @@ jobs:
poetry run pytest
poetry build

- name: Commit and tag the version
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add pyproject.toml
git commit -m "chore: release $VERSION"
git tag "$VERSION"
git push origin "HEAD:${GITHUB_REF_NAME}"
git push origin "$VERSION"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4

- name: Log in to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ vars.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}

- name: Build and push Docker image
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: .
file: ./Dockerfile
Expand All @@ -78,6 +68,16 @@ jobs:
${{ vars.DOCKER_IMAGE_NAME }}:${{ env.VERSION }}
${{ vars.DOCKER_IMAGE_NAME }}:latest

- name: Commit and tag the version
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add pyproject.toml
git commit -m "chore: release $VERSION"
git tag "$VERSION"
git push origin "HEAD:${GITHUB_REF_NAME}"
git push origin "$VERSION"

- name: Create GitHub release and upload Python artifacts
env:
GH_TOKEN: ${{ github.token }}
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

### Fixed

- Pinned the Docker build to the Debian 12 package repositories used by the
DSSAT base image, preventing the floating `stable` suite from mixing Debian
13 packages into a Debian 12 image.
- Removed exact Debian revision pins for GDAL and isolated Poetry from the
system-managed Python environment.
- Reordered the release workflow so a failed Docker build cannot publish a
version commit and Git tag before the release artifacts are ready.
- Updated GitHub and Docker actions to their Node.js 24 generations.
- Restored backward compatibility with legacy one-band GHR soil rasters.
- Automatically detect one-band legacy and two-band encoded soil rasters.
- Resolve legacy raster IDs through `GHR.db` and provide actionable errors for
Expand Down
44 changes: 30 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,27 +1,43 @@
FROM dssat/dssat-csm:v4.8.2.0

RUN apt-get update && apt-get install -y \
python3.11 \
python3.11-dev \
python3-pip \
python3-venv \
python3-poetry \
python3-virtualenv \
curl \
gdal-bin=3.6.2+dfsg-1+b2 \
libgdal-dev=3.6.2+dfsg-1+b2 \
# The DSSAT 4.8.2 image is Debian 12, but its APT sources use the floating
# "stable" suite. Pin the suite to bookworm so a future Debian release cannot
# mix packages from a different operating-system version into this image.
RUN sed -i \
-e 's/Suites: stable stable-updates/Suites: bookworm bookworm-updates/' \
-e 's/Suites: stable-security/Suites: bookworm-security/' \
/etc/apt/sources.list.d/debian.sources \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
python3 \
python3-dev \
python3-venv \
curl \
gdal-bin \
libgdal-dev \
&& rm -rf /var/lib/apt/lists/*

ENV GDAL_VERSION 3.6.2
ENV C_INCLUDE_PATH=/usr/include/python3.11/cpython
ENV CPLUS_INCLUDE_PATH=/usr/include/python3.11/cpython
ENV VIRTUAL_ENV="/opt/pythia-venv" \
PATH="/opt/pythia-venv/bin:${PATH}" \
PIP_NO_CACHE_DIR=1 \
POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_CREATE=false

# Install Poetry in an isolated environment instead of depending on the
# distribution's Poetry package or modifying Debian's managed Python.
RUN python3 -m venv /opt/pythia-venv \
&& python -m pip install --upgrade pip \
&& python -m pip install "poetry>=1.8,<3"

WORKDIR /app/pythia

# Cache third-party dependencies separately from the application source.
COPY pyproject.toml poetry.toml poetry.lock ./
RUN POETRY_VIRTUALENVS_CREATE=false poetry install --no-interaction --no-ansi
RUN poetry install --only main --no-root --no-ansi

COPY . ./
RUN poetry install --only main --no-ansi

ENV PATH="${PATH}:/app/pythia/bin"

ENTRYPOINT ["pythia"]
10 changes: 7 additions & 3 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

Pythia uses [semantic versioning](https://semver.org/): increment `MAJOR` for
incompatible changes, `MINOR` for backward-compatible features, and `PATCH` for
backward-compatible fixes. The one-band soil compatibility correction should
therefore be a patch release from 2.3.0 (for example, 2.3.1).
backward-compatible fixes.

The failed 2.3.1 workflow already published its version commit and tag before
the Docker step failed. Do not reuse or move that tag. After merging the Docker
release fix, publish 2.3.2 so every artifact is built from the same immutable
source revision.

## Before triggering the release

Expand Down Expand Up @@ -35,7 +39,7 @@ change.
## GitHub release workflow

Open [Actions → Release](https://github.com/DSSAT/pythia/actions/workflows/release.yml),
choose **Run workflow**, enter a plain semantic version such as `2.3.1`, and
choose **Run workflow**, enter a plain semantic version such as `2.3.2`, and
run it from the intended branch. Do not add a `v` prefix.

The workflow validates the version, updates `pyproject.toml`, builds and tests
Expand Down
2 changes: 2 additions & 0 deletions pythia/example_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def build_example_archive(data_root, output, package_readme=None):
readme = Path(package_readme).expanduser().resolve()
archive.write(readme, f"{archive_root}/README.md")
for source, relative in _release_files(root):
if package_readme and relative == Path("README.md"):
continue
archive.write(source, (Path(archive_root) / relative).as_posix())

size = destination.stat().st_size
Expand Down
2 changes: 2 additions & 0 deletions pythia/tests/example_data_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ def test_release_archive_is_portable_and_excludes_local_files(tmp_path):
(root / "OUTPUT" / "old-run").mkdir(parents=True)
(root / "OUTPUT" / "old-run" / "result.csv").write_text("result", encoding="utf-8")
(root / ".DS_Store").write_bytes(b"local")
(root / "README.md").write_text("old readme", encoding="utf-8")

executable = tmp_path / "dscsm048"
executable.write_text("executable", encoding="utf-8")
Expand All @@ -115,6 +116,7 @@ def test_release_archive_is_portable_and_excludes_local_files(tmp_path):
assert checksum.is_file()
assert manifest["excluded_members"] == []
assert "Simulation_Data/OUTPUT/" in manifest["members"]
assert manifest["members"].count("Simulation_Data/README.md") == 1
assert "Simulation_Data/OUTPUT/old-run/result.csv" not in manifest["members"]
for config in manifest["configs"].values():
serialized = json.dumps(config)
Expand Down
14 changes: 14 additions & 0 deletions release/RELEASE_NOTES_2.3.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Pythia 2.3.2

Pythia 2.3.2 delivers the soil compatibility, Sri Lanka example, validation,
documentation, and packaging improvements prepared for 2.3.1, together with a
corrected Docker and GitHub release pipeline.

The Docker build now keeps the DSSAT base image on Debian 12 repositories,
installs current Bookworm package revisions without fragile build-number pins,
and installs Poetry inside an isolated virtual environment. The GitHub Actions
used by the workflow now run on Node.js 24. Release commits and tags are
published only after tests, Python packaging, and the Docker build succeed.

Users of one-band GHR soil rasters should follow the compatibility and example
instructions in the 2.3.1 notes. No soil raster conversion is required.
Loading