Skip to content

fix(tui): make update hint transient (#2254)#2275

Open
Hmbown wants to merge 2 commits into
mainfrom
fix/2254-version-toast
Open

fix(tui): make update hint transient (#2254)#2275
Hmbown wants to merge 2 commits into
mainfrom
fix/2254-version-toast

Conversation

@Hmbown
Copy link
Copy Markdown
Owner

@Hmbown Hmbown commented May 27, 2026

Summary

  • only advertise a newer release after the GitHub release is non-draft, non-prerelease, and has the required CodeWhale assets plus checksum manifest uploaded
  • route the update notice through the existing timed status-toast queue instead of storing a persistent footer override
  • preserve the user-configured footer/statusline chips as the steady display

Fixes #2254.

Reported by @bevis-wong in #2254.

Also credits @idling11 for #2268, which identified the draft/prerelease guard that this PR folds into the broader release-readiness fix.

Verification

  • cargo test -p codewhale-tui version_hint_requires_complete_release_assets -- --nocapture
  • cargo test -p codewhale-tui version_hint_ignores_draft_prerelease_and_current_versions -- --nocapture
  • cargo check -p codewhale-tui --all-features --locked
  • cargo fmt --all -- --check
  • git diff --check

Greptile Summary

This PR fixes issue #2254 by routing the version-update notification through the existing timed status-toast queue (12 s TTL) instead of storing it as a persistent version_hint field that permanently overrode the user's configured footer chips. It also adds release-completeness validation before advertising an update.

  • Removes App::version_hint and the footer override path in footer_ui.rs; the update notice is now a StatusToastLevel::Info toast pushed once via push_status_toast.
  • Adds version_hint_from_release_json, release_has_required_assets, and release_has_uploaded_asset to gate the hint behind draft/prerelease flags and a per-asset state == \"uploaded\" check against REQUIRED_RELEASE_ASSETS.
  • New unit tests exercise the complete-release happy path, missing-manifest, pending-state, missing-state-field, draft, prerelease, and same-version cases.

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to the update-notification path and preserves all existing footer behaviour.

The removal of version_hint and the simplified footer path are straightforward; the new asset-validation helpers are covered by a thorough test suite that explicitly checks the previously flagged missing-state-field case. The is_newer_version string-compare fallback for unparseable semver tags is pre-existing behaviour, not introduced here. No state is silently dropped and the toast fires exactly once per session.

No files require special attention.

Important Files Changed

Filename Overview
crates/tui/src/tui/ui.rs Extracts version-check logic into three helper functions with thorough asset-validation; routes the result to the toast queue; adds REQUIRED_RELEASE_ASSETS constant and VERSION_HINT_TOAST_TTL_MS. Logic is correct and well-separated.
crates/tui/src/tui/app.rs Removes the now-unused version_hint: Option<String> field and its initialiser; no other logic changes.
crates/tui/src/tui/footer_ui.rs Removes the special-cased version_hint branch; footer now delegates entirely to active_status_toast(), simplifying the precedence chain.
crates/tui/src/tui/ui/tests.rs Adds two new tests covering the full matrix of release-validation cases including missing-state-field, covering the fix for the previously flagged None-arm issue.

Sequence Diagram

sequenceDiagram
    participant EL as Event Loop
    participant BG as Background Task (tokio::spawn)
    participant GH as GitHub API
    participant App as App (status_toasts)
    participant FUI as footer_ui

    EL->>BG: spawn version check (once per session)
    BG->>GH: GET /releases/latest
    GH-->>BG: JSON (tag_name, draft, prerelease, assets[])
    BG->>BG: release_has_required_assets()
    BG->>BG: is_newer_version(latest, current)
    BG-->>EL: Some(hint)

    EL->>App: push_status_toast(hint, Info, 12_000ms)
    Note over App: StatusToast queued with TTL

    loop every render frame
        FUI->>App: active_status_toast()
        App-->>FUI: Some(toast) or None (expired)
        FUI->>FUI: render toast in footer (or user chips if None)
    end
Loading

Reviews (2): Last reviewed commit: "fix(tui): require uploaded release asset..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the TUI version-check logic to display update notifications as temporary status toasts rather than a persistent footer hint. It also introduces strict validation to ensure update notifications are only shown for fully published releases containing all required assets. The reviewer feedback highlights two key improvements: simplifying the fragile hardcoded list of required release assets to check only for the final checksum manifest, and avoiding a potential panic by refactoring the version_check task handle unwrapping with safer let-chains.

Comment thread crates/tui/src/tui/ui.rs
Comment on lines +161 to +179
const REQUIRED_RELEASE_ASSETS: &[&str] = &[
"codewhale-artifacts-sha256.txt",
"codewhale-linux-arm64",
"codewhale-linux-arm64.tar.gz",
"codewhale-linux-x64",
"codewhale-linux-x64.tar.gz",
"codewhale-macos-arm64",
"codewhale-macos-arm64.tar.gz",
"codewhale-macos-x64",
"codewhale-macos-x64.tar.gz",
"codewhale-tui-linux-arm64",
"codewhale-tui-linux-x64",
"codewhale-tui-macos-arm64",
"codewhale-tui-macos-x64",
"codewhale-tui-windows-x64.exe",
"codewhale-windows-x64.exe",
"codewhale-windows-x64-portable.zip",
"codewhale-windows-x64.zip",
];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Hardcoding the entire list of 17 specific release asset filenames is extremely fragile and poses a significant maintainability risk.

If any of these assets are renamed, dropped, or if a new platform is added/removed in the future release pipeline, all older TUI clients will silently stop receiving update notifications entirely because release_has_required_assets will fail.

Suggested Improvement

Since the checksum manifest (codewhale-artifacts-sha256.txt) is generated and uploaded at the very end of the release workflow (after all other assets are built), its presence alone is a highly reliable and future-proof indicator that the release is complete.

We should simplify REQUIRED_RELEASE_ASSETS to only require the checksum manifest. This completely future-proofs the update notifier against any changes to the supported platforms or asset naming conventions in the release pipeline.

const REQUIRED_RELEASE_ASSETS: &[&str] = &[
    "codewhale-artifacts-sha256.txt",
];

Comment thread crates/tui/src/tui/ui.rs
@@ -947,7 +953,11 @@ async fn run_event_loop(
done = handle.is_finished();
}
if done && let Ok(Some(hint)) = version_check.take().unwrap().await {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using .unwrap() here can be avoided by leveraging let-chains to safely bind and await the JoinHandle. This is more idiomatic and eliminates any potential panic risk.

        if done && let Some(handle) = version_check.take() && let Ok(Some(hint)) = handle.await {

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment thread crates/tui/src/tui/ui.rs Outdated
@Hmbown
Copy link
Copy Markdown
Owner Author

Hmbown commented May 27, 2026

Independent review:

Verified fix for #2254 — addresses all three complaints (premature/static/overrides). Clean merge against PR #2256 v0.8.48 (footer_ui.rs auto-merges despite both touching the toast resolution chain).

Findings beyond prior bots:

  1. Reappears every session. Check runs once per startup with no dismiss/silence persistence. If a user sees the toast, waits 12s, then restarts before updating, they see it again. Consider a .local_state flag keyed on the advertised tag so an explicitly-expired toast doesn't re-fire for the same release.

  2. Fixed 12s TTL with no dedup. push_status_toast appends to a 24-deep VecDeque; heavy status traffic in the first 12s of a session (tool output, mode switches) can scroll the version hint out before the user notices. The previous design's "takes precedence" comment acknowledged this risk — worth a sticky variant or longer TTL (30-45s) for the version hint specifically.

  3. Test gap. Asset/draft gating is well-covered, but no test asserts TTL expiry actually fires active_status_toastNone. A tokio::time::pause test would lock in the transient contract.

  4. Title undersells scope. Commit 4eebfeb (required assets) is the "premature" half of bug: status-bar "new version available" banner is premature, static, and overrides user-configured cost display #2254 — worth surfacing in the PR body so reviewers don't think it's pure UX.

Non-blocking. Approves the direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: status-bar "new version available" banner is premature, static, and overrides user-configured cost display

2 participants