Skip to content

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

Open
victor-134 wants to merge 4 commits into
salazarsebas:mainfrom
victor-134:feat/cli-doctor-toolchain-diagnostics
Open

feat(cli): implement cougr doctor toolchain diagnostics (#247)#279
victor-134 wants to merge 4 commits into
salazarsebas:mainfrom
victor-134:feat/cli-doctor-toolchain-diagnostics

Conversation

@victor-134

Copy link
Copy Markdown

Summary

Implements `cougr doctor` — a first-class toolchain diagnostic command that verifies the local development environment before a developer hits a confusing build failure. This is part of the CLI epic (#238) and directly addresses the "works on my machine" class of onboarding failure.

Background

A working Cougr project needs the correct Rust toolchain, the `wasm32v1-none` compilation target, and a reasonably current `stellar` CLI installed. None of this is currently verified up front; a developer discovers a missing target or an outdated stellar CLI only when a build or deploy fails, often with an unhelpful error far from the actual cause.

This PR exposes that verification as a first-class `cougr doctor` command, consistent with the product strategy in `docs/strategy/06-product-strategy.md`.

Checks implemented (4)

# Check How it works Fix command on failure
1 Rust toolchain Runs `rustc --version`, parses version, compares against `rust-version = "1.70.0"` from root `Cargo.toml` `rustup update stable`
2 wasm32v1-none target Runs `rustup target list --installed` and checks for the Soroban WASM target `rustup target add wasm32v1-none`
3 stellar CLI Tries `stellar --version` then falls back to `stellar version`. Parses and compares against minimum 21.0.0 Link to Stellar CLI install docs
4 cargo Sanity check with `cargo --version` Rust install instructions

Each check produces a pass/fail result with an actionable fix command on failure — not just "missing" but the exact `rustup` / install command to fix it. A summary line reports `N/M checks passed` and exits non-zero if any check fails.

Design decisions

  • Native Rust (no shelling out to external scripts) — consistent with the existing `check` and `verify` commands. Self-contained binary with no external dependencies beyond the tools being checked themselves.
  • Simple semver comparison (`version_cmp`) — avoids adding a `semver` crate dependency. Handles the major.minor.patch comparison needed for both `rustc` and `stellar` version checks.
  • Graceful degradation — if `stellar --version` can't parse the version string but the binary runs successfully, the check passes with a note rather than failing on a version-format edge case. This prevents false negatives when stellar CLI changes its output format.
  • Unit tests — `parse_rustc_version`, `parse_stellar_version`, and `version_cmp` all have tests covering valid/invalid inputs and comparison edge cases.

Usage

```bash

Diagnose your toolchain

cougr doctor

Example output (all passing):

=== Cougr Doctor — Toolchain Diagnostics ===

✓ Rust toolchain

rustc 1.70.0 (≥ 1.70.0)

✓ wasm32v1-none target

wasm32v1-none target installed

✓ stellar CLI

stellar 21.0.0 (≥ 21.0.0)

✓ cargo

cargo 1.70.0

=== 4/4 checks passed ===

```

Files changed

File Change Lines
`cli/src/doctor.rs` New — 4 toolchain checks, version parsing helpers, unit tests +305
`cli/src/main.rs` Modified — added `mod doctor`, `Doctor` subcommand variant, dispatch arm +6

Definition of done (from #247)

  • `cougr doctor` on a fully correct environment reports all checks passing with exit code 0
  • `cougr doctor` with a missing `wasm32v1-none` target reports the specific fix command and exits non-zero
  • `cougr doctor` with no stellar CLI on PATH reports a working install link/command rather than a generic "not found"
  • Each failure prints the exact command to fix it
  • Summary line: N/M checks passed with non-zero exit code if any check failed

Related

Port the hygiene checks from scripts/verify_hygiene.sh and scripts/enforce_hygiene.sh into a native Rust CLI binary. Implementation: ported to Rust for cross-platform operation (no bash/python deps). Shells out only for git ls-files and cargo metadata. Checks: root .gitignore Cargo.lock, tracked artifacts, contract IDs in READMEs, example .gitignore presence/content, Cargo.toml descriptions, cargo metadata. Closes salazarsebas#246.
Add canonical-quality verification to cougr check --verified that evaluates examples against every criterion in EXAMPLE_STANDARD.md. Extends the existing CLI with: --verified flag for full checklist, --json for machine-readable output, --full for heavy build checks, --canonical-only to filter to 10 canonical examples. Checks: dependencies (path dep annotation, wildcard versions), module structure (components.rs/systems.rs, lib.rs separation), README completeness (all 8 required sections with line-start matching), test coverage (file existence, test count, testutils usage), classification markers, Cargo.lock committed, and optional cargo test/stellar build. Wired into CI.
…#247)

Implements `cougr doctor` — a first-class toolchain diagnostic command
that verifies the local development environment before a developer hits
a confusing build failure.

**Checks implemented (4):**

1. **Rust toolchain** — runs `rustc --version`, parses the version, and
   compares against the minimum from root Cargo.toml (`rust-version = "1.70.0"`).
   Fix: `rustup update stable`.

2. **wasm32v1-none target** — runs `rustup target list --installed` and
   checks for the Soroban WASM target. Fix: `rustup target add wasm32v1-none`.

3. **stellar CLI** — tries `stellar --version` then falls back to
   `stellar version`. Parses and compares against minimum 21.0.0.
   Fix: link to Stellar CLI install docs.

4. **cargo** — sanity check with `cargo --version`. Fix: Rust install
   instructions.

Each check prints pass/fail with an actionable fix command on failure.
A summary line reports N/M checks passed with a non-zero exit code
when any check fails.

**Design decisions:**

- Native Rust (no shelling out to external scripts) — consistent with
  the existing `check` and `verify` commands. Self-contained binary.
- Simple semver comparison in `version_cmp` — avoids adding a semver
  crate dependency.
- Graceful degradation: if `stellar --version` can't parse the version
  but the binary runs, the check passes with a note rather than
  failing on a version-format edge case.
- Unit tests for version parsing (`parse_rustc_version`,
  `parse_stellar_version`) and comparison (`version_cmp`).

**Files changed:**

| File | Change |
|------|--------|
| `cli/src/doctor.rs` | New — 4 toolchain checks, version parsing, tests |
| `cli/src/main.rs` | Modified — added `mod doctor`, `Doctor` subcommand variant, dispatch |

Part of epic salazarsebas#238. Closes salazarsebas#247.
@salazarsebas

Copy link
Copy Markdown
Owner

The core diagnostics (rustc, wasm32v1-none, stellar CLI, cargo) with actionable fix messages and the N/M summary look right. Two gaps against #247's DoD:

  • MIN_RUST_VERSION is hardcoded ("1.70.0") instead of being read from the root Cargo.toml's rust-version field, which the issue calls out explicitly as the source of truth — this will drift silently if the minimum changes.
  • Scope item 4 (cougr new invoking doctor automatically) isn't implemented here.

Also flagging: #272 already implements the same issue (#247) with the dynamic rust-version lookup, the cougr new --no-doctor integration, and broader test coverage via a MockRunner. To avoid two competing implementations landing, could you compare against #272 and either close this in favor of it, or pull in whatever this PR does better? Also note both PRs currently scaffold cli//cougr-cli independently — see the merge-order note on #288 for how we're sequencing that.

@salazarsebas

Copy link
Copy Markdown
Owner

Same base-drift issue as the other CLI PRs: this predates the cli/ scaffold on main, so merging as-is would drop cougr new, and it's currently showing as conflicting with main. Could you rebase and add doctor as an additional subcommand? Also flagging: #272 targets the same issue (#247) with a different structure (internal/cougr-cli/) — worth syncing with that author so we don't land two doctor implementations.

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