Repository navigation
refactor(rocm): move the clap command tree into cli.rs (proposal) - #889
jussielo-amd merged 13 commits into
Conversation
main.rs held the whole `rocm` command line definition: `Cli`, `Command`, the eleven subcommand enums nested under it and the clap value enums behind `--provider`, `--device`, `--framework` and similar arguments, about 1,340 lines of it. Move them to a new `apps/rocm/src/cli.rs`, as `apps/rocmd` already does for its own command tree. This is a pure move. Attributes, help text, defaults, aliases and declaration order (which is help order) are unchanged, and `rocm --help`, every subcommand's help and the completion scripts for all five shells are byte-identical before and after. The moved items become `pub(crate)` (the `Cli.command` field and the small `as_str`-style conversions included), and `main.rs` re-imports the types so every other module keeps reaching them as `crate::Command`, `crate::Provider` and so on. Three items that belong with the tree move with it: `SUPPORTED_ENGINES`, which only the clap `value_parser` attributes use, and the `From<WatcherModeArg> for WatcherMode` conversion, which sits next to the enum it converts. Module docs that said the clap types stay in main.rs now say cli.rs. `dispatch`, the process entry, the completion builder, the exit-code types and the shared helpers stay in main.rs. The parsing tests follow in the next commit. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…cli.rs Thirty-five of the tests in main.rs's shared test module are about the clap definition itself: what a flag parses to, which combinations clap refuses, what the rendered help says, and the value enums behind `--device` and `--framework`. Move them, with the four small helpers they share (`parse_serve`, `parse_runtimes`, `runtimes_restart_flags` and `serve_possible_values`), into a test module in cli.rs, so the tests sit with the definition they pin. Bodies, names and comments are unchanged, so the leaf test names are the same before and after; only the module path moves from `tests::` to `cli::tests::`. Tests whose primary subject is something else stay in main.rs even when they parse through the tree as a side step: the exit-code and dispatch tests, the completion builder, and the natural-language routing checks. Comments in other modules and in the ASCII output contract that named main.rs as the home of these tests now name cli.rs. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
docs/architecture.md and AGENTS.md both said a subsystem's clap command enum usually stays in main.rs. With the whole tree now in apps/rocm/src/cli.rs (as in apps/rocmd), update both: the module organization convention, the main.rs entry, a new cli.rs entry in the module map, and every per-module entry that named main.rs as the home of its command enum (`ComfyuiCommand`, `ConfigCommand`, `InstallTarget`, `RuntimesCommand`, `ServicesCommand`, `SetupCommand`, `Provider`) or of the moved parsing tests. The cli.rs module doc now says declaration order sets the nested help lists, not the top-level one, which `cli_command()` in main.rs sorts alphabetically. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
The services-prune entry in docs/architecture.md still said the clap definition and the constant's re-import were in main.rs, the pull request template called the clap declaration in main.rs expected, a driver_install module doc said InstallTarget and Cli remain in the crate root, and the engine_ipc entry did not say the WatcherModeArg conversion moved. Update them, and make the AGENTS.md sentence say the enum usually lives in cli.rs, with bootstrap.rs and remote/mod.rs as the subsystems that own theirs, to match docs/architecture.md. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Maintainers still need to decide whether cli.rs should own the apps/rocm command tree before the proposed architectural convention can be accepted.
No open issues 🎉
What changed in this PR
This proposal separates rocm’s clap command definitions from process and dispatch logic, following the existing rocmd layout. It aims to reduce main.rs size and editing conflicts without changing CLI behavior.
Changes:
- Relocates the command tree, value enums, conversions, and 35 parsing/help tests to
cli.rs, retaining crate-root imports for existing callers. - Keeps entry points, dispatch, completion builders, and shared helpers in
main.rs. - Updates architecture guidance and source comments to reflect the new locations.
| File | Description |
|---|---|
xtask/src/ascii_output_contract.rs |
Updates the ASCII-help test location in documentation. |
docs/architecture.md |
Documents the command-tree module and revised ownership. |
apps/rocm/src/setup_cmd.rs |
Updates the SetupCommand location comment. |
apps/rocm/src/services_cmd.rs |
Updates the ServicesCommand location comment. |
apps/rocm/src/service_records.rs |
Corrects comments about the prune constant’s importer. |
apps/rocm/src/service_launch.rs |
Updates command-tree ownership comments. |
apps/rocm/src/runtimes_cmd.rs |
Documents the enum location and retained crate-root import. |
apps/rocm/src/runtime_services.rs |
Updates the RuntimesCommand location comment. |
apps/rocm/src/main.rs |
Removes relocated definitions and tests; adds module imports. |
apps/rocm/src/install_cmd.rs |
Updates comments naming clap types and the moved test. |
apps/rocm/src/examine_report_text.rs |
Documents the relocated ASCII-help test. |
apps/rocm/src/engines_cmd.rs |
Updates enum ownership and import comments. |
apps/rocm/src/engine_ipc.rs |
Documents the watcher conversion’s new location. |
apps/rocm/src/driver_install.rs |
Updates comments locating CLI types. |
apps/rocm/src/config_cmd.rs |
Updates the ConfigCommand location comment. |
apps/rocm/src/chat.rs |
Updates a comment referencing the moved help test. |
apps/rocm/src/chat_cmd.rs |
Clarifies where Provider and inference parameters live. |
apps/rocm/src/bridge_snapshot.rs |
Updates the engine-inventory test location comment. |
AGENTS.md |
Revises command-tree placement guidance. |
.github/pull_request_template.md |
Aligns the architecture checklist with the proposed layout. |
Review effort: Balanced
Brings the branch up to date with main. Two files conflicted. engines_cmd.rs: main moved the engine runtime and env-root helpers into engine_install_env.rs and rewrote the module doc around that; the module doc keeps main's text with this branch's one edit, that EnginesCommand now lives in cli.rs. docs/architecture.md: the comfyui, config_cmd, engine_ipc and runtimes_cmd entries take main's rewritten text with this branch's clap-tree-location edits applied on top, and the engine_install_env.rs entry from main is kept as is. main.rs merged without conflict: main's three hunks (module list, re-import comment, engines_cmd import) touch no moved item. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
juhovainio
left a comment
There was a problem hiding this comment.
This is a clean move. I compared the lines added to cli.rs against the lines removed from main.rs, and the only differences are pub(crate) visibility, re-split use lines, one doc link now pointing at crate::gpu_policy::..., and the new module header and test scaffolding. No attributes, doc comments, help text, defaults, aliases or variant order were dropped, and the moved tests are identical. The docs (AGENTS.md, architecture.md, the PR template and module docs) are updated consistently, and CI is green.
This reflects a diff read plus CI, not a runtime check. The PR currently conflicts with main, so it needs a rebase or merge first, and it is worth confirming that any edits main made to the clap tree region were re-applied in cli.rs before merging.
Signed-off-by: Jussi Elo <jussi.elo@amd.com> # Conflicts: # docs/architecture.md
Signed-off-by: Jussi Elo <jussi.elo@amd.com>
Signed-off-by: Jussi Elo <jussi.elo@amd.com>
|
Merged |
Signed-off-by: Jussi Elo <jussi.elo@amd.com> # Conflicts: # apps/rocm/src/chat.rs # apps/rocm/src/main.rs # docs/architecture.md
Signed-off-by: Jussi Elo <jussi.elo@amd.com> # Conflicts: # docs/architecture.md
Signed-off-by: Jussi Elo <jussi.elo@amd.com>
|
Merged |
Signed-off-by: Jussi Elo <jussi.elo@amd.com> # Conflicts: # apps/rocm/src/examine_report_text.rs # apps/rocm/src/main.rs # docs/architecture.md
Signed-off-by: Jussi Elo <jussi.elo@amd.com> # Conflicts: # apps/rocm/src/bridge_snapshot.rs # apps/rocm/src/engine_ipc.rs # apps/rocm/src/main.rs # docs/architecture.md
Summary
This is a proposal, meant to be reviewed as one. It implements one option of an open question for the maintainers: whether
apps/rocmmay keep its whole clap command tree in acli.rs, asapps/rocmdalready does, instead of inmain.rs. If the answer is no, this PR can simply be closed; nothing else depends on it.The symptom that prompts the question is size.
apps/rocm/src/main.rsis about 5,075 lines, roughly 2,600 of them production code (inline test modules excluded by brace matching), and about 1,340 of those are one thing: theCliandCommanddefinitions, the ten subcommand enums nested under them and the clap value enums behind--provider,--device,--frameworkand similar arguments. Every open PR that adds a flag edits that region, so it is also where reviews collide. With the tree in its own file,main.rsis down to about 1,260 production lines and holds what is really glue: the process entry,dispatch, the completion builder, the exit-code types and the shared helpers. The other half of the size gap, thecomfyuidispatch function, is a separate follow-up; this PR deliberately does not touch it.The change is a pure move. No clap attribute, help text, subcommand order, default or alias changes. The convention texts that said the clap enum usually stays in
main.rs(the module organization section ofdocs/architecture.mdand the architecture guardrails inAGENTS.md) are updated to match, so the proposal and the documented convention agree.What moved
Cli,Command,BenchCommand,InstallTarget,EnginesCommand,RuntimesCommand,StorageCommand,ComfyuiCommand,ServicesCommand,AutomationsCommand,ConfigCommand,SetupCommandmain.rscli.rsFrameworkArg,InstallFormat,Provider,WatcherModeArg,TelemetryModeArg,DevicePolicyArg,SandboxToolArg,PermissionsModeArg, with theiras_str-style methods andFrom<FrameworkArg>main.rscli.rsSUPPORTED_ENGINES(thevalue_parserchoices of the--enginearguments; its only other user is a test inadvised_commands.rs, which reaches it through a test-only re-import inmain.rs)main.rscli.rsimpl From<WatcherModeArg> for WatcherMode(sits next to the enum it converts)main.rscli.rsparse_serve,parse_runtimes,runtimes_restart_flagsandserve_possible_valuesmain.rstest modulecli.rstest moduleMoved items become
pub(crate)(including theCli.commandfield and the small conversion methods), andmain.rsre-imports the types so every other module keeps reaching them ascrate::Command,crate::Providerand so on. Stays inmain.rs:dispatch, the process entry,cli_commandand the completion builders,FixExitCodeandClapExitCode,FreeformInvocation,ChatInferenceParams,GatedEngineAction,provider_name,device_policy_nameand the other shared helpers; each was checked against its callers and none of them is part of the tree.The test assignment goes by primary subject. Moved to
cli.rs:cli_command_definition_is_valid,top_level_help_lists_commands_alphabetically,every_framework_choice_reaches_the_library,the_framework_choice_is_offered_on_the_command_line,install_sdk_help_describes_the_gate_as_replacing_the_active_default,install_sdk_help_separates_the_two_consents_yes_carries,yes_help_says_what_happens_without_it_outside_a_terminal,out_of_scope_commands_are_marked_preview_in_help,runtimes_help_uses_the_runtime_noun_throughout,the_preview_marker_is_explained_and_not_contradicted,every_help_text_in_the_command_tree_is_ascii,bench_load_rejects_zero_and_unbounded_numeric_arguments,t5_bench_load_clap_parse_smoke,serve_engine_help_lists_match_engine_inventory,serve_device_help_lists_match_device_policy_names,serve_rejects_unknown_device_policy_as_usage_error,serve_accepts_device_policy_values_and_aliases,serve_parses_verbose_and_no_smoke_test_flags,serve_verbose_conflicts_with_managed,serve_defaults_have_all_flags_off,serve_parses_generation_flags,serve_rejects_out_of_range_sampling,serve_negative_sampling_space_form_reaches_range_validator,runtimes_activate_and_rollback_refuse_yes_without_restart_services,runtimes_restart_flags_parse_together_and_alone,runtimes_activate_parses_the_runtime_it_was_given,chat_negative_sampling_space_form_reaches_range_validator,chat_parses_generation_flags,chat_rejects_zero_max_tokens,update_rejects_zero_timeout_secs,services_prune_rejects_any_age_with_an_explicit_age,update_dry_run_does_not_require_apply,update_dry_run_conflicts_with_json,install_sdk_accepts_family_overrideandinstall_sdk_devel_flag_defaults_off_and_wires_through_when_passed.Stayed in
main.rseven though some of them parse through the tree as a side step, because their subject is something else: the exit-code and dispatch tests (exit_code_for_*,clap_error_exit_code_survives_the_clap_exit_code_round_trip,cli_command_rejects_unknown_flag_through_clap_exit_code,dispatch_carries_fixs_exit_code_through_to_exit_code_for), the completion builder tests (completions_generate_for_every_shell,completion_command_excludes_hidden_subcommands), the natural-language routing tests (top_level_cli_commands_are_not_treated_as_freeform,services_is_structured_not_freeform,remote_is_structured_not_freeform,completions_command_is_structured_not_freeform,completions_rejects_unknown_shell, thefreeform_invocation_*and mistyped-command tests),config_set_permissions_sets_mode(a config round trip) andupdate_apply_approval_never_credits_the_inert_yes_flag(about the approval line). The count is 35 rather than the 36 first estimated: the one that would make 36 is the freeform-routing group, where parsing is incidental.Verification
Ran locally on this branch before it was brought up to date with main; the checks marked (re-run) were repeated on the merge commit that brings main in (the engine runtime helper move and the comfyui split):
rocm --helpand the--helpand-houtput of every visible subcommand (76 of them, found by walking the help text recursively),--helpof the hidden subcommands,--version,rocm help, eight clap parse-error renderings (invalid values for the value enums, among others) androcm completionsfor bash, zsh, fish, powershell and elvish were captured from a binary built on the base commit and from one built on this branch, and diffed byte for byte: the diff is empty. The one expected difference is--version, which embeds the git commit hash; it is identical once the hash is masked.cargo test -p rocm --bin rocm -- --listand--list --ignored, compared by leaf test name before and after: identical (1,475 and 8, re-run against the current main). All 1,467 non-ignored tests pass (re-run); the 8 ignored ones are the same 8 as before. Thirty-five of the passing tests now report ascli::tests::....cargo fmt --all --check(re-run);cargo clippy -p rocm --all-targets -- -D warnings(re-run; earlier also with-p xtask);cargo test -p rocm --bin rocm advised_commands(it walks the clap tree);cargo test -p xtask(including the ASCII output contract, whose doc comment named the old home of the help walk);cargo xtask check-crate-edges,cargo xtask manifest --checkandcargo xtask lychee(all re-run).main.rs2,615 to 1,262 production lines on the current base,cli.rs1,384. Both are under 1,500.cargo clippy --target x86_64-pc-windows-msvc), which cannot build in this environment because the TLS dependency's C build needs a Windows toolchain. The moved code carries nocfg(windows)or other platform gates (the onlycfgincli.rsiscfg(test)), so the Windows CI lane is the check that matters for it. Also not run locally: the full workspace gate, the e2e suite and the smoke script; CI carries them.main.rs's test module, so none moved and no regression-seed file needed to move with it.User-visible behaviour
None, so there is no scenario to add or update. This is a pure internal move, and the byte-identical help and completion output above is the behaviour proof. The advised-command contract test runs unmodified and no e2e scenario or step definition is touched.
Notes for reviewers
Read it commit by commit (four commits, then a merge of main with two conflicted files: the
engines_cmd.rsmodule doc and four entries indocs/architecture.md, each taking main's text with the clap-tree-location edit re-applied on top; main's ownmain.rschanges touch no moved item). Two items beyond the usual tree and value enums moved with them:SUPPORTED_ENGINESand theFrom<WatcherModeArg> for WatcherModeconversion; the first commit's message says three items but names these two, so read it as two. The first commit createscli.rsand moves the tree and the value enums; its diff againstmain.rsis the deletion of one contiguous block plus the newuselines, and the module docs that said the clap types stay inmain.rsare corrected there. The second moves the 35 tests and their helpers; the moved bodies are line-for-line identical (checked by comparing the removed and added lines), only the module path changes fromtests::tocli::tests::, and a few comments in other modules that namedmain.rsas the test home now namecli.rs. The third updatesdocs/architecture.md(the convention, themain.rsentry, a newcli.rsentry and every per-module entry that said its command enum stays inmain.rs) and the matching sentence inAGENTS.md, which says the enum usually lives incli.rsand namesbootstrap.rsand the remote module as the subsystems that own their own enum. The fourth sweeps the remaining claims about where the tree lives: the services-prune entry inarchitecture.md(the constant is now imported only bycli.rs), the pull request template's note on the clap declaration, a module doc indriver_install.rsand the engine IPC entry.One detail worth knowing when reading the new module doc: declaration order sets the order of every nested
--helpcommand list, but the top-level list is sorted alphabetically bycli_command(), which stays inmain.rs. Nothing about either changes here.The move conflicts with open PRs that edit the tree. A trial merge of each open PR against this branch (compared with a trial merge against the base, so existing conflicts do not count) shows new conflicts in
main.rsfor the PRs that edit flags or help text, namely 299, 816, 817, 818, 819, 820, 826 and 857, plus a draft, 568. In each of these the conflicting hunks are doc comments, attributes or fields inside the moved region, or tests that moved, so re-applying them tocli.rsis mechanical. Two others (880 and 888) conflict inmain.rsoutside the tree: they touch a moved test and the import block. 853 only touches the docs and module comments edited here. (872, which was in this group, has since merged, and this branch already contains it.) Several older PRs (243, 631, 678, 723, 724, 725 and others) already conflict with the base inmain.rs, so they need a rebase regardless; the ones that also touch the tree (a newtaskfield onCommand::Serve, for example) would re-apply the same way. The change is deliberately landed in a few small commits so it can be reviewed as a proposal and dropped without affecting anything else.