github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/pkg/project/project.go (about) 1 package project 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 9 "github.com/BurntSushi/toml" 10 "github.com/pkg/errors" 11 12 "github.com/buildpacks/pack/pkg/logging" 13 "github.com/buildpacks/pack/pkg/project/types" 14 v01 "github.com/buildpacks/pack/pkg/project/v01" 15 v02 "github.com/buildpacks/pack/pkg/project/v02" 16 ) 17 18 type Project struct { 19 Version string `toml:"schema-version"` 20 } 21 22 type VersionDescriptor struct { 23 Project Project `toml:"_"` 24 } 25 26 var parsers = map[string]func(string) (types.Descriptor, toml.MetaData, error){ 27 "0.1": v01.NewDescriptor, 28 "0.2": v02.NewDescriptor, 29 } 30 31 func ReadProjectDescriptor(pathToFile string, logger logging.Logger) (types.Descriptor, error) { 32 projectTomlContents, err := os.ReadFile(filepath.Clean(pathToFile)) 33 if err != nil { 34 return types.Descriptor{}, err 35 } 36 37 var versionDescriptor struct { 38 Project struct { 39 Version string `toml:"schema-version"` 40 } `toml:"_"` 41 } 42 43 _, err = toml.Decode(string(projectTomlContents), &versionDescriptor) 44 if err != nil { 45 return types.Descriptor{}, errors.Wrapf(err, "parsing schema version") 46 } 47 48 version := versionDescriptor.Project.Version 49 if version == "" { 50 logger.Warn("No schema version declared in project.toml, defaulting to schema version 0.1") 51 version = "0.1" 52 } 53 54 if _, ok := parsers[version]; !ok { 55 return types.Descriptor{}, fmt.Errorf("unknown project descriptor schema version %s", version) 56 } 57 58 descriptor, tomlMetaData, err := parsers[version](string(projectTomlContents)) 59 if err != nil { 60 return types.Descriptor{}, err 61 } 62 63 warnIfTomlContainsKeysNotSupportedBySchema(version, tomlMetaData, logger) 64 65 return descriptor, validate(descriptor) 66 } 67 68 func warnIfTomlContainsKeysNotSupportedBySchema(schemaVersion string, tomlMetaData toml.MetaData, logger logging.Logger) { 69 unsupportedKeys := []string{} 70 71 // filter out any keys from [_] 72 for _, undecodedKey := range tomlMetaData.Undecoded() { 73 keyName := undecodedKey.String() 74 if keyName != "_" && !strings.HasPrefix(keyName, "_.schema-version") { 75 unsupportedKeys = append(unsupportedKeys, keyName) 76 } 77 } 78 79 if len(unsupportedKeys) != 0 { 80 logger.Warnf("The following keys declared in project.toml are not supported in schema version %s:\n", schemaVersion) 81 for _, unsupportedKey := range unsupportedKeys { 82 logger.Warnf("- %s\n", unsupportedKey) 83 } 84 logger.Warn("The above keys will be ignored. If this is not intentional, maybe try updating your schema version.\n") 85 } 86 } 87 88 func validate(p types.Descriptor) error { 89 if p.Build.Exclude != nil && p.Build.Include != nil { 90 return errors.New("project.toml: cannot have both include and exclude defined") 91 } 92 93 if len(p.Project.Licenses) > 0 { 94 for _, license := range p.Project.Licenses { 95 if license.Type == "" && license.URI == "" { 96 return errors.New("project.toml: must have a type or uri defined for each license") 97 } 98 } 99 } 100 101 for _, bp := range p.Build.Buildpacks { 102 if bp.ID == "" && bp.URI == "" { 103 return errors.New("project.toml: buildpacks must have an id or url defined") 104 } 105 if bp.URI != "" && bp.Version != "" { 106 return errors.New("project.toml: buildpacks cannot have both uri and version defined") 107 } 108 } 109 110 return nil 111 }