Metadata-Version: 2.4
Name: travertine
Version: 0.50.0a2
Requires-Dist: xotless>=4.0.0
Requires-Dist: ply
Requires-Dist: immutables
Requires-Dist: xotl-tools>=3.0.0
Requires-Dist: babel>=2.9.0,<3
License-File: LICENSE
Summary: Generating pricing tables from pricing programs
Author-email: Merchise Autrement <info@merchise.de>
Requires-Python: >=3.10
Description-Content-Type: text/x-rst; charset=UTF-8
Project-URL: Documentation, https://merchise-autrement.gitlab.io/travertine/
Project-URL: Repository, https://gitlab.merchise.org/mercurio-2018/travertine/

=================================================
 Generating pricing tables from pricing programs
=================================================

Travertine tries to solve the problem of generating price tables fast enough
for our xhg2 project.  This Rust runtime **is not a replacement** of the
Python runtime because there are still types of procedures which are not
implemented in Rust.


Preparing a release
===================

Releases are cut from ``main`` and published by the CI: pushing a tag whose name
is exactly the version builds the manylinux wheels (CPython 3.10 to 3.14) and
uploads them to PyPI.  Nothing is ever published from a developer's machine.

1. Make sure ``main`` is green: ``make lint``, ``make typecheck``, ``make test``
   and ``make docs/build``.

2. Complete the changelog in ``docs/source/history.rst``.  The topmost section
   is headed ``Unreleased.  Release X.Y.0`` while the version is being prepared;
   on the *final* release replace ``Unreleased`` with the date, as in
   ``2025-08-23.  Release 0.49.0``.  Pre-releases leave the heading alone.

3. Bump the version:

   - in ``pyproject.toml`` always, using the PEP 440 spelling (``0.50.0a1``,
     ``0.50.0rc1``, ``0.50.0``); and

   - in ``Cargo.toml`` only on the final release.  Cargo has no spelling for our
     pre-release versions, so the crate keeps the previous number until then.

   Refresh the locks afterwards so that their ``travertine`` entries match:
   ``make lock`` for ``uv.lock``, and ``cargo check`` (or ``make test-rust``)
   for ``Cargo.lock``.

4. Commit those files alone, with the message ``Pre-release X.Y.ZaN`` or
   ``Release X.Y.Z``.

5. Tag that commit with an annotated tag named exactly as the version, with no
   ``v`` prefix::

     git tag -a 0.50.0a1 -m 'Pre-release 0.50.0a1'

6. Push the commit and the tag to the ``gitlab`` remote (gitlab.merchise.org)::

     git push gitlab main
     git push gitlab 0.50.0a1

   The tag's pipeline runs `build wheels` and then `publish Python extensions in
   PyPI`, which uploads them with ``uv publish``.

The next change to land after a release is the one that opens the new
``Unreleased.  Release X.Y.0`` section in the changelog.


CI variables needed to publish the wheels
-----------------------------------------

The `publish Python extensions in PyPI` job only knows about two variables,
which it hands to ``uv publish`` as ``UV_PUBLISH_USERNAME`` and
``UV_PUBLISH_PASSWORD``:

``PYPI_USERNAME``
   The literal ``__token__``: PyPI no longer accepts a password, only API
   tokens, and the token is passed as the password of that user.

``PYPI_PASSWORD``
   The PyPI API token itself, ``pypi-`` prefix included.  Mask it.

Both are defined in the project settings of gitlab.merchise.org (Settings >
CI/CD > Variables); the job runs with ``GIT_STRATEGY: none``, so nothing else
in the repository can supply them.  Check them before tagging:

- The token must not have expired -- PyPI tokens do expire, and the failure
  only shows up at the end of the pipeline, once the wheels are already built.

- If either variable is *protected*, the tag must be protected as well
  (Settings > Repository > Protected tags), otherwise the variable is simply
  empty in the tag's pipeline and the upload fails with a 403.

- If either variable is scoped to an environment, the scope must be ``pypi``,
  which is the environment the publish job declares.

