diff --git a/pkg/compose/publish.go b/pkg/compose/publish.go index b5fdee6d84c..459a5f2f5e3 100644 --- a/pkg/compose/publish.go +++ b/pkg/compose/publish.go @@ -18,6 +18,7 @@ package compose import ( "context" + "errors" "fmt" "os" @@ -136,6 +137,9 @@ func (s *composeService) generateImageDigestsOverride(ctx context.Context, proje } func (s *composeService) preChecks(project *types.Project, options api.PublishOptions) (bool, error) { + if ok, err := s.checkOnlyBuildSection(project); !ok { + return false, err + } envVariables, err := s.checkEnvironmentVariables(project, options) if err != nil { return false, err @@ -214,3 +218,20 @@ func envFileLayers(project *types.Project) []ocipush.Pushable { } return layers } + +func (s *composeService) checkOnlyBuildSection(project *types.Project) (bool, error) { + errorList := []string{} + for _, service := range project.Services { + if service.Image == "" && service.Build != nil { + errorList = append(errorList, service.Name) + } + } + if len(errorList) > 0 { + errMsg := "your Compose stack cannot be published as it only contains a build section for service(s):\n" + for _, serviceInError := range errorList { + errMsg += fmt.Sprintf("- %q\n", serviceInError) + } + return false, errors.New(errMsg) + } + return true, nil +} diff --git a/pkg/e2e/fixtures/publish/Dockerfile b/pkg/e2e/fixtures/publish/Dockerfile new file mode 100644 index 00000000000..b17b6b06175 --- /dev/null +++ b/pkg/e2e/fixtures/publish/Dockerfile @@ -0,0 +1,15 @@ +# 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 alpine:latest \ No newline at end of file diff --git a/pkg/e2e/fixtures/publish/compose-build-only.yml b/pkg/e2e/fixtures/publish/compose-build-only.yml new file mode 100644 index 00000000000..e4736d983df --- /dev/null +++ b/pkg/e2e/fixtures/publish/compose-build-only.yml @@ -0,0 +1,9 @@ +services: + serviceA: + build: + context: . + dockerfile: Dockerfile + serviceB: + build: + context: . + dockerfile: Dockerfile diff --git a/pkg/e2e/publish_test.go b/pkg/e2e/publish_test.go index 52625cfd0e2..3a941534366 100644 --- a/pkg/e2e/publish_test.go +++ b/pkg/e2e/publish_test.go @@ -107,4 +107,13 @@ FOO=bar`), res.Combined()) assert.Assert(t, strings.Contains(res.Combined(), `BAR=baz`), res.Combined()) assert.Assert(t, strings.Contains(res.Combined(), `QUIX=`), res.Combined()) }) + + t.Run("refuse to publish with build section only", func(t *testing.T) { + res := c.RunDockerComposeCmdNoCheck(t, "-f", "./fixtures/publish/compose-build-only.yml", + "-p", projectName, "alpha", "publish", "test/test", "--with-env", "-y", "--dry-run") + res.Assert(t, icmd.Expected{ExitCode: 1}) + assert.Assert(t, strings.Contains(res.Combined(), "your Compose stack cannot be published as it only contains a build section for service(s):"), res.Combined()) + assert.Assert(t, strings.Contains(res.Combined(), "serviceA"), res.Combined()) + assert.Assert(t, strings.Contains(res.Combined(), "serviceB"), res.Combined()) + }) }