Repository navigation
ROCMAI-761: split runtimes_cmd, runtime_install_finalize and driver_install into focused modules - #844
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The edited source citation in docs/wsl.md remains a bare backtick path rather than a relative Markdown link, leaving the reference unchecked by the docs-links job.
1 open issue
What changed in this PR
This PR advances the CLI modular refactor by separating runtime lifecycle, driver planning, and system-package installation responsibilities, while preserving existing behavior and caller imports.
Changes:
- Extracts focused modules for system packages, rocDXG planning, torch alignment, runtime adoption, and uninstall.
- Moves shared path helpers and active-runtime marker definitions into the runtime registry.
- Updates module documentation, test commands, and comments to reflect the new locations.
| File | Description |
|---|---|
tests/e2e-cucumber/tests/e2e/driver_steps.rs |
Updates a comment naming the warning test’s location. |
tests/e2e-cucumber/features/examine.feature |
Updates a comment naming the driver-plan tests. |
docs/wsl.md |
Updates the digest trust-anchor source path. |
docs/testing.md |
Updates test filters and source references. |
docs/architecture.md |
Documents extracted modules and dependency boundaries. |
crates/rocm-core/src/openmpi.rs |
Updates a comment naming the OS-release reader. |
crates/rocm-core/src/diagnose.rs |
Updates comments referencing the driver-plan support matrix. |
apps/rocm/src/system_packages.rs |
Houses system-package installation flows and tests. |
apps/rocm/src/runtime_uninstall.rs |
Houses uninstall planning, revalidation, application, and tests. |
apps/rocm/src/runtime_registry.rs |
Receives shared path helpers and active-runtime marker definitions. |
apps/rocm/src/runtime_install_finalize/torch_alignment.rs |
Houses torch alignment, retention, manifest readers, and tests. |
apps/rocm/src/runtime_adopt.rs |
Houses runtime import, adoption, registration recovery, and tests. |
apps/rocm/src/main.rs |
Declares the new crate-level modules. |
apps/rocm/src/freeform_planner.rs |
Updates a comment referencing the platform reporting decision. |
apps/rocm/src/driver_plan/rocdxg.rs |
Houses WSL driver planning, pinned digests, and tests. |
apps/rocm/src/chat.rs |
Updates module documentation naming a test consumer. |
Review effort: Balanced
| the package's maintainer scripts as root. `rocm install driver` checks the | ||
| download against a digest pinned in the ROCm CLI source | ||
| (`ROCDXG_PINNED_DIGESTS` in `apps/rocm/src/driver_install.rs`), which also | ||
| (`ROCDXG_PINNED_DIGESTS` in `apps/rocm/src/driver_plan/rocdxg.rs`), which also |
There was a problem hiding this comment.
Fixed in 8ee1b79: the ROCDXG_PINNED_DIGESTS citation in docs/wsl.md is now a relative Markdown link to apps/rocm/src/driver_plan/rocdxg.rs, so docs-links checks it. I grepped the other docs for bare citations of driver_install.rs, runtime_install_finalize.rs and runtimes_cmd.rs and found no others outside docs/architecture.md, where every file reference is already a link.
There was a problem hiding this comment.
Correction to my earlier reply: the link I added broke the Sphinx -W build, because docs/wsl.md is {include}d into the docs site and a link to a file outside docs/ cannot resolve there. 2dfcfcd restores the bare path (now apps/rocm/src/driver_plan/rocdxg.rs), which is the form this file can carry. The docs-links job therefore will not check this citation.
juhovainio
left a comment
There was a problem hiding this comment.
I compared the moved code against the originals and it looks like a faithful mechanical move: the only differences are imports, mod/re-export lines, doc comments, a couple of rustfmt re-wraps and cfg attributes on moved items. I found no behaviour changes, no dropped cfg gates, the test count is unchanged (132 removed, 132 added), and ROCDXG_PINNED_DIGESTS is byte-identical.
One thing needs fixing before merge: the relative link added in docs/wsl.md breaks the Sphinx -W docs build (details inline). Everything else I checked is fine, though the cfg(unix) import gating for Windows was reasoned from the diff rather than compiled, so I'd lean on the Windows CI jobs, which were still pending when I looked.
| download against a digest pinned in the ROCm CLI source | ||
| (`ROCDXG_PINNED_DIGESTS` in `apps/rocm/src/driver_install.rs`), which also | ||
| (`ROCDXG_PINNED_DIGESTS` in | ||
| [rocdxg.rs](../apps/rocm/src/driver_plan/rocdxg.rs)), which also |
There was a problem hiding this comment.
This relative link fails the Sphinx -W docs build (docs/wsl.md:1077: 'myst' cross-reference target not found: '../apps/rocm/src/driver_plan/rocdxg.rs'), because docs/wsl.md is included in the Sphinx site, where links to files outside it can't be resolved. Please go back to a bare backtick path here, e.g. apps/rocm/src/driver_plan/rocdxg.rs.
There was a problem hiding this comment.
Thanks, you are right: docs/wsl.md is {include}d into the Sphinx site, so a relative link to a file outside docs/ cannot resolve there, and the Sphinx docs build (-W) job failed on it. Reverted to the bare path in 2dfcfcd, so docs/wsl.md now differs from main only in the path (driver_install.rs to driver_plan/rocdxg.rs). I did not check the includes before making the Copilot-suggested change.
juhovainio
left a comment
There was a problem hiding this comment.
Reviewed the refactor against the saved diff. Moved code matches the removed code: the only differing lines are imports, mod/re-export lines, doc comments and two rustfmt re-wraps. Visibility changes are limited to pub(crate)/pub(super) (no bare pub), ActiveRuntimeMarker keeps its serde shape, 132 tests were removed and 132 added with cfg gates balanced, and there is no new module cycle. Docs links and the ticket scope look consistent.
Non-blocking:
- The
examine.featurecomment now points at the wrong file forreal_os_releasecoverage (inline). runtime_install_finalize.rsstill has a stale "calls into" module doc; fine to leave per the ticket.- The
cfg(unix)import gating is only proven by the Windows lanes, which were still pending when I reviewed; please make sure they go green before merge.
| # `rocm install driver` builds a plan that runs against the real machine, so it | ||
| # deliberately reads the real `/etc/os-release` (see `real_os_release`); its | ||
| # parsing is covered by the unit tests in `driver_install.rs`. | ||
| # parsing is covered by the unit tests in `driver_plan.rs`. |
There was a problem hiding this comment.
This says the driver plan reads the real /etc/os-release via real_os_release and that its parsing is covered in driver_plan.rs. real_os_release and its test now live in system_packages.rs; driver_plan.rs has the plan-builder tests. Consider naming both so the pointer stays accurate.
There was a problem hiding this comment.
Done in e4911be: the note in examine.feature now names real_os_release in system_packages.rs (with its simulated-root test) and the plan-builder unit tests in driver_plan.rs. I left the module doc in runtime_install_finalize.rs as is, per your note.
nowycondro
left a comment
There was a problem hiding this comment.
🤖 Automated review (Claude Code) · 2dfcfcd
This automation never files a GitHub approval, so no approving review will appear here whatever the outcome — the merge decision stays with a human reviewer.
Review — needs work
Full review of the whole change (base 6eeec620…head 2dfcfcdb, the commit this review is pinned to — the PR head moved on twice more while this review was in progress, most recently to e4911be, a small e2e-comment-only follow-up not covered here).
Implements all seven PRs that ROCMAI-761 planned as a sequence (the ticket expected 7 incremental PRs; this one PR carries all seven commits instead, which the PR body discloses). Scope matches the ticket's symbol/destination table exactly; this is also the ticket's final/only PR, so naming the key in the title is correct under the ticket's own "only the final PR names this key" rule.
Blocking
docs/architecture.mdhas four stale/self-contradictory cross-references left over from the split —docs/architecture.md:56,docs/architecture.md:34,docs/architecture.md:50,docs/architecture.md:74
(1) Line 56'sruntime_adopt.rsentry says "...recover_setup_runtime_registrationregisters the runtimerocm setupcreated, withnewest_installed_runtime_manifestandsetup_runtime_pathsbeside it... arepub(crate)forruntimes()... the rest is private" — butnewest_installed_runtime_manifest,recover_setup_runtime_registrationandsetup_runtime_pathsare allpub(crate)(confirmed:apps/rocm/src/runtime_adopt.rs:66,380,445), which the same bullet's own earlier sentence requires (they're re-exported fromruntimes_cmd.rs). The bullet contradicts itself.
(2) Line 34'schat.rsentry saysChatRocmCommandActionis "read bydriver_install.rs's test module" — that test content moved todriver_plan.rsin this PR (confirmed viagit grep: onlydriver_plan.rs:2779-2818references it now).chat.rs's own doc comment (apps/rocm/src/chat.rs:10) was correctly updated to saydriver_plan.rs; the separatearchitecture.mdbullet about the same fact was not.
(3) Line 50'sfreeform_planner.rsentry saysplan_driver_requestis "read fromdriver_install.rs's test module" — its only caller is nowdriver_plan.rs:2764.
(4) Line 74'stherock/fetch.rsentry saystruthy_envis "re-exported bytherock.rsfordriver_install.rs" — the only consumer at the PR head isdriver_plan/rocdxg.rs(confirmed viagit grep;driver_install.rsno longer calls it);driver_plan.rs's own doc comment correctly attributes this to its child module.
All four were confirmed directly against the code, not inferred.docs/architecture.mdis this repo's authoritative, explicitly-verified module map (AGENTS.md requires keeping docs in sync with behavior/interface changes and grepping a claim's wording across every surface before trusting it); this PR rewrote the three source-file entries and the new-file entries carefully (verified accurate), but didn't propagate the consequence of thedriver_install.rs→driver_plan.rstest/call-site relocation to these three unrelated, pre-existing bullets.
Confidence 90 · mechanical · Fix: update the four bullets to namedriver_plan.rs/driver_plan/rocdxg.rsas appropriate, and fix the self-contradiction in theruntime_adopt.rsbullet.
Non-blocking
- Orphaned explanatory comment left in
driver_install.rs—apps/rocm/src/driver_install.rs:855-858
A block comment ("EAI-7406: distro selection must honor/etc/os-releaseID_LIKE...") sits at the very end of the file'smod tests, immediately followed by the closing brace — the three tests it describes (driver_plan_ubuntu_derivative_via_id_like_matches_ubuntu_plan,..._debian_derivative...,..._almalinux_via_id_like...) moved todriver_plan.rs:3078onward in this PR without it. Confirmed viagit grep EAI-7406(one hit, in the now-comment-less location) and locating the tests' new home.
Confidence 90 · mechanical · Fix: move the comment to precede theID_LIKEtests indriver_plan.rs; delete it fromdriver_install.rs.
Decisions for the author
- Bundling all seven planned PRs into one — tradeoff
The ticket's process explicitly expects 7 separate, incrementally-landable PRs (PRs 1-5 can start now. PRs 6-7 wait for Phase 8.1-A PR 2), partly so each is reviewable on its own. This PR deliberately combines them into one (disclosed up front: "The ticket asks for each step to ship as its own pull request. This pull request carries all seven steps instead"). Each commit is independently self-contained and was reviewed as such, but the combined diff (~8,300 lines) is a large single review surface. Not a defect — worth the author/maintainers confirming this was the intended tradeoff rather than a process slip.
Positive signals
- The security-critical
ROCDXG_PINNED_DIGESTStrust anchor was independently re-verified byte-for-byte identical between its old (driver_install.rs) and new (driver_plan/rocdxg.rs) locations, not just taken on the commit message's word. - Across all five reviewed clusters, every
pub(crate)/pub(super)visibility widening traced back to a real external caller — no needless over-exposure, and nothing under-widened either. ActiveRuntimeMarker's on-disk serde shape (derive, field names, types, order) is byte-for-byte preserved; only field visibility changed, exactly as required for user-persisted state.- All moved tests (well over 100, across every cluster) diffed byte-identical to their pre-PR bodies, including
cfg(unix)/cfg(feature = "e2e-test-hooks")gates, which were correctly re-declared per new file rather than dropped. - Module doc-comments' specific dependency/visibility/cycle-avoidance claims (e.g.
torch_alignment.rsanddriver_plan/rocdxg.rsas child modules specifically to avoid a cycle) held up under direct verification against the actualuse crate::lines.
Deployment notes
None.
What this covered
Every one of the 20 changed files read completely (base 6eeec620c3d451a52bd8f98ef218fb9e8a0549a4…head 2dfcfcdb3a59d09ac88817b545760433febefacd), each diffed function-by-function and test-by-test against its pre-PR body, via five independent fan-out workers grouped by coupling (system-packages/torch-alignment; driver-plan model+builders; driver-plan/rocdxg; runtimes_cmd/adopt/uninstall/registry; docs-accuracy), plus my own direct re-verification of every finding reported above and of the docs/wsl.md Sphinx-include question. CI for this exact commit: CodeQL completed (success); the main CI workflow (build/clippy/tests/docs-links/docs-build) was still in_progress and had not concluded at review time — no failure to report, but also no completed-green confirmation for this commit specifically; E2E self-hosted was cancelled (superseded by a later push) rather than run to completion.
Did not run: a real cargo build/cargo test (no Rust toolchain in this environment) — relied on exhaustive diff/grep-based static comparison instead of compiling; "prior changes" pass (no time to survey closed PRs touching these files); "history" (git log/blame) pass was done lightly and surfaced nothing. The PR head moved twice during this review (8ee1b794→2dfcfcdb→e4911be); this review is pinned to 2dfcfcdb, the state actually read. The mandatory pre-review duplicate-review check incidentally surfaced the text of two prior human/bot reviews, including a since-superseded finding about docs/wsl.md's link format — that specific point was independently re-derived here from AGENTS.md's documented Sphinx-{include} rule and the repo's actual docs/rocm-docs/install/wsl.md include directives (not taken from the other review), and was already fixed by the commit this review is pinned to.
Not reconciled against any discussion or review thread on this PR.
🤖 Generated with Claude Code
e4911be to
220834c
Compare
220834c to
9fa2739
Compare
nowycondro
left a comment
There was a problem hiding this comment.
🤖 Automated review (Claude Code) · 9fa2739
This automation never files a GitHub approval, so no approving review will appear here whatever the outcome — the merge decision stays with a human reviewer.
Review — no blocking findings
Full review of the whole change (base 87a7c7a7…head 9fa2739).
Implements the full ROCMAI-761 ticket: all seven symbol-move clusters the ticket's scope table lists, delivered as one PR (seven primary commits in the ticket's order, plus four small follow-up commits fixing docs issues an earlier review round raised) instead of the ticket's planned seven incremental PRs. This is the ticket's only/final PR, so naming the key in the title is correct under the ticket's own "only the final PR names this key" rule. Every symbol named in the ticket's scope table was independently confirmed present in its stated destination file, every acceptance criterion (re-exports compile, no new module cycle, leaf-test-count parity, docs/architecture.md coverage, serde-shape preservation) was independently verified against the code rather than assumed.
Blocking
None
Non-blocking
None
Decisions for the author
- Bundling all seven planned PRs into one — tradeoff
The ticket's process explicitly expects 7 separate, incrementally-landable PRs ("PRs 1-5 can start now. PRs 6-7 wait for Phase 8.1-A PR 2"), partly so each is reviewable on its own. This PR deliberately combines them into one, disclosed up front in the PR body ("The ticket asks for each step to ship as its own pull request. This pull request carries all seven steps instead"). Each commit is independently self-contained and moves a disjoint cluster, but the combined diff (~8,300 lines across 20 files) is a large single review surface. Not a defect — worth the author/maintainers confirming this was the intended tradeoff rather than a process slip.
Positive signals
- The security-critical
ROCDXG_PINNED_DIGESTStrust anchor was independently re-verified byte-for-byte identical (diff + extraction, not eyeballed) between its old (driver_install.rs) and new (driver_plan/rocdxg.rs) locations. ActiveRuntimeMarker's on-disk serde shape (derive list, all field names, types, order) is byte-for-byte preserved betweenruntimes_cmd.rs(old) andruntime_registry.rs(new); only field visibility changed, exactly what user-persisted state requires.- Total
#[test]count across the three original files (196) exactly matches the total across all nine resulting files (196) — independently counted, not taken from the PR body's own count — confirming no test was silently dropped or duplicated anywhere in the three-way, nine-file split. - Every
pub(crate)/pub(super)visibility widening checked (dozens, across all five file clusters) traced back to a real external caller found viagit grep; no barepubwas introduced anywhere, and nothing was under-widened either. docs/architecture.md's entries for all six new files and the rewritten entries for the three source files were checked claim-by-claim against the actual code (dependency direction,pub(crate)/pub(super)/private status, re-export lists) and held up in every case checked, including the two stale/self-contradictory bullets and the wrong-file comment an earlier review round had flagged — both are now fixed by this commit (9fa2739,ecbdec2) and independently reconfirmed fixed here rather than taken on that round's word.- A corrected doc comment ("optional override in this file" → "optional override of the driver plan") precisely tracks the fact that the two functions it refers to no longer live in the same file after the split — the kind of accuracy detail a mechanical move usually lets drift.
Deployment notes
None.
What this covered
Every one of the 20 changed files read completely in both pre-PR and post-PR state (base 87a7c7a76188edb0af904020a0a58942910ad27d…head 9fa2739181300ebfcf9e8e75464edf7db2f2c812), each production function, struct, enum and test diffed individually against its pre-PR body. Four independent fan-out workers covered: (1) system_packages.rs + runtime_install_finalize.rs + runtime_install_finalize/torch_alignment.rs + openmpi.rs; (2) driver_plan.rs + driver_plan/rocdxg.rs; (3) the shrunk driver_install.rs + the four one-line comment edits in chat.rs/freeform_planner.rs/diagnose.rs + main.rs's new mod lines; (4) runtimes_cmd.rs + runtime_registry.rs. A fifth cluster (runtime_adopt.rs + runtime_uninstall.rs) could not get an independent worker spawned after repeated transient capacity failures in this environment, so I reviewed it myself directly with the same methodology (extracted and diffed every function/struct/test against the pre-PR runtimes_cmd.rs, confirmed re-exports and callers via git grep) — flagged here as not an independent pass. I also did my own docs-accuracy pass (docs/architecture.md, docs/testing.md, docs/wsl.md, examine.feature, driver_steps.rs) and retrieved ROCMAI-761 directly from Jira (not via any link in the PR body) to check the scope table and acceptance criteria.
CI for this exact commit: all 26 checks completed, every one SUCCESS except Skill checks (skillscope), correctly SKIPPED (no skill files touched) — full green, including both Windows jobs, clippy, cargo fmt, the ratcheted coverage check, Sphinx docs build (-W), Markdown links resolve (lychee), E2E tests and E2E consolidated report.
Did not run: a real cargo build/cargo test (no Rust toolchain in this environment) — relied on exhaustive diff/grep-based static comparison plus the green CI above as compile/test confirmation; a "prior changes" pass across the other open PRs the body names as touching these same files (out of scope for this review, and already disclosed by the author); "history" (git log/blame) was done lightly — confirmed 3 commits landed on main ahead of this PR's base, none overlapping the regions this PR edits.
The mandatory pre-review duplicate-check (required to avoid double-posting) necessarily surfaced the text of a prior nowycondro review at an older, superseded commit (2dfcfcdb) plus two human reviews. Both of that prior review's findings (stale/self-contradictory docs/architecture.md cross-references; a wrong-file reference in examine.feature) were independently re-confirmed fixed by this review's own direct reading of the current commits, not taken on the earlier review's word.
Not reconciled against any discussion or review thread on this PR.
🤖 Generated with Claude Code
…install_finalize.rs into system_packages.rs Step 1 of 7 in splitting runtimes_cmd.rs, runtime_install_finalize.rs and driver_install.rs into focused modules. system_packages.rs is a leaf that uses only std, anyhow and rocm_core. It takes the OpenMPI, libatomic and libnuma install flows, the print-or-run decision (SystemPackageInstallAction), the apt guard that refuses removals of ROCm packages, the argv runner and real_os_release. SdkInstallConsents stays where it is: it carries a therock consent type, and the moved functions take a plain bool. Moved code is byte-identical apart from the edits below. Non-move edits: - runtime_install_finalize.rs re-exports ensure_openmpi_for_vllm, ensure_libatomic_for_torch and ensure_libnuma_for_torch so main.rs and engines_cmd.rs keep their imports; real_os_release is not re-exported. - driver_install.rs imports real_os_release from crate::system_packages instead of crate::runtime_install_finalize, which removes its only reference to that module. - runtime_install_finalize.rs: the module doc no longer says driver_install.rs reads real_os_release from it and points at system_packages.rs; its anyhow import drops Context and bail, its std::process import is dropped, and its test module imports Context as _ itself and drops the chat and providers imports the moved test used. - main.rs declares the new module. - Two tests move with the code: an_injected_consent_does_not_approve_privileged_package_installs and real_os_release_ignores_a_simulated_host_root (with its ExpectedOsRelease helper). The first reaches the consent helper through the existing pub(crate) runtime_install_finalize::tests::consents_for_install_sdk_argv, so no production item is widened for a test. - docs/testing.md and the rocm-core openmpi.rs doc comment name system_packages::real_os_release; docs/architecture.md gets an entry for the new file and updated entries for the two source files. The leaf-name test list is unchanged. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…_install.rs into driver_plan.rs
Step 2 of 7. driver_plan.rs is a leaf (std and rocm_core only) holding the plan `rocm install driver` builds and prints: DriverInstallPlan, DriverPlanCommand, DriverCommandPhase, PrivilegeEscalation, render_driver_install_plan with driver_plan_approval_label, and the helpers every plan builder shares (driver_command, driver_root_preflight_checks, resolve_shell_default_template, is_safe_shell_token). The per-distro builders and the WSL rocDXG plan stay in driver_install.rs for the next steps.
Moved code is identical apart from the edits below.
Non-move edits:
- Visibility: the moved types, the plan and command fields, DriverInstallPlan::execution_commands, PrivilegeEscalation::{detect, prefix, needs_sudo_binary} and the helper functions become pub(crate) because driver_install.rs now reaches them across the module boundary. driver_plan_approval_label stays private.
- render_driver_install_plan's signature wraps over several lines in rustfmt's output because pub(crate) lengthened it.
- driver_install.rs imports the moved names from crate::driver_plan; its test module imports DriverPlanCommand itself; the empty_as_unknown import moves with the renderer.
- main.rs declares the new module.
- Seven tests move with the code: the six resolve_shell_default_template_* tests and is_safe_shell_token_rejects_quote_and_semicolon_payloads. The plan-building tests that only call render_driver_install_plan on a built plan stay with the builders.
- docs/architecture.md gets an entry for driver_plan.rs and an updated driver_install.rs entry.
The leaf-name test list is unchanged.
Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…o driver_plan/rocdxg.rs Step 3 of 7. driver_plan/rocdxg.rs is a child of driver_plan.rs holding the WSL2 rocDXG plan: the version and digest-environment constants, ROCDXG_PINNED_DIGESTS, the version and digest well-formedness checks, RocdxgVerification and resolve_rocdxg_verification, the refusal plan and wsl_rocdxg_driver_plan. It uses only items that stay in its parent for good (the plan model, driver_command, driver_root_preflight_checks, resolve_shell_default_template) plus truthy_env from therock.rs. ROCDXG_PINNED_DIGESTS is the trust anchor for an unattended root install. Its doc comment and table were compared byte for byte against the previous file and are identical. Moved code is identical apart from the edits below. Non-move edits: - Visibility: wsl_rocdxg_driver_plan becomes pub(crate) so driver_plan.rs can re-export it for the builders still in driver_install.rs; the other moved items stay private. - driver_plan.rs declares the child module, re-exports wsl_rocdxg_driver_plan, and re-exports scoped_rocdxg_env under cfg(test). - scoped_rocdxg_env, the test helper that clears the rocDXG environment, moves next to the constants it clears as a cfg(test) pub(crate) function (dedented, body unchanged) because tests that stay in driver_install.rs use it as well. That re-export is temporary scaffolding for the intermediate state: when the builders and their tests move, they can reach it through the parent. - Twelve wsl_rocdxg_* tests move with the code; the plan-routing tests and the reboot test, which also call a plan builder, stay in driver_install.rs. The moved tests import render_driver_install_plan from the parent, and the imports only the Unix-only digest test uses (fs, Path, test_paths) are gated on cfg(unix) as that test is. - driver_install.rs imports wsl_rocdxg_driver_plan and, in its tests, scoped_rocdxg_env from crate::driver_plan; its imports of resolve_shell_default_template and the cfg(unix) std::path::Path go, since nothing left there uses them. - One comment in driver_install.rs said every other optional override lives in that file; it now says the overrides are the driver plan's, since resolve_rocdxg_verification and resolve_shell_default_template are no longer in it. - docs/wsl.md names the new path for ROCDXG_PINNED_DIGESTS; docs/testing.md's driver unit-test command also selects driver_plan, which already holds tests moved by the previous step; docs/architecture.md gets an entry for the new file and updated driver_install.rs and driver_plan.rs entries. The leaf-name test list is unchanged. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…r_install.rs into driver_plan.rs Step 4 of 7. The plan builders now sit next to the plan model they construct: build_driver_install_plan_read and build_driver_install_plan_at, the apt, dnf and SLES plans, the ID_LIKE fallback, the repository URL and version helpers, resolve_repo_version_expr with RETIRED_DRIVER_VERSION_VARS, the unreadable-os-release and invalid-override refusal plans, codename_for_version, and install_driver_only_reports_on / host_install_driver_only_reports. driver_install.rs keeps the handler, the shell runner and the state and reconciliation code, and no longer holds any plan construction. Moved code is identical apart from the edits below. Non-move edits: - Visibility: build_driver_install_plan_read and invalid_driver_version_override_plan become pub(crate) (the handler calls the first; a test that stays with the executor builds a plan with the second). PrivilegeEscalation::prefix and needs_sudo_binary, is_safe_shell_token, driver_root_preflight_checks and resolve_shell_default_template, which the previous steps widened, are private again because nothing outside driver_plan.rs and its child module uses them now; a child module may use its parent's private items. - driver_install.rs re-exports host_install_driver_only_reports, the one name chat.rs and freeform_planner.rs use. install_driver_only_reports_on is not re-exported because no consumer outside the moved tests uses it, and an unused re-export fails clippy. - driver_plan.rs makes its test module pub(crate) so the tests that stay in driver_install.rs can reuse test_examine and os_release_found (both widened to pub(crate) for that); the staying tests are the ones that drive the executor, the state and reconciliation, should_execute and the unsupported-plan approval. The scoped_rocdxg_env re-export added in the previous step is dropped, scoped_rocdxg_env is pub(super), and the moved tests import it from the child module. - Imports: driver_plan.rs adds ExamineSummary, and in its test module fs and ProcessCommand (cfg(unix), like the dpkg-query stub test that uses them), PathBuf and scoped_rocdxg_env. driver_install.rs imports what it still uses from crate::driver_plan, in its prod code and in its tests. - Module docs: the driver_plan.rs and driver_install.rs headers describe the new split (the old driver_install.rs header said it owned the plan types). Doc and comment paths that named driver_install.rs for the plan builders now name driver_plan.rs: chat.rs, freeform_planner.rs, two comments in rocm-core's diagnose.rs, the e2e driver_steps.rs and examine.feature comments (text only, no step or scenario change), docs/testing.md, and docs/architecture.md, whose three driver entries are rewritten. - Test moves: the 64 plan-builder tests and their seven helpers move with the code; ten tests stay in driver_install.rs. The leaf-name test list is unchanged. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…tall_finalize.rs into a child module Step 5 of 7. runtime_install_finalize/torch_alignment.rs holds what to do about the torch an engine install finds in a managed runtime: TorchAlignment and TorchAlignmentPlan with plan_torch_alignment, align_runtime_torch and the render and report functions, TorchRetention with classify_retained_torch and its render and report functions, and the manifest readers (sdk_torch_build_for_key, sdk_torch_build_from_manifest, runtime_python_for_key, runtime_library_paths_for_key, runtime_index_url_for_key). It is a child, not a crate-level module, because it uses the parent's device check (RuntimeDeviceCheck, device_check_verdict), which stays there, while the parent calls into it from settle_engine_install and maybe_auto_install_sdk_preferred_engine; as a sibling the two would form a cycle. Moved code is identical apart from the edits below. Non-move edits: - Visibility: the items the parent calls become pub(super): TorchAlignment, TorchRetention, report_torch_alignment, report_torch_retention, classify_retained_torch, retained_diverged_package, deliberately_diverged_package, sdk_torch_build_for_key, runtime_python_for_key and runtime_library_paths_for_key. The rest stays private. deliberately_diverged_package's signature wraps over several lines in rustfmt's output because of that. - The parent declares the child module and imports the names it uses from it. Nothing is re-exported, because no file outside the parent uses these names. - Imports: the child gets the std, anyhow and crate imports its code needs, and reaches the parent's device check through super; its tests also import the parent's EngineDependencyCheck, classify_dependency_details and render_engine_dependency_check, which stay private in the parent and are visible to a descendant, and the test helpers they use from crate::tests. The parent drops the runtime_manifest_for_selector import and the test helper imports that only the moved code and tests used. - 25 tests move with the code (the planning, rendering, opt-out, retention and manifest-reader tests). The tests of the device check, the dependency check and the finalization stay in the parent. - docs/architecture.md gets an entry for the new file and a rewritten runtime_install_finalize.rs entry. The leaf-name test list is unchanged. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…runtimes_cmd.rs into runtime_adopt.rs Step 6 of 7. runtime_adopt.rs holds what registers a runtime that `rocm install sdk` did not install: import_runtime_manifest, the adopt request, options and probe functions with their helpers (normalize_adopt_channel, runtime_key_component, resolve_adopt_python_input, infer_python_env_root, absolute_existing_file_path_preserving_symlink, parse_therock_runtime_id, write_runtime_registry_manifest), recover_setup_runtime_registration, newest_installed_runtime_manifest and setup_runtime_paths. paths_equivalent and normalize_path_for_compare move to runtime_registry.rs: adopt and uninstall both need them, and leaving them in runtimes_cmd.rs would make runtime_adopt and runtimes_cmd a cycle. runtime_adopt.rs depends on runtime_registry.rs and therock.rs, not on runtimes_cmd.rs. Moved code is identical apart from the edits below. Non-move edits: - Visibility: import_runtime_manifest, AdoptRuntimeOptions, adopt_runtime_from_python_options, AdoptRuntimeRequest and adopt_runtime_from_probe become pub(crate), and so do the fields of the two structs, because runtimes() builds the options and two tests that stay in runtimes_cmd.rs build the request. paths_equivalent and normalize_path_for_compare become pub(crate) in runtime_registry.rs. - runtimes_cmd.rs re-exports newest_installed_runtime_manifest, recover_setup_runtime_registration and setup_runtime_paths from runtime_adopt, and normalize_path_for_compare from runtime_registry, so engines_cmd.rs, engine_runtime_select.rs, examine_report_text.rs, runtime_install_finalize.rs, main.rs and the therock.rs test keep their imports. It imports the three adopt names runtimes() calls and paths_equivalent privately, and drops the two rocm_core imports only the moved code used. - runtime_adopt.rs takes the registry names it needs (manifest paths, activation validation, paths_equivalent) from runtime_registry directly, not through runtimes_cmd. - Seven tests move with the code. Three tests that mix the moved functions with activation, list rendering or uninstall stay in runtimes_cmd.rs, which imports AdoptRuntimeRequest and adopt_runtime_from_probe for its tests; moving them would give runtime_adopt's tests a dependency on runtimes_cmd. - Module docs: the runtimes_cmd.rs and runtime_registry.rs headers name the new module; the claim in runtimes_cmd.rs's header that comfyui.rs reads normalize_path_for_compare and recover_setup_runtime_registration from it was not true (comfyui.rs imports runtime_usability_status) and is replaced by the real list of re-exports. docs/architecture.md gets an entry for the new file and updated runtimes_cmd.rs and runtime_registry.rs entries. The leaf-name test list is unchanged. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…ntime_uninstall.rs Step 7 of 7. runtime_uninstall.rs holds `rocm runtimes uninstall` and the storage pruning that removes a registered runtime: RuntimeUninstallResult, InstallRootDecision, RuntimeUninstallPlan, plan_runtime_uninstall, print_runtime_uninstall_plan, revalidate_runtime_uninstall_plan, RuntimeUninstallConfirmation, confirm_and_revalidate_runtime_uninstall, uninstall_runtime, apply_runtime_uninstall, should_remove_runtime_install_root, local_runtime_manifest_matches and ensure_runtime_install_root_is_safe_to_remove. Uninstall reads the active-runtime marker, so ActiveRuntimeMarker, active_runtime_marker_path and active_runtime_marker_matches move first, in this same step, to runtime_registry.rs; leaving them in runtimes_cmd.rs would make runtime_uninstall and runtimes_cmd a cycle. write_active_runtime_marker stays with the activation transaction. ActiveRuntimeMarker is user state on disk. Its derive, field names, field types and field order are unchanged, so its serde shape is unchanged; only the visibility of its fields changes. Moved code is identical apart from the edits below. Non-move edits: - Visibility: the fields of ActiveRuntimeMarker become pub(crate) because activate_runtime and rollback_runtime build it and tests read it. RuntimeUninstallPlan, RuntimeUninstallConfirmation, plan_runtime_uninstall, print_runtime_uninstall_plan, confirm_and_revalidate_runtime_uninstall and apply_runtime_uninstall become pub(crate), and so do the fields of RuntimeUninstallResult that runtimes() reads, because runtimes() calls the uninstall flow across the module boundary. active_runtime_marker_matches becomes pub(crate) in runtime_registry.rs. revalidate_runtime_uninstall_plan and the folder-safety helpers stay private. - runtimes_cmd.rs re-exports uninstall_runtime, should_remove_runtime_install_root and InstallRootDecision from runtime_uninstall, and ActiveRuntimeMarker and active_runtime_marker_path from runtime_registry, so storage.rs and main.rs keep their imports. It imports the five uninstall names runtimes() calls, and drops the imports only the moved code used (the std path types and serde derives at the top level, and two rocm_core names); its test module imports PathBuf itself. - runtime_uninstall.rs takes the registry names it needs (marker check and path, paths_equivalent, manifest selection) from runtime_registry directly, and uses no item of runtimes_cmd.rs. - Thirteen tests move with the code. The one uninstall test that first activates a runtime, and the tests that exercise the activation transaction through the marker, stay in runtimes_cmd.rs, since moving them would give runtime_uninstall's tests a dependency on runtimes_cmd. The moved uninstall test that imports a manifest takes import_runtime_manifest from runtime_adopt. - Module docs: the runtimes_cmd.rs and runtime_registry.rs headers name the new module and the marker; docs/architecture.md gets an entry for the new file and rewritten runtimes_cmd.rs and runtime_registry.rs entries. The leaf-name test list is unchanged. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
The ROCDXG_PINNED_DIGESTS trust anchor moved to driver_plan/rocdxg.rs; cite it as a relative Markdown link so the docs-links check notices when it moves again. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
docs/wsl.md is included into the Sphinx site, where a link to a file outside docs/ cannot be resolved and fails the -W build. A bare path is the form that file can carry. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
real_os_release and its simulated-root test live in system_packages.rs; the plan-builder tests live in driver_plan.rs. The comment now points at each. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
…cture.md Four architecture.md bullets still named driver_install.rs for things the split moved (the chat.rs and freeform_planner.rs test consumers, the truthy_env consumer), and the runtime_adopt.rs bullet called three pub(crate) functions private. The EAI-7406 note about ID_LIKE matching moves with the tests it describes. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
After the command clusters left main.rs, the entries for the system-package, install-finalize, driver-install and runtimes modules still named main.rs as the caller of install() or as a re-export consumer. They now name install_cmd.rs and config_cmd.rs. Signed-off-by: Jussi Elo <jussi.elo@amd.com>
9fa2739 to
2e3b83b
Compare

