Skip to content

Added a new CI job that validates all built-in default images exist#40

Merged
nezhar merged 1 commit into
mainfrom
images-ci-task
Mar 12, 2026
Merged

Added a new CI job that validates all built-in default images exist#40
nezhar merged 1 commit into
mainfrom
images-ci-task

Conversation

@nezhar

@nezhar nezhar commented Mar 12, 2026

Copy link
Copy Markdown
Collaborator

This pull request introduces a new CI job to validate that the built-in default container images are available in their respective registries. It adds a Python script to perform the validation and integrates it into the GitHub Actions workflow.

CI workflow enhancements:

  • Added a new default-images job to .github/workflows/ci.yml that checks out the repository, sets up Python, installs dependencies, and runs the image validation script.

Image validation tooling:

  • Introduced scripts/check_default_images.py, a script that verifies the existence of default container images by inspecting their manifests via Docker. It ensures canonical defaults by clearing relevant environment variables and reports any missing images.

Summary by CodeRabbit

  • New Features

    • Added a CI job that validates default container images are resolvable in registries before merge.
  • Chores

    • Added a validation script used by CI to check image availability, surface per-image errors, and fail the run on missing images.
    • Made default image configuration environment-aware so runtime overrides are respected and validations reflect actual values.

@coderabbitai

coderabbitai Bot commented Mar 12, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds a new CI job "default-images" that runs a Python script to validate built-in default container images via the docker CLI; also refactors default-image constants to be produced by a function that respects environment overrides.

Changes

Cohort / File(s) Summary
CI Workflow
\.github/workflows/ci.yml
Added default-images job to CI: checks out repo, sets up Python 3.12, installs deps (including dev extras), and runs scripts/check_default_images.py.
Image Validation Script
scripts/check_default_images.py
New script that unsets image override env vars, verifies presence of docker CLI, runs docker manifest inspect (with timeout) for each default image, logs per-image status, aggregates failures, and exits non‑zero on any missing/unresolvable image.
Default images / constants
src/vibepod/constants.py
Replaced static DEFAULT_IMAGES dict with get_default_images() and added IMAGE_OVERRIDE_ENV_KEYS; DEFAULT_IMAGES is now initialized by calling that function (behavior preserved but computed at runtime).

Sequence Diagram(s)

sequenceDiagram
  participant GH as "GitHub Actions"
  participant Runner as "CI Runner"
  participant Script as "check_default_images.py"
  participant Docker as "docker CLI"
  participant Registry as "Image Registry"

  GH->>Runner: start "default-images" job
  Runner->>Runner: setup Python 3.12, install deps
  Runner->>Script: run script
  Script->>Docker: docker manifest inspect <image> (per image)
  Docker->>Registry: fetch manifest
  Registry-->>Docker: manifest / error
  Docker-->>Script: success / error
  Script-->>Runner: aggregate results, exit code
  Runner-->>GH: job success/failure
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through CI at dawn's first light,

I nudged the env and checked each sight,
I asked docker kindly, one-by-one,
fetched manifests till the job was done,
a crunchy carrot for a job run right. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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 describes the main change: adding a CI job to validate that built-in default images exist, which is exactly what the PR accomplishes across the three modified files.

✏️ 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 images-ci-task
📝 Coding Plan
  • Generate coding plan for human review comments

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

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
scripts/check_default_images.py (1)

12-26: Avoid duplicating the image override key list here.

This becomes a second source of truth next to src/vibepod/constants.py. If a new image override is added there and not here, this script can end up validating an overridden image instead of the built-in default.

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

