Skip to content

Add proxy and datasette autopull for latest tag#45

Merged
nezhar merged 2 commits into
mainfrom
proxy-latest
Mar 15, 2026
Merged

Add proxy and datasette autopull for latest tag#45
nezhar merged 2 commits into
mainfrom
proxy-latest

Conversation

@nezhar
Copy link
Copy Markdown
Collaborator

@nezhar nezhar commented Mar 15, 2026

Eensures that Docker images tagged as latest are checked for updates before container startup for proxy and datasette

Summary by CodeRabbit

  • New Features

    • Added --paste-images flag to enable direct image pasting into applications via X11 support.
  • Bug Fixes

    • Image updates now execute conditionally only when using the latest tag, preventing unnecessary updates on pinned versions.
  • Tests

    • Added comprehensive test coverage for paste-images functionality and X11 environment handling.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 15, 2026

📝 Walkthrough

Walkthrough

The changes introduce conditional image update checks using a new _is_latest_tag() helper across multiple commands (logs, proxy, run) to skip unnecessary updates unless the image tag is latest. Additionally, X11 paste-image support is added to the run command via a new --paste-images flag with corresponding helper logic and comprehensive test coverage.

Changes

Cohort / File(s) Summary
Core image tag detection
src/vibepod/core/docker.py
New private helper _is_latest_tag() that returns true if image specifies latest tag explicitly or by omission (no tag).
Conditional image updates
src/vibepod/commands/logs.py, src/vibepod/commands/proxy.py
Added conditional image pull logic guarded by _is_latest_tag() checks; update/restart operations now only execute for latest-tagged images.
Run command paste-images feature
src/vibepod/commands/run.py
Added --paste-images flag and _x11_volumes_and_env() helper to enable X11 paste-image support; reads DISPLAY env var and conditionally mounts X11 socket; includes conditional proxy image pull guarded by tag check.
Feature tests
tests/test_run.py
Comprehensive test suite for X11 volumes, DISPLAY environment handling, and paste-images flag behavior with various configurations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through Docker streams,
With latest tags and paste-image dreams,
X11 sockets now in place,
Conditional pulls speed up the race!
No needless pulls when tags are new—
Just wisdom in what update won't do. 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective: adding automatic pull/update behavior for proxy and datasette services when using the latest tag.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch proxy-latest
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Mar 15, 2026

Greptile Summary

This PR introduces two features: (1) automatic update checks for Docker images tagged latest before starting the proxy and datasette containers, and (2) a new --paste-images flag on the run command that forwards the host's X11 socket into the agent container for clipboard-based image pasting.

Key changes:

  • A new _is_latest_tag(image) helper in docker.py gates auto-pull to only latest-tagged images, avoiding unnecessary network calls for pinned versions.
  • logs.py (datasette) correctly handles the update: it checks the return value of pull_if_newer and explicitly removes the stale container before re-creating it.
  • proxy.py and run.py call pull_if_newer but discard the return value, meaning a newly-pulled image will never be applied to an already-running proxy container — ensure_proxy returns the existing running container unchanged.
  • run.py also omits the user-facing info log when checking for proxy updates, making the behavior inconsistent with proxy.py and logs.py.
  • The --paste-images feature and its supporting _x11_volumes_and_env helper are well-implemented and well-tested.

Confidence Score: 2/5

  • Not safe to merge as-is — the proxy auto-pull silently has no effect on already-running containers in both proxy.py and run.py.
  • The core goal of the PR (auto-pull latest images) is partially broken: the datasette path in logs.py works correctly, but the proxy path in both proxy.py and run.py discards the pull_if_newer return value and never restarts the running proxy with the newer image. This is a logic bug that silently defeats the main purpose of the feature. The --paste-images feature is solid and well-tested.
  • src/vibepod/commands/proxy.py and src/vibepod/commands/run.py both need the same fix: check the return value of pull_if_newer and remove the stale proxy container before calling ensure_proxy, mirroring the pattern already used in logs.py.

Important Files Changed

