Skip to content

Stop burying JSON output, and use the image already present when a pull fails - #36

Open
lefoulkrod wants to merge 2 commits into
mainfrom
claude/electron-app-assessment-3am8hs
Open

lefoulkrod wants to merge 2 commits into
mainfrom
claude/electron-app-assessment-3am8hs

Conversation

@lefoulkrod

Copy link
Copy Markdown
Contributor

Two defects found while driving --json from another program.

What changed

Command output was buried under a usage dump. SilenceUsage was never set, so cobra printed the whole usage block after any command that returned an error from RunE. Under --json that put a wall of prose on stderr behind a single line of JSON.

It fired on ordinary use rather than only on failure: status --json exits non-zero whenever Omnideck is not running, so checking a stopped installation produced a full usage dump every time.

Errors now print from Execute, which also lets errAborted — the sentinel that carries no message — exit quietly instead of leaving a bare Error: behind the output the caller asked for. Unknown flags and human-facing failures still explain themselves:

$ omnideck status --json --name desktop     # stopped
exit 1, stderr empty
$ omnideck status                           # nothing installed
Error: Omnideck is not set up.
Run: omnideck setup
$ omnideck status --nope
Error: unknown flag: --nope

Creating an instance always pulled, and a failed pull ended setup even when the image was already here. That makes two ordinary things impossible: setting Omnideck up again without a network, and repairing an installation whose container is gone but whose image never went anywhere.

A failed pull is now only fatal when the image is genuinely absent. When it is present the step reports Using the copy already on this computer and carries on — an image named by digest cannot have changed since it was fetched, and one named by tag is no worse off than it was a moment ago.

This adds ImageExists to the engine interface. Podman answers through image exists' exit status; Docker has no such command, so an inspect stands in.

How it was tested

  • go test ./..., go vet ./..., gofmt — all clean
  • Two new tests in workflow: the local image is used when the registry is unreachable, and an unreachable registry still fails with full cleanup when nothing is present
  • Exercised by hand against real Podman 4.9.3 on Linux: a full setupstatusstopstart cycle driven non-interactively through --json, with the registry blocked, which is the case the second fix exists for. Before it, setup failed at pull_image with exit status 125 despite the image being present.
  • Verified the three output paths above, including that human errors and flag errors still print

Not exercised on macOS or Windows. The Docker adapter change is symmetrical with the Podman one and covered by the existing cross-platform argument tests, but the docker image inspect path has not been run against a real Docker daemon.

Release and security check

  • I considered whether this changes permissions, downloaded software, executed commands, dependencies, configuration files, or release artifacts.
  • New or updated dependencies are necessary and come from their expected upstream project.
  • User-facing documentation and tests were updated where needed.

Both changes affect executed commands. The first alters only what is printed. The second adds one read-only command per engine (podman image exists / docker image inspect) and changes when a pull failure is fatal — it never skips a pull, so an image is still fetched whenever it can be. No dependencies added.

One consequence worth naming: a tag that has moved will not be re-fetched if the pull itself fails, so a repair in that state reuses the older local image rather than failing. That seemed better than refusing to repair at all, but it is a behaviour change.

Related

Filed separately while reviewing this surface: #28 (web port binds every interface), #29 (JSON_MODE_SPEC.md is referenced but absent), #30 (status exit codes), #31 (container differs from the desktop's), #32 (remove argument style), #33 (no machine-readable version), #34 (errAborted shape), #35 (ImageDigest conflates two states).


Generated by Claude Code

claude added 2 commits August 2, 2026 00:53
A failing command has already said what went wrong, in the shape the
caller asked for. Cobra then printed the entire usage block after it,
which under --json put a wall of prose on stderr behind a single line of
JSON — and status --json exits non-zero whenever Omnideck is not
running, so that happened on an ordinary check of a stopped
installation, not only on failure.

Errors are now printed by Execute, which also lets the one error that
carries no message exit quietly instead of leaving a bare "Error:"
behind the output the caller asked for. Unknown flags and human-facing
failures still explain themselves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UuoUM7Fu1upEAJFsC3Ps1b
Creating an instance always pulled, and a pull that failed ended setup
even when the image it wanted was already on the machine. That makes
two ordinary things impossible: setting Omnideck up again without a
network, and repairing an installation whose container is gone but whose
image never went anywhere.

A failed pull is now only fatal when the image is genuinely absent. When
it is here, the step says so and carries on — an image named by digest
cannot have changed since it was fetched, and one named by tag is no
worse off than it was a moment ago.

Both engines gain a presence check for this. Podman reports it through
an exit status; Docker has no such command, so an inspect stands in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UuoUM7Fu1upEAJFsC3Ps1b
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