@@ -11,6 +11,7 @@ import (
1111 "github.com/compose-spec/compose-go/v2/consts"
1212 "github.com/compose-spec/compose-go/v2/dotenv"
1313 "github.com/compose-spec/compose-go/v2/loader"
14+ composeschema "github.com/compose-spec/compose-go/v2/schema"
1415 composetypes "github.com/compose-spec/compose-go/v2/types"
1516 "github.com/docker/buildx/util/buildflags"
1617 dockeropts "github.com/docker/cli/opts"
@@ -35,21 +36,7 @@ func ParseComposeFiles(fs []File) (*Config, error) {
3536}
3637
3738func ParseCompose (cfgs []composetypes.ConfigFile , envs map [string ]string ) (* Config , error ) {
38- if envs == nil {
39- envs = make (map [string ]string )
40- }
41- cfg , err := loader .LoadWithContext (context .Background (), composetypes.ConfigDetails {
42- ConfigFiles : cfgs ,
43- Environment : envs ,
44- }, func (options * loader.Options ) {
45- projectName := "bake"
46- if v , ok := envs [consts .ComposeProjectName ]; ok && v != "" {
47- projectName = v
48- }
49- options .SetProjectName (projectName , false )
50- options .SkipNormalization = true
51- options .Profiles = []string {"*" }
52- })
39+ cfg , err := loadComposeFiles (cfgs , envs )
5340 if err != nil {
5441 return nil , err
5542 }
@@ -208,6 +195,67 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf
208195 return & c , nil
209196}
210197
198+ func loadComposeFiles (cfgs []composetypes.ConfigFile , envs map [string ]string , options ... func (* loader.Options )) (* composetypes.Project , error ) {
199+ if envs == nil {
200+ envs = make (map [string ]string )
201+ }
202+
203+ cfgDetails := composetypes.ConfigDetails {
204+ ConfigFiles : cfgs ,
205+ Environment : envs ,
206+ }
207+
208+ raw , err := loader .LoadModelWithContext (context .Background (), cfgDetails , append ([]func (* loader.Options ){func (opts * loader.Options ) {
209+ projectName := "bake"
210+ if v , ok := envs [consts .ComposeProjectName ]; ok && v != "" {
211+ projectName = v
212+ }
213+ opts .SetProjectName (projectName , false )
214+ opts .SkipNormalization = true
215+ opts .SkipValidation = true
216+ }}, options ... )... )
217+ if err != nil {
218+ return nil , err
219+ }
220+
221+ filtered := make (map [string ]any )
222+ for _ , key := range []string {"services" , "secrets" } {
223+ if key == "services" {
224+ if services , ok := raw ["services" ].(map [string ]any ); ok {
225+ filteredServices := make (map [string ]any )
226+ for svcName , svc := range services {
227+ if svc == nil {
228+ filteredServices [svcName ] = map [string ]any {}
229+ } else if svcMap , ok := svc .(map [string ]any ); ok {
230+ filteredService := make (map [string ]any )
231+ for _ , svcField := range []string {"image" , "build" , "environment" , "env_file" } {
232+ if val , ok := svcMap [svcField ]; ok {
233+ filteredService [svcField ] = val
234+ }
235+ }
236+ filteredServices [svcName ] = filteredService
237+ }
238+ }
239+ filtered ["services" ] = filteredServices
240+ }
241+ } else if v , ok := raw [key ]; ok {
242+ filtered [key ] = v
243+ }
244+ }
245+
246+ if err := composeschema .Validate (filtered ); err != nil {
247+ return nil , err
248+ }
249+
250+ return loader .ModelToProject (filtered , loader .ToOptions (& cfgDetails , append ([]func (* loader.Options ){func (options * loader.Options ) {
251+ options .SkipNormalization = true
252+ options .Profiles = []string {"*" }
253+ }}, options ... )), composetypes.ConfigDetails {
254+ ConfigFiles : cfgs ,
255+ Environment : envs ,
256+ })
257+ }
258+
211259func validateComposeFile (dt []byte , fn string ) (bool , error ) {
212260 envs , err := composeEnv ()
213261 if err != nil {
@@ -225,16 +273,7 @@ func validateComposeFile(dt []byte, fn string) (bool, error) {
225273}
226274
227275func validateCompose (dt []byte , envs map [string ]string ) error {
228- _ , err := loader .LoadWithContext (context .Background (), composetypes.ConfigDetails {
229- ConfigFiles : []composetypes.ConfigFile {
230- {
231- Content : dt ,
232- },
233- },
234- Environment : envs ,
235- }, func (options * loader.Options ) {
236- options .SetProjectName ("bake" , false )
237- options .SkipNormalization = true
276+ _ , err := loadComposeFiles ([]composetypes.ConfigFile {{Content : dt }}, envs , func (options * loader.Options ) {
238277 // consistency is checked later in ParseCompose to ensure multiple
239278 // compose files can be merged together
240279 options .SkipConsistencyCheck = true
0 commit comments