Filename Overview
src/vibepod/core/docker.py Adds _is_latest_tag helper to detect images using the latest tag. Logic is correct but the function is named with a private prefix despite being imported by multiple public modules.
src/vibepod/commands/proxy.py Adds latest-tag auto-pull before proxy startup, but discards the pull_if_newer return value, meaning a newly-pulled image won't be applied to an already-running proxy container.
src/vibepod/commands/run.py Adds --paste-images flag with X11 forwarding (well-tested) and proxy latest-tag auto-pull, but both the return value of pull_if_newer is discarded and the user-facing info log is missing, so proxy updates silently have no effect on running containers.
src/vibepod/commands/logs.py Wraps existing datasette pull-if-newer logic with an _is_latest_tag guard — correctly checks the return value and removes the stale container before restarting.
tests/test_run.py Adds solid unit tests for _x11_volumes_and_env and the --paste-images CLI flag, covering DISPLAY set, unset, and default-off cases. No tests for proxy auto-pull behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Start proxy/run/logs command] --> B{_is_latest_tag?}
    B -- No --> E[Skip pull]
    B -- Yes --> C[pull_if_newer]
    C --> D{Image updated?}

    D -- "logs.py ✅" --> F[Remove existing datasette container]
    F --> G[ensure_datasette creates fresh container]

    D -- "proxy.py / run.py ❌\nreturn value discarded" --> H[ensure_proxy called]
    H --> I{Proxy already running?}
    I -- Yes --> J[Return existing container\nNEW IMAGE IGNORED]
    I -- No --> K[Start new proxy container]

    E --> H
Loading

Last reviewed commit: 92243c3

Comment on lines +45 to +47
if _is_latest_tag(proxy_image):
info("Checking for proxy image updates…")
manager.pull_if_newer(proxy_image)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Proxy update not applied to running container

pull_if_newer returns True when a newer image was downloaded, but the result is discarded here. As a result, if the proxy container is already running, ensure_proxy will find it with status == "running" and return immediately without restarting it with the new image — so the update never takes effect.

Compare this with how logs.py handles the datasette update (lines 63–70): it checks the return value of pull_if_newer, and if an update was found, it explicitly removes the existing container before calling ensure_datasette, which then creates a fresh one.

The fix is to apply the same pattern:

if _is_latest_tag(proxy_image):
    info("Checking for proxy image updates…")
    updated = manager.pull_if_newer(proxy_image)
    if updated:
        info("New image available — restarting proxy")
        existing = manager.find_proxy()
        if existing:
            existing.remove(force=True)

Comment on lines +326 to +327
if _is_latest_tag(proxy_image):
manager.pull_if_newer(proxy_image)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Proxy image update silently ignored for running containers

Same issue as in proxy.py: the return value of pull_if_newer is discarded. If the proxy container is already running (e.g., started by a prior vp proxy start or a previous vp run), ensure_proxy returns the existing container unchanged, and the freshly-pulled image is never used.

There's also no informational log here telling the user that an update check is happening, unlike the equivalent code in proxy.py and logs.py.

if _is_latest_tag(proxy_image):
    info("Checking for proxy image updates…")
    updated = manager.pull_if_newer(proxy_image)
    if updated:
        info("New proxy image available — restarting proxy")
        existing = manager.find_proxy()
        if existing:
            existing.remove(force=True)

Comment on lines +44 to +47
def _is_latest_tag(image: str) -> bool:
"""Return True when *image* uses the ``latest`` tag (explicitly or by omission)."""
name = image.split("/")[-1]
return ":" not in name or name.endswith(":latest")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Private-named helper imported across public modules

_is_latest_tag uses the single-underscore convention to signal a private/internal symbol, but it is now imported and used in three separate command modules (logs.py, proxy.py, and run.py). Consider renaming it to is_latest_tag (without the leading underscore) to reflect that it is intentionally part of the module's public surface.

Suggested change
def _is_latest_tag(image: str) -> bool:
"""Return True when *image* uses the ``latest`` tag (explicitly or by omission)."""
name = image.split("/")[-1]
return ":" not in name or name.endswith(":latest")
def is_latest_tag(image: str) -> bool:
"""Return True when *image* uses the ``latest`` tag (explicitly or by omission)."""
name = image.split("/")[-1]
return ":" not in name or name.endswith(":latest")

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
src/vibepod/commands/run.py (2)

26-26: Consider making _is_latest_tag a public helper.

