Skip to content

Add ESC to abort image pull with fall-back to local#341

Merged
gtsiolis merged 4 commits into
mainfrom
pro-324-esc-to-abort-image-pull-with-fall-back-to-local-b20c
Jul 1, 2026
Merged

Add ESC to abort image pull with fall-back to local#341
gtsiolis merged 4 commits into
mainfrom
pro-324-esc-to-abort-image-pull-with-fall-back-to-local-b20c

Conversation

@gtsiolis

@gtsiolis gtsiolis commented Jun 25, 2026

Copy link
Copy Markdown
Member

Makes a floating-tag (latest/empty) image pull interruptible and resilient, so a slow pull no longer blocks the whole start with no way out. Implements PRO-324; builds on PRO-323 (ImageExists). Idea: @carole-lavillonniere .

Behavior

  • ESC to bail. When a newer version is downloading, a local copy exists, and we're interactive, the spinner shows Pulling new version… (press esc to keep current version). ESC cancels only the pull and starts on the local image; Ctrl+C / q still quit.
  • Auto offline fall-back. A pull that fails with a local copy present falls back to it (any mode): Could not pull <image> (<err>); using the local image.
  • Still fatal otherwise. Pull fails + no local copy → ErrorEvent + silent error + telemetry, as before.

The hint only arms once Docker reports real layer download, never on a cache hit.

How it works

pullImages checks ImageExists and delegates each pull to a new pullImage, which runs under a per-pull cancel context and selects on the pull result or a buffered skip channel. The domain stays UI-free: it emits output.PullSkippableEvent with a cancel channel it owns; the TUI binds ESC to signal it during the pulling phase. Gated on localExists && interactive.

Tests

start_test.go (skip/use-local, fall-back, fatal, non-interactive, cancel-propagates) · docker_test.go (progress closes on immediate pull error) · app_test.go (ESC signals skip, inert otherwise) · plain_sink_test.go (event suppressed). PTY coverage skipped — both triggers are timing/registry-dependent and are covered by the deterministic unit/UI tests.

Pulling a new version... Using existing version... ESC
Screenshot 2026-06-29 at 18 23 25 Screenshot 2026-06-29 at 18 23 28

@gtsiolis gtsiolis self-assigned this Jun 25, 2026
@gtsiolis gtsiolis added semver: patch docs: needed Pull request requires documentation updates labels Jun 25, 2026
@gtsiolis gtsiolis force-pushed the pro-324-esc-to-abort-image-pull-with-fall-back-to-local-b20c branch 3 times, most recently from 8c36b88 to 2919f92 Compare June 29, 2026 15:44
@gtsiolis

Copy link
Copy Markdown
Member Author

@carole-lavillonniere I've added you as reviewer since you originally proposed this[1]! 😁

@gtsiolis gtsiolis marked this pull request as ready for review June 29, 2026 15:47
@gtsiolis gtsiolis requested a review from a team as a code owner June 29, 2026 15:47
@gtsiolis gtsiolis force-pushed the pro-324-esc-to-abort-image-pull-with-fall-back-to-local-b20c branch from 2919f92 to ef3a7bb Compare June 30, 2026 09:17
gtsiolis and others added 2 commits July 1, 2026 07:03
During a floating-tag pull, if a local copy of the image is already present
and we're interactive, show "press esc to keep current version" once real
layer download begins. Pressing ESC cancels only the in-flight pull (Ctrl+C
still quits) and starts the emulator with the existing local image. A failed
pull (e.g. offline) with a local copy present now falls back automatically
instead of aborting the start.

The domain stays UI-free: pullImage runs the pull under a per-pull cancel
context and selects on a skip channel the TUI signals via the new
PullSkippableEvent.

Generated with [Linear](https://linear.app/localstack/issue/PRO-324/esc-to-abort-image-pull-with-fall-back-to-local#agent-session-ee6a32f4)

Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com>
Two correctness fixes in the ESC-to-abort-pull flow (PRO-324):

1. Deadlock on an immediate pull error. DockerRuntime.PullImage returned
   the error from client.ImagePull before registering `defer close(progress)`,
   so the progress channel was never closed on that path. pullImage now waits
   on the progress goroutine to drain (`<-progressDone`), turning that prior
   goroutine leak into a hang of the whole start flow — exactly in the
   offline/unreachable-registry scenario this feature targets. Close progress
   unconditionally so callers can never hang. Regression test points a
   DockerRuntime at an unreachable socket and asserts progress is closed.

2. Ctrl+C during a pull was conflated with a pull failure. A cancelled parent
   context surfaced as a pull error and, when a local image existed, was
   swallowed by the local-image fall-back (returning success), so the start
   continued on an already-cancelled context instead of aborting. Propagate
   context.Canceled before the fall-back. Regression test cancels the parent
   context mid-pull and asserts the cancellation propagates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gtsiolis gtsiolis force-pushed the pro-324-esc-to-abort-image-pull-with-fall-back-to-local-b20c branch from ef3a7bb to a7a39d0 Compare July 1, 2026 07:04

@carole-lavillonniere carole-lavillonniere 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.

Nice! 🌟

Comment thread internal/ui/app.go Outdated

// pullSkipHint replaces the "Pulling <image>" spinner text once a skippable pull
// starts downloading, telling the user they can bail out to the local image.
const pullSkipHint = "Pulling new version… (press esc to keep current version)"

@anisaoshafi anisaoshafi Jul 1, 2026

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.

tiny nit: probably uppercase ESC is more user friendly and stands out? Screenshot 2026-06-29 at 18 23 25

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We don't have a strong consistency around this yet, but sounds good.

@linear can you make the change?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

On it. I’m updating that copy now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Done — the copy now uses uppercase ESC, and the matching test was updated too. The UI tests passed and the change is pushed.

Address review feedback: uppercase ESC stands out better in the spinner text.

Generated with [Linear](https://linear.app/localstack/issue/PRO-324/esc-to-abort-image-pull-with-fall-back-to-local#agent-session-ee6a32f4)

Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com>
@gtsiolis

gtsiolis commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

Thanks, both! Merging... 🌮 🌮 🌮

@gtsiolis gtsiolis merged commit 5c1fc80 into main Jul 1, 2026
13 checks passed
@gtsiolis gtsiolis deleted the pro-324-esc-to-abort-image-pull-with-fall-back-to-local-b20c branch July 1, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs: needed Pull request requires documentation updates semver: patch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants