github.com/SAP/cloud-mta-build-tool@v1.2.27/internal/buildops/build_params.go (about) 1 package buildops 2 3 import ( 4 "os" 5 "path/filepath" 6 "reflect" 7 "strings" 8 9 "github.com/pkg/errors" 10 11 "github.com/SAP/cloud-mta-build-tool/internal/archive" 12 "github.com/SAP/cloud-mta-build-tool/internal/commands" 13 "github.com/SAP/cloud-mta/mta" 14 ) 15 16 const ( 17 // SupportedPlatformsParam - name of build-params property for supported platforms 18 SupportedPlatformsParam = "supported-platforms" 19 20 // ModuleArtifactDefaultName - the default name of the build artifact. 21 // It can be changed using properties like build-result or build-artifact-name in the build parameters. 22 ModuleArtifactDefaultName = "data.zip" 23 builderParam = "builder" 24 requiresParam = "requires" 25 buildResultParam = "build-result" 26 nameParam = "name" 27 artifactsParam = "artifacts" 28 buildArtifactNameParam = "build-artifact-name" 29 targetPathParam = "target-path" 30 noSourceParam = "no-source" 31 ) 32 33 // BuildRequires - build requires section. 34 type BuildRequires struct { 35 Name string `yaml:"name,omitempty"` 36 Artifacts []string `yaml:"artifacts,omitempty"` 37 TargetPath string `yaml:"target-path,omitempty"` 38 } 39 40 // GetBuildRequires - gets Requires property of module's build-params property 41 // as generic property and converts it to slice of BuildRequires structures 42 func GetBuildRequires(module *mta.Module) []BuildRequires { 43 // check existence of module's build-params.require property 44 if module.BuildParams != nil && module.BuildParams[requiresParam] != nil { 45 requires := module.BuildParams[requiresParam].([]interface{}) 46 buildRequires := []BuildRequires{} 47 // go through requirements 48 for _, reqI := range requires { 49 // cast requirement to generic map 50 reqMap, ok := reqI.(map[string]interface{}) 51 if !ok { 52 reqMap = commands.ConvertMap(reqI.(map[interface{}]interface{})) 53 } 54 // init resulting typed requirement 55 reqStr := BuildRequires{ 56 Name: getStrParam(reqMap, nameParam), 57 Artifacts: []string{}, 58 TargetPath: getStrParam(reqMap, targetPathParam), 59 } 60 // fill Artifacts field of resulting requirement 61 if reqMap[artifactsParam] == nil { 62 reqStr.Artifacts = nil 63 } else { 64 for _, artifact := range reqMap[artifactsParam].([]interface{}) { 65 reqStr.Artifacts = append(reqStr.Artifacts, []string{artifact.(string)}...) 66 } 67 } 68 // add typed requirement to result 69 buildRequires = append(buildRequires, []BuildRequires{reqStr}...) 70 71 } 72 return buildRequires 73 } 74 return nil 75 } 76 77 // getStrParam - get string parameter from the map 78 func getStrParam(m map[string]interface{}, param string) string { 79 if m[param] == nil { 80 return "" 81 } 82 return m[param].(string) 83 } 84 85 // Order of modules building is done according to the dependencies defined in build parameters. 86 // In case of problems in this definition build process should not start and corresponding error must be provided. 87 // Possible problems: 88 // 1. Cyclic dependencies 89 // 2. Dependency on not defined module 90 91 // GetRequiresArtifacts returns the source path, target path and patterns of files and folders to copy from a module's requires section 92 func GetRequiresArtifacts(ep dir.ISourceModule, mta *mta.MTA, requires *BuildRequires, moduleName string, resolveBuildResult bool) (source string, target string, patterns []string, err error) { 93 // validate module names - both in process and required 94 module, err := mta.GetModuleByName(moduleName) 95 if err != nil { 96 return "", "", nil, errors.Wrapf(err, reqFailedOnModuleGetMsg, moduleName, requires.Name, moduleName) 97 } 98 99 requiredModule, err := mta.GetModuleByName(requires.Name) 100 if err != nil { 101 return "", "", nil, errors.Wrapf(err, reqFailedOnModuleGetMsg, moduleName, requires.Name, requires.Name) 102 } 103 104 _, defaultBuildResult, err := commands.CommandProvider(*requiredModule) 105 if err != nil { 106 return "", "", nil, errors.Wrapf(err, reqFailedOnCommandsGetMsg, moduleName, requires.Name, requires.Name) 107 } 108 109 // Build paths for artifacts copying 110 sourcePath, err := GetModuleSourceArtifactPath(ep, false, requiredModule, defaultBuildResult, resolveBuildResult) 111 if err != nil { 112 return "", "", nil, errors.Wrapf(err, reqFailedOnBuildResultMsg, moduleName, requires.Name) 113 } 114 targetPath := getRequiredTargetPath(ep, module, requires) 115 return sourcePath, targetPath, requires.Artifacts, nil 116 } 117 118 // ProcessRequirements - Processes build requirement of module (using moduleName). 119 func ProcessRequirements(ep dir.ISourceModule, mta *mta.MTA, requires *BuildRequires, moduleName string) error { 120 sourcePath, targetPath, artifacts, err := GetRequiresArtifacts(ep, mta, requires, moduleName, true) 121 if err != nil { 122 return err 123 } 124 // execute copy of artifacts 125 err = dir.CopyByPatterns(sourcePath, targetPath, artifacts) 126 if err != nil { 127 return errors.Wrapf(err, reqFailedOnCopyMsg, moduleName, requires.Name) 128 } 129 return nil 130 } 131 132 // GetModuleSourceArtifactPath - get the module's artifact that has to be archived in the mtar, from the project sources 133 func GetModuleSourceArtifactPath(loc dir.ISourceModule, depDesc bool, module *mta.Module, defaultBuildResult string, resolveBuildResult bool) (path string, e error) { 134 if module.Path == "" { 135 return "", nil 136 } 137 path = loc.GetSourceModuleDir(module.Path) 138 if !depDesc { 139 buildResult := defaultBuildResult 140 var ok bool 141 if module.BuildParams != nil && module.BuildParams[buildResultParam] != nil { 142 buildResult, ok = module.BuildParams[buildResultParam].(string) 143 if !ok { 144 return "", errors.Errorf(WrongBuildResultMsg, module.BuildParams[buildResultParam], module.Name) 145 } 146 } 147 if buildResult != "" { 148 path = filepath.Join(path, buildResult) 149 if resolveBuildResult { 150 path, e = dir.FindPath(path) 151 if e != nil { 152 return "", e 153 } 154 } 155 } 156 } 157 return path, nil 158 } 159 160 // IsArchive - check if file is a folder or an archive 161 func IsArchive(path string, resolvePath bool) (isArchive bool, e error) { 162 163 if !resolvePath { 164 return guessIfArchive(path), nil 165 } 166 info, err := os.Stat(path) 167 168 if err != nil { 169 return false, err 170 } 171 isFolder := info.IsDir() 172 isArchive = false 173 if !isFolder { 174 isArchive = guessIfArchive(path) 175 } 176 return isArchive, nil 177 } 178 179 func guessIfArchive(path string) bool { 180 ext := filepath.Ext(path) 181 return ext == ".zip" || ext == ".jar" || ext == ".war" 182 } 183 184 // GetModuleTargetArtifactPath - get the path to where the module's artifact should be created in the temp folder, from which it's archived in the mtar 185 func GetModuleTargetArtifactPath(moduleLoc dir.IModule, depDesc bool, module *mta.Module, defaultBuildResult string, 186 resolveBuildResult bool) (path string, toArchive bool, e error) { 187 188 if module.Path == "" { 189 return "", false, nil 190 } 191 if depDesc { 192 path = filepath.Join(moduleLoc.GetTargetModuleDir(module.Path)) 193 } else { 194 moduleSourceArtifactPath, err := GetModuleSourceArtifactPath(moduleLoc, depDesc, module, defaultBuildResult, resolveBuildResult) 195 if err != nil { 196 return "", false, err 197 } 198 isArchive, err := IsArchive(moduleSourceArtifactPath, resolveBuildResult) 199 if err != nil { 200 return "", false, errors.Wrapf(err, wrongPathMsg, moduleSourceArtifactPath) 201 } 202 artifactName, artifactExt, err := getArtifactInfo(isArchive, module, moduleSourceArtifactPath) 203 if err != nil { 204 return "", false, err 205 } 206 toArchive = !isArchive 207 208 artifactRelPath, err := moduleLoc.GetSourceModuleArtifactRelPath(module.Path, moduleSourceArtifactPath) 209 if err != nil { 210 return "", false, err 211 } 212 path = filepath.Join(moduleLoc.GetTargetModuleDir(module.Name), artifactRelPath, artifactName+artifactExt) 213 } 214 return path, toArchive, nil 215 } 216 217 func getArtifactInfo(isArchive bool, module *mta.Module, moduleSourceArtifactPath string) (artifactName, artifactExt string, err error) { 218 var ok bool 219 var artifactFullName string 220 if isArchive { 221 artifactFullName = filepath.Base(moduleSourceArtifactPath) 222 } else { 223 artifactFullName = ModuleArtifactDefaultName 224 } 225 artifactExt = filepath.Ext(artifactFullName) 226 artifactName = artifactFullName[0 : len(artifactFullName)-len(artifactExt)] 227 if module.BuildParams != nil && module.BuildParams[buildArtifactNameParam] != nil { 228 artifactName, ok = module.BuildParams[buildArtifactNameParam].(string) 229 if !ok { 230 return "", "", errors.Errorf(WrongBuildArtifactNameMsg, module.BuildParams[buildArtifactNameParam], module.Name) 231 } 232 } 233 return 234 } 235 236 // getRequiredTargetPath - provides path of required artifacts 237 func getRequiredTargetPath(ep dir.ISourceModule, module *mta.Module, requires *BuildRequires) string { 238 path := ep.GetSourceModuleDir(module.Path) 239 if requires.TargetPath != "" { 240 // if target folder provided - artifacts will be saved in the sub-folder of the module folder 241 path = filepath.Join(path, requires.TargetPath) 242 } 243 return path 244 } 245 246 // PlatformDefined - if platform defined 247 // If platforms parameter not defined then no limitations on platform, method returns true 248 // Non empty list of platforms has to contain specific platform 249 func PlatformDefined(module *mta.Module, platform string) bool { 250 if module.BuildParams == nil || module.BuildParams[SupportedPlatformsParam] == nil { 251 return true 252 } 253 supportedPlatforms := module.BuildParams[SupportedPlatformsParam] 254 if reflect.TypeOf(supportedPlatforms).Elem().Kind() == reflect.String { 255 sp := supportedPlatforms.([]string) 256 for _, p := range sp { 257 if strings.ToLower(p) == platform { 258 return true 259 } 260 } 261 return false 262 } 263 sp := supportedPlatforms.([]interface{}) 264 for _, p := range sp { 265 if strings.ToLower(p.(string)) == platform { 266 return true 267 } 268 } 269 return false 270 } 271 272 // IfNoSource - checks if "no-source" build parameter defined and set to "true" 273 func IfNoSource(module *mta.Module) bool { 274 if module.BuildParams != nil && module.BuildParams[noSourceParam] != nil { 275 noSource, ok := module.BuildParams[noSourceParam].(bool) 276 return ok && noSource 277 } 278 return false 279 }