The function _is_latest_tag is imported across multiple modules (run.py, proxy.py, logs.py), but its leading underscore conventionally marks it as private. Consider renaming it to is_latest_tag to reflect its cross-module usage.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/vibepod/commands/run.py` at line 26, The helper function _is_latest_tag
is used across modules but named as private; rename the function to
is_latest_tag in its defining module and update all imports/usages (e.g., in
run.py, proxy.py, logs.py) to import is_latest_tag instead of _is_latest_tag;
ensure the function signature and behavior remain unchanged and run
tests/linters to catch any remaining references to _is_latest_tag.

326-327: Consider adding an info message for consistency.

In proxy.py, the update check logs "Checking for proxy image updates…" before calling pull_if_newer. Here it's silent. For consistency and user visibility, consider adding a similar info message.

♻️ Proposed fix
         if _is_latest_tag(proxy_image):
+            info("Checking for proxy image updates…")
             manager.pull_if_newer(proxy_image)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/vibepod/commands/run.py` around lines 326 - 327, Add a user-visible info
log before attempting to pull the proxy image for consistency: inside the if
block that checks _is_latest_tag(proxy_image) in run.py, call the same
logger/info used in proxy.py (e.g., processLogger.info or the module's logger)
with "Checking for proxy image updates…" prior to invoking
manager.pull_if_newer(proxy_image) so the update check is logged the same way as
in proxy.py.
tests/test_run.py (1)

174-178: Consider adding unit tests for _is_latest_tag.

The new _is_latest_tag helper in docker.py is used across multiple commands but lacks dedicated unit tests. Consider adding tests to cover edge cases like registry URLs with ports (e.g., registry.example.com:5000/image:latest), images without tags, and explicit non-latest tags.

Do you want me to generate unit tests for _is_latest_tag or open an issue to track this?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_run.py` around lines 174 - 178, Add unit tests for the helper
function _is_latest_tag to cover missing and tricky tag parsing cases: create
tests that call docker._is_latest_tag for (1) an image with explicit :latest
(e.g., "repo/image:latest"), (2) an image with a registry including a port and
:latest (e.g., "registry.example.com:5000/image:latest"), (3) an image with no
tag (e.g., "repo/image") and assert the expected behavior, (4) an image with an
explicit non-latest tag (e.g., "repo/image:1.2.3") and (optionally) (5) an image
referenced by digest (e.g., "repo/image@sha256:..."); assert True for latest
cases and False for non-latest cases, using the _is_latest_tag function name to
locate the code under test. Ensure tests are added to the test suite and use
clear descriptive test names for each edge case.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/vibepod/commands/run.py`:
- Line 26: The helper function _is_latest_tag is used across modules but named
as private; rename the function to is_latest_tag in its defining module and
update all imports/usages (e.g., in run.py, proxy.py, logs.py) to import
is_latest_tag instead of _is_latest_tag; ensure the function signature and
behavior remain unchanged and run tests/linters to catch any remaining
references to _is_latest_tag.
- Around line 326-327: Add a user-visible info log before attempting to pull the
proxy image for consistency: inside the if block that checks
_is_latest_tag(proxy_image) in run.py, call the same logger/info used in
proxy.py (e.g., processLogger.info or the module's logger) with "Checking for
proxy image updates…" prior to invoking manager.pull_if_newer(proxy_image) so
the update check is logged the same way as in proxy.py.

In `@tests/test_run.py`:
- Around line 174-178: Add unit tests for the helper function _is_latest_tag to
cover missing and tricky tag parsing cases: create tests that call
docker._is_latest_tag for (1) an image with explicit :latest (e.g.,
"repo/image:latest"), (2) an image with a registry including a port and :latest
(e.g., "registry.example.com:5000/image:latest"), (3) an image with no tag
(e.g., "repo/image") and assert the expected behavior, (4) an image with an
explicit non-latest tag (e.g., "repo/image:1.2.3") and (optionally) (5) an image
referenced by digest (e.g., "repo/image@sha256:..."); assert True for latest
cases and False for non-latest cases, using the _is_latest_tag function name to
locate the code under test. Ensure tests are added to the test suite and use
clear descriptive test names for each edge case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 91959aa5-196a-4cd9-aa58-3334e38e27ff

📥 Commits

Reviewing files that changed from the base of the PR and between 1e8039a and 92243c3.

📒 Files selected for processing (5)
  • src/vibepod/commands/logs.py
  • src/vibepod/commands/proxy.py
  • src/vibepod/commands/run.py
  • src/vibepod/core/docker.py
  • tests/test_run.py

@nezhar nezhar merged commit bb6e938 into main Mar 15, 2026
20 checks passed
@nezhar nezhar deleted the proxy-latest branch March 20, 2026 13:54
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.

1 participant