diff --git a/scripts/verify-version-consistency.sh b/scripts/verify-version-consistency.sh index c0b2ae7..a1066fc 100755 --- a/scripts/verify-version-consistency.sh +++ b/scripts/verify-version-consistency.sh @@ -1,10 +1,29 @@ #!/usr/bin/env bash # verify-version-consistency.sh — Block A of preflight. -# csproj is 3-digit SemVer; repo.json AssemblyVersion is 4-digit (.0 suffix). +# +# csproj is 3-digit SemVer; repo.json AssemblyVersion is 4-digit. +# +# Two states, and conflating them is what made this check unsatisfiable: +# +# Published csproj == repo.json == the tag in every DownloadLink. +# Unreleased csproj is ahead; repo.json and the links stay on whatever is +# actually downloadable. +# +# repo.json is the distribution manifest, so its version has to describe what the +# links serve. A manifest claiming 1.11.0 while every link serves v1.5.6 makes +# Dalamud offer an update, install the old build, and offer the same update on +# the next launch. +# +# Default run allows both states and enforces what holds in each. Pass --release +# to demand the published one; that is the mode for cutting a tag, and it is what +# catches the v1.2.2 burn (csproj bumped, repo.json forgotten). set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" +RELEASE_MODE=0 +[ "${1:-}" = "--release" ] && RELEASE_MODE=1 + CSPROJ="$ROOT/HellionChat/HellionChat.csproj" REPO_JSON="$ROOT/repo.json" @@ -14,23 +33,38 @@ ok() { echo "verify-version-consistency: OK — $1"; } CSPROJ_VER="$(grep -oE '[^<]+' "$CSPROJ" | head -1 | sed -E 's/<[^>]+>//g')" [ -n "$CSPROJ_VER" ] || fail "$CSPROJ has no element" -EXPECTED_4DIGIT="${CSPROJ_VER}.0" - REPO_VER="$(jq -r '.[0].AssemblyVersion' "$REPO_JSON")" -[ "$REPO_VER" = "$EXPECTED_4DIGIT" ] \ - || fail "csproj=$CSPROJ_VER expects repo.json AssemblyVersion=$EXPECTED_4DIGIT but got $REPO_VER. Fix: align in $REPO_JSON." - TEST_VER="$(jq -r '.[0].TestingAssemblyVersion' "$REPO_JSON")" -[ "$TEST_VER" = "$EXPECTED_4DIGIT" ] \ - || fail "TestingAssemblyVersion=$TEST_VER must match $EXPECTED_4DIGIT. Fix: align in $REPO_JSON." -TAG="v$CSPROJ_VER" +# Always: the manifest must agree with itself. +[ "$TEST_VER" = "$REPO_VER" ] \ + || fail "TestingAssemblyVersion=$TEST_VER must match AssemblyVersion=$REPO_VER in $REPO_JSON." + +# Always: every link must serve exactly the version the manifest claims. This is +# the check that actually protects users -- a mismatch here is an update loop. +REPO_TAG="v${REPO_VER%.*}" for KEY in DownloadLinkInstall DownloadLinkUpdate DownloadLinkTesting; do URL="$(jq -r ".[0].$KEY" "$REPO_JSON")" case "$URL" in - *"/$TAG/"*) ;; - *) fail "$KEY=$URL does not contain tag $TAG. Fix: update $REPO_JSON $KEY to releases/download/$TAG/latest.zip." ;; + *"/$REPO_TAG/"*) ;; + *) fail "$KEY=$URL does not serve $REPO_TAG, which is what AssemblyVersion=$REPO_VER claims. Either point the link at $REPO_TAG or set AssemblyVersion to the version the link serves." ;; esac done -ok "csproj=$CSPROJ_VER, repo.json=$EXPECTED_4DIGIT, tag $TAG present in DownloadLinks" +# Always: the build must never be older than what is published. +LOWER="$(printf '%s\n%s\n' "$CSPROJ_VER" "${REPO_VER%.*}" | sort -V | head -1)" +[ "$LOWER" = "${REPO_VER%.*}" ] \ + || fail "csproj=$CSPROJ_VER is older than the published ${REPO_VER%.*}. A build behind the manifest cannot be right." + +if [ "$RELEASE_MODE" -eq 1 ]; then + [ "$REPO_VER" = "${CSPROJ_VER}.0" ] \ + || fail "release mode: csproj=$CSPROJ_VER requires repo.json AssemblyVersion=${CSPROJ_VER}.0 but got $REPO_VER. Fix: align $REPO_JSON and point the DownloadLinks at v$CSPROJ_VER." + ok "release: csproj=$CSPROJ_VER, repo.json=$REPO_VER, links serve $REPO_TAG" + exit 0 +fi + +if [ "$REPO_VER" = "${CSPROJ_VER}.0" ]; then + ok "published: csproj=$CSPROJ_VER, repo.json=$REPO_VER, links serve $REPO_TAG" +else + ok "unreleased: csproj=$CSPROJ_VER ahead of published ${REPO_VER%.*}, links serve $REPO_TAG consistently" +fi