Repository navigation
feat: tell the user when a newer release exists - #14
jeroenrinzema wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Background-task cancellation, cache-write failures, clock rollback, and concurrent runs can prevent reliable checks or violate the daily request limit.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 4
Open (4)
What changed in this PR
Adds background release checks for interactive CLI runs while minimizing network and latency costs.
Changes:
- Adds cached, daily release checks and update notices.
- Aligns crate metadata with release tags and validates future releases.
- Documents update-check behavior and opt-out controls.
| File | Description |
|---|---|
src/update.rs |
Implements release checking, caching, notices, and tests. |
src/main.rs |
Integrates checks into command execution. |
src/output.rs |
Exposes shared terminal styling. |
README.md |
Documents update notifications. |
Cargo.toml |
Aligns the crate version with releases. |
Cargo.lock |
Updates locked package metadata. |
.github/workflows/release.yml |
Validates release tags against the crate version. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| let cache = read(&path); | ||
| let known = cache.as_ref().and_then(|cache| cache.latest.clone()); | ||
| if !due(cache.as_ref(), now()) { |
There was a problem hiding this comment.
Not taking this one. The race is real but its cost is one extra 302 with an empty body, and the runs most likely to overlap — scripts and CI — are already silent, since the check needs a terminal on stderr and honours CI. A lock file buys nothing against that and brings its own failure modes: staleness after a SIGKILL, a shared BRAINPOD_CONFIG on a network filesystem, and cleanup on a path that is deliberately best-effort everywhere else. "At most once a day" is about not turning every command into a request, which the stamp does hold. Happy to revisit if the endpoint ever costs more than a redirect.
a765cc9 to
a3844d0
Compare
f78bd8c to
f31a032
Compare
a3844d0 to
21c482c
Compare
The check reads where the releases 'latest' alias redirects, which answers with no body, at most once a day, cached beside the configuration file. It starts before the command and is read after it, so it waits on nothing the command was not already waiting on, and runs a program reads stay silent. The crate version is what the notice compares against, so it is brought back in line with the published tags and the release workflow now refuses a tag that disagrees with it.
21c482c to
ef639af
Compare

Interactive runs now report a newer release underneath the command's own output:
What it costs
version-check.jsonbeside the configuration file; every other run that day reads it and touches nothing.https://github.com/brainpodnl/cli/releases/latestredirects, so the answer is a 302 withcontent-length: 0. The releases API would return the whole release, notes and assets included, and carries an unauthenticated rate limit.What stays silent
--json, anything whose stderr is not a terminal, anything withCIset, andBRAINPOD_NO_UPDATE_CHECK=1. Those runs make no request at all.A version neither side can order is never compared: only plain
major.minor.patchis ranked, so the0.0.0-dev+<sha>that #13 gives unstamped builds says nothing rather than nagging a developer about their own checkout.Why this is stacked
The notice is only as good as the version the binary reports, and on
mainthat is the hardcoded0.1.0no release ever carried — the comparison would have been dead on arrival. #13 makes--versionthe release tag and gates it in CI, so this branch simply readsenv!("BRAINPOD_VERSION")and adds no version plumbing of its own.Verification
cargo fmt --check,cargo clippy --all-targets -- -D warnings,cargo test(97 passed).{"checkedAt":…,"latest":"0.0.5"}.brainpod 0.0.0-dev+a3844d058a01) with a9.9.9release cached: silent.BRAINPOD_VERSION=0.0.5build: notice rendered.--jsonandBRAINPOD_NO_UPDATE_CHECK=1printed nothing.