use `--progress` to configure progress UI stylet push

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2023-06-12 09:27:32 +02:00 committed by Nicolas De loof
parent 9384e5f4d7
commit cfe91becc7
8 changed files with 106 additions and 34 deletions

View File

@ -27,8 +27,7 @@ import (
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
buildx "github.com/docker/buildx/util/progress" buildx "github.com/docker/buildx/util/progress"
cliopts "github.com/docker/cli/opts" cliopts "github.com/docker/cli/opts"
"github.com/docker/compose/v2/pkg/progress" ui "github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/api"
@ -37,14 +36,13 @@ import (
type buildOptions struct { type buildOptions struct {
*ProjectOptions *ProjectOptions
composeOptions composeOptions
quiet bool quiet bool
pull bool pull bool
push bool push bool
progress string args []string
args []string noCache bool
noCache bool memory cliopts.MemBytes
memory cliopts.MemBytes ssh string
ssh string
} }
func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions, error) { func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions, error) {
@ -60,7 +58,7 @@ func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions,
return api.BuildOptions{ return api.BuildOptions{
Pull: opts.pull, Pull: opts.pull,
Push: opts.push, Push: opts.push,
Progress: opts.progress, Progress: ui.Mode,
Args: types.NewMappingWithEquals(opts.args), Args: types.NewMappingWithEquals(opts.args),
NoCache: opts.noCache, NoCache: opts.noCache,
Quiet: opts.quiet, Quiet: opts.quiet,
@ -69,14 +67,7 @@ func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions,
}, nil }, nil
} }
var printerModes = []string{ func buildCommand(p *ProjectOptions, progress *string, backend api.Service) *cobra.Command {
buildx.PrinterModeAuto,
buildx.PrinterModeTty,
buildx.PrinterModePlain,
buildx.PrinterModeQuiet,
}
func buildCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
opts := buildOptions{ opts := buildOptions{
ProjectOptions: p, ProjectOptions: p,
} }
@ -85,24 +76,21 @@ func buildCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
Short: "Build or rebuild services", Short: "Build or rebuild services",
PreRunE: Adapt(func(ctx context.Context, args []string) error { PreRunE: Adapt(func(ctx context.Context, args []string) error {
if opts.quiet { if opts.quiet {
opts.progress = buildx.PrinterModeQuiet ui.Mode = ui.ModeQuiet
devnull, err := os.Open(os.DevNull) devnull, err := os.Open(os.DevNull)
if err != nil { if err != nil {
return err return err
} }
os.Stdout = devnull os.Stdout = devnull
} }
if !utils.StringContains(printerModes, opts.progress) {
return fmt.Errorf("unsupported --progress value %q", opts.progress)
}
return nil return nil
}), }),
RunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error { RunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
if cmd.Flags().Changed("ssh") && opts.ssh == "" { if cmd.Flags().Changed("ssh") && opts.ssh == "" {
opts.ssh = "default" opts.ssh = "default"
} }
if progress.Mode == progress.ModePlain && !cmd.Flags().Changed("progress") { if cmd.Flags().Changed("progress") && opts.ssh == "" {
opts.progress = buildx.PrinterModePlain fmt.Fprint(os.Stderr, "--progress is a global compose flag, better use `docker compose --progress xx build ...")
} }
return runBuild(ctx, backend, opts, args) return runBuild(ctx, backend, opts, args)
}), }),
@ -111,7 +99,6 @@ func buildCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
cmd.Flags().BoolVar(&opts.push, "push", false, "Push service images.") cmd.Flags().BoolVar(&opts.push, "push", false, "Push service images.")
cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false, "Don't print anything to STDOUT") cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false, "Don't print anything to STDOUT")
cmd.Flags().BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image.") cmd.Flags().BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image.")
cmd.Flags().StringVar(&opts.progress, "progress", buildx.PrinterModeAuto, fmt.Sprintf(`Set type of progress output (%s)`, strings.Join(printerModes, ", ")))
cmd.Flags().StringArrayVar(&opts.args, "build-arg", []string{}, "Set build-time variables for services.") cmd.Flags().StringArrayVar(&opts.args, "build-arg", []string{}, "Set build-time variables for services.")
cmd.Flags().StringVar(&opts.ssh, "ssh", "", "Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent)") cmd.Flags().StringVar(&opts.ssh, "ssh", "", "Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent)")
cmd.Flags().Bool("parallel", true, "Build images in parallel. DEPRECATED") cmd.Flags().Bool("parallel", true, "Build images in parallel. DEPRECATED")
@ -124,6 +111,8 @@ func buildCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
cmd.Flags().Bool("no-rm", false, "Do not remove intermediate containers after a successful build. DEPRECATED") cmd.Flags().Bool("no-rm", false, "Do not remove intermediate containers after a successful build. DEPRECATED")
cmd.Flags().MarkHidden("no-rm") //nolint:errcheck cmd.Flags().MarkHidden("no-rm") //nolint:errcheck
cmd.Flags().VarP(&opts.memory, "memory", "m", "Set memory limit for the build container. Not supported by BuildKit.") cmd.Flags().VarP(&opts.memory, "memory", "m", "Set memory limit for the build container. Not supported by BuildKit.")
cmd.Flags().StringVar(progress, "progress", buildx.PrinterModeAuto, fmt.Sprintf(`Set type of ui output (%s)`, strings.Join(printerModes, ", ")))
cmd.Flags().MarkHidden("progress") //nolint:errcheck
return cmd return cmd
} }

