Skip to content

feat(update): add --dry-run flag showing version, images, and .env diff without applying#411

Merged
Lightheartdevs merged 4 commits intoLight-Heart-Labs:mainfrom
buddy0323:feat/update-dry-run
Mar 24, 2026
Merged

feat(update): add --dry-run flag showing version, images, and .env diff without applying#411
Lightheartdevs merged 4 commits intoLight-Heart-Labs:mainfrom
buddy0323:feat/update-dry-run

Conversation

@buddy0323
Copy link
Contributor

Summary

  • dream update --dry-run (alias -n) previews what an update would change without pulling images or restarting any containers
  • New GET /api/update/dry-run endpoint in routers/updates.py returns version comparison, configured image tags, and update-relevant .env keys as structured JSON
  • CLI output is divided into four sections: Version (installed vs. latest, changelog URL), Image tags (what docker compose pull would fetch), Model configuration (TIER, LLM_MODEL, GGUF_FILE, CTX_SIZE, GPU_BACKEND, N_GPU_LAYERS), and .env keys the update path reads/writes
  • Dashboard API is queried first to avoid a duplicate GitHub call; GitHub releases API is used as a direct fallback when the API is unreachable
  • cmd_update() dispatcher now passes "$@" so all flags reach the function

Files changed

  • routers/updates.py — added GET /api/update/dry-run endpoint and _UPDATE_ENV_KEYS constant
  • dream-cli — added cmd_dry_run(), wired --dry-run/-n into cmd_update(), fixed dispatcher arg forwarding, added help example

Test plan

  • dream update --dry-run on an up-to-date install → shows "up to date", lists current images and .env keys, exits 0
  • dream update --dry-run when a newer GitHub release exists → shows "update available" with version diff and changelog URL
  • dream update -n (short flag) works identically
  • dream update (no flag) still performs the real update unchanged
  • GET /api/update/dry-run via dashboard API returns dry_run: true, correct current_version, images list, and env_keys
  • With dashboard API unreachable, CLI falls back to GitHub API and local compose parsing without error
  • No containers are started, stopped, or re-created during dry run (verify with docker events)

Copy link
Collaborator

@Lightheartdevs Lightheartdevs left a comment

Choose a reason for hiding this comment

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

Review: Needs Work

The dry-run concept is solid but there are a couple bugs:

1. --force flag silently removed (breaking change)

The new argument parsing in cmd_update() replaces the old case block and drops --force|-f handling entirely. Unrecognized flags are now silently ignored via *) shift. Users relying on dream update --force will get no error — it'll just be ignored. Please restore the --force flag alongside --dry-run.

2. Bash subshell variable scoping bug

images_shown is set to false, then updated to "true" inside a pipe (| while read ...). Due to bash subshell scoping, the update never propagates to the parent shell. The fallback image display will always run regardless. Fix: use a process substitution or temp file instead of a pipe.

3. Ruff lint failure

CI shows a Python lint failure — likely the str | None union syntax which requires Python 3.10+. Use Optional[str] for broader compatibility.

What's good

  • The cmd_dry_run() function is strictly read-only — verified no writes anywhere
  • Good coverage: version, images, model config, .env keys
  • API endpoint properly auth-gated

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

@buddy0323
Copy link
Contributor Author

Thanks for the detailed review — addressed all three items:

  1. --force / -f — Restored in cmd_update() alongside --dry-run|-n, with force_flag passed through to _check_version_compat again. Replaced the silent *) shift with explicit errors for unknown flags or stray arguments so nothing is dropped quietly.

  2. images_shown / pipe subshell — Replaced the | while read pattern with process substitution (while read … done < <(…)) and only set images_shown when we actually print at least one image line, so the compose fallback message is correct.

  3. Ruff / Python typing — Swapped str | None for Optional[str] (with from typing import Optional) in updates.py for broader compatibility.

Pushed in the latest commit; let me know if you want anything else tightened before re-review.

@Lightheartdevs Lightheartdevs merged commit 93b4f4f into Light-Heart-Labs:main Mar 24, 2026
14 of 21 checks passed
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.

2 participants