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
9 changes: 9 additions & 0 deletions .github/workflows/TestWithSinglePython.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,12 @@ jobs:
with:
token: ${{secrets.QLTY_COVERAGE_TOKEN}}
files: cov.info
- name: Build wheel
run: |
python -m pip install build
python -m build --wheel
- name: Smoke test wheel import
run: |
python -m venv /tmp/smoke
/tmp/smoke/bin/pip install dist/*.whl
/tmp/smoke/bin/python -c "import debrisframe"
90 changes: 90 additions & 0 deletions .github/workflows/buildAndUploadPyPi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Build DebrisFrame and publish it to TestPyPI and PyPI.
#
# Release-first flow (matches AvaFrame):
# 1. Create a GitHub release for the new version tag (X.Y.Z). This creates the
# tag and triggers Zenodo, which archives the release and mints the DOI.
# 2. Dispatch this workflow from the Actions tab, selecting that release tag in
# the "Use workflow from" dropdown.
#
# hatch-vcs derives the version from the git tag, so the workflow must run against
# the tag; otherwise the build gets a local version segment (e.g. +g<hash>) that
# PyPI rejects. The guard step below enforces this.

name: Build and upload to PyPI

on:
workflow_dispatch:

jobs:
build:
name: Build distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Verify the workflow runs on a release tag
if: github.ref_type != 'tag'
run: |
echo "::error::Dispatch this workflow against a release tag (X.Y.Z), not '${{ github.ref_name }}'."
exit 1

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

- name: Install build tools
run: |
python -m pip install --upgrade pip
pip install build twine

- name: Build sdist and wheel
run: python -m build

- name: Check distribution metadata
run: twine check dist/*

- name: Smoke test wheel install
run: |
python -m venv /tmp/smoke
/tmp/smoke/bin/pip install dist/*.whl
/tmp/smoke/bin/python -c "import debrisframe"

- uses: actions/upload-artifact@v7
with:
name: dist
path: dist/*

publish_testpypi:
name: Publish to TestPyPI
needs: build
runs-on: ubuntu-latest
environment: testpypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v8
with:
name: dist
path: dist

- uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/

publish_pypi:
name: Publish to PyPI
needs: publish_testpypi
runs-on: ubuntu-latest
environment: pypi
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v8
with:
name: dist
path: dist

- uses: pypa/gh-action-pypi-publish@release/v1
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# DebrisFrame

How to install DebrisFrame can be found [here](https://docs.debrisframe.org/en/latest/installation.html#).
[![PyPI](https://img.shields.io/pypi/v/debrisframe.svg)](https://pypi.org/project/debrisframe/)

Install from PyPI:

```
pip install debrisframe
```

How to install DebrisFrame from source can be found [here](https://docs.debrisframe.org/en/latest/installation.html#).

[![Maintainability](https://qlty.sh/badges/0bf94b24-fee3-4fb1-9520-9e09adfe7195/maintainability.svg)](https://qlty.sh/gh/OpenNHM/projects/DebrisFrame)

Expand Down
2 changes: 2 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ General
* :doc:`introduction`
* :doc:`installation`
* :doc:`workflow`
* :doc:`release`

.. toctree::
:maxdepth: 4
Expand All @@ -29,6 +30,7 @@ General
introduction.rst
installation.rst
workflow.rst
release.rst


Computational modules
Expand Down
12 changes: 12 additions & 0 deletions docs/source/installation.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
Install DebrisFrame
---------------------

From PyPI
^^^^^^^^^

::

pip install debrisframe

This installs AvaFrame (``avaframe>=2.2b1``) as a dependency.

From source
^^^^^^^^^^^

Running DebrisFrame means running AvaFrame's com1DFA with parameters for debris flows (:py:mod:`c1TIF`).
Therefore, follow AvaFrame's `installation instructions <https://docs.avaframe.org/en/latest/complexUsage.html>`_ first.
Expand Down
37 changes: 37 additions & 0 deletions docs/source/release.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Release procedure
-----------------

DebrisFrame is versioned from git tags via ``hatch-vcs`` and published to PyPI by the
``Build and upload to PyPI`` GitHub Actions workflow. Releases follow a release-first flow:
the GitHub release is created first (triggering Zenodo), then the PyPI workflow is run
against that release tag.

Prerequisites (one-time)
^^^^^^^^^^^^^^^^^^^^^^^^

- PyPI and TestPyPI trusted publishers configured for the repository:

- owner: ``OpenNHM``
- repository: ``DebrisFrame``
- workflow filename: ``buildAndUploadPyPi.yml``
- environment: ``pypi`` (PyPI) and ``testpypi`` (TestPyPI)

- GitHub environments ``pypi`` and ``testpypi`` created in the repository settings.
- The repository linked to Zenodo, with ``.zenodo.json`` present on ``master``.

Create a release
^^^^^^^^^^^^^^^^

1. Make sure all packaging changes are merged into ``master``.
2. Create a new GitHub release and set its tag to the new version, e.g. ``X.Y.Z`` (GitHub
creates the tag if it does not exist). Publishing the release makes Zenodo archive it
and mint the DOI.
3. Run the ``Build and upload to PyPI`` workflow from the Actions tab
(``workflow_dispatch``). In the "Use workflow from" dropdown, select the release tag
``X.Y.Z`` so the build runs on the tagged commit.
4. The workflow builds the sdist and wheel, checks the metadata, publishes to TestPyPI,
and then to PyPI.

The version is taken from the git tag. If the workflow does not run on a version tag,
hatch-vcs adds a local version segment (e.g. ``+g<hash>``) that PyPI rejects; the workflow
fails early in that case.
26 changes: 22 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,17 @@ name = "debrisframe"
description = "The Open Debris flow Framework"
readme = "README.md"
dynamic = ["version"]
license = { text = "EUPL" }
license = "EUPL-1.2"
authors = [
{ name = "DebrisFrame Contributors", email = "felix@avaframe.org" }
]
urls = { Homepage = "http://debrisframe.org" }
keywords = ["debris flow", "natural hazards", "simulation", "open source"]
classifiers = [
# How mature is this project? Common values are
# 3 - Alpha 4 - Beta 5 - Production/Stable
"Development Status :: 3 - Alpha",
# Indicate who your project is intended for
"Intended Audience :: Science/Research",
"License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand All @@ -27,8 +26,14 @@ classifiers = [
]
requires-python = ">=3.9,<3.14"
dependencies = [
"avaframe>=2.2b1",
]


[project.urls]
Homepage = "http://opennhm.org"
Repository = "https://github.com/OpenNHM/DebrisFrame"
Issues = "https://github.com/OpenNHM/DebrisFrame/issues"

[tool.flake8]
max-line-length = 109
select = ['B950']
Expand All @@ -44,6 +49,13 @@ source = "vcs"
version_scheme = "no-guess-dev"
local_scheme = "node-and-date"

[tool.hatch.build.targets.wheel]
packages = ["debrisframe"]
exclude = ["debrisframe/tests", "debrisframe/data"]

[tool.hatch.build.targets.sdist]
exclude = ["debrisframe/tests", "debrisframe/data"]

[tool.pixi.workspace]
channels = ["conda-forge/label/qgis_ltr", "https://prefix.dev/conda-forge"]
platforms = ["linux-64", "win-64", "osx-64"]
Expand All @@ -67,6 +79,12 @@ pixi-pycharm = "*"
debrisframe = { path = "./", editable = true }
avaframe = { path = "../AvaFrame", editable = true }

# The local editable AvaFrame reports a pre-release dev version (e.g. 2.1+57.g...),
# which cannot satisfy debrisframe's published avaframe>=2.2b1 pin. Relax the
# constraint for local development; the published metadata keeps the pin.
[tool.pixi.feature.dev.pypi-options.dependency-overrides]
avaframe = ">=2.1"

# Environments
[tool.pixi.environments]
default = { features = ["dev"], solve-group = "default" }
Expand Down
36 changes: 0 additions & 36 deletions setup.py

This file was deleted.

Loading