diff --git a/paths/resolve.go b/paths/resolve.go index c23a717d1..62a250a77 100644 --- a/paths/resolve.go +++ b/paths/resolve.go @@ -96,7 +96,10 @@ func (r *relativePathsResolver) absPath(value any) (any, error) { if filepath.IsAbs(v) { return v, nil } - return filepath.Join(r.workingDir, v), nil + if v != "" { + return filepath.Join(r.workingDir, v), nil + } + return v, nil } return nil, fmt.Errorf("unexpected type %T", value) } diff --git a/schema/compose-spec.json b/schema/compose-spec.json index 54e3b8968..81dacbcf2 100644 --- a/schema/compose-spec.json +++ b/schema/compose-spec.json @@ -461,6 +461,7 @@ "target": {"type": "string"} } }, + "required": ["path", "action"], "additionalProperties": false, "patternProperties": {"^x-": {}} } diff --git a/validation/validation.go b/validation/validation.go index 25b37d9e4..758383017 100644 --- a/validation/validation.go +++ b/validation/validation.go @@ -18,17 +18,20 @@ package validation import ( "fmt" + "os" "strings" "github.com/compose-spec/compose-go/v2/tree" + "github.com/pkg/errors" ) type checkerFunc func(value any, p tree.Path) error var checks = map[tree.Path]checkerFunc{ - "volumes.*": checkVolume, - "configs.*": checkFileObject("file", "environment", "content"), - "secrets.*": checkFileObject("file", "environment"), + "volumes.*": checkVolume, + "configs.*": checkFileObject("file", "environment", "content"), + "secrets.*": checkFileObject("file", "environment"), + "services.*.develop.watch.*.path": checkPath, } func Validate(dict map[string]any) error { @@ -85,3 +88,14 @@ func checkFileObject(keys ...string) checkerFunc { return nil } } + +func checkPath(value any, p tree.Path) error { + v := value.(string) + if v == "" { + return errors.Errorf("%s: value can't be blank", p) + } + if _, err := os.Stat(v); err != nil { + return errors.Wrapf(err, "%s: invalid path %s", p, value) + } + return nil +}