Stop borrowing Stalwart's version number

The middle field was the Stalwart generation a build targeted -- 16 for
0.16 -- which leaves nowhere to go when Stalwart reaches 1.0. There is no
honest value for it: 2.1 sorts below the 2.16 already deployed, so every
image and About screen would have read as a downgrade. Tying our
numbering to somebody else's was the mistake, and which Stalwart a build
needs is said properly in the README badge and KNOWN-ISSUES, where it can
be precise rather than one digit.

The version is now the date of the commit it was built from, and the pull
request moves after the + as build metadata. It is provenance rather than
a rank: at the rate they merge here it climbs without bound and says
nothing about how new a build is. Everything after the + is ignored when
versions are compared, which reads correctly -- two builds from the same
day differ in where they came from, not in age -- and nothing depends on
that comparison anyway, since images are pruned by creation time and a
rollback names a git ref.

The date is the commit's own, so rebuilding an old commit gives the
version it had the first time. package.json is no longer the source of
anything and sits at 0.0.0, which is what an unversioned build reports
and is meant to look wrong.

The formatting is a pure function now, so the rules have tests. They had
none while the version was the thing naming every image we ship.
This commit is contained in:
2026-08-30 14:38:07 -07:00
parent d75e9bc769
commit 2f55b1e3e1
9 changed files with 169 additions and 59 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@ihasmail/web",
"version": "2.16.0",
"version": "0.0.0",
"private": true,
"license": "AGPL-3.0-or-later",
"type": "module",
+5 -3
View File
@@ -1,6 +1,8 @@
/**
* What this build calls itself: `2.16.57`, or `2.16.57+g1fa6578` for a commit
* that did not come through a pull request. Baked in by Vite; see
* `scripts/version.mjs` for where the parts come from.
* What this build calls itself: `2026.8.30+pr129` -- the date of the commit it
* was built from, and the pull request that commit arrived through. A commit
* that did not come through one carries its short SHA instead,
* `2026.8.30+g1fa6578`. Baked in by Vite; see `scripts/version.mjs` for why the
* parts are what they are.
*/
export const APP_VERSION = __IHASMAIL_VERSION__;
+1 -1
View File
@@ -30,7 +30,7 @@ export function AboutSettings() {
</tbody>
</table>
<p className="hint" style={{ marginTop: 6 }}>Stalwart does not publish its version number to mail clients, so ihasmail reports the edition where the server gives one. ihasmail requires 0.16 or newer, and sign-in refuses anything older.</p>
<p className="hint">The middle number of ihasmail's own version is the Stalwart generation it is built for: <strong>v2.16.x</strong> targets Stalwart 0.16. The last is the pull request it was built from, and a trailing <code>+g</code> and short commit means the build is past that pull request rather than exactly it.</p>
<p className="hint">ihasmail's own version is the date of the commit it was built from, followed by where that commit came from: <strong>v2026.8.30+pr129</strong> was built from a commit dated the 30th of August 2026 that arrived through pull request 129. A commit that did not come through one carries its short SHA instead <code>+g1fa6578</code>. The version deliberately says nothing about Stalwart; what this build needs from the server is the line above.</p>
<h2>Server capabilities</h2>
<div className="row wrap gap-4">
{caps.map((c) => <span key={c} className="chip mono" style={{ fontSize: ".78em" }}>{c.replace("urn:ietf:params:jmap:", "")}</span>)}