Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package docker-compose for openSUSE:Factory checked in at 2025-09-19 15:34:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/docker-compose (Old) and /work/SRC/openSUSE:Factory/.docker-compose.new.27445 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "docker-compose" Fri Sep 19 15:34:48 2025 rev:78 rq:1305985 version:2.39.4 Changes: -------- --- /work/SRC/openSUSE:Factory/docker-compose/docker-compose.changes 2025-09-18 21:12:25.827866795 +0200 +++ /work/SRC/openSUSE:Factory/.docker-compose.new.27445/docker-compose.changes 2025-09-19 15:35:26.004459402 +0200 @@ -1,0 +2,20 @@ +Fri Sep 19 11:23:39 UTC 2025 - Johannes Kastl <[email protected]> + +- Update to version 2.39.4: + * Improvements + - Add support of develop.watch.initial_sync attribute by + @glours in #13232 + * Fixes + - Volume ls command can run without a project by @ndeloof in + #13221 + - Fix support for build with bake when target docker endpoint + requires TLS by @ndeloof in #13231 + - Disable Tty if run command started from a piped command by + @glours in #13233 + * Internal + - Test: Set stop_signal to SIGTERM by @ricardobranco777 in + #13214 + * Dependencies + - Bump compose-go to version v2.9.0 by @glours in #13234 + +------------------------------------------------------------------- Old: ---- docker-compose-2.39.3.obscpio New: ---- docker-compose-2.39.4.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ docker-compose.spec ++++++ --- /var/tmp/diff_new_pack.sSapYZ/_old 2025-09-19 15:35:26.800492837 +0200 +++ /var/tmp/diff_new_pack.sSapYZ/_new 2025-09-19 15:35:26.804493005 +0200 @@ -17,7 +17,7 @@ Name: docker-compose -Version: 2.39.3 +Version: 2.39.4 Release: 0 Summary: Define and run multi-container applications with Docker License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.sSapYZ/_old 2025-09-19 15:35:26.840494516 +0200 +++ /var/tmp/diff_new_pack.sSapYZ/_new 2025-09-19 15:35:26.844494685 +0200 @@ -3,7 +3,7 @@ <param name="url">https://github.com/docker/compose</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v2.39.3</param> + <param name="revision">v2.39.4</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.sSapYZ/_old 2025-09-19 15:35:26.864495524 +0200 +++ /var/tmp/diff_new_pack.sSapYZ/_new 2025-09-19 15:35:26.868495693 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/docker/compose</param> - <param name="changesrevision">385b3f5c9643955e68b7009f6a305933678b51ea</param></service></servicedata> + <param name="changesrevision">a32dc3da722e6b2e4fbfc72e40b1a697c4686460</param></service></servicedata> (No newline at EOF) ++++++ docker-compose-2.39.3.obscpio -> docker-compose-2.39.4.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/MAINTAINERS new/docker-compose-2.39.4/MAINTAINERS --- old/docker-compose-2.39.3/MAINTAINERS 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/MAINTAINERS 1970-01-01 01:00:00.000000000 +0100 @@ -1,124 +0,0 @@ -# Docker maintainers file -# -# This file describes who runs the docker/compose project and how. -# This is a living document - if you see something out of date or missing, speak up! -# -# It is structured to be consumable by both humans and programs. -# To extract its contents programmatically, use any TOML-compliant -# parser. -# -# This file is compiled into the MAINTAINERS file in docker/opensource. -# -[Org] - - [Org."Core maintainers"] - - # The Core maintainers are the ghostbusters of the project: when there's a problem others - # can't solve, they show up and fix it with bizarre devices and weaponry. - # They have final say on technical implementation and coding style. - # They are ultimately responsible for quality in all its forms: usability polish, - # bugfixes, performance, stability, etc. When ownership can cleanly be passed to - # a subsystem, they are responsible for doing so and holding the - # subsystem maintainers accountable. If ownership is unclear, they are the de facto owners. - - people = [ - "glours", - "jhrotko", - "milas", - "ndeloof", - "nicksieger", - "StefanScherer", - "ulyssessouza" - ] - - [Org."Regular maintainers"] - # The Regular maintainers are people who aren't Core maintainers but are around - # to help reviewing and fixing bugs, just on a less regular basis than previously. - # Most of them were previously Core maintainers of Compose. - people = [ - "aiordache", - "chris-crone", - "gtardif", - "laurazard", - "maxcleme", - "rumpl", - "thaJeztah" - ] - -[people] - -# A reference list of all people associated with the project. -# All other sections should refer to people by their canonical key -# in the people section. - - # ADD YOURSELF HERE IN ALPHABETICAL ORDER - - [people.aiordache] - Name = "Anca Iordache" - Email = "[email protected]" - GitHub = "aiordache " - - [people.chris-crone] - Name = "Christopher Crone" - Email = "[email protected]" - GitHub = "chris-crone" - - [people.glours] - Name = "Guillaume Lours" - Email = "[email protected]" - GitHub = "glours" - - [people.gtardif] - Name = "Guillaume Tardif" - Email = "[email protected]" - GitHub = "gtardif" - - [people.jhrotko] - Name = "Joana Hrotko" - Email = "[email protected]" - Github = "jhrotko" - - [people.laurazard] - Name = "Laura Brehm" - Email = "[email protected]" - GitHub = "laurazard" - - [people.maxcleme] - Name = "Maxime Clement" - Email = "[email protected]" - GitHub = "maxcleme" - - [people.milas] - Name = "Milas Bowman" - Email = "[email protected]" - GitHub = "milas" - - [people.nicksieger] - Name = "Nick Sieger" - Email = "[email protected]" - GitHub = "nicksieger" - - [people.ndeloof] - Name = "Nicolas Deloof" - Email = "[email protected]" - GitHub = "ndeloof" - - [people.rumpl] - Name = "Djordje Lukic" - Email = "[email protected]" - GitHub = "rumpl" - - [people.thaJeztah] - Name = "Sebastiaan van Stijn" - Email = "[email protected]" - GitHub = "thaJeztah " - - [people.StefanScherer] - Name = "Stefan Scherer" - Email = "[email protected]" - GitHub = "StefanScherer" - - [people.ulyssessouza] - Name = "Ulysses Souza" - Email = "<[email protected]" - Github = "ulyssessouza" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/cmd/compose/run.go new/docker-compose-2.39.4/cmd/compose/run.go --- old/docker-compose-2.39.3/cmd/compose/run.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/cmd/compose/run.go 2025-09-19 10:31:20.000000000 +0200 @@ -50,7 +50,6 @@ Detach bool Remove bool noTty bool - tty bool interactive bool user string workdir string @@ -155,6 +154,10 @@ buildOpts := buildOptions{ ProjectOptions: p, } + // We remove the attribute from the option struct and use a dedicated var, to limit confusion and avoid anyone to use options.tty. + // The tty flag is here for convenience and let user do "docker compose run -it" the same way as they use the "docker run" command. + var ttyFlag bool + cmd := &cobra.Command{ Use: "run [OPTIONS] SERVICE [COMMAND] [ARGS...]", Short: "Run a one-off command on a service", @@ -178,9 +181,16 @@ if cmd.Flags().Changed("no-TTY") { return fmt.Errorf("--tty and --no-TTY can't be used together") } else { - options.noTty = !options.tty + options.noTty = !ttyFlag } + } else if !cmd.Flags().Changed("no-TTY") && !cmd.Flags().Changed("interactive") && !dockerCli.In().IsTerminal() { + // while `docker run` requires explicit `-it` flags, Compose enables interactive mode and TTY by default + // but when compose is used from a scripr has stdin piped from another command, we just can't + // Here, we detect we run "by default" (user didn't passed explicit flags) and disable TTY allocation if + // we don't have an actual terminal to attach to for interactive mode + options.noTty = true } + if options.quiet { progress.Mode = progress.ModeQuiet devnull, err := os.Open(os.DevNull) @@ -238,7 +248,7 @@ flags.BoolVar(&options.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file") cmd.Flags().BoolVarP(&options.interactive, "interactive", "i", true, "Keep STDIN open even if not attached") - cmd.Flags().BoolVarP(&options.tty, "tty", "t", true, "Allocate a pseudo-TTY") + cmd.Flags().BoolVarP(&ttyFlag, "tty", "t", true, "Allocate a pseudo-TTY") cmd.Flags().MarkHidden("tty") //nolint:errcheck flags.SetNormalizeFunc(normalizeRunFlags) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/cmd/compose/volumes.go new/docker-compose-2.39.4/cmd/compose/volumes.go --- old/docker-compose-2.39.3/cmd/compose/volumes.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/cmd/compose/volumes.go 2025-09-19 10:31:20.000000000 +0200 @@ -55,24 +55,21 @@ } func runVol(ctx context.Context, dockerCli command.Cli, backend api.Service, services []string, options volumesOptions) error { - project, _, err := options.projectOrName(ctx, dockerCli, services...) + project, name, err := options.projectOrName(ctx, dockerCli, services...) if err != nil { return err } - names := project.ServiceNames() - - if len(services) == 0 { - services = names - } - - for _, service := range services { - if !slices.Contains(names, service) { - return fmt.Errorf("no such service: %s", service) + if project != nil { + names := project.ServiceNames() + for _, service := range services { + if !slices.Contains(names, service) { + return fmt.Errorf("no such service: %s", service) + } } } - volumes, err := backend.Volumes(ctx, project, api.VolumesOptions{ + volumes, err := backend.Volumes(ctx, name, api.VolumesOptions{ Services: services, }) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/go.mod new/docker-compose-2.39.4/go.mod --- old/docker-compose-2.39.3/go.mod 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/go.mod 2025-09-19 10:31:20.000000000 +0200 @@ -8,7 +8,7 @@ github.com/Microsoft/go-winio v0.6.2 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/buger/goterm v1.0.4 - github.com/compose-spec/compose-go/v2 v2.8.2 + github.com/compose-spec/compose-go/v2 v2.9.0 github.com/containerd/containerd/v2 v2.1.4 github.com/containerd/errdefs v1.0.0 github.com/containerd/platforms v1.0.0-rc.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/go.sum new/docker-compose-2.39.4/go.sum --- old/docker-compose-2.39.3/go.sum 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/go.sum 2025-09-19 10:31:20.000000000 +0200 @@ -78,8 +78,8 @@ github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= -github.com/compose-spec/compose-go/v2 v2.8.2 h1:A1iVoZJUex7buGv1CpnC5uwNuyTMBYpDAmBnAQmia9Q= -github.com/compose-spec/compose-go/v2 v2.8.2/go.mod h1:Oky9AZGTRB4E+0VbTPZTUu4Kp+oEMMuwZXZtPPVT1iE= +github.com/compose-spec/compose-go/v2 v2.9.0 h1:UHSv/QHlo6QJtrT4igF1rdORgIUhDo1gWuyJUoiNNIM= +github.com/compose-spec/compose-go/v2 v2.9.0/go.mod h1:Oky9AZGTRB4E+0VbTPZTUu4Kp+oEMMuwZXZtPPVT1iE= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/api/api.go new/docker-compose-2.39.4/pkg/api/api.go --- old/docker-compose-2.39.3/pkg/api/api.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/api/api.go 2025-09-19 10:31:20.000000000 +0200 @@ -101,7 +101,7 @@ // Generate generates a Compose Project from existing containers Generate(ctx context.Context, options GenerateOptions) (*types.Project, error) // Volumes executes the equivalent to a `docker volume ls` - Volumes(ctx context.Context, project *types.Project, options VolumesOptions) ([]VolumesSummary, error) + Volumes(ctx context.Context, project string, options VolumesOptions) ([]VolumesSummary, error) } type VolumesOptions struct { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/compose/shellout.go new/docker-compose-2.39.4/pkg/compose/shellout.go --- old/docker-compose-2.39.3/pkg/compose/shellout.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/compose/shellout.go 2025-09-19 10:31:20.000000000 +0200 @@ -65,6 +65,7 @@ _ = os.RemoveAll(certs) } env[client.EnvOverrideCertPath] = certs + env["DOCKER_TLS"] = "1" if !endpoint.SkipTLSVerify { env[client.EnvTLSVerify] = "1" } @@ -73,7 +74,7 @@ if err != nil { return nil, cleanup, err } - err = os.WriteFile(filepath.Join(certs, flags.DefaultCaFile), endpoint.TLSData.Cert, 0o600) + err = os.WriteFile(filepath.Join(certs, flags.DefaultCertFile), endpoint.TLSData.Cert, 0o600) if err != nil { return nil, cleanup, err } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/compose/volumes.go new/docker-compose-2.39.4/pkg/compose/volumes.go --- old/docker-compose-2.39.3/pkg/compose/volumes.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/compose/volumes.go 2025-09-19 10:31:20.000000000 +0200 @@ -20,18 +20,15 @@ "context" "slices" - "github.com/compose-spec/compose-go/v2/types" "github.com/docker/compose/v2/pkg/api" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/volume" ) -func (s *composeService) Volumes(ctx context.Context, project *types.Project, options api.VolumesOptions) ([]api.VolumesSummary, error) { - projectName := project.Name - +func (s *composeService) Volumes(ctx context.Context, project string, options api.VolumesOptions) ([]api.VolumesSummary, error) { allContainers, err := s.apiClient().ContainerList(ctx, container.ListOptions{ - Filters: filters.NewArgs(projectFilter(projectName)), + Filters: filters.NewArgs(projectFilter(project)), }) if err != nil { return nil, err @@ -51,7 +48,7 @@ } volumesResponse, err := s.apiClient().VolumeList(ctx, volume.ListOptions{ - Filters: filters.NewArgs(projectFilter(projectName)), + Filters: filters.NewArgs(projectFilter(project)), }) if err != nil { return nil, err diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/compose/volumes_test.go new/docker-compose-2.39.4/pkg/compose/volumes_test.go --- old/docker-compose-2.39.3/pkg/compose/volumes_test.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/compose/volumes_test.go 2025-09-19 10:31:20.000000000 +0200 @@ -20,7 +20,6 @@ "context" "testing" - "github.com/compose-spec/compose-go/v2/types" "github.com/docker/compose/v2/pkg/api" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" @@ -59,7 +58,6 @@ } ctx := context.Background() - project := &types.Project{Name: testProject} args := filters.NewArgs(projectFilter(testProject)) listOpts := container.ListOptions{Filters: args} volumeListArgs := filters.NewArgs(projectFilter(testProject)) @@ -75,14 +73,14 @@ // Test without service filter - should return all project volumes volumeOptions := api.VolumesOptions{} - volumes, err := tested.Volumes(ctx, project, volumeOptions) + volumes, err := tested.Volumes(ctx, testProject, volumeOptions) expected := []api.VolumesSummary{vol1, vol2, vol3} assert.NilError(t, err) assert.DeepEqual(t, volumes, expected) // Test with service filter - should only return volumes used by service1 volumeOptions = api.VolumesOptions{Services: []string{"service1"}} - volumes, err = tested.Volumes(ctx, project, volumeOptions) + volumes, err = tested.Volumes(ctx, testProject, volumeOptions) expected = []api.VolumesSummary{vol1, vol2} assert.NilError(t, err) assert.DeepEqual(t, volumes, expected) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/compose/watch.go new/docker-compose-2.39.4/pkg/compose/watch.go --- old/docker-compose-2.39.3/pkg/compose/watch.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/compose/watch.go 2025-09-19 10:31:20.000000000 +0200 @@ -232,9 +232,19 @@ logrus.Warnf("path '%s' also declared by a bind mount volume, this path won't be monitored!\n", trigger.Path) continue } else { - var initialSync bool - success, err := trigger.Extensions.Get("x-initialSync", &initialSync) - if err == nil && success && initialSync && isSync(trigger) { + shouldInitialSync := trigger.InitialSync + + // Check legacy extension attribute for backward compatibility + if !shouldInitialSync { + var legacyInitialSync bool + success, err := trigger.Extensions.Get("x-initialSync", &legacyInitialSync) + if err == nil && success && legacyInitialSync { + shouldInitialSync = true + logrus.Warnf("x-initialSync is DEPRECATED, please use the official `initial_sync` attribute\n") + } + } + + if shouldInitialSync && isSync(trigger) { // Need to check initial files are in container that are meant to be synced from watch action err := s.initialSync(ctx, project, service, trigger, syncer) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/build_test.go new/docker-compose-2.39.4/pkg/e2e/build_test.go --- old/docker-compose-2.39.3/pkg/e2e/build_test.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/e2e/build_test.go 2025-09-19 10:31:20.000000000 +0200 @@ -19,6 +19,7 @@ import ( "fmt" "net/http" + "os" "regexp" "runtime" "strconv" @@ -29,6 +30,7 @@ "github.com/stretchr/testify/require" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" + "gotest.tools/v3/poll" ) func TestLocalComposeBuild(t *testing.T) { @@ -608,3 +610,38 @@ out := res.Combined() assert.Check(t, strings.Contains(out, "secret-build-test Built")) } + +func TestBuildTLS(t *testing.T) { + t.Helper() + + c := NewParallelCLI(t) + const dindBuilder = "e2e-dind-builder" + tmp := t.TempDir() + + t.Cleanup(func() { + c.RunDockerCmd(t, "rm", "-f", dindBuilder) + c.RunDockerCmd(t, "context", "rm", dindBuilder) + }) + + c.RunDockerCmd(t, "run", "--name", dindBuilder, "--privileged", "-p", "2376:2376", "-d", "docker:dind") + + poll.WaitOn(t, func(_ poll.LogT) poll.Result { + res := c.RunDockerCmd(t, "logs", dindBuilder) + if strings.Contains(res.Combined(), "API listen on [::]:2376") { + return poll.Success() + } + return poll.Continue("waiting for Docker daemon to be running") + }, poll.WithTimeout(10*time.Second)) + + time.Sleep(1 * time.Second) // wait for dind setup + c.RunDockerCmd(t, "cp", dindBuilder+":/certs/client", tmp) + + c.RunDockerCmd(t, "context", "create", dindBuilder, "--docker", + fmt.Sprintf("host=tcp://localhost:2376,ca=%s/client/ca.pem,cert=%s/client/cert.pem,key=%s/client/key.pem,skip-tls-verify=1", tmp, tmp, tmp)) + + cmd := c.NewDockerComposeCmd(t, "-f", "fixtures/build-test/minimal/compose.yaml", "build") + cmd.Env = append(cmd.Env, "DOCKER_CONTEXT="+dindBuilder) + cmd.Stdout = os.Stdout + res := icmd.RunCmd(cmd) + res.Assert(t, icmd.Expected{Err: "Built"}) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/compose_run_test.go new/docker-compose-2.39.4/pkg/e2e/compose_run_test.go --- old/docker-compose-2.39.3/pkg/e2e/compose_run_test.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/e2e/compose_run_test.go 2025-09-19 10:31:20.000000000 +0200 @@ -222,4 +222,60 @@ res := c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/compose.yaml", "run", "build", "echo", "hello world") res.Assert(t, icmd.Expected{Out: "hello world"}) }) + + t.Run("compose run with piped input detection", func(t *testing.T) { + if composeStandaloneMode { + t.Skip("Skipping test compose with piped input detection in standalone mode") + } + // Test that piped input is properly detected and TTY is automatically disabled + // This tests the logic added in run.go that checks dockerCli.In().IsTerminal() + cmd := c.NewCmd("sh", "-c", "echo 'piped-content' | docker compose -f ./fixtures/run-test/piped-test.yaml run --rm piped-test") + res := icmd.RunCmd(cmd) + + res.Assert(t, icmd.Expected{Out: "piped-content"}) + res.Assert(t, icmd.Success) + }) + + t.Run("compose run piped input should not allocate TTY", func(t *testing.T) { + if composeStandaloneMode { + t.Skip("Skipping test compose with piped input detection in standalone mode") + } + // Test that when stdin is piped, the container correctly detects no TTY + // This verifies that the automatic noTty=true setting works correctly + cmd := c.NewCmd("sh", "-c", "echo '' | docker compose -f ./fixtures/run-test/piped-test.yaml run --rm tty-test") + res := icmd.RunCmd(cmd) + + res.Assert(t, icmd.Expected{Out: "No TTY detected"}) + res.Assert(t, icmd.Success) + }) + + t.Run("compose run piped input with explicit --tty should fail", func(t *testing.T) { + if composeStandaloneMode { + t.Skip("Skipping test compose with piped input detection in standalone mode") + } + // Test that explicitly requesting TTY with piped input fails with proper error message + // This should trigger the "input device is not a TTY" error + cmd := c.NewCmd("sh", "-c", "echo 'test' | docker compose -f ./fixtures/run-test/piped-test.yaml run --rm --tty piped-test") + res := icmd.RunCmd(cmd) + + res.Assert(t, icmd.Expected{ + ExitCode: 1, + Err: "the input device is not a TTY", + }) + }) + + t.Run("compose run piped input with --no-TTY=false should fail", func(t *testing.T) { + if composeStandaloneMode { + t.Skip("Skipping test compose with piped input detection in standalone mode") + } + // Test that explicitly disabling --no-TTY (i.e., requesting TTY) with piped input fails + // This should also trigger the "input device is not a TTY" error + cmd := c.NewCmd("sh", "-c", "echo 'test' | docker compose -f ./fixtures/run-test/piped-test.yaml run --rm --no-TTY=false piped-test") + res := icmd.RunCmd(cmd) + + res.Assert(t, icmd.Expected{ + ExitCode: 1, + Err: "the input device is not a TTY", + }) + }) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/fixtures/build-test/minimal/Dockerfile new/docker-compose-2.39.4/pkg/e2e/fixtures/build-test/minimal/Dockerfile --- old/docker-compose-2.39.3/pkg/e2e/fixtures/build-test/minimal/Dockerfile 1970-01-01 01:00:00.000000000 +0100 +++ new/docker-compose-2.39.4/pkg/e2e/fixtures/build-test/minimal/Dockerfile 2025-09-19 10:31:20.000000000 +0200 @@ -0,0 +1,16 @@ +# 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. + +FROM scratch +COPY . . \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/fixtures/build-test/minimal/compose.yaml new/docker-compose-2.39.4/pkg/e2e/fixtures/build-test/minimal/compose.yaml --- old/docker-compose-2.39.3/pkg/e2e/fixtures/build-test/minimal/compose.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/docker-compose-2.39.4/pkg/e2e/fixtures/build-test/minimal/compose.yaml 2025-09-19 10:31:20.000000000 +0200 @@ -0,0 +1,3 @@ +services: + test: + build: . \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/fixtures/dependencies/recreate-no-deps.yaml new/docker-compose-2.39.4/pkg/e2e/fixtures/dependencies/recreate-no-deps.yaml --- old/docker-compose-2.39.3/pkg/e2e/fixtures/dependencies/recreate-no-deps.yaml 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/e2e/fixtures/dependencies/recreate-no-deps.yaml 2025-09-19 10:31:20.000000000 +0200 @@ -9,6 +9,7 @@ nginx: image: nginx:alpine + stop_signal: SIGTERM healthcheck: test: "echo | nc -w 5 localhost:80" interval: 2s diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/fixtures/restart-test/compose-depends-on.yaml new/docker-compose-2.39.4/pkg/e2e/fixtures/restart-test/compose-depends-on.yaml --- old/docker-compose-2.39.3/pkg/e2e/fixtures/restart-test/compose-depends-on.yaml 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/e2e/fixtures/restart-test/compose-depends-on.yaml 2025-09-19 10:31:20.000000000 +0200 @@ -3,6 +3,7 @@ image: nginx:alpine init: true command: tail -f /dev/null + stop_signal: SIGTERM depends_on: nginx: {condition: service_healthy, restart: true} @@ -10,6 +11,7 @@ image: nginx:alpine init: true command: tail -f /dev/null + stop_signal: SIGTERM depends_on: nginx: { condition: service_healthy } @@ -17,6 +19,7 @@ image: nginx:alpine labels: TEST: ${LABEL:-test} + stop_signal: SIGTERM healthcheck: test: "echo | nc -w 5 localhost:80" interval: 2s diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/fixtures/run-test/piped-test.yaml new/docker-compose-2.39.4/pkg/e2e/fixtures/run-test/piped-test.yaml --- old/docker-compose-2.39.3/pkg/e2e/fixtures/run-test/piped-test.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/docker-compose-2.39.4/pkg/e2e/fixtures/run-test/piped-test.yaml 2025-09-19 10:31:20.000000000 +0200 @@ -0,0 +1,9 @@ +services: + piped-test: + image: alpine + command: cat + # Service that will receive piped input and echo it back + tty-test: + image: alpine + command: sh -c "if [ -t 0 ]; then echo 'TTY detected'; else echo 'No TTY detected'; fi" + # Service to test TTY detection \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/fixtures/watch/exec.yaml new/docker-compose-2.39.4/pkg/e2e/fixtures/watch/exec.yaml --- old/docker-compose-2.39.3/pkg/e2e/fixtures/watch/exec.yaml 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/e2e/fixtures/watch/exec.yaml 2025-09-19 10:31:20.000000000 +0200 @@ -9,6 +9,7 @@ watch: - path: . target: /data + initial_sync: true action: sync+exec exec: command: echo "SUCCESS" \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/fixtures/watch/x-initialSync.yaml new/docker-compose-2.39.4/pkg/e2e/fixtures/watch/x-initialSync.yaml --- old/docker-compose-2.39.3/pkg/e2e/fixtures/watch/x-initialSync.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/docker-compose-2.39.4/pkg/e2e/fixtures/watch/x-initialSync.yaml 2025-09-19 10:31:20.000000000 +0200 @@ -0,0 +1,15 @@ +services: + test: + build: + dockerfile_inline: FROM alpine + command: ping localhost + volumes: + - /data + develop: + watch: + - path: . + target: /data + action: sync+exec + exec: + command: echo "SUCCESS" + x-initialSync: true \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/e2e/watch_test.go new/docker-compose-2.39.4/pkg/e2e/watch_test.go --- old/docker-compose-2.39.3/pkg/e2e/watch_test.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/e2e/watch_test.go 2025-09-19 10:31:20.000000000 +0200 @@ -405,3 +405,27 @@ c.RunDockerComposeCmdNoCheck(t, "-p", projectName, "kill", "-s", "9") } + +func TestCheckWarningXInitialSyn(t *testing.T) { + c := NewCLI(t) + const projectName = "test_watch_warn_initial_syn" + + defer c.cleanupWithDown(t, projectName) + + tmpdir := t.TempDir() + composeFilePath := filepath.Join(tmpdir, "compose.yaml") + CopyFile(t, filepath.Join("fixtures", "watch", "x-initialSync.yaml"), composeFilePath) + cmd := c.NewDockerComposeCmd(t, "-p", projectName, "-f", composeFilePath, "--verbose", "up", "--watch") + buffer := bytes.NewBuffer(nil) + cmd.Stdout = buffer + watch := icmd.StartCmd(cmd) + + poll.WaitOn(t, func(l poll.LogT) poll.Result { + if strings.Contains(watch.Combined(), "x-initialSync is DEPRECATED, please use the official `initial_sync` attribute") { + return poll.Success() + } + return poll.Continue("%v", watch.Stdout()) + }) + + c.RunDockerComposeCmdNoCheck(t, "-p", projectName, "kill", "-s", "9") +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/docker-compose-2.39.3/pkg/mocks/mock_docker_compose_api.go new/docker-compose-2.39.4/pkg/mocks/mock_docker_compose_api.go --- old/docker-compose-2.39.3/pkg/mocks/mock_docker_compose_api.go 2025-09-08 18:07:00.000000000 +0200 +++ new/docker-compose-2.39.4/pkg/mocks/mock_docker_compose_api.go 2025-09-19 10:31:20.000000000 +0200 @@ -499,7 +499,7 @@ } // Volumes mocks base method. -func (m *MockService) Volumes(ctx context.Context, project *types.Project, options api.VolumesOptions) ([]api.VolumesSummary, error) { +func (m *MockService) Volumes(ctx context.Context, project string, options api.VolumesOptions) ([]api.VolumesSummary, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Volumes", ctx, project, options) ret0, _ := ret[0].([]api.VolumesSummary) @@ -589,18 +589,6 @@ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Log", reflect.TypeOf((*MockLogConsumer)(nil).Log), containerName, message) } -// Register mocks base method. -func (m *MockLogConsumer) Register(container string) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Register", container) -} - -// Register indicates an expected call of Register. -func (mr *MockLogConsumerMockRecorder) Register(container any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockLogConsumer)(nil).Register), container) -} - // Status mocks base method. func (m *MockLogConsumer) Status(container, msg string) { m.ctrl.T.Helper() ++++++ docker-compose.obsinfo ++++++ --- /var/tmp/diff_new_pack.sSapYZ/_old 2025-09-19 15:35:27.156507790 +0200 +++ /var/tmp/diff_new_pack.sSapYZ/_new 2025-09-19 15:35:27.160507957 +0200 @@ -1,5 +1,5 @@ name: docker-compose -version: 2.39.3 -mtime: 1757347620 -commit: 385b3f5c9643955e68b7009f6a305933678b51ea +version: 2.39.4 +mtime: 1758270680 +commit: a32dc3da722e6b2e4fbfc72e40b1a697c4686460 ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/docker-compose/vendor.tar.gz /work/SRC/openSUSE:Factory/.docker-compose.new.27445/vendor.tar.gz differ: char 131, line 2
