fix(check): fail when the manifest is behind the tag, not merely different
`task check` asserted plugin.json's version EQUALS the latest tag. `git describe` is local-only, so any checkout that had not fetched the tag CI just pushed went red on a commit that was correct — three times in one backlog session, on the loop push → CI tags and pushes the bump → pull → red until you also fetch tags. The fault the assertion exists for is the manifest failing to move: a release whose manifest still names the old version, so no installed host ever sees the update. That is manifest < tag. Ahead is normal and is now quiet. Ordering needed a real comparison, and bin/doctor had already grown one for #30, so it moves to bin/newer-version with its own tests rather than existing twice. Seven cases including the lexical trap (0.8.10 beats 0.8.9) and a missing component counting as zero. Verified by mutation: manifest 0.1.0 against tag v0.9.0 exits 201 naming both versions; manifest 9.9.9 exits 0; the real tree exits 0. Closes #34 Bump-Type: patch
This commit is contained in:
+8
-2
@@ -104,8 +104,14 @@ tasks:
|
|||||||
if [ -f '{{.PLUGIN_MANIFEST}}' ]; then
|
if [ -f '{{.PLUGIN_MANIFEST}}' ]; then
|
||||||
manifest_v=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' '{{.PLUGIN_MANIFEST}}' | head -1)
|
manifest_v=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' '{{.PLUGIN_MANIFEST}}' | head -1)
|
||||||
tag_v=$(git -C '{{.TASKFILE_DIR}}' describe --tags --abbrev=0 2>/dev/null | sed 's/^v//' || echo '')
|
tag_v=$(git -C '{{.TASKFILE_DIR}}' describe --tags --abbrev=0 2>/dev/null | sed 's/^v//' || echo '')
|
||||||
if [ -n "$tag_v" ] && [ "$manifest_v" != "$tag_v" ]; then
|
# Ordering, not equality. The fault this guards is the manifest
|
||||||
echo "ERROR: plugin.json version ($manifest_v) != latest tag ($tag_v)" >&2
|
# failing to MOVE — a release tag whose manifest still names the old
|
||||||
|
# version, so no installed host ever sees the update. A manifest
|
||||||
|
# ahead of the newest tag this checkout knows about is the normal
|
||||||
|
# state between the tagger's bump commit and a tag fetch (#34).
|
||||||
|
if [ -n "$tag_v" ] && [ "$manifest_v" != "$tag_v" ] \
|
||||||
|
&& [ "$(sh '{{.TASKFILE_DIR}}/bin/newer-version' "$manifest_v" "$tag_v")" = "$tag_v" ]; then
|
||||||
|
echo "ERROR: plugin.json version ($manifest_v) is behind the latest tag ($tag_v) — installed hosts never see the update" >&2
|
||||||
fail=1
|
fail=1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
|||||||
+3
-9
@@ -252,16 +252,10 @@ manifest_version() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# newer_version a b — echoes whichever sorts higher on major.minor.patch.
|
# newer_version a b — echoes whichever sorts higher on major.minor.patch.
|
||||||
|
# Lives in bin/newer-version because `task check` needs the same ordering (#34)
|
||||||
|
# and a second copy is a second thing to get wrong.
|
||||||
newer_version() {
|
newer_version() {
|
||||||
printf '%s\n%s\n' "$1" "$2" | awk -F. '
|
sh "$SELF_DIR/newer-version" "$1" "$2"
|
||||||
{ raw[NR] = $0; for (i = 1; i <= 3; i++) n[NR, i] = ($i == "" ? 0 : $i + 0) }
|
|
||||||
END {
|
|
||||||
for (i = 1; i <= 3; i++) {
|
|
||||||
if (n[1, i] > n[2, i]) { print raw[1]; exit }
|
|
||||||
if (n[1, i] < n[2, i]) { print raw[2]; exit }
|
|
||||||
}
|
|
||||||
print raw[1]
|
|
||||||
}'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
installed_v=''
|
installed_v=''
|
||||||
|
|||||||
Executable
+26
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# newer-version A B — echo whichever of two dotted versions sorts higher.
|
||||||
|
# Equal versions echo A. Missing components count as zero, so 0.9 == 0.9.0.
|
||||||
|
#
|
||||||
|
# Exists because two callers need ordering rather than equality:
|
||||||
|
# - bin/doctor, comparing the installed plugin generation against the newest
|
||||||
|
# manifest on the host (#30);
|
||||||
|
# - task check, which must fail when plugin.json is BEHIND the latest tag and
|
||||||
|
# stay quiet when it is ahead — the normal state on a checkout that has not
|
||||||
|
# fetched the tag CI just pushed (#34).
|
||||||
|
#
|
||||||
|
# sort -V would do it in one line and is not portable enough for this fleet.
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
[ $# -eq 2 ] || { echo "usage: newer-version A B" >&2; exit 2; }
|
||||||
|
|
||||||
|
printf '%s\n%s\n' "$1" "$2" | awk -F. '
|
||||||
|
{ raw[NR] = $0; for (i = 1; i <= 3; i++) n[NR, i] = ($i == "" ? 0 : $i + 0) }
|
||||||
|
END {
|
||||||
|
for (i = 1; i <= 3; i++) {
|
||||||
|
if (n[1, i] > n[2, i]) { print raw[1]; exit }
|
||||||
|
if (n[1, i] < n[2, i]) { print raw[2]; exit }
|
||||||
|
}
|
||||||
|
print raw[1]
|
||||||
|
}'
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Tests for bin/newer-version.
|
||||||
|
#
|
||||||
|
# Extracted from bin/doctor (#30) once `task check` needed the same comparison
|
||||||
|
# (#34): check asserted plugin.json == latest tag, which is red on any checkout
|
||||||
|
# that has not fetched the tag the CI tagger just pushed. The assertion it
|
||||||
|
# actually wants is "not behind", and ordering needs a real comparison.
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
||||||
|
SUT="$ROOT/bin/newer-version"
|
||||||
|
|
||||||
|
pass=0
|
||||||
|
fail=0
|
||||||
|
|
||||||
|
if [ ! -f "$SUT" ]; then
|
||||||
|
printf 'FAIL: %s does not exist\n' "$SUT"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# expect <winner> <a> <b> <label>
|
||||||
|
expect() {
|
||||||
|
_got=$(sh "$SUT" "$2" "$3")
|
||||||
|
if [ "$_got" = "$1" ]; then
|
||||||
|
pass=$((pass + 1)); printf ' ok %s\n' "$4"
|
||||||
|
else
|
||||||
|
fail=$((fail + 1)); printf ' FAIL %s (newer-version %s %s -> %s, want %s)\n' "$4" "$2" "$3" "$_got" "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
expect 0.9.0 0.9.0 0.8.5 'higher minor wins, left'
|
||||||
|
expect 0.9.0 0.8.5 0.9.0 'higher minor wins, right'
|
||||||
|
expect 0.8.10 0.8.10 0.8.9 'numeric compare, not lexical — 10 beats 9'
|
||||||
|
expect 1.0.0 1.0.0 0.99.99 'major dominates'
|
||||||
|
expect 0.8.5 0.8.5 0.8.5 'equal returns the value'
|
||||||
|
expect 0.9.1 0.9.1 0.9 'a missing component counts as zero'
|
||||||
|
expect 0.9 0.9 0.9.0 'equal with a missing component returns the left, per contract'
|
||||||
|
|
||||||
|
printf '\nnewer_version: %d passed, %d failed\n' "$pass" "$fail"
|
||||||
|
[ "$fail" -eq 0 ]
|
||||||
Reference in New Issue
Block a user