commit 91cf156d9cc715094ce9ae00909830b99c69b4c8
parent 1346b401d5b4df4b65ff58a61fc59046460705e4
Author: Florian Dold <dold@taler.net>
Date: Tue, 8 Sep 2026 22:26:55 +0200
sysadmin docs: describe CI Debian version policy
Document tag selection, snapshot ordering and full checkout requirements
for Debian CI publishers. Replace the developer manual's previous nightly
version advice with a link to the system administration chapter.
Diffstat:
3 files changed, 174 insertions(+), 1 deletion(-)
diff --git a/developer/taler-developer-manual.rst b/developer/taler-developer-manual.rst
@@ -185,7 +185,10 @@ Right now, that process is manual.
We support tagged and published pre-release versions via tags of the form ``v${major}.${minor}.${patch}-dev.${n}``.
The corresponding Debian version must be ``${major}.${minor}.${patch}~dev${n}``.
-Nightly Debian packages should follow the `Debian conventions <https://wiki.debian.org/Versioning>`__ of ``{upcoming_version}~git{date}.{hash}-{revision}``.
+Nightly Debian packages built by Buildbot use the highest eligible SemVer
+tag and the snapshot mapping described in
+:ref:`ci-debian-package-versions`. The system administration documentation
+also covers checkout caching and diagnosing version-generation failures.
Testing Tools
-------------
diff --git a/system-administration/ci-debian-versions.rst b/system-administration/ci-debian-versions.rst
@@ -0,0 +1,169 @@
+..
+ This file is part of GNU TALER.
+ Copyright (C) 2026 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free Software
+ Foundation; either version 3.0, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+
+ @author Florian Dold
+
+.. _ci-debian-package-versions:
+
+CI Debian Package Versions
+==========================
+
+The Debian publishers on ``buildbot.gnunet.org`` derive their package
+versions from the highest eligible SemVer tag in the repository. The build
+still uses the commit scheduled by Buildbot; selecting a version tag does
+not change the source checkout.
+
+This policy covers ``gnunet``, ``exchange``, ``merchant``, ``donau``,
+``challenger``, ``anastasis``, ``sync``, ``libeufin``, ``taler-rust``,
+``depolymerization``, ``taler-mailbox``, ``taldir``, and
+``taler-typescript-core``. All Debian packages produced by a repository use
+its shared version helper.
+
+Tag selection
+-------------
+
+Eligible tags have the form ``vX.Y.Z`` or ``vX.Y.Z-dev.K``. Each numeric
+component is a nonnegative integer without leading zeroes, except for zero
+itself. Both annotated and lightweight tags are accepted. Optional SemVer
+build metadata, such as ``+build.001``, is accepted but ignored in version
+comparisons and omitted from the generated versions.
+
+Selection compares the numeric components according to SemVer precedence.
+For example, ``v1.2.3-dev.10`` sorts after ``v1.2.3-dev.9``, and
+``v1.2.3`` sorts after both. The highest eligible tag is selected across the
+whole repository, including tags whose commits are not ancestors of HEAD.
+Tag dates and proximity to HEAD do not determine the result.
+
+When several tags have equal precedence, prefer the tag without build
+metadata. If there is still a tie, choose the lexicographically first tag
+name. Unsupported tags are reported and excluded. These include historical
+forms such as ``v0.9.4a``, Debian-specific tags, and prereleases other than
+``-dev.K``. The generated snapshot forms below are reserved for CI output
+and are not eligible release tags. Version generation fails if no eligible
+tag exists.
+
+Snapshot versions and ordering
+------------------------------
+
+Let ``N`` be the result of ``git rev-list --count TAG..HEAD``, where ``TAG``
+is the selected tag. A build is an exact tagged release only when
+``git rev-parse HEAD`` equals ``git rev-parse 'TAG^{commit}'``. A count of
+zero alone does not establish an exact release: HEAD can be an ancestor of
+the tagged commit. Such a build still receives a snapshot suffix with
+``N = 0``.
+
+.. list-table:: Version mapping
+ :header-rows: 1
+ :widths: 30 35 35
+
+ * - Selected tag and checkout
+ - SemVer
+ - Debian version
+ * - ``vX.Y.Z``, exact commit
+ - ``X.Y.Z``
+ - ``X.Y.Z``
+ * - ``vX.Y.Z``, different commit
+ - ``X.Y.(Z+1)-0.N``
+ - ``X.Y.(Z+1)~0.N``
+ * - ``vX.Y.Z-dev.K``, exact commit
+ - ``X.Y.Z-dev.K``
+ - ``X.Y.Z~devK``
+ * - ``vX.Y.Z-dev.K``, different commit
+ - ``X.Y.Z-dev.K.N``
+ - ``X.Y.Z~devK.N``
+
+``Z+1`` means incrementing the patch component. For example, twelve commits
+beyond ``v1.6.43`` produce SemVer ``1.6.44-0.12`` and Debian version
+``1.6.44~0.12``. Twelve commits beyond ``v1.6.44-dev.9`` produce
+``1.6.44-dev.9.12`` and ``1.6.44~dev9.12``.
+
+A snapshot sorts after its selected tag in both systems. A stable-tag
+snapshot sorts before the next patch's ``dev.0`` release; a development-tag
+snapshot sorts before the next development tag, with ``K`` incremented
+by one. For example, these sequences have matching order::
+
+ 1.6.43 < 1.6.44-0.12 < 1.6.44-dev.0
+ 1.6.43 < 1.6.44~0.12 < 1.6.44~dev0
+
+ 1.6.44-dev.9 < 1.6.44-dev.9.12 < 1.6.44-dev.10 < 1.6.44
+ 1.6.44~dev9 < 1.6.44~dev9.12 < 1.6.44~dev10 < 1.6.44
+
+The mapping also preserves equality. Neither a commit hash nor build
+metadata is added to the Debian version to break a SemVer tie. Different
+commits can therefore receive the same version, for example when their
+counts relative to the selected tag are equal. Use the logged HEAD commit
+and the artifact path containing the CI commit reference to identify a
+particular build.
+
+Buildbot checkout and packaging requirements
+--------------------------------------------
+
+The container factories in ``taler-deployment.git/buildbot/master.cfg``
+retain full checkouts for these repositories. They use Git ``mode='full'``,
+``method='fresh'``, ``shallow=False``, and ``tags=True``. The fresh checkout
+cleans build outputs while retaining Git history. The workspace preparation
+step replaces a previous shallow checkout once, then keeps the full
+checkout for subsequent builds.
+
+Each repository provides ``contrib/ci/version.sh``, backed by
+``contrib/ci/debian-version.py``. Existing job-local ``version.sh`` paths
+delegate to this entry point. Packaging containers must explicitly install
+Python 3, including architecture-specific Containerfiles and templates used
+to generate jobs.
+
+The helper requires a full checkout and fetches all tags for the exact
+scheduled commit with::
+
+ git fetch --no-recurse-submodules --tags origin COMMIT
+
+``COMMIT`` is the full HEAD commit ID. Fetching by commit supports detached
+HEADs and avoids guessing a branch name. Do not introduce a fetch depth
+limit: incomplete history changes the commit count. A shallow checkout or a
+failed fetch causes version generation to fail.
+
+Standard output contains only the Debian version. Standard error records
+the selected tag, HEAD commit, count, SemVer, and Debian version, as well as
+excluded tags and errors. Packaging jobs must stop on errors and reject
+empty output before changing the changelog or building packages. In a shell
+script with ``set -e``, keep assignment separate from export::
+
+ VERSION="$(./contrib/ci/version.sh)"
+ export VERSION
+ : "${VERSION:?version generation returned an empty version}"
+
+Using ``export VERSION="$(...)"`` can hide the helper's failure status.
+
+Maintaining and diagnosing the policy
+-------------------------------------
+
+Keep ``contrib/ci/debian-version.py`` and ``contrib/ci/test_version.py``
+identical across the affected repositories. Run the conformance suite in a
+Debian container with Git, Python 3, Bash, and ``dpkg`` installed::
+
+ python3 contrib/ci/test_version.py
+
+The suite exercises tag selection, detached checkouts, tags on other
+branches, snapshot mapping, Debian ordering, compatibility entry points,
+and packaging callers' error handling. The Debian ordering check is skipped
+when ``dpkg`` is unavailable. Changes to checkout caching should also run
+the Buildbot tests in ``taler-deployment.git/buildbot/test_container_steps.py``.
+
+When a package version looks unexpected, first inspect the helper's
+selected-tag and HEAD diagnostics. Check the highest eligible tag across
+all branches, then compare the tagged commit to HEAD and inspect the
+``TAG..HEAD`` count. For a shallow-checkout failure, check the builder's
+cache policy and workspace migration. For a fetch failure, check access to
+``origin`` and the scheduled commit. Fix the checkout or tag problem before
+retrying the package build.
diff --git a/system-administration/index.rst b/system-administration/index.rst
@@ -33,3 +33,4 @@ Internal System Administration
prometheus-postgres-exporter
grafana-loki
debian-repos
+ ci-debian-versions