diff --git a/types/project.go b/types/project.go index 852361be..4f1646ca 100644 --- a/types/project.go +++ b/types/project.go @@ -985,19 +985,18 @@ func (p *Project) WithServicesTransform(fn func(name string, s ServiceConfig) (S services := newProject.Services eg, ctx := errgroup.WithContext(context.Background()) + collected := Services{} eg.Go(func() error { - s := Services{} for expect > 0 { select { case <-ctx.Done(): // interrupted as some goroutine returned an error return nil case r := <-resultCh: - s[r.name] = r.service + collected[r.name] = r.service expect-- } } - newProject.Services = s return nil }) for n, s := range services { @@ -1015,7 +1014,11 @@ func (p *Project) WithServicesTransform(fn func(name string, s ServiceConfig) (S return nil }) } - return newProject, eg.Wait() + if err := eg.Wait(); err != nil { + return newProject, err + } + newProject.Services = collected + return newProject, nil } // CheckContainerNameUnicity validate project doesn't have services declaring the same container_name diff --git a/types/project_test.go b/types/project_test.go index 3b8af339..1883d7b3 100644 --- a/types/project_test.go +++ b/types/project_test.go @@ -904,3 +904,23 @@ func TestWithSelectedJob(t *testing.T) { func ptr[T any](s T) *T { return &s } + +func TestWithServicesTransform_concurrent(t *testing.T) { + const n = 100 + p := &Project{Services: Services{}} + for i := 0; i < n; i++ { + p.Services[fmt.Sprintf("svc_%d", i)] = ServiceConfig{Image: fmt.Sprintf("img_%d", i)} + } + + got, err := p.WithServicesTransform(func(_ string, s ServiceConfig) (ServiceConfig, error) { + s.Image += "-transformed" + return s, nil + }) + assert.NilError(t, err) + assert.Equal(t, len(got.Services), n) + for i := 0; i < n; i++ { + name := fmt.Sprintf("svc_%d", i) + want := fmt.Sprintf("img_%d-transformed", i) + assert.Equal(t, got.Services[name].Image, want) + } +}