feat: four-part versions, and a published version is never used again
0.2.6.1 is a maintenance release of 0.2.6. The build refused four parts, update_canary.sh's automatic bump could not add one to "6.1", and neither publish script would have noticed a version being published twice — which is what happened to 0.2.6 this morning: it was rebuilt with the Presentations hardening and uploaded over the first 0.2.6, and a room that had installed the first can never be offered the second. One release library now holds the version pattern (three or four parts, no leading zeros, no .0 maintenance), orders by dpkg --compare-versions, refuses a version that has ever been published or is not newer than all of them, uploads with --ignore-existing and checks the server's checksum, writes a manifest only for a package the server holds, and reads the channel back over HTTPS afterwards. update_canary.sh takes the version explicitly; update_stable.sh refuses to go backwards. The classroom updater refuses a manifest whose version, package name or checksum is malformed, and refuses a download whose own control file is not the version the manifest promised, so a room can never loop on reinstalling and rebooting. tests/test-release-versions.sh: 87 checks against a stand-in server and real dpkg. The Trixie gate now also rehearses a stable room: 0.2.2 to an interim 0.2.6.1 upgraded with settings, channel and Presentations=false intact, and the installed updater answering correctly. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
6f2d169355
commit
690ef95aff
+41
-55
@@ -4,76 +4,62 @@ set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
source "$ROOT/tools/release-lib.sh"
|
||||
|
||||
# Stable never gets a package of its own. It is pointed at one canary
|
||||
# already published, so the file every classroom downloads is byte for
|
||||
# byte the one the canary machine ran.
|
||||
if [[ $# -eq 1 ]]; then
|
||||
version="$1"
|
||||
|
||||
package_name="ekklesia-classroom_${version}_amd64.deb"
|
||||
package_path="$ROOT/repo/packages/$package_name"
|
||||
|
||||
if [[ ! -f "$package_path" ]]; then
|
||||
echo "Package does not exist locally:"
|
||||
echo "$package_path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
hash="$(sha256sum "$package_path" | awk '{print $1}')"
|
||||
|
||||
mkdir -p "$ROOT/repo/stable"
|
||||
|
||||
cat > "$ROOT/repo/stable/manifest.json" <<EOF
|
||||
{
|
||||
"version": "$version",
|
||||
"package": "/packages/$package_name",
|
||||
"sha256": "$hash",
|
||||
"requires_reboot": true
|
||||
}
|
||||
EOF
|
||||
else
|
||||
if [[ ! -f "$ROOT/repo/canary/manifest.json" ]]; then
|
||||
if [[ ! -f "$RELEASE_LOCAL/canary/manifest.json" ]]; then
|
||||
echo "No local canary manifest exists."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$ROOT/repo/stable"
|
||||
cp "$ROOT/repo/canary/manifest.json" "$ROOT/repo/stable/manifest.json"
|
||||
|
||||
version="$(python3 -c \
|
||||
'import json; print(json.load(open("repo/stable/manifest.json"))["version"])')"
|
||||
'import json, sys; print(json.load(open(sys.argv[1]))["version"])' \
|
||||
"$RELEASE_LOCAL/canary/manifest.json")"
|
||||
fi
|
||||
|
||||
echo "Promoting $version to STABLE"
|
||||
release_require_version "$version"
|
||||
|
||||
rsync -av \
|
||||
-e ssh \
|
||||
"$ROOT/repo/stable/manifest.json" \
|
||||
classroom-control:/srv/ekklesia/classroom-updates/stable/manifest.json
|
||||
package_name="$(release_package_name "$version")"
|
||||
package_path="$RELEASE_LOCAL/packages/$package_name"
|
||||
|
||||
if [[ ! -f "$package_path" ]]; then
|
||||
echo "Package does not exist locally:"
|
||||
echo "$package_path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
package_name="ekklesia-classroom_${version}_amd64.deb"
|
||||
if [[ "$(release_package_version "$package_path")" != "$version" ]]; then
|
||||
echo "$package_name says it is $(release_package_version "$package_path")." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# THE PERMANENT URL.
|
||||
#
|
||||
# .../stable/latest.deb is a symlink beside the manifest pointing at the
|
||||
# versioned package the manifest names, so there is one download address
|
||||
# that never changes and still no second place recording which version is
|
||||
# current. The manifest remains the only answer to that question.
|
||||
#
|
||||
# It is swapped AFTER the manifest, and by rename, for two reasons. A
|
||||
# rename is atomic, so nothing ever downloads a half-written pointer; and
|
||||
# going last means latest.deb can only ever lag the manifest by a moment,
|
||||
# never lead it — it can never offer a package the channel has not
|
||||
# published. The versioned file itself is never touched again once
|
||||
# uploaded.
|
||||
ssh classroom-control "
|
||||
set -e
|
||||
cd /srv/ekklesia/classroom-updates/stable
|
||||
test -f ../packages/$package_name
|
||||
ln -sfn ../packages/$package_name latest.deb.new
|
||||
mv -Tf latest.deb.new latest.deb
|
||||
"
|
||||
# A classroom only ever installs a version newer than its own, so a stable
|
||||
# manifest that went backwards would reach nobody and would only make the
|
||||
# channel say something untrue.
|
||||
current="$(release_channel_version stable || true)"
|
||||
|
||||
echo "https://updates.riverofglorymn.org/stable/latest.deb -> $package_name"
|
||||
if [[ -n "$current" ]] && ! release_version_gt "$version" "$current"; then
|
||||
echo "Stable is on $current; $version is not newer." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
hash="$(sha256sum "$package_path" | awk '{print $1}')"
|
||||
|
||||
echo "Promoting $version to STABLE (from ${current:-nothing})"
|
||||
|
||||
# Refuses unless the server already holds exactly this package.
|
||||
release_publish_manifest stable "$version" "$hash"
|
||||
|
||||
echo "$RELEASE_URL/stable/latest.deb -> $package_name"
|
||||
|
||||
echo
|
||||
release_verify_channel stable "$version"
|
||||
|
||||
echo
|
||||
echo "Ekklesia Classroom $version is now STABLE"
|
||||
echo "https://updates.riverofglorymn.org/stable/manifest.json"
|
||||
echo "$RELEASE_URL/stable/manifest.json"
|
||||
|
||||
Reference in New Issue
Block a user