In `@scripts/check_default_images.py` around lines 12 - 26, The list of image
override env keys is duplicated in _unset_image_env_overrides; instead of
hardcoding the tuple, import and reuse the canonical list from
src.vibepod.constants (e.g. IMAGE_OVERRIDE_ENV_KEYS) and iterate over that
constant inside the _unset_image_env_overrides function so the script stays in
sync with the single source of truth in constants.py.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/check_default_images.py`:
- Around line 29-39: The `_check_image_exists` function currently calls
`subprocess.run(["docker", "manifest", "inspect", image], ...)` without a
timeout and can hang; add a reasonable timeout argument to the `subprocess.run`
call and handle `subprocess.TimeoutExpired` by returning (False, "<timeout
message>") so CI fails fast. Update `_check_image_exists` to pass e.g.
`timeout=<n_seconds>` to `subprocess.run`, and wrap the call in a try/except
catching `subprocess.TimeoutExpired` to produce a clear error string (and also
preserve the existing stderr/stdout/error fallback handling for non-zero return
codes).

---

Nitpick comments:
In `@scripts/check_default_images.py`:
- Around line 12-26: The list of image override env keys is duplicated in
_unset_image_env_overrides; instead of hardcoding the tuple, import and reuse
the canonical list from src.vibepod.constants (e.g. IMAGE_OVERRIDE_ENV_KEYS) and
iterate over that constant inside the _unset_image_env_overrides function so the
script stays in sync with the single source of truth in constants.py.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9386114f-22e9-4a60-9f0a-ff7231e7ab51

📥 Commits

Reviewing files that changed from the base of the PR and between e1ca81c and 07e1070.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • scripts/check_default_images.py

Comment thread scripts/check_default_images.py

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
scripts/check_default_images.py (1)

48-51: Move environment override cleanup before importing from vibepod.constants.

The from vibepod.constants import ... statement on line 48 triggers module initialization, which eagerly sets DEFAULT_IMAGES = get_default_images() at module scope. Since this occurs before _unset_image_env_overrides() clears the VP_IMAGE_* variables on line 50, any pre-set overrides are captured in the module-level DEFAULT_IMAGES dictionary. This leaves the module state inconsistent with the canonical defaults this script intends to validate.

Reorder the code to clear environment overrides before the import statement.

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

In `@scripts/check_default_images.py` around lines 48 - 51, Call
_unset_image_env_overrides to clear VP_IMAGE_* before vibepod.constants is
imported: move the env-cleanup so it runs before importing
get_default_images/IMAGE_OVERRIDE_ENV_KEYS, e.g., remove the top-level "from
vibepod.constants import IMAGE_OVERRIDE_ENV_KEYS, get_default_images", call
_unset_image_env_overrides(...) first, then dynamically import the module
(importlib.import_module("vibepod.constants")) and read IMAGE_OVERRIDE_ENV_KEYS
and get_default_images from that module so DEFAULT_IMAGES isn't initialized with
overridden env vars; reference _unset_image_env_overrides,
IMAGE_OVERRIDE_ENV_KEYS and get_default_images when making these changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/vibepod/constants.py`:
- Around line 84-86: The default value for the "datasette" mapping is a too-long
inline f-string causing an E501 lint error; split/wrap the default expression so
the line is under the max length by formatting the os.environ.get call across
multiple lines (e.g., use parentheses and break the f-string or concatenate the
components) where the key "datasette" and the call
os.environ.get("VP_DATASETTE_IMAGE", f"{os.environ.get('VP_IMAGE_NAMESPACE',
'vibepod')}/datasette:latest") appear so Ruff accepts the file.

---

Nitpick comments:
In `@scripts/check_default_images.py`:
- Around line 48-51: Call _unset_image_env_overrides to clear VP_IMAGE_* before
vibepod.constants is imported: move the env-cleanup so it runs before importing
get_default_images/IMAGE_OVERRIDE_ENV_KEYS, e.g., remove the top-level "from
vibepod.constants import IMAGE_OVERRIDE_ENV_KEYS, get_default_images", call
_unset_image_env_overrides(...) first, then dynamically import the module
(importlib.import_module("vibepod.constants")) and read IMAGE_OVERRIDE_ENV_KEYS
and get_default_images from that module so DEFAULT_IMAGES isn't initialized with
overridden env vars; reference _unset_image_env_overrides,
IMAGE_OVERRIDE_ENV_KEYS and get_default_images when making these changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1047d5d7-97d8-45c6-9d6d-e15cb990793c

📥 Commits

Reviewing files that changed from the base of the PR and between 07e1070 and 196d4e1.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • scripts/check_default_images.py
  • src/vibepod/constants.py

Comment thread src/vibepod/constants.py

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
src/vibepod/constants.py (1)

55-91: Inconsistent default namespace across images.

The VP_IMAGE_NAMESPACE fallback defaults to 'vibepod' for some images (claude, codex, datasette, proxy) but 'nezhar' for others (gemini, opencode, devstral, auggie, copilot). This means setting VP_IMAGE_NAMESPACE=myregistry won't override the hardcoded fallback for images that don't have an explicit override env var set.

If this is intentional (images live in different registries), consider documenting it. If not, unify the defaults.

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

In `@src/vibepod/constants.py` around lines 55 - 91, The get_default_images
mapping uses two different hardcoded fallback namespaces ('vibepod' and
'nezhar'), causing VP_IMAGE_NAMESPACE to not override some images; update the
get_default_images function so every image key (e.g., "claude", "gemini",
"opencode", "devstral", "auggie", "copilot", "codex", "datasette", "proxy")
constructs its default from the same os.environ.get('VP_IMAGE_NAMESPACE',
'<chosen-default>') value (pick a single default like 'vibepod' or make
per-image namespace env vars explicit), ensuring VP_IMAGE_NAMESPACE consistently
overrides defaults or add a clear comment documenting intentional differences.
🤖 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/constants.py`:
- Around line 55-91: The get_default_images mapping uses two different hardcoded
fallback namespaces ('vibepod' and 'nezhar'), causing VP_IMAGE_NAMESPACE to not
override some images; update the get_default_images function so every image key
(e.g., "claude", "gemini", "opencode", "devstral", "auggie", "copilot", "codex",
"datasette", "proxy") constructs its default from the same
os.environ.get('VP_IMAGE_NAMESPACE', '<chosen-default>') value (pick a single
default like 'vibepod' or make per-image namespace env vars explicit), ensuring
VP_IMAGE_NAMESPACE consistently overrides defaults or add a clear comment
documenting intentional differences.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f845badb-779c-4f2d-a9c0-bf8df3a65bf0

📥 Commits

Reviewing files that changed from the base of the PR and between 196d4e1 and 13b287b.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • scripts/check_default_images.py
  • src/vibepod/constants.py

@nezhar nezhar merged commit 626787c into main Mar 12, 2026
19 checks passed
@nezhar nezhar deleted the images-ci-task branch March 20, 2026 13:55
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