Skip to content

feat: detect deployed-image vs catalog-image drift and warn (CashPilot-Desktop-kca)#97

Merged
GeiserX merged 1 commit into
mainfrom
fix/loop-kca-image-drift
Jul 18, 2026
Merged

feat: detect deployed-image vs catalog-image drift and warn (CashPilot-Desktop-kca)#97
GeiserX merged 1 commit into
mainfrom
fix/loop-kca-image-drift

Conversation

@GeiserX

@GeiserX GeiserX commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Problem (from the ProxyBase migration review — CashPilot#103 / desktop PR #96)

sampleHealth records health_up for any container that is running, regardless of its image, and notifications() never alerted on a deployed-but-worthless container. So when a provider retires its client image (as ProxyBase did, proxybase/proxybaseghcr.io/proxybaseorg/peer-cli), an existing deployment stays green while earning $0.

Fix

  • catalog.ImageOutdated(deployed, catalogImage) (+ splitImage) — true when the provider changed the image repo/path or the catalog re-pinned to a different digest. Conservative: empty images and a pure tag-vs-digest difference of the same repo are not flagged.
  • App.outdatedServices(deployments) compares each deployment's Image against catalog.Get(slug).Docker.Image; the drifted slugs ride on AppState.outdatedServices.
  • UI badge — an update available badge on both the deployed-services table row (next to status) and the catalog card (next to "Deployed").
  • Notificationnotifications() raises a warning per drifted service prompting a re-deploy.

Health semantics are unchanged (a running container still counts as up); drift is an additive, separate signal — matching the web repo's 5wi.

Tests

  • catalog: TestSplitImage + TestImageOutdated (repo migration, digest re-pin, identical, empty, tag-vs-digest, tag-only).
  • app: TestOutdatedServices (drift flagged, match ignored, unknown slug ignored) + TestNotificationsFlagsOutdated.
  • go build, go vet, go test -race ./... green; frontend tsc typechecks.

Closes bead CashPilot-Desktop-kca. Mirror of the web bead CashPilot-5wi.

Summary by CodeRabbit

  • New Features
    • Added update-available indicators for deployed services whose images differ from the catalog.
    • Added dashboard warnings prompting users to redeploy outdated services.
    • Added update indicators to matching service catalog entries.
  • Bug Fixes
    • Improved image comparison to detect repository and digest changes while avoiding false positives for tag-versus-digest differences.

… (CashPilot-Desktop-kca)

When a provider retires its client image (as ProxyBase did), an existing
deployment keeps running — and so looks healthy (sampleHealth records
health_up for any running container) — while earning nothing, and
notifications never flagged it.

Add catalog.ImageOutdated (with splitImage) comparing each deployment's
image against the catalog's current docker.image; surface the drifted slugs
on AppState.outdatedServices, badge them 'update available' on the deployed-
services table and catalog card, and raise a warning notification prompting
a re-deploy. Deliberately conservative: empty images and pure tag-vs-digest
differences of the same repo are not flagged. Mirrors the web repo's 5wi.
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds conservative Docker image-drift detection, exposes outdated service slugs through app state, emits redeployment warnings, and displays update-available badges in the service catalog and deployed-services table.

Changes

Outdated service detection and presentation

Layer / File(s) Summary
Image drift comparison
internal/catalog/catalog.go, internal/catalog/catalog_test.go
Parses image references and flags repository changes or differing digests, with coverage for supported formats and conservative comparison cases.
App state and notifications
app.go, app_test.go
Computes outdated deployed service slugs, includes them in AppState, and emits warning notifications requesting redeployment.
Dashboard update indicators
frontend/src/main.ts, frontend/src/wails.d.ts
Propagates outdated service state and renders update-available badges in catalog cards and deployed-service rows.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: detecting deployed-vs-catalog image drift and surfacing warnings.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/loop-kca-image-drift

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.

@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.03%. Comparing base (95cf369) to head (7882e33).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #97      +/-   ##
==========================================
+ Coverage   74.92%   75.03%   +0.10%     
==========================================
  Files          14       14              
  Lines        3418     3433      +15     
==========================================
+ Hits         2561     2576      +15     
  Misses        669      669              
  Partials      188      188              
Files with missing lines Coverage Δ
internal/catalog/catalog.go 47.74% <100.00%> (+8.16%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@GeiserX

GeiserX commented Jul 18, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@GeiserX
GeiserX merged commit ab8b25c into main Jul 18, 2026
5 of 6 checks passed
@GeiserX
GeiserX deleted the fix/loop-kca-image-drift branch July 18, 2026 16:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app.go (1)

365-376: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Avoid redundant iteration by passing the pre-computed outdatedServices to notifications.

a.outdatedServices(deployments) is called once for the AppState struct and then again inside a.notifications(..., deployments). You can compute it once and pass the result down to keep things DRY.

♻️ Proposed refactor

Compute it once in GetAppState:

 	deployments := a.store.ListDeployments()
 	earnings := a.store.ListLatestEarnings()
+	outdated := a.outdatedServices(deployments)
 	return AppState{
 		Config:           a.cfg.Config(),
 		Runtime:          runtimeStatus,
 		Services:         a.catalog.ListVisible(),
 		Deployments:      deployments,
-		OutdatedServices: a.outdatedServices(deployments),
+		OutdatedServices: outdated,
 		Earnings:         earnings,
 		Guides:           runtime.InstallGuides(),
-		Notifications:    a.notifications(runtimeStatus, earnings, deployments),
+		Notifications:    a.notifications(runtimeStatus, earnings, deployments, outdated),
 		Currencies:       supportedCurrencies(),

Then update the notifications signature to accept it:

-func (a *App) notifications(status runtime.Status, earnings []store.EarningsRecord, deployments []store.Deployment) []Notification {
+func (a *App) notifications(status runtime.Status, earnings []store.EarningsRecord, deployments []store.Deployment, outdated []string) []Notification {
 	var items []Notification
 	// ...
-	for _, slug := range a.outdatedServices(deployments) {
+	for _, slug := range outdated {
 		name := slug
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app.go` around lines 365 - 376, In GetAppState, compute
a.outdatedServices(deployments) once and reuse that value for both the
AppState.OutdatedServices field and the notifications call. Update notifications
to accept the precomputed outdated services parameter and remove its internal
recomputation, preserving existing notification behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app.go`:
- Around line 365-376: In GetAppState, compute a.outdatedServices(deployments)
once and reuse that value for both the AppState.OutdatedServices field and the
notifications call. Update notifications to accept the precomputed outdated
services parameter and remove its internal recomputation, preserving existing
notification behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b0950f20-f9a9-4850-ab4b-920b9f4d2a9e

📥 Commits

Reviewing files that changed from the base of the PR and between 95cf369 and 7882e33.

📒 Files selected for processing (6)
  • app.go
  • app_test.go
  • frontend/src/main.ts
  • frontend/src/wails.d.ts
  • internal/catalog/catalog.go
  • internal/catalog/catalog_test.go

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