Skip to content

feat: passive update nudge — notify when a newer snipemgr release is available #44

Description

@jackvaughanjr

Summary

snipemgr has no way to tell users when a newer version of itself is available. This issue tracks a lightweight, low-friction nudge that checks once per day (configurable) and prints a single advisory line to stderr after a successful command.

Desired behaviour

  • After any successful command, if a newer snipemgr release exists on GitHub, print:
    Note: snipemgr v1.4.0 is available (you have v1.3.0). Run 'snipemgr self-upgrade' to update.
    
  • The check is not performed on every invocation. A cache file (~/.snipemgr/update-check.json) stores the last-checked timestamp and the latest version seen. The remote GitHub API is only called when the cache is stale.
  • Default check interval: 24 hours. Configurable via snipemgr.yaml:
    update_check_interval: 24h   # set to 0 to disable
  • --no-update-check flag suppresses the check for a single invocation (useful in scripts/automation).
  • The nudge is not shown during snipemgr self-upgrade itself.
  • Dev builds (version == "dev") are silently skipped.

Implementation notes

New package: internal/selfupdate/checker.go

  • Cache struct (last_checked, latest_version) — JSON, stored at ~/.snipemgr/update-check.json
  • LoadCache(path string) Cache — returns empty Cache on missing/malformed file
  • SaveCache(path string, c Cache) — silently discards errors; a failed write must never break the tool
  • ShouldCheck(c Cache, interval time.Duration) bool — returns false when interval ≤ 0
  • Check(ctx context.Context, currentVersion, token string) (CheckResult, error) — single GET /repos/jackvaughanjr/2snipe-manager/releases/latest with a context deadline; uses registry.CompareVersions for the version comparison

Wiring in cmd/root.go

  • viper.SetDefault("update_check_interval", "24h") in initConfig
  • --no-update-check persistent flag
  • Package-level var updateNudge string
  • In PersistentPreRunE (after initLogging): call maybeCheckUpdate(cmd)
    • Load cache; if fresh, compare cached version vs current → set updateNudge
    • If stale: call selfupdate.Check with a 3-second context deadline, update cache, set updateNudge
    • Silently swallow errors (debug-log only)
  • PersistentPostRunE on rootCmd: print updateNudge to stderr if non-empty

HTTP considerations

  • Reuses registry.github_token from snipemgr.yaml for authenticated requests (higher rate limit)
  • The 3-second deadline means the worst-case latency added to a command — on the one stale-cache invocation per day — is 3 seconds. Cache-hit invocations add zero latency.
  • Rate limit: unauthenticated = 60 req/hr; authenticated = 5000 req/hr. One call per day per machine is well within either limit.

Acceptance criteria

  • ~/.snipemgr/update-check.json is created/updated at most once per update_check_interval
  • Nudge appears on stderr after any successful subcommand when a newer version exists
  • No nudge on snipemgr self-upgrade or when --no-update-check is passed
  • update_check_interval: 0 in config fully disables the check
  • Dev builds (version == "dev") never trigger a check or nudge
  • Network errors or API failures are silent (debug log only); they never cause a command to fail
  • Cache file is human-readable JSON

Related

Companion to #45 — the nudge references snipemgr self-upgrade.

Metadata

Metadata

Assignees

No one assigned

    Labels

    tier-2Solid features, moderate complexity

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions