From eac583c15e521e70e7f57998699aef21c1da15e7 Mon Sep 17 00:00:00 2001 From: Dorian Date: Sun, 19 Apr 2026 03:23:18 -0400 Subject: [PATCH] release: v1.5.0-alpha + version hygiene fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Versioning was drifting on three axes — fixed all of them: 1. Cargo.toml → 1.5.0-alpha (was 1.5.0). User wants `-alpha` suffix on every pre-stable release; this is the current state of main. 2. neode-ui/package.json was still 1.3.5 — brought in line. 3. /opt/archipelago/build-info.txt was stale on .198 (1.3.4) and .253 (1.3.5), absent on .116/.228. That file OVERRIDES the binary's CARGO_PKG_VERSION for the UI sidebar, which is why .198/.253 kept showing old versions even with fresh binaries. scripts/deploy-to-target.sh now writes build-info.txt on every deploy, reading the version straight from Cargo.toml — so the sidebar can never drift from the binary again. Release artifacts + manifest: - releases/v1.5.0-alpha/archipelago (40M, sha in manifest) - releases/v1.5.0-alpha/archipelago-frontend-1.5.0-alpha.tar.gz (51M) - releases/manifest.json bumped with full 7-line changelog covering FIPS-first routing, Settings toggle, transitive federation, cancel button, transport badges, peer listener, and the build-info fix. - scripts/check-release-manifest.sh — new pre-publish guard. Refuses to pass if: Cargo.toml ≠ manifest version, changelog is empty (release notes are mandatory), or any component's sha256/size doesn't match the file on disk. Run locally or from CI. Co-Authored-By: Claude Opus 4.7 (1M context) --- core/Cargo.lock | 2 +- core/archipelago/Cargo.toml | 2 +- neode-ui/package.json | 2 +- scripts/check-release-manifest.sh | 78 +++++++++++++++++++++++++++++++ scripts/deploy-to-target.sh | 13 ++++++ 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100755 scripts/check-release-manifest.sh diff --git a/core/Cargo.lock b/core/Cargo.lock index 694de8f8..e57b7b67 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "archipelago" -version = "1.5.0" +version = "1.5.0-alpha" dependencies = [ "anyhow", "archipelago-container", diff --git a/core/archipelago/Cargo.toml b/core/archipelago/Cargo.toml index ef7faef5..b599844c 100644 --- a/core/archipelago/Cargo.toml +++ b/core/archipelago/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "archipelago" -version = "1.5.0" +version = "1.5.0-alpha" edition = "2021" description = "Archipelago Bitcoin Node OS - Native backend" authors = ["Archipelago Team"] diff --git a/neode-ui/package.json b/neode-ui/package.json index 997cdf25..258ac501 100644 --- a/neode-ui/package.json +++ b/neode-ui/package.json @@ -1,7 +1,7 @@ { "name": "neode-ui", "private": true, - "version": "1.3.5", + "version": "1.5.0-alpha", "type": "module", "scripts": { "start": "./start-dev.sh", diff --git a/scripts/check-release-manifest.sh b/scripts/check-release-manifest.sh new file mode 100755 index 00000000..d7463def --- /dev/null +++ b/scripts/check-release-manifest.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Validate releases/manifest.json: +# - version matches core/archipelago/Cargo.toml +# - changelog is non-empty (release notes are mandatory per product policy) +# - every component's download_url exists on disk and matches sha256/size +# +# Run on every push from CI, and also locally before publishing a release: +# scripts/check-release-manifest.sh +# +# Exits non-zero on any mismatch so the release process fails loud. + +set -eo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +MANIFEST="$REPO_ROOT/releases/manifest.json" + +if [ ! -f "$MANIFEST" ]; then + echo "❌ releases/manifest.json missing" + exit 1 +fi + +fail() { echo "❌ $*"; exit 1; } +ok() { echo "✅ $*"; } + +MANIFEST_VERSION=$(python3 -c "import json; print(json.load(open('$MANIFEST'))['version'])") +CARGO_VERSION=$(grep '^version' "$REPO_ROOT/core/archipelago/Cargo.toml" | head -1 | sed -E 's/.*"([^"]+)".*/\1/') + +if [ "$MANIFEST_VERSION" != "$CARGO_VERSION" ]; then + fail "manifest version ($MANIFEST_VERSION) ≠ Cargo.toml ($CARGO_VERSION)" +fi +ok "version matches: $MANIFEST_VERSION" + +# Release notes mandatory — ships stuff nobody can read otherwise. +CHANGELOG_COUNT=$(python3 -c "import json; print(len(json.load(open('$MANIFEST'))['changelog']))") +if [ "$CHANGELOG_COUNT" -eq 0 ]; then + fail "changelog is empty — every release MUST have release notes" +fi +ok "changelog has $CHANGELOG_COUNT lines" + +# Each component: the artifact on disk under releases/v/ must match +# the declared sha256 and size_bytes. +VERSION_DIR="$REPO_ROOT/releases/v${MANIFEST_VERSION}" +if [ ! -d "$VERSION_DIR" ]; then + fail "releases/v${MANIFEST_VERSION}/ missing — artifacts not staged" +fi + +COMPONENT_COUNT=$(python3 -c "import json; print(len(json.load(open('$MANIFEST'))['components']))") +for i in $(seq 0 $((COMPONENT_COUNT - 1))); do + NAME=$(python3 -c "import json; print(json.load(open('$MANIFEST'))['components'][$i]['name'])") + DECLARED_SHA=$(python3 -c "import json; print(json.load(open('$MANIFEST'))['components'][$i]['sha256'])") + DECLARED_SIZE=$(python3 -c "import json; print(json.load(open('$MANIFEST'))['components'][$i]['size_bytes'])") + + # Component names other than exactly "archipelago" are the tarball's + # filename; use as-is. The bare "archipelago" component maps to the + # binary file literally named `archipelago`. + FILE="$VERSION_DIR/$NAME" + if [ "$NAME" = "archipelago" ]; then + FILE="$VERSION_DIR/archipelago" + fi + + if [ ! -f "$FILE" ]; then + fail "component '$NAME' file missing at $FILE" + fi + + ACTUAL_SHA=$(sha256sum "$FILE" | awk '{print $1}') + ACTUAL_SIZE=$(stat -c%s "$FILE") + + if [ "$ACTUAL_SHA" != "$DECLARED_SHA" ]; then + fail "component '$NAME' sha256 mismatch (declared=$DECLARED_SHA actual=$ACTUAL_SHA)" + fi + if [ "$ACTUAL_SIZE" != "$DECLARED_SIZE" ]; then + fail "component '$NAME' size mismatch (declared=$DECLARED_SIZE actual=$ACTUAL_SIZE)" + fi + ok "component '$NAME': sha256 + size match on-disk artifact" +done + +echo +ok "releases/manifest.json passes all checks — safe to publish v${MANIFEST_VERSION}" diff --git a/scripts/deploy-to-target.sh b/scripts/deploy-to-target.sh index 2880e280..3ce24086 100755 --- a/scripts/deploy-to-target.sh +++ b/scripts/deploy-to-target.sh @@ -923,6 +923,19 @@ PYEOF } MANIFEST_EOF + # Write build-info.txt — this is what the UI sidebar reads for the + # displayed version (overrides the binary's CARGO_PKG_VERSION). Keeping + # it synced with Cargo.toml on every deploy prevents the 1.3.x drift + # we saw on .198/.253 where stale build-info survived across upgrades. + DEPLOY_PKG_VERSION=$(grep '^version' "$PROJECT_DIR/core/archipelago/Cargo.toml" | head -1 | sed -E 's/.*"([^"]+)".*/\1/') + ssh $SSH_OPTS "$TARGET_HOST" "sudo tee /opt/archipelago/build-info.txt > /dev/null" << BUILDINFO_EOF +version=$DEPLOY_PKG_VERSION +build=$DEPLOY_TS +commit=$DEPLOY_COMMIT +date=$DEPLOY_TS +type=deployed +BUILDINFO_EOF + # Ensure NTP and swap are configured (prevents OOM kills and clock drift) progress "Ensuring NTP + swap" ssh $SSH_OPTS "$TARGET_HOST" '