Skip to content

Report only what doctor's checks actually establish - #7

Open
Dione-b wants to merge 1 commit into
developfrom
fix/2464-upgrade-check-stale-version
Open

Report only what doctor's checks actually establish#7
Dione-b wants to merge 1 commit into
developfrom
fix/2464-upgrade-check-stale-version

Conversation

@Dione-b

@Dione-b Dione-b commented Aug 6, 2026

Copy link
Copy Markdown
Member

Motivation

Copilot's review of the upstream PR (stellar#2670) flagged three places where the new diagnostics claim more than the data behind them supports. All three are real, and each one can send a user chasing a cause that was never observed:

  1. upgrade_check.rs records last_checked_by even when the fetch to crates.io failed — the attempt still paces the next check — but doctor reported the file as "last refreshed by" that install. That credits an install with version data it never fetched.
  2. The single-install branch of check_installs printed a count without calling list_installs, so the one case where a listing would settle "which executable is this?" was the one case that omitted path and version. The separate Running executable line is not necessarily the entry PATH resolves by name, and carries no version.
  3. common_version == None meant either "known versions disagree" or "at least one executable could not be asked". Both landed on a message blaming differing versions, so two unrunnable binaries — both listed as unknown version — were reported as a version conflict.

Groundwork for stellar#2464.

Behavior

doctor says "checked", not "refreshed". The cache writer is the last writer/pacer, not the source of the versions stored beside it. Kept that semantics — it is the one that answers "which install is holding the next check back?" — and made the wording match the field name (last_checked_by), in the four doctor messages and in the field/struct docs.

Alternative discarded: recording the writer only after a successful refresh. That would make "refreshed by" literally true, but it loses the diagnostic that matters. When a stale install fails its fetch and stamps the file, it still suppresses everyone else's check for 24h; dropping its identity would leave the file crediting whichever install last succeeded, hiding exactly the install a user needs to find.

Every discovered install is listed. list_installs now runs for any non-zero count, including one.

Undetermined agreement is no longer reported as disagreement. Introduced InstalledVersions { Agreed(String), Disagree, Unanswered(usize) }:

Situation Report
All answered, all the same N Stellar CLI executables on PATH, all reporting X:
Known versions differ ⚠️ ...reporting different versions; an outdated one can report a version that disagrees with 'stellar --version':
One or more did not answer, no contradiction among those that did ⚠️ Found N Stellar CLI executables on PATH, M of which did not report a version, so whether they agree could not be determined:

An observed disagreement still wins when it sits alongside a failed probe — a contradiction between two known versions is a fact, and a third unrunnable binary does not soften it.

Tests

Unit (cmd/soroban-cli/src/commands/doctor.rs) — four cases for summarize_versions: agreement, distinct known versions, probes that returned nothing (both all-unknown and one-unknown), and disagreement coexisting with a failed probe.

Integration (cmd/crates/soroban-test/tests/it/doctor.rs) — two new end-to-end cases driving real subprocesses through a fake PATH:

  • does_not_blame_differing_versions_when_a_version_could_not_be_read — two unrunnable CLIs; asserts the undetermined message and that different versions is absent.
  • reports_a_disagreement_even_when_another_executable_is_unreadable27.1.0 + 22.8.0 + one unrunnable across two PATH entries; asserts the disagreement still surfaces.

Also extended reports_the_running_executable_and_a_lone_install to assert the lone install is listed with its version, and updated the four cache-writer assertions to the new wording. New helper write_unrunnable_cli writes a script that fails both version queries.

Full run, all green:

Command Result
cargo fmt --all -- --check clean
cargo clippy --all-targets (and --features additional-libs) no warnings
cargo test -p soroban-cli --lib (and --features additional-libs) 332 passed
cargo test -p soroban-test --test it -- doctor:: version:: plugin:: help:: message:: 31 passed
cargo test -p soroban-test -- --skip integration:: 133 passed, 1 ignored
cargo test --workspace --exclude soroban-test all passed

Not run: make rpc-test (--features it -- integration), which needs a local RPC — nothing here touches RPC paths.

Note for reviewers running these locally: the integration tests execute target/debug/stellar and do not rebuild it, so cargo build --bin stellar is needed first or the assertions run against a stale binary.

Release Impact

No breaking changes. No data migration: this commit does not change the upgrade_check.json shape — last_checked_by and its optional fields are unchanged, and files written before it existed still load.

User-visible surface is stellar doctor's stderr diagnostics only: four cache-writer lines reworded from "refreshed" to "checked", one new message for undetermined versions, and the single-install case now followed by a listing. No command, flag, or help text changed, so FULL_HELP_DOCS.md is untouched. Anything matching on doctor's exact stderr text would need updating — no such consumer is known in this repo beyond the tests updated here.

Checklist

  • Public and internal documentation updated to reflect behavior changes. — doc comments on CheckWriter, UpgradeCheck::last_checked_by, show_version_cache_writer and check_installs now state that the writer paces the next check rather than vouching for the recorded versions. No user-facing docs changed: no CLI surface change, so FULL_HELP_DOCS.md is unaffected.
  • Error messages and failure codes reviewed or updated to cover new scenarios. — this change is that review; the unreadable-version case gained its own message instead of borrowing the disagreement one. No exit codes changed; doctor remains diagnostic-only.
  • Command examples and tutorials use isolated data or local test environments, adhering to security best practices. — tests inject PATH from a per-test temp dir and the cache via STELLAR_DATA_HOME; nothing touches the real config/data dirs, the network, or any key material.
  • Dependencies, lockfiles, and CI/CD workflows are synchronized with the new changes. — no dependency, Cargo.lock or workflow change; the new tests live in the existing soroban-test it target already run by CI.
  • All automated tests and linting checks pass successfully. — see the table above.

Motivation: Copilot's review of stellar#2670 found three
`doctor` diagnostics claiming more than the data behind them supports,
each able to send a user after a cause that was never observed.

Behavior:

- A check whose fetch failed still stamps the cache, but leaves the
  recorded versions untouched, so "last refreshed by" credited an
  install with version data it never fetched. Say "checked" instead, in
  the messages and the field docs: the writer paces the next check
  rather than vouching for the versions stored beside it. Recording it
  only after a successful fetch was the alternative, and it hides the
  install worth finding -- a stale one whose fetch fails still
  suppresses everyone else's check for a day.
- The single-install branch printed a count without the listing, so the
  one case a listing would settle was the one case that omitted path and
  version. List every discovered install.
- Absent agreement was reported as disagreement: two executables that
  cannot be run are both unknown, yet the message blamed differing
  versions. `InstalledVersions` now keeps Agreed, Disagree and
  Unanswered apart. An observed disagreement still wins over a failed
  probe alongside it, because that one is a fact.

Tests: four unit cases for `summarize_versions`, and two integration
cases driving real subprocesses through a fake `PATH` -- two unrunnable
CLIs, and a disagreement sitting next to an unreadable binary. The
lone-install listing and the reworded cache-writer lines are asserted
too.

Release impact: no breaking change and no migration. The
`upgrade_check.json` shape is untouched and older files still load. Only
`doctor`'s stderr wording changes -- no command, flag or help text does,
so `FULL_HELP_DOCS.md` stands as is.

Co-authored-by: Nearx-Labs <nearxlabs@nearx.com.br>
@Dione-b
Dione-b force-pushed the fix/2464-upgrade-check-stale-version branch from b783bcf to b7df621 Compare August 6, 2026 00:20
@Dione-b
Dione-b requested a review from pedro-pelicioni August 6, 2026 00:21
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