Upgrade dry-run reports would-switch before candidate validation
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19
- Forks
- 18
- Avg merge
- 16h 43m
- Merged PRs (30d)
- 118
Description
Summary
ocm upgrade --dry-run can report would-switch even when the equivalent real upgrade will fail during candidate preparation.
The dry-run returns before OCM stages or validates the target runtime, so it does not exercise the managed Codex candidate check or other candidate-specific compatibility checks.
Reproduction
With OCM 0.2.34, an environment bound to OpenClaw 2026.7.1, and target version 2026.8.1:
ocm upgrade <env> --version 2026.8.1 --dry-run --json
returns:
{
"outcome": "would-switch",
"runtimeReleaseVersion": "2026.8.1",
"runtimeReleaseChannel": "stable",
"note": "dry run: no runtime, env, service, or snapshot changed"
}
Running the equivalent real upgrade immediately afterward fails before cutover:
ocm upgrade <env> --version 2026.8.1 --json
upgrade preparation failed before cutover
candidate managed Codex preflight failed
No environment state changed, but the successful dry-run did not predict the real preparation failure.
Root Cause
The runtime-bound upgrade path returns its dry-run result before calling prepare_isolated_upgrade_target():
- Dry-run return:
src/cli/upgrade.rs:2236 - Candidate preparation and validation:
src/cli/upgrade.rs:2270
The existing dry-run test verifies only that no persistent state changes:
tests/upgrade_command_tests.rs:2500
It does not verify parity with candidate preparation failures.
Expected Behavior
A dry-run should execute every non-persistent check required before cutover, including candidate runtime preparation and validation.
For official release targets, OCM should:
- Prepare the candidate in disposable staging.
- Run the same candidate validation used by the real upgrade.
- Remove all temporary staging afterward.
- Leave the runtime registry, environment, service, snapshots, and upgrade history unchanged.
- Report a failed or would-fail outcome when candidate validation fails.
- Report
would-switchorwould-updateonly after candidate validation succeeds.
If a candidate check cannot be executed during dry-run, the result must explicitly identify it as not run rather than reporting an unconditional would-switch.
This should use the corrected config-migration ordering tracked in #107 so expected target migrations do not create another dry-run false failure.
Regression Coverage
Add dry-run coverage that verifies:
- a forced candidate validation failure is reported by dry-run;
- the same failure is reported by the real upgrade;
- a valid candidate still reports
would-switch; - temporary candidate staging is removed;
- no runtime is published;
- environment config and binding remain byte-identical;
- service desired/running state is unchanged;
- no snapshot or upgrade-history transaction is created;
- batch dry-run uses the same candidate-validation behavior.
Impact
Operators and automation can receive a successful dry-run, proceed with an upgrade, and then encounter a preparation failure that the dry-run could have detected.
The current output overstates readiness because it validates release resolution and service planning, not the actual candidate runtime.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/cli/upgrade.rs around the dry-run return at line 2236 and candidate preparation at line 2270, then read the existing coverage in tests/upgrade_command_tests.rs around line 2500. Run the upgrade tests and compare dry-run with real-upgrade candidate failures. Done means dry-run reports candidate failures, preserves all listed state, cleans staging, and covers valid, batch, and failure cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100