Skip to content

Commit ca55904

Browse files
author
maks2134
committed
Fix: respect required: false for env_file in publish command
Fixes #13648 The docker compose publish command was ignoring the required: false setting on env_file entries, causing failures when optional env files were missing. This change modifies three functions: 1. checkForSensitiveData - skips scanning env files with required: false 2. processFile - only processes required env files into layers 3. checkEnvironmentVariables - only considers required env files for environment variable warnings Added tests to verify the fix works correctly. Signed-off-by: Maks Kozlov <maks@example.com> Signed-off-by: maks2134 <maks210306@yandex.by>
1 parent c758557 commit ca55904

File tree

4 files changed

+91
-2
lines changed

4 files changed

+91
-2
lines changed

pkg/compose/publish.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,10 @@ func processFile(ctx context.Context, file string, project *types.Project, extFi
251251
}
252252
for name, service := range base.Services {
253253
for i, envFile := range service.EnvFiles {
254+
// Only process env files that are required
255+
if !envFile.Required {
256+
continue
257+
}
254258
hash := fmt.Sprintf("%x.env", sha256.Sum256([]byte(envFile.Path)))
255259
envFiles[envFile.Path] = hash
256260
f, err = transform.ReplaceEnvFile(f, name, i, hash)
@@ -351,8 +355,12 @@ func (s *composeService) checkEnvironmentVariables(project *types.Project, optio
351355
errorList := map[string][]string{}
352356

353357
for _, service := range project.Services {
354-
if len(service.EnvFiles) > 0 {
355-
errorList[service.Name] = append(errorList[service.Name], fmt.Sprintf("service %q has env_file declared.", service.Name))
358+
for _, envFile := range service.EnvFiles {
359+
// Only consider required env files
360+
if envFile.Required {
361+
errorList[service.Name] = append(errorList[service.Name], fmt.Sprintf("service %q has env_file declared.", service.Name))
362+
break // Only need to add one error per service
363+
}
356364
}
357365
}
358366

@@ -438,6 +446,10 @@ func (s *composeService) checkForSensitiveData(project *types.Project) ([]secret
438446
for _, service := range project.Services {
439447
// Check env files
440448
for _, envFile := range service.EnvFiles {
449+
// Skip env files that are not required
450+
if !envFile.Required {
451+
continue
452+
}
441453
findings, err := scan.ScanFile(envFile.Path)
442454
if err != nil {
443455
return nil, fmt.Errorf("failed to scan env file %s: %w", envFile.Path, err)

pkg/compose/publish_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package compose
1818

1919
import (
2020
"slices"
21+
"strings"
2122
"testing"
2223

2324
"github.com/compose-spec/compose-go/v2/loader"
@@ -100,3 +101,69 @@ services:
100101
return !slices.Contains([]string{".Data", ".Digest", ".Size"}, path.String())
101102
}, cmp.Ignore()))
102103
}
104+
105+
func Test_createLayers_withRequiredFalse(t *testing.T) {
106+
project, err := loader.LoadWithContext(t.Context(), types.ConfigDetails{
107+
WorkingDir: "testdata/publish/",
108+
Environment: types.Mapping{},
109+
ConfigFiles: []types.ConfigFile{
110+
{
111+
Filename: "testdata/publish/compose-required-false.yaml",
112+
},
113+
},
114+
})
115+
assert.NilError(t, err)
116+
project.ComposeFiles = []string{"testdata/publish/compose-required-false.yaml"}
117+
118+
service := &composeService{}
119+
layers, err := service.createLayers(t.Context(), project, api.PublishOptions{
120+
WithEnvironment: true,
121+
})
122+
assert.NilError(t, err)
123+
124+
assert.Equal(t, len(layers), 2)
125+
126+
assert.Equal(t, layers[0].Annotations["com.docker.compose.file"], "compose-required-false.yaml")
127+
128+
assert.Equal(t, layers[1].MediaType, "application/vnd.docker.compose.envfile")
129+
130+
envFileHash := layers[1].Annotations["com.docker.compose.envfile"]
131+
assert.Assert(t, len(envFileHash) > 0)
132+
assert.Assert(t, envFileHash != "missing.env")
133+
}
134+
135+
func Test_checkEnvironmentVariables_withRequiredFalse(t *testing.T) {
136+
project := &types.Project{
137+
Services: types.Services{
138+
"test": {
139+
Name: "test",
140+
EnvFiles: []types.EnvFile{
141+
{
142+
Path: "missing.env",
143+
Required: false,
144+
},
145+
{
146+
Path: "existing.env",
147+
Required: true,
148+
},
149+
},
150+
},
151+
"test2": {
152+
Name: "test2",
153+
EnvFiles: []types.EnvFile{
154+
{
155+
Path: "optional.env",
156+
Required: false,
157+
},
158+
},
159+
},
160+
},
161+
}
162+
163+
service := &composeService{}
164+
165+
err := service.checkEnvironmentVariables(project, api.PublishOptions{})
166+
assert.Assert(t, err != nil)
167+
assert.Assert(t, strings.Contains(err.Error(), `service "test" has env_file declared.`))
168+
assert.Assert(t, !strings.Contains(err.Error(), `service "test2"`))
169+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name: test-required-false
2+
services:
3+
test:
4+
image: test
5+
env_file:
6+
- path: missing.env
7+
required: false
8+
- path: existing.env
9+
required: true
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
EXISTING_VAR=value

0 commit comments

Comments
 (0)