Skip to content

Add automatic version check with cached notifications#89

Draft
jamesainslie wants to merge 8 commits into
mainfrom
add-version-check
Draft

Add automatic version check with cached notifications#89
jamesainslie wants to merge 8 commits into
mainfrom
add-version-check

Conversation

@jamesainslie
Copy link
Copy Markdown
Contributor

@jamesainslie jamesainslie commented Mar 1, 2026

Summary

Adds a post-execution version check that queries the GitHub Releases API and notifies users when a newer version of stave is available. Results are cached locally (default 24 hours) so the check doesn't add latency on every run. Once a user has been notified about a specific version, the notification is silenced until the next release.

  • Auto-check: After any target execution, a one-liner notification appears if a newer version exists. Completely silent on errors, in CI, or when disabled via config/env.
  • Explicit check: stave --check-update fetches fresh release data and renders the full changelog with styled terminal output (headings, bullet points, links).
  • Configurable: update_check.enabled and update_check.interval in stave.yaml, plus STAVE_NO_UPDATE_CHECK=1 env var override.

What changed

  • New pkg/update/ package: GitHub API client, JSON file cache, version comparison (semver), styled terminal notifications with glamour markdown rendering.
  • New pkg/env.InCI(): Canonical CI environment detection, replacing duplicated logic in internal/hooks/runtime.go.
  • New config.UpdateCheckConfig: Enabled flag and check interval with viper/YAML support.
  • pkg/stave/main.go: CheckUpdate field on RunParams, --check-update pseudo-flag, post-execution hook in RunCompiled().
  • Test isolation fixes: testGitInit in both internal/hooks and pkg/stave now properly isolates from user git config (GIT_CONFIG_GLOBAL/SYSTEM + local core.hooksPath override).

Test plan

  • 30 new tests across pkg/update/ (cache, GitHub client via httptest, auto-check suppression chain, explicit check, semver comparison)
  • CI env detection tests in pkg/env/
  • Config loading tests (defaults, YAML override, env override)
  • Flag parsing test in cmd/stave/
  • Full test suite: 578 tests passing
  • golangci-lint: 0 issues

Design document for automatic update checking against the GitHub
Releases API with cached results, one-time notifications per new
version, and an explicit --check-update flag for full changelog display.
Check for new versions after target execution with cached results (24h TTL).
Shows a one-liner notification once per new version, auto-disables in CI.
Adds --check-update flag for explicit check with full changelog display.

New package pkg/update/ with GitHub client, cache, and core logic.
Configurable via update_check settings in stave.yaml and
STAVE_NO_UPDATE_CHECK environment variable.
Without this, all CheckAndNotify tests silently pass in GitHub Actions
because env.InCI() returns true and short-circuits before reaching the
code under test.
W1: Consolidate CI detection — internal/hooks now delegates to env.InCI()
    instead of maintaining a separate CI env var list with different semantics.
W2: Deduplicate CI env var lists — export env.CIEnvVarNames() as the
    canonical source; both test files now consume it.
W3: Consistent error format — github.go status errors now use verb-phrase
    prefix matching the pattern used by all other errors in the function.
W4: Thread io.Writer into changelogStyle() — uses *os.File type assertion
    for terminal background detection instead of hardcoded os.Stdin/Stdout.
S1: Unexport DefaultUpdateCheckInterval — only used within config package.
S2: Unexport CachePath — only used within pkg/update.
S3: Wrap ExplicitCheck error with "checking for updates" context.
S5: Isolate cache subtests — each subtest gets its own temp directory.
S6: Document intentional unconditional update check after target execution.
testGitInit in both internal/hooks and pkg/stave now sets
GIT_CONFIG_GLOBAL and GIT_CONFIG_SYSTEM to /dev/null via cmd.Env
(compatible with t.Parallel) and writes a local core.hooksPath override
so production code under test doesn't inherit the user's global
hooks path.

Also adds .worktrees/ to .gitignore so the markdown linter doesn't
scan untracked worktree content, and removes the design doc from
tracking per convention.
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.

1 participant