mirror of
https://github.com/docker/compose.git
synced 2026-10-12 02:13:08 +00:00
fix(create, start): clear error when targeting a job by name
docker compose create <job> / start <job> failed with the raw compose-go error "no such service: <name>", since project loading rejects the job name before rejectScheduledJobs or any job-aware logic ever runs -- unlike run, neither command knows how to detect that a name is a declared job. The result gave no hint that jobs exist or that run is the right command. Jobs stay run-only by design; this only replaces the error message when the target is a declared job, via a small helper (jobTargetErr) shared by both commands, reloading unselected exactly like run's own job-detection fallback. Any other "no such service" (a real typo) keeps the original, precise error. Signed-off-by: Nicolas De Loof <[email protected]>
This commit is contained in:
committed by
Nicolas De loof
parent
c8596c67fe
commit
f07bec20cf
+13
-3
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/docker/compose/v5/cmd/display"
|
||||
"github.com/docker/compose/v5/pkg/api"
|
||||
"github.com/docker/compose/v5/pkg/compose"
|
||||
)
|
||||
@@ -71,9 +72,18 @@ func createCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Bac
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
RunE: p.WithServices(dockerCli, func(ctx context.Context, project *types.Project, services []string) error {
|
||||
return runCreate(ctx, dockerCli, backendOptions, opts, buildOpts, project, services)
|
||||
}),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
err := p.WithServices(dockerCli, func(ctx context.Context, project *types.Project, services []string) error {
|
||||
return runCreate(ctx, dockerCli, backendOptions, opts, buildOpts, project, services)
|
||||
})(cmd, args)
|
||||
if jobErr, replaced := jobTargetErr(cmd.Context(), dockerCli, p, args, err); replaced {
|
||||
if display.Mode == display.ModeJSON {
|
||||
return makeJSONError(jobErr)
|
||||
}
|
||||
return jobErr
|
||||
}
|
||||
return err
|
||||
},
|
||||
ValidArgsFunction: completeServiceNames(dockerCli, p),
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
|
||||
@@ -322,6 +322,34 @@ func isNoSuchServiceErr(err error) bool {
|
||||
return strings.Contains(err.Error(), "no such service")
|
||||
}
|
||||
|
||||
// jobTargetErr recognizes an otherwise-raw compose-go selection error as
|
||||
// targeting a declared job: unlike run, create and start don't materialize
|
||||
// jobs — targeting one with either is run-only by design — so on a match it
|
||||
// only returns a clearer error message (replaced=true), never falls
|
||||
// through to acting on the job. names is the caller's original
|
||||
// (unselected-by-profile) argument list, checked as-is against
|
||||
// project.AllJobs() the same way run's own fallback resolves a job name.
|
||||
func jobTargetErr(ctx context.Context, dockerCli command.Cli, p *ProjectOptions, names []string, err error) (jobErr error, replaced bool) {
|
||||
if err == nil || len(names) == 0 || !isNoSuchServiceErr(err) {
|
||||
return err, false
|
||||
}
|
||||
backend, berr := compose.NewComposeService(dockerCli)
|
||||
if berr != nil {
|
||||
return err, false
|
||||
}
|
||||
unselected, _, uerr := p.ToProject(ctx, dockerCli, backend, nil, skipUnsupportedAttributesWarning, composecli.WithoutEnvironmentResolution)
|
||||
if uerr != nil {
|
||||
return err, false
|
||||
}
|
||||
jobs := unselected.AllJobs()
|
||||
for _, name := range names {
|
||||
if _, ok := jobs[name]; ok {
|
||||
return fmt.Errorf("job %q can only be triggered with \"docker compose run\"", name), true
|
||||
}
|
||||
}
|
||||
return err, false
|
||||
}
|
||||
|
||||
func runRun(ctx context.Context, backend api.Compose, project *types.Project, options runOptions, createOpts createOptions, buildOpts buildOptions, dockerCli command.Cli) error {
|
||||
project, err := options.apply(project)
|
||||
if err != nil {
|
||||
|
||||
@@ -54,6 +54,9 @@ func startCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *Back
|
||||
func runStart(ctx context.Context, dockerCli command.Cli, backendOptions *BackendOptions, opts startOptions, services []string) error {
|
||||
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
|
||||
if err != nil {
|
||||
if jobErr, replaced := jobTargetErr(ctx, dockerCli, opts.ProjectOptions, services, err); replaced {
|
||||
return jobErr
|
||||
}
|
||||
return err
|
||||
}
|
||||
// a label-reconstructed project (no compose file) declares no jobs;
|
||||
|
||||
Reference in New Issue
Block a user