fix(services): list running services started from a custom process-compose file - #2920
Conversation
`devbox services ls` early-returned "No services found in your project" whenever `d.Services()` (the project's statically defined service set from devbox.json plugins and the default process-compose.yaml) was empty. This happened before it ever checked whether the process manager was running, so services started with `devbox services up --process-compose-file <custom.yaml>` were never listed — even though process-compose was running them. Reorder the logic so that when the process manager is running we list the services it is actually running via `services.ListServices`, which queries the running process-compose server directly and is independent of any compose file or the static service set. The static set is now only consulted as a fallback when the process manager is not running. Fixes #2611 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AqRoYD21ykMzWYVBsw3MMa
There was a problem hiding this comment.
Pull request overview
This PR fixes devbox services ls failing to list services started via a custom --process-compose-file by ensuring ls queries the running process-compose instance first (instead of returning early based on the statically defined service set).
Changes:
- Reordered
ListServiceslogic to prefer live process-compose service listing when the process manager is running. - Kept the static service-set listing as a fallback path when the process manager is not running.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| pcSvcs, err := services.ListServices(ctx, d.projectDir, d.stderr) | ||
| if err != nil { | ||
| fmt.Fprintln(d.stderr, "Error listing services: ", err) | ||
| } else { | ||
| fmt.Fprintln(d.stderr, "Services running in process-compose:") | ||
| fmt.Fprintln(tw, "PID\tNAME\tNAMESPACE\tSTATUS\tAGE\tHEALTH\tRESTARTS\tEXIT CODE") | ||
| for _, s := range pcSvcs { | ||
| fmt.Fprintf(tw, "%d\t%s\t%s\t%s\t%s\t%s\t%d\t%d\n", s.PID, s.Name, s.Namespace, s.Status, s.Age, s.Health, s.Restarts, s.ExitCode) | ||
| } | ||
| tw.Flush() | ||
| } | ||
| return nil | ||
| } |
Previously `devbox services ls` printed the error from services.ListServices but returned nil, so the command exited 0 even when it could not reach the running process-compose server — hiding failures in scripts and CI. Return the (wrapped) error so the command exits non-zero. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AqRoYD21ykMzWYVBsw3MMa
|
@claude please review this PR for correctness, and flag anything that would block merging. |
|
Claude finished @mikeland73's task in 1m 7s —— View job Review: PR #2920 — fix(services): list running services from a custom process-compose file
No blockers found. This looks correct and safe to merge. Findings
Verification limitationsI was not able to run |
|
I reviewed the diff for correctness and merge-readiness. The change is correct and I don't see anything that blocks merging. CI is fully green (all 25 checks). Correctness — behavior matrix (old → new)
The reorder fixes the reported case — services started from a custom Non-blocking notes
Generated by Claude Code |
…rg-m7isxa # Conflicts: # internal/devbox/services.go
Summary
Fixes #2611.
devbox services lsdid not display services that were started with a custom--process-compose-file, e.g.:devbox services up -d --process-compose-file my-process-compose.yaml devbox services ls # -> "No services found in your project"Root cause
ListServices(internal/devbox/services.go) fetched the project'sstatically defined service set via
d.Services()and returned early with"No services found in your project" whenever that set was empty — before
ever checking whether the process manager was running:
d.Services()is built fromdevbox.jsonplugin services plusFromUserProcessCompose(projectDir, d.customProcessComposeFile). Whenlsisinvoked (a separate process from
up),customProcessComposeFileis empty, soit only reads the default
process-compose.yaml. Services defined solely in acustom-named compose file are therefore absent from the set, and the command
returned early even though process-compose was actively running them.
Meanwhile
services.ListServicesconnects to the running process-composeserver by port (
GetProcessManagerPort) and lists the live processes — it doesnot depend on the compose file or the static set at all. The early return
simply prevented that call from happening.
Fix
Reorder the logic so that when the process manager is running we list the
services it is actually running, regardless of
d.Services(). The staticallydefined set is now only consulted as a fallback when the process manager is
not running (to show the available-but-not-running services, or the
"No services found" message). No behavior changes for existing cases where the
static set is non-empty.
How was it tested?
go build ./internal/devbox/andgo vet ./internal/devbox/are clean.internal/devboxpackage's remaining test failures in this sandbox arepre-existing and environmental (they require the
nixbinary, which is notinstalled here); they do not exercise
ListServices.Manual reproduction from the issue:
cc @szymon-filipiak (issue reporter)
Community Contribution License
All community contributions in this pull request are licensed to the project
maintainers under the terms of the
Apache 2 License.
By creating this pull request, I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 License as stated in
the
Community Contribution License.
🤖 Generated with Claude Code
https://claude.ai/code/session_01AqRoYD21ykMzWYVBsw3MMa
Generated by Claude Code