feat!: consolidate cot cli commands into one - #587
Conversation
|
| Project | cot |
| Branch | elijah/cot-proxy-cmd |
| Testbed | github-ubuntu-latest |
Click to view all benchmark results
| Benchmark | Latency | Benchmark Result milliseconds (ms) (Result Δ%) | Upper Boundary milliseconds (ms) (Limit %) |
|---|---|---|---|
| empty_router/empty_router | 📈 view plot 🚷 view threshold | 14.27 ms(+68.95%)Baseline: 8.44 ms | 15.97 ms (89.34%) |
| json_api/json_api | 📈 view plot 🚷 view threshold | 1.16 ms(+10.04%)Baseline: 1.05 ms | 1.38 ms (84.16%) |
| nested_routers/nested_routers | 📈 view plot 🚷 view threshold | 1.04 ms(+6.16%)Baseline: 0.98 ms | 1.26 ms (82.92%) |
| single_root_route/single_root_route | 📈 view plot 🚷 view threshold | 1.02 ms(+7.54%)Baseline: 0.95 ms | 1.22 ms (83.36%) |
| single_root_route_burst/single_root_route_burst | 📈 view plot 🚷 view threshold | 17.55 ms(+2.64%)Baseline: 17.10 ms | 21.57 ms (81.35%) |
- help for workspaces and packages now dispatch to the custom help handler
Codecov Report❌ Patch coverage is
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 2 files with indirect coverage changes 🚀 New features to boost your workflow:
|
| #[cfg(unix)] | ||
| { | ||
| let err = std::process::Command::new(&proj.path).args(args).exec(); | ||
| anyhow::bail!("Failed to exec {}: {err}", proj.path.display()); | ||
| } | ||
|
|
||
| #[cfg(not(unix))] | ||
| { | ||
| let status = std::process::Command::new(&proj.path).args(args).status()?; | ||
| std::process::exit(status.code().unwrap_or(1)); | ||
| } |
There was a problem hiding this comment.
Where's the difference between Unix-like and non-Unix-like platforms coming from? Why do we need separate code paths here?
There was a problem hiding this comment.
The idea here is to replace the cot process with that of the child(the binary) whenever we forward to(or run) the binary. The exec call is only available on POSIX. Windows doesn't provide a way to do this, so we just spawn the child and block until it exits. Left a comment to outline this behavior as well.
On a side note, one issue i think isnt being handled is signal forwarding in the non-Unix case
There was a problem hiding this comment.
Do we need all this machinery here? Any chance that running cargo run would suffice instead?
…h/cot-proxy-cmd # Conflicts: # cot-cli/tests/snapshot_testing/external/check.rs
Background
cotcurrently exposes CLI commands through two separate entry points:cot-clicrate (cot <command>): handles project scaffolding, migration listing, migration generation, and shell completions.check, running migrations (which is also triggered implicitly at startup), and any custom user-defined task commands.In addition, running and building a
cotapp relies on Cargo tooling. In summary, there are three ways to invoke CLI commands today:cot <command>via thecot-clicratecot-cliThis PR focuses on unifying 1 and 2 for ergonomics:
cotnow acts as the single entry point for all commands, proxying any unrecognized command to the compiled binary if it exists there. Option 3 (Cargo invocation) is out of scope for this PR and can be revisited in a follow-up if proxying those commands makes sense.Approach
When
cotreceives a command it does not recognize, it resolves the target binary (target/debugby default, ortarget/releaseif--releaseis passed), queries it for its available commands via a metadata flag, and either forwards the command along with all provided arguments or returns an error if the command is not found in the binary either.Metadata
To support proxying, the
cotcrate exposes a--metadataflag. At runtime, the binary uses reflection to enumerate all registered CLI commands and prints them as JSON to stdout. This serves two purposes: it tellscot-cliwhether a given command should be forwarded, and it provides the information needed to render accurate help text.Example:
Caching
Querying the binary on every invocation would be wasteful, so the metadata response is cached in
.cot/command-cache.json. The cache stores the binary's modified time (mtime) alongside the metadata and is invalidated automatically whenever the binary is rebuilt.Workspaces
When working inside a Cargo workspace, a
--package(-p) flag must be provided to specify which package's binary should be targeted.Type of change