config: add --filter to select services by profile or label - #14046
config: add --filter to select services by profile or label#14046ndeloof wants to merge 1 commit into
Conversation
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🟡 NEEDS ATTENTION
One confirmed medium-severity logic gap: profile=* does not auto-activate profiled services, contrary to the PR description.
| return err | ||
| } | ||
| // Filtering on a profile implies activating it. | ||
| if profiles := serviceFilter.Profiles(); len(profiles) > 0 { |
There was a problem hiding this comment.
[medium] profile=* filter silently produces incomplete results — profiled services are never activated
The PR description states that profile=* "selects every service declaring at least one profile" with no need for a separate --profile flag, but the implementation contradicts this.
Filter.Profiles() explicitly excludes the wildcard with e.Value != "*", so WithProfiles is never called for the profile=* case. Since SelectNames only iterates over project.Services (active services), any profiled service that was not already activated at load time silently stays in DisabledServices and is invisible to the filter.
The e2e test (pkg/e2e/config_test.go line 134) actually confirms the workaround: it passes --profile "*" as a separate CLI flag alongside --filter profile=* to activate all profiles first. Without that extra flag, the filter returns an empty or incomplete list — the opposite of "no separate --profile is needed."
Trigger path: A user runs
docker compose config --services --filter profile=*
without any --profile flag and expects all profiled services to appear. Instead they get only those whose profile happens to already be active (typically none beyond the default set).
Fix: detect the wildcard in runServices (or in Filter.Profiles()) and call project.WithProfiles with all profiles the project declares before filtering:
if profiles := serviceFilter.Profiles(); len(profiles) > 0 {
project, err = project.WithProfiles(append(project.Profiles, profiles...))
if err != nil {
return err
}
}
// NEW: handle profile=* wildcard — activate every declared profile so that
// SelectNames can see all profiled services.
if serviceFilter.HasWildcardProfile() {
project, err = project.WithProfiles(project.AllProfiles())
if err != nil {
return err
}
}Or, simpler, change Profiles() to return the sentinel "*" and let the caller pass it to WithProfiles (if WithProfiles handles "*" already via the existing --profile "*" mechanism).
| Confidence | Score |
|---|---|
| 🟢 strong | 100/100 |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Add a --filter criteria=value option to docker compose config --services, restricting the printed service names to those matching the given criteria: - profile=NAME selects services declaring the profile. Filtering on a profile implies activating it, so the services need not be otherwise enabled with --profile. Profiles must be selected explicitly: the "*" wildcard is rejected. - label=KEY[=VALUE] selects services carrying the label. Expressions with the same criteria are alternatives; distinct criteria must all be satisfied, following the docker --filter conventions. This gives a first-class way to script service selection, e.g. stopping only the services of a profile without stopping the profile-less ones: services=$(docker compose config --services --filter profile=workers) [ -n "$services" ] && docker compose stop $services The expression parsing and matching live in a new pkg/filter package, deliberately decoupled from the config command so the same selection mechanism can later be offered by commands operating on a subset of services (stop, restart, down, ...). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
c5584ee to
f2762a1
Compare
What I did
Added a repeatable
--filter criteria=valueoption todocker compose config --services, restricting the printed service names to those matching the criteria:profile=NAMEselects services declaring the profile. Filtering on a profile implies activating it (consistent with naming a profile-gated service explicitly), so no separate--profileis needed.label=KEY[=VALUE]selects services carrying the label.Same criteria = alternatives, distinct criteria = all required (
docker --filterconventions).This gives a first-class, scriptable way to select services, e.g. stopping only a profile's services without stopping the profile-less ones:
The expression parsing and matching live in a new
pkg/filterpackage, deliberately decoupled from theconfigcommand so the same selection mechanism can later be offered directly by commands operating on a subset of services (stop,restart,down, ...).Related issue
Addresses #13993
Created with: Claude Code