block the publication of an OCI artifact if one or more services contain only a build section

Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
This commit is contained in:
Guillaume Lours 2025-03-03 14:51:39 +01:00
parent 876ecc48be
commit 66dfa7d181
4 changed files with 54 additions and 0 deletions

View File

@ -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
}

View File

@ -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

View File

@ -0,0 +1,9 @@
services:
serviceA:
build:
context: .
dockerfile: Dockerfile
serviceB:
build:
context: .
dockerfile: Dockerfile

View File

@ -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())
})
}