From 547f42e92d76abc271a88b8800737494455705c0 Mon Sep 17 00:00:00 2001 From: Dushnilin Date: Sun, 9 Aug 2026 20:25:32 +0300 Subject: [PATCH] fix(install): fail when a rolled-back upgrade leaves an unstamped build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit installed_backend_sha() rejects the unsubstituted __COMPILED_COMMIT_SHA__ placeholder and the literal "unknown", so a stale build on disk reports no SHA at all. install_backend_package treated that empty value as "fresh install" and fell through to the presence check, which passes trivially after an apk rollback — the package and its version are still there. The run printed WARN Package manager reported errors during installation, but tachyon is installed — continuing directly after the backend install had been rolled back, and then continued through the remaining steps to a green banner over a failed upgrade. Record whether tachyon was installed before the install and treat "was present, still reports no SHA afterwards" as the failure it is. A genuine first install has no package present beforehand and is unaffected. Co-Authored-By: Claude Opus 5 --- install.sh | 15 ++++++++++++--- tests/installer_rollback_detection.sh | 13 +++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index 0852b579..013dfe65 100755 --- a/install.sh +++ b/install.sh @@ -2450,19 +2450,28 @@ install_backend_package() { cfg_hash_before="${_sha_out%% *}" fi - local backend_sha_before + local backend_sha_before backend_present_before=0 backend_sha_before="$(installed_backend_sha)" + pkg_is_installed "tachyon" && backend_present_before=1 if ! pkg_install_files "$TACHYON_BACKEND_FILE"; then # "tachyon is installed" is not evidence of success on a rebuilt tag: apk # rolls the transaction back to the identical old version, so both the # package name and its version still check out. Only a moved commit SHA - # proves new files landed. Without a SHA to compare (fresh install, or an - # unstamped build) fall back to the presence check. + # proves new files landed. + # + # An empty backend_sha_before does NOT mean "fresh install". installed_backend_sha + # rejects the unsubstituted __COMPILED_COMMIT_SHA__ placeholder and the literal + # "unknown", and a stale build on disk is exactly where both show up — so the + # upgrade this check exists to catch used to land in the presence branch and + # print a success warning over a rolled-back transaction. Presence before the + # install is what distinguishes an upgrade from a first install. local backend_sha_after backend_sha_after="$(installed_backend_sha)" if [ -n "$backend_sha_before" ] && [ "$backend_sha_before" = "$backend_sha_after" ]; then fail "tachyon installation failed: still running build $backend_sha_before, the package manager rolled the upgrade back (see $LOG_FILE)" + elif [ "$backend_present_before" = 1 ] && [ -z "$backend_sha_after" ]; then + fail "tachyon installation failed: the installed build still reports no commit SHA, so the package manager rolled the upgrade back (see $LOG_FILE)" elif pkg_is_installed "tachyon"; then warn "Package manager reported errors during installation, but tachyon is installed — continuing" else diff --git a/tests/installer_rollback_detection.sh b/tests/installer_rollback_detection.sh index 255e821a..3fa42aeb 100644 --- a/tests/installer_rollback_detection.sh +++ b/tests/installer_rollback_detection.sh @@ -70,6 +70,19 @@ assert_eq "" "$(read_sha "")" "a missing constants module must yield no SHA" grep -Fq 'rolled the upgrade back' "$INSTALLER" || fail "install.sh must fail loudly when the backend SHA did not move after install" +# An empty "before" SHA is not evidence of a fresh install: installed_backend_sha +# rejects both the placeholder and "unknown", which is exactly what a stale build +# on disk reports. Presence before the install is what separates an upgrade from a +# first install, so the rollback check must consult it — otherwise a rolled-back +# upgrade of an unstamped build reaches the "installed — continuing" branch and the +# run marches on over a failure. +sed -n '/^install_backend_package() {/,/^}/p' "$INSTALLER" >"$WORK_DIR/backend.sh" +[ -s "$WORK_DIR/backend.sh" ] || fail "install.sh must define install_backend_package" +grep -Fq 'backend_present_before' "$WORK_DIR/backend.sh" || + fail "install_backend_package must record whether tachyon was installed before the upgrade" +grep -Fq 'still reports no commit SHA' "$WORK_DIR/backend.sh" || + fail "an upgrade that leaves the installed build without a SHA must fail, not warn and continue" + # 120s was below the time the package hooks legitimately need to stop and restart # the service; being killed there makes apk roll the transaction back. for pm in apk opkg; do