From 3045909db4955702cdee00a677f154724f38d0a7 Mon Sep 17 00:00:00 2001 From: Greg Jackson Date: Thu, 26 Mar 2026 19:18:25 +0000 Subject: [PATCH] fix: auto-upgrade marker no longer masks newer remote versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a just-upgraded-from marker persists across sessions, the update check would write UP_TO_DATE to cache and exit immediately — never fetching the remote VERSION. Users silently miss updates that landed after their last upgrade. Remove the early exit and premature cache write so the script falls through to the remote check after consuming the marker. This ensures JUST_UPGRADED is still emitted for the preamble, while also detecting any newer versions available upstream. Fixes #515 --- bin/gstack-update-check | 5 ++--- browse/test/gstack-update-check.test.ts | 29 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/bin/gstack-update-check b/bin/gstack-update-check index 7b165468..31e9fdb6 100755 --- a/bin/gstack-update-check +++ b/bin/gstack-update-check @@ -113,12 +113,11 @@ if [ -f "$MARKER_FILE" ]; then OLD="$(cat "$MARKER_FILE" 2>/dev/null | tr -d '[:space:]')" rm -f "$MARKER_FILE" rm -f "$SNOOZE_FILE" - mkdir -p "$STATE_DIR" - echo "UP_TO_DATE $LOCAL" > "$CACHE_FILE" if [ -n "$OLD" ]; then echo "JUST_UPGRADED $OLD $LOCAL" fi - exit 0 + # Don't exit — fall through to remote check in case + # more updates landed since the upgrade fi # ─── Step 3: Check cache freshness ────────────────────────── diff --git a/browse/test/gstack-update-check.test.ts b/browse/test/gstack-update-check.test.ts index ccc7572e..47300f0a 100644 --- a/browse/test/gstack-update-check.test.ts +++ b/browse/test/gstack-update-check.test.ts @@ -92,6 +92,35 @@ describe('gstack-update-check', () => { expect(cache).toContain('UP_TO_DATE'); }); + // ─── Path C2: Just-upgraded marker + newer remote ────────── + test('just-upgraded marker does not mask newer remote version', () => { + writeFileSync(join(gstackDir, 'VERSION'), '0.4.0\n'); + writeFileSync(join(stateDir, 'just-upgraded-from'), '0.3.3\n'); + writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.5.0\n'); + + const { exitCode, stdout } = run(); + expect(exitCode).toBe(0); + // Should output both the just-upgraded notice AND the new upgrade + expect(stdout).toContain('JUST_UPGRADED 0.3.3 0.4.0'); + expect(stdout).toContain('UPGRADE_AVAILABLE 0.4.0 0.5.0'); + // Cache should reflect the upgrade available, not UP_TO_DATE + const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8'); + expect(cache).toContain('UPGRADE_AVAILABLE 0.4.0 0.5.0'); + }); + + // ─── Path C3: Just-upgraded marker + remote matches local ── + test('just-upgraded with no further updates writes UP_TO_DATE cache', () => { + writeFileSync(join(gstackDir, 'VERSION'), '0.4.0\n'); + writeFileSync(join(stateDir, 'just-upgraded-from'), '0.3.3\n'); + writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n'); + + const { exitCode, stdout } = run(); + expect(exitCode).toBe(0); + expect(stdout).toBe('JUST_UPGRADED 0.3.3 0.4.0'); + const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8'); + expect(cache).toContain('UP_TO_DATE'); + }); + // ─── Path D1: Fresh cache, UP_TO_DATE ─────────────────────── test('exits silently when cache says UP_TO_DATE and is fresh', () => { writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');