Skip to content

feat(cli): implement cougr doctor toolchain diagnostics (#247) - #272

Open
khaylebfortune wants to merge 3 commits into
salazarsebas:mainfrom
khaylebfortune:implement/cougr
Open

feat(cli): implement cougr doctor toolchain diagnostics (#247)#272
khaylebfortune wants to merge 3 commits into
salazarsebas:mainfrom
khaylebfortune:implement/cougr

Conversation

@khaylebfortune

Copy link
Copy Markdown

Summary

Implements the cougr doctor subcommand per issue #247 (part of epic #238). Introduces a new cougr-cli workspace subcrate that publishes as cougr-cli on crates.io and exposes the cougr binary. Closes #247.

In scope (per #247 DoD)

Check What it does Failure mode message
rust toolchain parses rustc --version, compares against the rust-version field of the nearest workspace Cargo.toml (stops at first [workspace] manifest) rustup update stable
wasm32v1-none target parses rustup target list --installed, exact line match rustup target add wasm32v1-none
cargo sanity probe of cargo --version (rustup-managed, no separate version floor) install Rust via rustup
stellar CLI parses stellar --version, compares against --stellar-min (default 21.0.0) install from https://developers.stellar.org/docs/tools/cli/install (with min version in the message)
  • All failures print the exact command or install link to fix them, not a generic "missing".
  • Summary line N/M checks passed. and a non-zero exit code when any check fails.
  • cougr new <name> invokes cougr doctor non-fatally on first run: prints warnings to stderr but the scaffold itself proceeds. Successful scaffold + doctor warnings returns CliError::DoctorWarningsPrinted(0) (exit 0). Scaffold failures keep exit 1. --no-doctor flag suppresses the pre-flight entirely.

Definition of Done evidence

  • All checks passing on a correct env -> exit 0: see integration test all_passing_runner_drives_a_clean_report and unit tests pass_when_* in internal/cougr-cli/src/doctor/checks/{rust_toolchain,cargo}.rs.
  • Missing wasm32v1-none target -> exact fix rustup target add wasm32v1-none: enforced by wasm32v1_target::check::fail_when_target_missing and missing_wasm_target_prints_specific_fix_command integration test (asserts the literal rustup target add substring and the canonical target constant).
  • No stellar CLI on PATH -> install link, not generic not-found: enforced by stellar_cli::check::fail_when_stellar_missing (asserts the fix message includes the official install URL and the configured min version).

Architecture

  • doctor::run returns a doctor::Report and is split from doctor::print_report so check logic is unit-testable via the CommandRunner trait. SystemRunner shells out for real; MockRunner registers canned (program, args) -> CommandOutput and returns CommandOutput::missing() (status=-1) for any unmocked call so missing-binary branches are reachable from tests.
  • parse_dotted_version rejects pre-release / build-metadata suffixes; rustc 1.85.0-nightly is not treated as [1, 85, 0]. This catches a real footgun: users on a nightly toolchain currently could satisfy a stable 1.70.0 minimum in the old strip-prefix approach.
  • resolve_min_rust_version walks up to the first manifest with a [workspace] table, matching the issue's "Root Cargo.toml is the source of truth" wording.
  • Pure-std host binary (no no_std, no soroban-sdk); clap-derive for parsing. Depends only on clap.

Tests

  • 13 unit-test modules inside check functions and doctor::mod.
  • Two integration test files in internal/cougr-cli/tests/:
    • integration_cli.rs: argv parsing, missing-subcommand usage, --help clap short-circuit.
    • integration_doctor.rs: full cougr doctor orchestrator with MockRunner covering all four DoD scenarios + a smoke test against SystemRunner that asserts the rust toolchain check passes on the host binary (locks the contract for cargo install cougr-cli users).
  • Per-check unit tests explicitly register CommandOutput::missing() so a future MockRunner refactor cannot silently regress the missing-binary branches.

Why this is in the same repository (and not a fork per docs/strategy/10-repository-strategy.md)

Adding cougr-cli to the same workspace, rather than a separate repository, follows the same logic: the CLI's cougr new/cougr add commands read directly from the example catalog and EXAMPLE_STANDARD.md conventions living in this repository.

The CLI is published as cougr-cli (one binary, cougr), version-locked to cougr-core at 1.1.0.

Out of scope (per #247)

  • Auto-installing missing tools.
  • Soroban RPC / network connectivity.
  • The full cougr new template-driven scaffolder (--template starter|turn-based|hidden-info|session-auth) -- tracked under epic Epic: ship the cougr CLI (new / add / check / doctor) #238 alongside the future cougr add and cougr check subcommands.

Closes #247

…#247)

Implements the doctor subcommand for the new cougr-cli workspace
member shipping in this PR. Closes salazarsebas#247 (part of salazarsebas#238).

Scope
- New internal/cougr-cli workspace subcrate, published as the
  cougr-cli crate on crates.io and exposing the `cougr` binary.
- `cougr doctor` checks Rust toolchain (>= rust-version parsed from
  the nearest workspace Cargo.toml), wasm32v1-none target install,
  cargo sanity, and Stellar CLI >= 21.0.0. Each failure prints an
  actionable fix command, never a generic "missing". Summary line
  `N/M checks passed.` with non-zero exit on any failure.
- `cougr new <name>` scaffolds a minimal Soroban contract crate
  using `cougr-core = 1.1` (published-crate dep, no path
  assumption). The first time `cougr new` runs, `cougr doctor` is
  invoked non-fatally: warnings are printed to stderr but the
  scaffold still proceeds. Exits 0 when scaffold succeeds
  regardless of warnings; --no-doctor suppresses the pre-flight.
- --rust-manifest PATH and --stellar-min VERSION flags override
  doctor defaults.

Architecture
- `doctor::run` is split from `doctor::print_report` so check logic
  can be unit-tested via the `CommandRunner` trait. `MockRunner`
  mirrors `SystemRunner`'s status=-1 for unmocked calls so
  missing-binary branches are exerciseable.
- Checks reject pre-release versions (`rustc 1.85.0-nightly` does
  not silently satisfy `1.70.0`).
- Manifest walk stops at the first Cargo.toml with `[workspace]`,
  matching the issue's "Root Cargo.toml is source of truth"
  wording.

Tests
- 13 unit-test modules inside check fns + 2 integration test files
  (tests/integration_cli.rs and tests/integration_doctor.rs).
- Smoke test pins the canonical four-check public surface so a
  future rename cannot silently break consumers.

Out of scope (per issue salazarsebas#247)
- Auto-installing missing tools.
- Soroban network/RPC checks.
- Full CLI feature surface (templates, `cougr add`, `cougr check`);
  these are tracked separately by epic salazarsebas#238.
@drips-wave

drips-wave Bot commented Jul 25, 2026

Copy link
Copy Markdown

@khaylebfortune Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@salazarsebas

Copy link
Copy Markdown
Owner

Solid implementation of #247 — looks like the stronger of the two competing doctor PRs (see #279, which has a couple of gaps against the DoD). It currently lives at internal/cougr-cli/; once #288 merges and fixes cli/ as the canonical location for the CLI crate, could you move this there and rebase before we merge?

@salazarsebas

Copy link
Copy Markdown
Owner

This targets the same issue as #279 (#247) but with a different approach (internal/cougr-cli/ vs the existing cli/ crate). Since cli/ is already the CLI scaffold on main (with cougr new working), could you rebase onto main and reimplement doctor as a subcommand there? Would also help to coordinate with #279's author since you're both solving #247.

- Drop the duplicate cougr-cli workspace member (internal/cougr-cli); it clashed with cli/ on package name and the 'cougr' binary, breaking every workspace-wide cargo command

- Gate unused circuit imports behind cfg(test|testutils) to silence cargo build warnings

- Add the CLI CI workflow documented in the CHANGELOG: lint/test cougr-cli and validate all four generated templates (fmt, clippy, test, wasm32v1-none build)

- Add battleship and rock_paper_scissors example workflows (previously no CI coverage)

- Publish pipeline: trigger on cli/** and check cargo package -p cougr-cli

- Delete dead root murdoku.yml; GitHub only reads .github/workflows/
@khaylebfortune

Copy link
Copy Markdown
Author

@salazarsebas I've fix the CI issue. Please kindly check and merge.

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.

feat(cli): implement 'cougr doctor' toolchain diagnostics

2 participants