Skip to content

Commit 27a3a6a

Browse files
committed
mange properly include.project_directory when including files
Signed-off-by: Guillaume Lours <[email protected]>
1 parent 00e000c commit 27a3a6a

File tree

5 files changed

+102
-6
lines changed

5 files changed

+102
-6
lines changed

loader/include.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
"github.com/compose-spec/compose-go/v2/types"
3030
)
3131

32-
// loadIncludeConfig parse the require config from raw yaml
32+
// loadIncludeConfig parse the required config from raw yaml
3333
func loadIncludeConfig(source any) ([]types.IncludeConfig, error) {
3434
if source == nil {
3535
return nil, nil
@@ -76,11 +76,19 @@ func ApplyInclude(ctx context.Context, configDetails types.ConfigDetails, model
7676
p = path
7777

7878
if i == 0 { // This is the "main" file, used to define project-directory. Others are overrides
79-
relworkingdir = loader.Dir(path)
80-
if r.ProjectDirectory == "" {
79+
80+
switch {
81+
case r.ProjectDirectory == "":
82+
relworkingdir = loader.Dir(path)
8183
r.ProjectDirectory = filepath.Dir(path)
82-
}
84+
case !filepath.IsAbs(r.ProjectDirectory):
85+
relworkingdir = loader.Dir(r.ProjectDirectory)
86+
r.ProjectDirectory = filepath.Join(configDetails.WorkingDir, r.ProjectDirectory)
8387

88+
default:
89+
relworkingdir = r.ProjectDirectory
90+
91+
}
8492
for _, f := range included {
8593
if f == path {
8694
included = append(included, path)

loader/include_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"os"
2222
"path/filepath"
23+
"runtime"
2324
"testing"
2425

2526
"github.com/compose-spec/compose-go/v2/types"
@@ -162,6 +163,67 @@ services:
162163

163164
}
164165

166+
func TestIncludeWithProjectDirectory(t *testing.T) {
167+
var envs map[string]string
168+
if runtime.GOOS == "windows" {
169+
envs = map[string]string{"COMPOSE_CONVERT_WINDOWS_PATHS": "1"}
170+
}
171+
p, err := LoadWithContext(context.Background(), types.ConfigDetails{
172+
WorkingDir: "testdata/include",
173+
Environment: envs,
174+
ConfigFiles: []types.ConfigFile{
175+
{
176+
Filename: "testdata/include/project-directory.yaml",
177+
},
178+
},
179+
}, withProjectName("test-load-project-directory", true))
180+
assert.NilError(t, err)
181+
assert.Equal(t, filepath.ToSlash(p.Services["service"].Build.Context), "testdata/subdir")
182+
assert.Equal(t, filepath.ToSlash(p.Services["service"].Volumes[0].Source), "testdata/subdir/compose-test-extends-imported.yaml")
183+
assert.Equal(t, filepath.ToSlash(p.Services["service"].EnvFiles[0].Path), "testdata/subdir/extra.env")
184+
185+
}
186+
187+
func TestNestedIncludeAndExtends(t *testing.T) {
188+
fileName := "compose.yml"
189+
yaml := `
190+
include:
191+
- project_directory: .
192+
path: dir/included.yaml
193+
`
194+
tmpdir := t.TempDir()
195+
path := createFile(t, tmpdir, yaml, fileName)
196+
197+
yaml = `
198+
services:
199+
included:
200+
extends:
201+
file: dir/extended.yaml
202+
service: extended
203+
`
204+
createFileSubDir(t, tmpdir, "dir", yaml, "included.yaml")
205+
206+
yaml = `
207+
services:
208+
extended:
209+
image: alpine
210+
`
211+
createFile(t, filepath.Join(tmpdir, "dir"), yaml, "extended.yaml")
212+
p, err := Load(types.ConfigDetails{
213+
WorkingDir: tmpdir,
214+
ConfigFiles: []types.ConfigFile{{
215+
Filename: path,
216+
}},
217+
Environment: nil,
218+
}, func(options *Options) {
219+
options.SkipNormalization = true
220+
options.ResolvePaths = true
221+
options.SetProjectName("project", true)
222+
})
223+
assert.NilError(t, err)
224+
assert.Equal(t, p.Services["included"].Image, "alpine")
225+
}
226+
165227
func createFile(t *testing.T, rootDir, content, fileName string) string {
166228
path := filepath.Join(rootDir, fileName)
167229
assert.NilError(t, os.WriteFile(path, []byte(content), 0o600))

loader/loader.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,26 @@ func (l localResourceLoader) Load(_ context.Context, p string) (string, error) {
148148
return l.abs(p), nil
149149
}
150150

151-
func (l localResourceLoader) Dir(path string) string {
152-
path = l.abs(filepath.Dir(path))
151+
func (l localResourceLoader) Dir(originalPath string) string {
152+
path := l.abs(originalPath)
153+
if !l.isDir(path) {
154+
path = l.abs(filepath.Dir(originalPath))
155+
}
153156
rel, err := filepath.Rel(l.WorkingDir, path)
154157
if err != nil {
155158
return path
156159
}
157160
return rel
158161
}
159162

163+
func (l localResourceLoader) isDir(path string) bool {
164+
fileInfo, err := os.Stat(path)
165+
if err != nil {
166+
return false
167+
}
168+
return fileInfo.IsDir()
169+
}
170+
160171
func (o *Options) clone() *Options {
161172
return &Options{
162173
SkipValidation: o.SkipValidation,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
services:
2+
service:
3+
build:
4+
dockerfile_inline: |
5+
FROM busybox
6+
COPY compose-test-extends-imported.yaml compose.yaml
7+
volumes:
8+
- type: bind
9+
source: compose-test-extends-imported.yaml
10+
target: /mnt/bind/compose.yaml
11+
env_file:
12+
- extra.env
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include:
2+
- project_directory: ../subdir
3+
path: ./dir/compose.yaml

0 commit comments

Comments
 (0)