Skip to content

chore(cli): clean up old container images and stale binaries after update #581

@Aureliolo

Description

@Aureliolo

Summary

synthorg update pulls new container images but never removes old ones. Over multiple updates, stale images accumulate and waste disk space -- especially since images are digest-pinned (each version is a distinct layer set). Additionally, on Windows the old CLI binary is renamed to .old.*.tmp before replacement but cleanup relies on os.Remove in the same process; if the re-exec happens before that remove, or if the remove fails silently, stale .old.*.tmp files may persist.

Scope

1. Container image cleanup (uninstall)

PR #590 adds image cleanup to synthorg uninstall:

  • Lists ghcr.io/aureliolo/synthorg-* images with sizes
  • Prompts user for confirmation
  • Removes via docker rmi --force by image ID

2. Windows binary auto-deletion (uninstall)

PR #590 replaces the manual PowerShell instruction with automatic cleanup:

  • Writes a temp .bat file that polls tasklist until the CLI PID exits
  • Deletes the binary, empty parent dirs, and the .bat itself
  • Falls back to manual PowerShell instruction if spawn fails

3. Container image cleanup (update) -- REMAINING

After pullAndPersist succeeds and before restartIfRunning, offer to prune the previous version's images:

  • Track the previous image tag/digests (from state.ImageTag / state.VerifiedDigests before update)
  • After successful pull + persist, remove the old images (docker rmi the previous digest-pinned refs)
  • Prompt user for confirmation in interactive mode; auto-accept in non-interactive
  • Optionally run docker image prune --filter dangling=true to clean up any orphaned layers
  • Report disk space reclaimed

4. Windows stale .old.*.tmp cleanup on next invocation -- REMAINING

The selfupdate.ReplaceAt function on Windows:

  1. Creates a .old.*.tmp temp file
  2. Renames the current binary to that temp path
  3. Renames the new binary into place
  4. Calls os.Remove(oldPath) -- best-effort

Remaining work:

  • On next synthorg invocation, scan the binary's directory for *.old.*.tmp files and remove them
  • Add a test that verifies no stale .old.*.tmp files remain after a simulated update cycle

Acceptance Criteria

Context

Discovered during PR #576 (CLI update compose refresh). The update flow was audited and this gap identified.

Metadata

Metadata

Assignees

No one assigned

    Labels

    prio:mediumShould do, but not blockingscope:smallLess than 1 day of workspec:toolsDESIGN_SPEC Section 11 - Tool & Capability Systemtype:choreMaintenance, cleanup, dependency updates

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions