mudlet/test/ci
Vadim Peretokin 71f736297b
infrastructure: reject a release tag that does not match APP_VERSION (#9701)
#### Brief overview of PR changes/additions
- Adds `CI/check-release-tag.sh`: APP_VERSION must be three-component,
and a release tag must be exactly `Mudlet-<APP_VERSION>`.
- Wires it into the tag-build validation (`CI/validate_deployment.sh`,
`CI/validate-deployment-for-windows.sh`) so a bad tag fails minutes
after the push, before an asset exists, and into
`create-github-release.yml` as the last gate before anything is
published. The PTB path gets the version-shape half, which nothing
checks on `development` today.
- Covers it with `test/ci/release-tag-version-test.sh`, registered as
`ReleaseTagVersionTest`.

#### Motivation for adding to Mudlet
Tagging `Mudlet-5.0` instead of `Mudlet-5.0.0` would strand the entire
4.22.0 user base with no error anywhere, and it is the one version
mistake CI does not currently catch.

The updater takes the version it offers from the tag, not the binary:
`Release::Release()` strips the `Mudlet-` prefix
(`src/updater/Release.cpp:49`) and `SemVer::getRegExp()` needs three
components (`src/updater/SemVer.cpp:111`), so `"5.0"` is invalid,
`Release::operator<` (`src/updater/Release.cpp:96`) reports the release
as not newer, and `Feed::getUpdates()` returns nothing. The update check
goes on logging `0 update(s) available` - the same line as a week with
no release.

The asymmetry is what makes it dangerous. A stale APP_VERSION with a
correct tag fails loudly, because `CI/prepare-release-assets.sh:62`
rejects assets by tag prefix. A short tag with a correct APP_VERSION
passes everything, because `Mudlet-5.0.0-linux-x64.AppImage.tar`
genuinely does start with `Mudlet-5.0`.

**Why the build scripts and not only the workflow:**
`create-github-release.yml` is `workflow_run`-triggered, so it cannot
fail before the assets are built - by the time it runs, the full matrix
has already finished. The validate scripts run at the start of every tag
build on all three platforms and already parse APP_VERSION, so that is
where the fast failure belongs. The workflow keeps a copy because it
always runs from the default branch, so it still guards a tag placed on
a commit that predates this change.

APP_VERSION is deliberately left at 4.22.0 - bumping it is a release
decision, not a QA fix. This guard is what catches a mismatch when the
bump happens.

#### Other info (issues closed, discussion etc)
From the 5.0 release QA sweep, finding C1, "A two-component release tag
silently disables auto-update for every existing user". Pre-existing
mechanism, no single commit introduced it.

Three claims from an earlier draft did not survive checking and were
corrected: `src/sparkleupdater.mm` installs no
`versionComparatorForUpdater:`, so Sparkle's default component-wise
comparator would still offer `5.0` over `4.22.0` (macOS breaks on the
opposite mismatch instead); the update check does log, it is just
indistinguishable from having nothing to offer; and SemVer does accept a
prerelease component, so rejecting `Mudlet-5.0.0-rc1` follows from
APP_VERSION being unable to carry a suffix, not from the updater.

No video - a CI guard is not visually observable. The shell output below
is the evidence instead.

**Test case:** `ctest -R ReleaseTagVersionTest`, and the guard run
directly:

```
$ CI/check-release-tag.sh 5.0.0 Mudlet-5.0.0
Release tag 'Mudlet-5.0.0' matches APP_VERSION '5.0.0'.
exit=0

$ CI/check-release-tag.sh 5.0.0 Mudlet-5.0
error: release tag 'Mudlet-5.0' does not match APP_VERSION '5.0.0'.
The tag has to be exactly 'Mudlet-5.0.0'.

Publishing under a mismatched tag breaks auto-update, without saying so. [...]
exit=1
```

Replayed over every release tag since 4.18.5, each against the
APP_VERSION at that tag - all accepted, so the guard blocks nothing
Mudlet has actually shipped. Executing the real `Determine release type`
step under GitHub's shell flags fails on `Mudlet-5.0` + `5.0.0` and on a
PTB with APP_VERSION `5.0`, and passes on `Mudlet-5.0.0` + `5.0.0` and
on a normal PTB. The updater trace was confirmed by compiling
`Release.cpp` + `SemVer.cpp` and comparing: tag `Mudlet-5.0.0` gives
`(4.22.0 < release) = true`, tag `Mudlet-5.0` gives `false`.

Assisted-by: Claude:claude-opus-5
2026-08-07 06:14:11 +02:00
..
milestone-resolution-test.sh infrastructure: fix milestone assignment, unbreak the key sequence tests (#9679) 2026-08-06 06:07:10 +02:00
release-checksums-test.sh fix: Windows auto-update failing on a release binary with no checksum (#9617) 2026-08-03 12:30:14 +02:00
release-tag-version-test.sh infrastructure: reject a release tag that does not match APP_VERSION (#9701) 2026-08-07 06:14:11 +02:00