View File

@ -26,6 +26,7 @@ import (
"strings" "strings"
"syscall" "syscall"
buildx "github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/compose-spec/compose-go/cli" "github.com/compose-spec/compose-go/cli"
@ -43,7 +44,7 @@ import (
"github.com/docker/compose/v2/cmd/formatter" "github.com/docker/compose/v2/cmd/formatter"
"github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/compose" "github.com/docker/compose/v2/pkg/compose"
"github.com/docker/compose/v2/pkg/progress" ui "github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils" "github.com/docker/compose/v2/pkg/utils"
) )
@ -273,6 +274,7 @@ func RootCommand(streams command.Cli, backend api.Service) *cobra.Command { //no
version bool version bool
parallel int parallel int
dryRun bool dryRun bool
progress string
) )
c := &cobra.Command{ c := &cobra.Command{
Short: "Docker Compose", Short: "Docker Compose",
@ -326,16 +328,36 @@ func RootCommand(streams command.Cli, backend api.Service) *cobra.Command { //no
formatter.SetANSIMode(streams, ansi) formatter.SetANSIMode(streams, ansi)
if noColor, ok := os.LookupEnv("NO_COLOR"); ok && noColor != "" { if noColor, ok := os.LookupEnv("NO_COLOR"); ok && noColor != "" {
progress.NoColor() ui.NoColor()
formatter.SetANSIMode(streams, formatter.Never) formatter.SetANSIMode(streams, formatter.Never)
} }
switch ansi { switch ansi {
case "never": case "never":
progress.Mode = progress.ModePlain ui.Mode = ui.ModePlain
case "always": case "always":
progress.Mode = progress.ModeTTY ui.Mode = ui.ModeTTY
} }
switch progress {
case ui.ModeAuto:
ui.Mode = ui.ModeAuto
case ui.ModeTTY:
if ansi == "never" {
return fmt.Errorf("can't use --progress tty while ANSI support is disabled")
}
ui.Mode = ui.ModeTTY
case ui.ModePlain:
if ansi == "always" {
return fmt.Errorf("can't use --progress plain while ANSI support is forced")
}
ui.Mode = ui.ModePlain
case ui.ModeQuiet, "none":
ui.Mode = ui.ModeQuiet
default:
return fmt.Errorf("unsupported --progress value %q", progress)
}
if opts.WorkDir != "" { if opts.WorkDir != "" {
if opts.ProjectDir != "" { if opts.ProjectDir != "" {
return errors.New(`cannot specify DEPRECATED "--workdir" and "--project-directory". Please use only "--project-directory" instead`) return errors.New(`cannot specify DEPRECATED "--workdir" and "--project-directory". Please use only "--project-directory" instead`)
@ -404,7 +426,7 @@ func RootCommand(streams command.Cli, backend api.Service) *cobra.Command { //no
portCommand(&opts, streams, backend), portCommand(&opts, streams, backend),
imagesCommand(&opts, streams, backend), imagesCommand(&opts, streams, backend),
versionCommand(streams), versionCommand(streams),
buildCommand(&opts, backend), buildCommand(&opts, &progress, backend),
pushCommand(&opts, backend), pushCommand(&opts, backend),
pullCommand(&opts, backend), pullCommand(&opts, backend),
createCommand(&opts, backend), createCommand(&opts, backend),
@ -425,6 +447,8 @@ func RootCommand(streams command.Cli, backend api.Service) *cobra.Command { //no
}, },
) )
c.Flags().StringVar(&progress, "progress", buildx.PrinterModeAuto, fmt.Sprintf(`Set type of progress output (%s)`, strings.Join(printerModes, ", ")))
c.Flags().StringVar(&ansi, "ansi", "auto", `Control when to print ANSI control characters ("never"|"always"|"auto")`) c.Flags().StringVar(&ansi, "ansi", "auto", `Control when to print ANSI control characters ("never"|"always"|"auto")`)
c.Flags().IntVar(&parallel, "parallel", -1, `Control max parallelism, -1 for unlimited`) c.Flags().IntVar(&parallel, "parallel", -1, `Control max parallelism, -1 for unlimited`)
c.Flags().BoolVarP(&version, "version", "v", false, "Show the Docker Compose version information") c.Flags().BoolVarP(&version, "version", "v", false, "Show the Docker Compose version information")
@ -460,3 +484,10 @@ func setEnvWithDotEnv(prjOpts *ProjectOptions) error {
} }
return nil return nil
} }
var printerModes = []string{
ui.ModeAuto,
ui.ModeTTY,
ui.ModePlain,
ui.ModeQuiet,
}

View File

@ -46,6 +46,7 @@ Define and run multi-container applications with Docker.
| `-f`, `--file` | `stringArray` | | Compose configuration files | | `-f`, `--file` | `stringArray` | | Compose configuration files |
| `--parallel` | `int` | `-1` | Control max parallelism, -1 for unlimited | | `--parallel` | `int` | `-1` | Control max parallelism, -1 for unlimited |
| `--profile` | `stringArray` | | Specify a profile to enable | | `--profile` | `stringArray` | | Specify a profile to enable |
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, quiet) |
| `--project-directory` | `string` | | Specify an alternate working directory<br>(default: the path of the, first specified, Compose file) | | `--project-directory` | `string` | | Specify an alternate working directory<br>(default: the path of the, first specified, Compose file) |
| `-p`, `--project-name` | `string` | | Project name | | `-p`, `--project-name` | `string` | | Project name |

View File

@ -11,7 +11,6 @@ Build or rebuild services
| `--dry-run` | | | Execute command in dry run mode | | `--dry-run` | | | Execute command in dry run mode |
| `-m`, `--memory` | `bytes` | `0` | Set memory limit for the build container. Not supported by BuildKit. | | `-m`, `--memory` | `bytes` | `0` | Set memory limit for the build container. Not supported by BuildKit. |
| `--no-cache` | | | Do not use cache when building the image | | `--no-cache` | | | Do not use cache when building the image |
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, quiet) |
| `--pull` | | | Always attempt to pull a newer version of the image. | | `--pull` | | | Always attempt to pull a newer version of the image. |
| `--push` | | | Push service images. | | `--push` | | | Push service images. |
| `-q`, `--quiet` | | | Don't print anything to STDOUT | | `-q`, `--quiet` | | | Don't print anything to STDOUT |