Why
This delivers ROCMAI-761, part of the
rocm-climodular refactoring epic. Three modules inapps/rocm/srceach bundle several unrelated seams:runtimes_cmd.rsmixes theruntimes()dispatch and activation transaction with import and adopt code and the uninstall flow,runtime_install_finalize.rscarries host system-package installation (sudoapt, dnf, zypper) next to engine settling, anddriver_install.rsis mostly a per-distro plan catalog plus a digest-pinned WSL rocDXG plan rather than the handler its docs describe.driver_install.rsalso reached intoruntime_install_finalize.rsonly to read/etc/os-release. This gives each seam its own module and removes that reach.The ticket asks for each step to ship as its own pull request. This pull request carries all seven steps instead, as seven commits in the ticket's order, each one a self-contained move that builds and passes the module tests on its own.
What changes
Every commit is a pure move: code is moved verbatim, and the only edits are re-exports, visibility widening and import paths, each listed in the commit message.
system_packages.rs(new, a leaf using onlystd,anyhowandrocm_core): the OpenMPI, libatomic and libnuma install flows, the print-or-run decision, the apt guard that refuses removals of ROCm packages, the argv runner andreal_os_release.runtime_install_finalize.rsre-exports the threeensure_*names somain.rsandengines_cmd.rskeep their imports, anddriver_install.rsnow importsreal_os_releasefromsystem_packagesand no longer refers toruntime_install_finalizeat all.driver_plan.rs(new): the plan model (DriverInstallPlan,DriverPlanCommand,DriverCommandPhase,PrivilegeEscalation), its renderer and the helpers every builder shares.driver_plan/rocdxg.rs(new, a child ofdriver_plan.rs): the WSL rocDXG plan includingROCDXG_PINNED_DIGESTS, which is a trust anchor; its doc comment and table were compared byte for byte against the old file and are identical.build_driver_install_plan_read/_at, the apt, dnf and SLES plans, theID_LIKEfallback, repository helpers,install_driver_only_reports_on/host_install_driver_only_reports) move intodriver_plan.rs.driver_install.rskeeps the handler, the shell runner and the state and reconciliation code, and re-exportshost_install_driver_only_reportsforchat.rsandfreeform_planner.rs.runtime_install_finalize/torch_alignment.rs(new, a child): torch alignment and retention and the manifest readers. It is a child rather than a sibling because it uses the parent's device check (RuntimeDeviceCheck,device_check_verdict), which stays there; as a crate-level sibling the two would form a cycle.runtime_adopt.rs(new): import, adopt and setup-runtime recovery.paths_equivalentandnormalize_path_for_comparemove toruntime_registry.rs, because adopt and uninstall both need them and leaving them inruntimes_cmd.rswould make a cycle.runtimes_cmd.rsre-exports the names other modules import from it.runtime_uninstall.rs(new): the uninstall plan, confirmation, revalidation and apply code. First, in the same commit,ActiveRuntimeMarker,active_runtime_marker_pathandactive_runtime_marker_matchesmove toruntime_registry.rs(uninstall reads the marker; leaving it inruntimes_cmd.rswould be a cycle). The marker is user state on disk: its derive, field names, types and order are unchanged, so its serde shape is unchanged; only field visibility changes.Path and symbol pins that named the old locations are updated in the same commits:
docs/testing.md(including thedriver_installtest command, which now also selectsdriver_plan),docs/wsl.md(ROCDXG_PINNED_DIGESTS), therocm-coreopenmpi.rsanddiagnose.rscomments, and the comment text intests/e2e-cucumber/tests/e2e/driver_steps.rsandtests/e2e-cucumber/features/examine.feature(no step or scenario changes).docs/architecture.mdgets one entry per new file and rewritten entries for the three source files; I checked each claim in them about who depends on whom, and what ispub(crate),pub(super)or private, against the code. A few existing claims that the moves made false or that were already wrong are corrected where they sat: theruntimes_cmd.rsheader saidcomfyui.rsreadnormalize_path_for_compareandrecover_setup_runtime_registrationfrom it (it importsruntime_usability_status), and onedriver_install.rscomment said every other optional override lived in that file.Differences from the ticket text:
driver_install.rsre-exports onlyhost_install_driver_only_reports, not alsoinstall_driver_only_reports_on, because no consumer outside the moved tests uses the latter and an unused re-export fails clippy. On current main the staying testsdk_install_auto_engine_selection_prefers_vllm_for_supported_familiesdoes not usereal_os_release, so it needed no import change. Tests that need the activation transaction or list rendering as well as a moved function (a few inruntimes_cmd.rs) and the executor, state and reconciliation tests indriver_install.rsstay with that code rather than moving, so no moved module's tests depend on its caller. Norocm-coresystem_packages.rsexists on main or in an open pull request, soapps/rocm/src/system_packages.rsuses the name the ticket gives; ifrocm-corelater gets a module with the same name it lives in another crate.Verification
Run locally, per commit unless noted:
cargo test -p rocm --bin rocm -- --list, and with--ignored,: testlines, module paths stripped, sorted) before and after every commit: the diff is empty each time, and also for thee2e-test-hooksvariant at the end.system_packages,driver_plan,torch_alignment,runtime_adopt,runtime_uninstall).cargo fmt --all --check,cargo clippy -p rocm --all-targets -- -D warningsand the same with--features e2e-test-hooks(thetorch_runtime_dep_checks_disabledvariant and thereal_os_releasesimulated-root test only compile there),cargo build -p rocm --features e2e-test-hooks,cargo build --workspace,cargo xtask manifest --check,cargo xtask check-crate-edges,cargo test -p xtask.cargo test -p rocm --bin rocmrun, with and withoute2e-test-hooks: all pass.modand re-export lines, module and doc comments, and the two function signatures that rustfmt re-wrapped becausepub(crate)orpub(super)lengthened them, no code line differs.use crate::lines reach onlyruntime_registry,therock,cli_report,engines_cmd(from the torch-alignment child, the same edge its parent already has) and the root helpers;driver_planandsystem_packagesuse no crate module in production code, anddriver_plan/rocdxg.rsreadstruthy_envfromtherock.origin/mainand a conflict-marker grep: clean.Not run locally: the full workspace test suite,
tests/e2e-cucumber, and the Windows lane. The imports that only acfg(unix)test uses are gated oncfg(unix)to match, but that is reasoned rather than compiled on Windows. Nothing user-observable changes (no command output, exit code, file or engine selection), so there is no new scenario; the existing e2e scenarios, including therocm_doctor_skillanddriver-install-*ones, are expected to pass unchanged and are left to the e2e lanes.Scope
A behaviour-preserving split of three
apps/rocmmodules, nothing else: no behaviour, output, serde shape or trust-anchor value changes. Out of scope, as the ticket lists them: merging the two registry writers, the twoinfer_python_env_rootcopies and the tworeal_os_releasecopies, and the existingengines_cmd/runtime_install_finalizecycle (this removesdriver_install's reach intoruntime_install_finalizebut does not touch that one).Open pull requests that edit the same files and will have to re-apply any change to a moved function in its new file: #840, the
main.rscommand-cluster move (driver_install.rs,runtime_install_finalize.rs), #842 and #829 (driver_install.rs), #832 (runtime_registry.rs,runtimes_cmd.rs), and #811, #610, #541 and #437 (runtimes_cmd.rs). #181 and #778, which the ticket flagged as touchingdriver_install.rs, are both merged.