Skip to content

fix(runtimes): keep the rollback target when re-selecting the active runtime - #485

Merged
rominf merged 1 commit into
mainfrom
fix-runtimes-rollback-target
Oct 2, 2026
Merged

rominf merged 1 commit into
mainfrom
fix-runtimes-rollback-target

Conversation

@rominf

@rominf rominf commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator
  • If this PR fixes a bug, searched tests/e2e-cucumber/expectations.toml for the fixed ticket ID and removed/narrowed any now-stale xfail rows. — no rows reference the runtimes lifecycle scenarios.
  • If this PR adds a new subcommand or subsystem, its domain implementation lives in its own file per docs/architecture.md. — N/A, no new subcommand.
  • Every new or changed user-facing message was read against the code path that runs after it, and its test asserts the resulting state — not only the wording, per AGENTS.md §3. — see "Changed user-facing output" below; scenario 08 asserts the registry state via rocm runtimes list, not the activation wording.

Summary

Re-selecting the ROCm runtime you are already using silently discarded the rollback target, so the recovery path the previous activation had just offered disappeared with no sign it had gone.

$ rocm runtimes activate A      # in use: A
$ rocm runtimes activate B      # in use: B, rollback target: A
                                # → "if this causes problems, run `rocm runtimes rollback`"
$ rocm runtimes activate B      # ← re-select the one already in use
                                # rollback target: gone. `rocm runtimes rollback` now hard-errors.

Root cause. activate_runtime derived the rollback target from the runtime being left. When the requested runtime is already the active one there is nothing being left, so the derivation produced None — and that None was written over the recorded target rather than leaving it alone. Deriving from the current runtime is correct only when the user is actually switching.

Fix. When the requested runtime is already active, the registry pointers are left as they are. The guard that prevents a runtime being recorded as its own rollback target is preserved: in the branch that does record a new target, the current runtime differs from the requested one by construction, so the previous .filter() was redundant there.

Risk: low. One function, no API or schema change, no migration. The behaviour change is confined to the previously-destructive no-op path.

Changed user-facing output

On a re-activation of the already-active runtime, rocm runtimes activate now reports the preserved rollback target instead of <unset>, and consequently prints the rollback hint:

  changed_from_runtime_key: A        (was: <unset>)
  next step: if this causes problems, run `rocm runtimes rollback` …

The hint is now truthful — rollback genuinely is available. The changed_from_ label reads a little oddly for a command that changed nothing; it is reporting the rollback target on record. Happy to follow up with a dedicated "already in use" report for that path if reviewers prefer it, but that is a wording decision beyond this fix.

Test plan

runtime-lifecycle-08 pins the behaviour and fails before this change, passes after — verified both ways against a locally built binary. It plants read-only tarball runtimes in an isolated registry, so it needs no GPU, no Python and no download, and runs on the mock lane on every PR (measured ~21s against that job's 15-minute cap).

  • All 8 runtime_lifecycle scenarios pass against the built binary: 35 steps, 0 failures.
  • cargo test --workspace --all-targets, cargo clippy --workspace --all-targets -- -D warnings, cargo clippy -p e2e-cucumber --test e2e -- -D warnings, cargo fmt --all --check, and the feature_naming guard all pass.

Scope

Deliberately not included: a broader conformance check that walks every sequence of activate/rollback/uninstall and compares the listing against a model of the documented state machine. That is how this defect was found — the shortest sequence exposing it is three activations, which is why none of the seven existing scenarios covered it — but its per-run cost is still being weighed, so only the targeted regression lands here.

Fixes #486

…runtime

Activating the runtime already in use recomputed the rollback target from
the runtime being left. There is none in that case, so it cleared the
recorded one -- silently taking away the recovery path the previous
activation had just offered ("if this causes problems, run `rocm runtimes
rollback`"). Nothing the user could see had changed, so nothing signalled
that the undo was gone.

Deriving the target from the current runtime is right only when the user
is actually leaving one. When the requested runtime is already active the
activation is a no-op for the registry pointers, so the recorded target is
now preserved instead of overwritten. The guard that stopped a runtime
being recorded as its own rollback target is kept: in the branch that
records a new target, the current runtime differs from the requested one
by construction.

The shortest command sequence that exposes this is three activations in a
row, which is why none of the seven existing lifecycle scenarios caught
it -- every one- and two-command sequence conforms. Scenario
runtime-lifecycle-08 pins it: it fails before this change and passes
after, and needs no GPU or download, so it runs on the mock lane every PR.

Signed-off-by: Roman Inflianskas <Roman.Inflianskas@amd.com>
@rominf
rominf requested a review from a team as a code owner October 1, 2026 13:01
@rominf
rominf requested a review from juhovainio October 1, 2026 13:01

@juhovainio juhovainio left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Traced this through activate_runtime, rollback_runtime, and the uninstall path that clears previous_runtime_key. The fix is correct: the rollback target should only ever be re-derived from current when you're actually leaving it, and re-selecting the already-active runtime now leaves the recorded target alone instead of wiping it. I checked the case I was worried about — previous_runtime_key surviving a reselect while pointing at a runtime that's since been uninstalled — and confirmed the uninstall path already clears that field when it matches, so no inconsistent state is reachable through this change.

Test coverage is an e2e-cucumber scenario rather than a unit test, which is the right call here per AGENTS.md §3 ("a unit test asserting the internal helper does NOT discharge this"). The new scenario asserts registry state via rocm runtimes list, not activation wording, matching the PR's own checklist claim. PR body claims (no stale expectations.toml rows, scope) all check out against the repo as it stands.

This is a diff-only read — approving based on that, not a substitute for CI or your own pass.

@rominf
rominf added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit 3007dff Oct 2, 2026
37 of 38 checks passed
@rominf
rominf deleted the fix-runtimes-rollback-target branch October 2, 2026 12:54
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.

runtimes: re-selecting the runtime already in use silently discards the rollback target

2 participants