diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f22b477..b8b21c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,8 +2,10 @@ name: Build and test on: push: + branches: ["**"] # not tags: a release tag runs this workflow through release.yml pull_request: workflow_dispatch: + workflow_call: jobs: build-test: @@ -41,12 +43,3 @@ jobs: with: name: mess-static-linux-64 path: .pixi/envs/static/bin/mess* - - - name: Upload mess-static to the Auto-Mech channel - if: matrix.environment == 'static' && github.event_name == 'push' && github.ref_name == 'master' && github.repository_owner == 'Auto-Mech' - run: | - pixi publish --path static --target-dir dist - # As before: an upload of an existing version fails, which is not an error here - pixi exec rattler-build upload anaconda -o Auto-Mech dist/*.conda || true - env: - ANACONDA_API_KEY: ${{ secrets.ANACONDA_API_KEY }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..62b930f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,98 @@ +name: Release + +on: + push: + tags: + - "v*.*.*" + +permissions: + contents: read + +jobs: + # Releases are made from master only: stop if the tag is on another branch + check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # all branches, to compare the tag with master + + - name: Check that the tagged commit is on master + run: git merge-base --is-ancestor "$GITHUB_SHA" origin/master + + test: + needs: check + uses: ./.github/workflows/build.yml + + publish: + needs: test + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # for prefix.dev Trusted Publishing + + steps: + - uses: actions/checkout@v4 + + - uses: prefix-dev/setup-pixi@v0.11.3 + with: + pixi-version: v0.84.1 + environments: release + cache: true + + - name: Build the conda packages + run: pixi run build-conda + + - name: Upload the conda packages + uses: actions/upload-artifact@v4 + with: + name: conda-packages + path: dist/*.conda + + # Only the main repository is a trusted publisher of the channel + - name: Publish the conda packages to prefix.dev + if: github.repository_owner == 'Auto-Mech' + run: pixi run publish-conda + + release: + needs: publish + runs-on: ubuntu-latest + permissions: + contents: write # to create the GitHub release + + steps: + - uses: actions/checkout@v4 + + - name: Download the conda packages + uses: actions/download-artifact@v4 + with: + name: conda-packages + path: dist/ + + # The static executables that the test job built and tested + - name: Download the static executables + uses: actions/download-artifact@v4 + with: + name: mess-static-linux-64 + path: mess-static/ + + - name: Archive the static executables + run: | + name="mess-static-${GITHUB_REF_NAME#v}-linux-64" + mv mess-static "$name" + chmod +x "$name"/* # artifacts do not keep file permissions + tar -czf "dist/$name.tar.gz" "$name" + + - name: Extract release notes + id: extract-release-notes + uses: ffurrer2/extract-release-notes@v2 + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ github.ref_name }} + body: ${{ steps.extract-release-notes.outputs.release_notes }} + files: | + dist/*.conda + dist/*.tar.gz diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6a12b3c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,36 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +Versions are `YYYY.M.N`, where `N` counts the releases within the month. + +## [Unreleased] + +### Added + +- The `mess` conda package: the executables linked against conda-forge's ILP64 OpenBLAS and GSL. +- Releases: a version tag builds and tests both packages, publishes them, and makes a GitHub release with the packages and a tarball of the static executables. + +### Changed + +- `mess-static` is built from source with CMake, instead of repackaging prebuilt executables. The executables are `mess`, `messpf` and `messabs`, and their output for the examples is unchanged. +- `mess` and `mess-static` share one version. +- The packages are published to the [`automech`](https://prefix.dev/channels/automech) channel on prefix.dev. The `auto-mech` channel on anaconda.org keeps the earlier `mess-static` packages and gets no new ones. +- `examples/mess.inp` sets `WithCRM`, which its radiative oscillators need. + +### Removed + +- The `gumbo` executable from `mess-static`: its example input (`examples/messsym.inp`) does not run, so it cannot be tested. + +## [2026.2.4] - 2026-02-04 + +- `mess-static` on anaconda.org, with executables built from the source of that date. + +## [2025.9.0] - 2025-09-25 + +- `mess-static` on anaconda.org, packaged with Pixi. + +## [2024.5.16] - 2024-05-16 + +- `mess-static` on anaconda.org, the first conda package of the static executables. diff --git a/README.md b/README.md index 6297062..b21880d 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,37 @@ rate coefficients for complex-forming reactions via solution of the one-dimensio ## Installation -The Auto-Mech channel provides fully static executables that run on any x86-64 Linux, with no runtime dependencies: +The [`automech`](https://prefix.dev/channels/automech) channel on prefix.dev provides two conda packages with the same executables (`mess`, `messpf`, `messabs`). +Install only one of them. + +**`mess-static`** has fully static executables that run on any x86-64 Linux, with no runtime dependencies: +``` +# conda (or mamba) +conda install -c https://repo.prefix.dev/automech mess-static + +# Pixi, for all your projects +pixi global install -c https://repo.prefix.dev/automech mess-static + +# Pixi, in a workspace +pixi workspace channel add https://repo.prefix.dev/automech && pixi add mess-static +``` + +**`mess`** is linked against the conda-forge libraries (OpenBLAS, GSL), so it also needs the `conda-forge` channel: ``` -conda install -c auto-mech mess-static +# conda (or mamba) +conda install -c https://repo.prefix.dev/automech -c conda-forge mess + +# Pixi, for all your projects +pixi global install -c https://repo.prefix.dev/automech -c conda-forge mess + +# Pixi, in a workspace (which has the conda-forge channel by default) +pixi workspace channel add https://repo.prefix.dev/automech && pixi add mess ``` -They are also attached to each run of the GitHub Actions workflow (artifact `mess-static-linux-64`). + +The static executables are also attached to each [GitHub release](https://github.com/Auto-Mech/MESS/releases) as a tarball, for systems without conda. +The changes in each release are listed in [`CHANGELOG.md`](CHANGELOG.md). + +The `auto-mech` channel on anaconda.org keeps the `mess-static` packages up to version 2026.2.4 and gets no new ones. ## Building from source diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000..d0a918c --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,24 @@ +# Releasing MESS + +These notes are for the maintainers who make releases. + +`mess` and `mess-static` share one version, `YYYY.M.N`, where `N` counts the releases within the month, starting from 0. +To release, from an up-to-date `master` of this repository: +1. List the changes to the source since the last release: + ``` + git log --no-merges $(git describe --tags --abbrev=0)..HEAD -- src examples + ``` +2. Describe them under `[Unreleased]` in `CHANGELOG.md`, and commit. +3. Run `pixi run release YYYY.M.N` (for example, `pixi run release 2026.11.0`). + This updates the version (in `pixi.toml` and `static/recipe.yaml`) and the changelog, then commits, tags and pushes. + +The tag starts the release workflow (`.github/workflows/release.yml`), which: +- stops unless the tagged commit is on `master`; +- builds and tests both packages; +- publishes them to the [`automech`](https://prefix.dev/channels/automech) channel on prefix.dev; +- makes a GitHub release with the packages, a tarball of the static executables, and the changelog entry as its notes. + +Publishing uses Trusted Publishing: the channel lists this repository and `release.yml` as a trusted publisher, so there are no API keys or secrets. +If the publish job fails, fix the cause and re-run the job: files that were already uploaded are skipped. + +`pixi run version` shows the current version. diff --git a/pixi.lock b/pixi.lock index 95fbe93..063962a 100644 --- a/pixi.lock +++ b/pixi.lock @@ -24,6 +24,44 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-ilp64-0.3.34-pthreads_h79482e6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda - conda_source: mess[b5469410] @ . + release: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hda65f42_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.46.1-default_hbd61a6d_103.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20260512-pl5321h373387f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.9.0-hd2095e1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-16.2.0-he0feb66_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.3-hb03c661_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.54.1-h0737f62_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.2-h25fd6f3_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.6-hdb14827_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.5-h781a0a9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.15.2-h6e52b48_100_cp315.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/ca-certificates-2026.10.23-hbd8a1cb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/cli-ui-0.17.2-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/contextlib2-21.6.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/docopt-0.6.2-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.15-9_cp315.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/schema-0.7.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tabulate-0.10.0-pyhcf101f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tbump-6.9.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.15.2-pyh5ded981_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/unidecode-1.4.0-pyhcf101f3_1.conda + - pypi: https://files.pythonhosted.org/packages/23/06/b4f06ca7afb5d9e942c642980c308ffcfa1fa0e8b0a3ddbec78483ef1614/keepachangelog-2.0.0-py3-none-any.whl static: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -42,6 +80,7 @@ packages: - openmp_impl <0.0a0 license: BSD-3-Clause license_family: BSD + purls: [] run_exports: strong: - _openmp_mutex >=4.5 @@ -77,6 +116,7 @@ packages: - libgcc >=14 license: bzip2-1.0.6 license_family: BSD + purls: [] run_exports: weak: - bzip2 >=1.0.8,<2.0a0 @@ -276,6 +316,7 @@ packages: - binutils_impl_linux-64 2.46.1 license: GPL-3.0-only license_family: GPL + purls: [] run_exports: {} size: 742109 timestamp: 1791565468810 @@ -346,6 +387,7 @@ packages: - ncurses >=6.6,<7.0a0 license: BSD-2-Clause license_family: BSD + purls: [] run_exports: weak: - libedit >=3.1.20260512,<3.2.0a0 @@ -374,9 +416,24 @@ packages: - expat 2.9.0.* license: MIT license_family: MIT + purls: [] run_exports: {} size: 78894 timestamp: 1793054221966 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.7.0-h81df57d_1.conda + sha256: c8c7583ef063bc3c430f1d48298e5ad24f796a35c22ed5b14183325825a61106 + md5: 6525a0b06aa4fd390795f0740636a9dd + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: MIT + license_family: MIT + purls: [] + run_exports: + weak: + - libffi >=3.7.0,<3.8.0a0 + size: 68004 + timestamp: 1787753412298 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-16.2.0-ha9f2e26_7.conda sha256: e031634c3a928f9594eba868bc46ef5230d6571a364a0c63215b06c4563bfcea md5: 735629b400b70eeab21a2ba8f5b1c2ce @@ -388,6 +445,7 @@ packages: - libgomp 16.2.0 he0feb66_7 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + purls: [] run_exports: {} size: 1058444 timestamp: 1790303109576 @@ -423,6 +481,7 @@ packages: - __glibc >=2.17,<3.0.a0 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL + purls: [] run_exports: strong: - _openmp_mutex >=4.5 @@ -437,11 +496,24 @@ packages: constrains: - xz 5.8.3.* license: 0BSD + purls: [] run_exports: weak: - liblzma >=5.8.3,<6.0a0 size: 112995 timestamp: 1786348617826 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-hb03c661_2.conda + sha256: 46820b4a835e175940ae20bec00fdddaff804cda27a1408ab1b95e77a2196437 + md5: fcfed1dc5053eb1901b66e7b1fc32588 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + license: BSD-2-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 92759 + timestamp: 1786650399772 - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.71.0-hc5e5977_0.conda sha256: a4386712ad6d5bc18943b198407c39e2f8ae2fa9c6418bb37bba96f1d382f109 md5: 726df214814a8b06135a6a674bc54589 @@ -524,6 +596,22 @@ packages: - libsanitizer 16.2.0 size: 8115383 timestamp: 1790303148068 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.54.1-h0737f62_101.conda + sha256: c294029f893d05286f1061bbab85b820f1eea73dd859af4bcc619197bcc34810 + md5: 36e097bf5f1e0699e88c8ac801f2dc65 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + - libzlib >=1.3.2,<2.0a0 + constrains: + - icu <0.0a0 + license: blessing + purls: [] + run_exports: + weak: + - libsqlite >=3.54.1,<4.0a0 + size: 980491 + timestamp: 1793051548007 - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.1-h6154650_1.conda sha256: 7e463000fa1cba3f3a6597b776f6ab301d425a96e3bc20d0d9d76a3b9f237aa3 md5: 5c526561e1d2a2e071941174eae84557 @@ -552,6 +640,20 @@ packages: run_exports: {} size: 6615436 timestamp: 1790303132935 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.42.4-hcfc3c73_1.conda + sha256: 0e2e8f2daa9306e67f046e31092d637431d8cf0a26c407ab22401d108c2d4631 + md5: d852293faea3c04a6e896b908b43aded + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=15 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: + weak: + - libuuid >=2.42.4,<3.0a0 + size: 36134 + timestamp: 1793891599274 - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.52.1-h280c20c_1.conda sha256: 67761d0206f84140047a367eaf9befe03a7e157a29ee25aee0047b40801cc6b6 md5: 01c4ed87826af55996768af6dbc936b4 @@ -574,6 +676,7 @@ packages: - zlib 1.3.2 *_3 license: Zlib license_family: Other + purls: [] run_exports: weak: - libzlib >=1.3.2,<2.0a0 @@ -586,6 +689,7 @@ packages: - __glibc >=2.17,<3.0.a0 - libgcc >=14 license: X11 AND BSD-3-Clause + purls: [] run_exports: weak: - ncurses >=6.6,<7.0a0 @@ -622,11 +726,45 @@ packages: - libgcc >=15 license: Apache-2.0 license_family: Apache + purls: [] run_exports: weak: - openssl >=3.6.5,<4.0a0 size: 3195299 timestamp: 1791098052301 +- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.15.2-h6e52b48_100_cp315.conda + build_number: 100 + sha256: dd6fdef748df5636029673a834ca3632ce44c86d71e4986d70bcdb2ae5607a25 + md5: 38c3edc23439db3ca383be02ae2b702e + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libedit >=3.1.20260512,<3.2.0a0 + - libexpat >=2.8.5,<3.0a0 + - libffi >=3.7.0,<3.8.0a0 + - libgcc >=15 + - liblzma >=5.8.3,<6.0a0 + - libmpdec >=4.0.0,<5.0a0 + - libsqlite >=3.54.1,<4.0a0 + - libuuid >=2.42.4,<3.0a0 + - libzlib >=1.3.2,<2.0a0 + - ncurses >=6.6,<7.0a0 + - openssl >=3.5.9,<4.0a0 + - python_abi 3.15.* *_cp315 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - zstd >=1.5.7,<1.6.0a0 + license: Python-2.0 + purls: [] + run_exports: + weak: + - python_abi 3.15.* *_cp315 + noarch: + - python + size: 29327137 + timestamp: 1793015518763 + python_site_packages_path: lib/python3.15/site-packages - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.6-hb03c661_2.conda sha256: 186a5b225077ad5f4656966da947d43307101950751ef4a239b455588756b4e1 md5: 007602d697e07c11ff9864964eba5ee3 @@ -640,6 +778,23 @@ packages: - rhash >=1.4.6,<2.0a0 size: 194994 timestamp: 1786731436520 +- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h1df4ec4_4.conda + build_number: 104 + sha256: a1a241d172c1ccab067ba245206dd048bc3c2d1b84504b53c9468e99adfc16a1 + md5: 676a2f9b1c4fcf57b70aa5c65f6c60d0 + depends: + - libgcc >=15 + - __glibc >=2.17,<3.0.a0 + - libzlib >=1.3.2,<2.0a0 + constrains: + - xorg-libx11 >=1.8.13,<2.0a0 + license: TCL + purls: [] + run_exports: + weak: + - tk >=8.6.13,<8.7.0a0 + size: 3566806 + timestamp: 1787272857910 - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.7-hb78ec9c_7.conda sha256: 47d682b9f6d6ec9eb1a6e6c3e75ea6273e899e78fb7fc59f81d39745009fbc60 md5: aa459086047c0e5e27023ab19f8cb86a @@ -648,6 +803,7 @@ packages: - libzlib >=1.3.2,<2.0a0 license: BSD-3-Clause license_family: BSD + purls: [] run_exports: weak: - zstd >=1.5.7,<1.6.0a0 @@ -659,9 +815,61 @@ packages: depends: - __unix license: ISC + purls: [] run_exports: {} size: 130057 timestamp: 1792772446739 +- conda: https://conda.anaconda.org/conda-forge/noarch/cli-ui-0.17.2-pyhd8ed1ab_0.tar.bz2 + sha256: 86a2428e5738c65a4cbb5468810024eb589753255e7f1ebf10a65804ce9372a2 + md5: e210df0dfab7781247c2a7ba09673400 + depends: + - colorama >=0.4.1 + - python >=3.7,<4.0 + - tabulate >=0.8.3 + - unidecode >=1.0.23 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/cli-ui?source=hash-mapping + run_exports: {} + size: 17216 + timestamp: 1661938037728 +- conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_1.conda + sha256: ab29d57dc70786c1269633ba3dff20288b81664d3ff8d21af995742e2bb03287 + md5: 962b9857ee8e7018c22f2776ffa0b2d7 + depends: + - python >=3.9 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/colorama?source=hash-mapping + run_exports: {} + size: 27011 + timestamp: 1733218222191 +- conda: https://conda.anaconda.org/conda-forge/noarch/contextlib2-21.6.0-pyhd8ed1ab_1.conda + sha256: 90e12ef22f91937e723116b79cb42f3ab38c407970398a843b1eac358ca68c45 + md5: 4de17d73a4afd4ce03b370fe4480100f + depends: + - python >=3.9 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/contextlib2?source=hash-mapping + run_exports: {} + size: 18056 + timestamp: 1734475348772 +- conda: https://conda.anaconda.org/conda-forge/noarch/docopt-0.6.2-pyhd8ed1ab_2.conda + sha256: 7581a21e9bbe279d73d8ea32333f07ab286d2880edcee76a52480e2e4e53470d + md5: a83e0c5be564702a79a9e3efda32009f + depends: + - python >=3.9 + license: MIT + license_family: MIT + purls: + - pkg:pypi/docopt?source=hash-mapping + run_exports: {} + size: 18876 + timestamp: 1733817956506 - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-4.18.0-he073ed8_9.conda sha256: 41557eeadf641de6aeae49486cef30d02a6912d8da98585d687894afd65b356a md5: 86d9cba083cd041bfbf242a01a7a1999 @@ -692,6 +900,31 @@ packages: run_exports: {} size: 23329491 timestamp: 1790303058123 +- conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.15-9_cp315.conda + build_number: 9 + sha256: 976c4a6db967a62385aa633daaab19a929f986b979a7ad836b8b70e15ca7aefd + md5: b23461631fe2abdbade0cb64babe7344 + constrains: + - python 3.15.* *_cp315 + license: BSD-3-Clause + license_family: BSD + purls: [] + run_exports: {} + size: 6800 + timestamp: 1788302827589 +- conda: https://conda.anaconda.org/conda-forge/noarch/schema-0.7.8-pyhd8ed1ab_0.conda + sha256: 77b8343f0a6779de199070b533c9b24aa74b0b5987e0f22800351e282296aa51 + md5: 3c1c8d749d36f503fcc52f6aabb4c9be + depends: + - contextlib2 >=0.5.5 + - python >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/schema?source=hash-mapping + run_exports: {} + size: 25371 + timestamp: 1784572938499 - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.28-h4ee821c_9.conda sha256: c47299fe37aebb0fcf674b3be588e67e4afb86225be4b0d452c7eb75c086b851 md5: 13dc3adbc692664cd3beabd216434749 @@ -706,13 +939,69 @@ packages: - __glibc >=2.28,<3.0.a0 size: 24008591 timestamp: 1765578833462 +- conda: https://conda.anaconda.org/conda-forge/noarch/tabulate-0.10.0-pyhcf101f3_0.conda + sha256: 3f661e98a09f976775a494488beb3d35ebb00f535b169c6bd891f2e280d55783 + md5: 3b887b7b3468b0f494b4fad40178b043 + depends: + - python >=3.10 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tabulate?source=hash-mapping + run_exports: {} + size: 43964 + timestamp: 1772732795746 +- conda: https://conda.anaconda.org/conda-forge/noarch/tbump-6.9.0-pyhd8ed1ab_0.tar.bz2 + sha256: 831d28b05f5a28a8c1e50c2a1ff574d3d49b4d8b34c30a6fd0528514e6028985 + md5: 7dc2c1dae131bf141ceac251848bd6b4 + depends: + - cli-ui >=0.10.3 + - docopt >=0.6.2 + - python >=3.6,<4.0 + - schema >=0.7.1 + - tomlkit >=0.5.8 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/tbump?source=hash-mapping + run_exports: {} + size: 28785 + timestamp: 1652622787739 +- conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.15.2-pyh5ded981_0.conda + sha256: e6aa9e1c4d4e229280ef5446ebbc99e7b65c874deb47f83be6a751ba20332cc8 + md5: eadfe340211fea481536d602af9ace99 + depends: + - python >=3.11 + - python + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomlkit?source=compressed-mapping + run_exports: {} + size: 51412 + timestamp: 1792143573427 - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2026e-h5d301ff_0.conda sha256: 2b7ca858879f183ce2dcc65b300f48a0133d5430550f35b23d80d405a0788dbf md5: abccc3810d2b97e570dee487f2b46e38 license: LicenseRef-Public-Domain + purls: [] run_exports: {} size: 119208 timestamp: 1792758382821 +- conda: https://conda.anaconda.org/conda-forge/noarch/unidecode-1.4.0-pyhcf101f3_1.conda + sha256: 184d1377f88251983ef5154aea0d6cb73108afc8510ed66526afb1c44b2e1259 + md5: 53cb4b14ab0841e104e2bd11ee64b840 + depends: + - python >=3.10 + - python + license: GPL-2.0-or-later + license_family: GPL + purls: + - pkg:pypi/unidecode?source=hash-mapping + run_exports: {} + size: 189632 + timestamp: 1762257681278 - conda_source: mess-static[5770cfd9] @ static variants: c_stdlib: sysroot @@ -847,3 +1136,13 @@ packages: - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-ilp64-0.3.34-pthreads_h79482e6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-16.2.0-h934c35e_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-ilp64-0.3.34-pthreads_h8097de1_2.conda +- pypi: https://files.pythonhosted.org/packages/23/06/b4f06ca7afb5d9e942c642980c308ffcfa1fa0e8b0a3ddbec78483ef1614/keepachangelog-2.0.0-py3-none-any.whl + name: keepachangelog + version: 2.0.0 + sha256: 0b2259fd73b55f2b99e61035ff83f3d86d0f2764841a7e2de86e31e675e42fee + requires_dist: + - httpx==0.27.* ; extra == 'testing' + - starlette==0.37.* ; extra == 'testing' + - flask-restx==1.* ; extra == 'testing' + - pytest-cov==5.* ; extra == 'testing' + requires_python: '>=3.9' diff --git a/pixi.toml b/pixi.toml index e7306de..35ffe32 100644 --- a/pixi.toml +++ b/pixi.toml @@ -6,7 +6,7 @@ preview = ["pixi-build"] [package] name = "mess" -version = "2.10.32" +version = "2026.2.4" [package.build.backend] name = "pixi-build-cmake" @@ -39,6 +39,27 @@ mess = { path = "." } [feature.static.dependencies] mess-static = { path = "static" } +# Release tooling (see tbump.toml and RELEASING.md) +[feature.release.dependencies] +python = "*" +tbump = "*" + +[feature.release.pypi-dependencies] +keepachangelog = "*" + +[feature.release.tasks] +# Build both conda packages into dist/ +build-conda = "pixi publish --target-dir dist && pixi publish --path static --target-dir dist" +# Publish them to prefix.dev, skipping files that were already uploaded, so that a +# failed release can be rerun +publish-conda = "pixi upload prefix --skip-existing --channel automech dist/*.conda" +# Initiate release +version = "tbump current-version" +changelog = { cmd = "keepachangelog release {{ version }}", args = ["version"] } +release = "tbump" + [environments] default = ["dynamic"] static = ["static"] +# Only the release tooling: this environment does not build MESS +release = { features = ["release"], no-default-feature = true } diff --git a/static/README.md b/static/README.md index 4a89cc0..2c1067c 100644 --- a/static/README.md +++ b/static/README.md @@ -12,4 +12,5 @@ pixi publish --path static --target-dir dist # build dist/mess-static- ``` The executables are then in `.pixi/envs/static/bin/`. -The GitHub Actions workflow uploads them as a build artifact, and uploads the conda package to the Auto-Mech channel on pushes to `master` of `Auto-Mech/MESS`. +The GitHub Actions workflow uploads them as a build artifact. +Each release publishes the conda package to the `automech` channel on prefix.dev and attaches the executables to the GitHub release (see `RELEASING.md`). diff --git a/static/pixi.toml b/static/pixi.toml index 975748e..d383e12 100644 --- a/static/pixi.toml +++ b/static/pixi.toml @@ -2,10 +2,7 @@ # This is a package of the root workspace (see ../pixi.toml). # It uses the rattler-build backend so that recipe.yaml can drop the run-exports # of its build and host dependencies: the package has no runtime dependencies. - -[package] -name = "mess-static" -version = "2026.11.0" +# The name and version of the package are set in recipe.yaml. [package.build.backend] name = "pixi-build-rattler-build" diff --git a/static/recipe.yaml b/static/recipe.yaml index 11c5b77..19dfa22 100644 --- a/static/recipe.yaml +++ b/static/recipe.yaml @@ -1,6 +1,6 @@ package: name: mess-static - version: "2026.11.0" + version: "2026.2.4" source: path: .. diff --git a/tbump.toml b/tbump.toml new file mode 100644 index 0000000..bd75106 --- /dev/null +++ b/tbump.toml @@ -0,0 +1,41 @@ +github_url = "https://github.com/Auto-Mech/MESS" + +# One version for both packages, mess and mess-static: YYYY.M.N, where N counts the +# releases within the month, starting from 0 +[version] +current = "2026.2.4" +regex = ''' + (?P\d+) + \. + (?P\d+) + \. + (?P\d+) + ''' + +[git] +message_template = "Bump to {new_version}" +tag_template = "v{new_version}" + +[[file]] +src = "pixi.toml" +search = 'version = "{current_version}"' + +[[file]] +src = "static/recipe.yaml" +search = 'version: "{current_version}"' + +[[before_commit]] +name = "Update changelog" +cmd = "pixi run changelog {new_version}" + +[[before_commit]] +name = "Add changelog to commit" +cmd = "git add CHANGELOG.md" + +[[before_commit]] +name = "Update lockfile" +cmd = "pixi lock" + +[[before_commit]] +name = "Add lockfile to commit" +cmd = "git add pixi.lock"