View File

@ -280,6 +280,16 @@ options:
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: progress
value_type: string
default_value: auto
description: Set type of progress output (auto, tty, plain, quiet)
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: project-directory - option: project-directory
value_type: string value_type: string
description: |- description: |-

View File

@ -90,9 +90,9 @@ options:
- option: progress - option: progress
value_type: string value_type: string
default_value: auto default_value: auto
description: Set type of progress output (auto, tty, plain, quiet) description: Set type of ui output (auto, tty, plain, quiet)
deprecated: false deprecated: false
hidden: false hidden: true
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false

37
pkg/progress/quiet.go Normal file
View File

@ -0,0 +1,37 @@
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package progress
import "context"
type quiet struct{}
func (q quiet) Start(_ context.Context) error {
return nil
}
func (q quiet) Stop() {
}
func (q quiet) Event(_ Event) {
}
func (q quiet) Events(_ []Event) {
}
func (q quiet) TailMsgf(_ string, _ ...interface{}) {
}

View File

@ -107,6 +107,8 @@ const (
ModeTTY = "tty" ModeTTY = "tty"
// ModePlain dump raw events to output // ModePlain dump raw events to output
ModePlain = "plain" ModePlain = "plain"
// ModeQuiet don't display events
ModeQuiet = "quiet"
) )
// Mode define how progress should be rendered, either as ModePlain or ModeTTY // Mode define how progress should be rendered, either as ModePlain or ModeTTY
@ -119,6 +121,9 @@ func NewWriter(ctx context.Context, out io.Writer, progressTitle string) (Writer
if !ok { if !ok {
dryRun = false dryRun = false
} }
if Mode == ModeQuiet {
return quiet{}, nil
}
f, isConsole := out.(console.File) // see https://github.com/docker/compose/issues/10560 f, isConsole := out.(console.File) // see https://github.com/docker/compose/issues/10560
if Mode == ModeAuto && isTerminal && isConsole { if Mode == ModeAuto && isTerminal && isConsole {
return newTTYWriter(f, dryRun, progressTitle) return newTTYWriter(f, dryRun, progressTitle)