You've already forked sap-jenkins-library
							
							
				mirror of
				https://github.com/SAP/jenkins-library.git
				synced 2025-10-30 23:57:50 +02:00 
			
		
		
		
	go: mta build (#1128)
move mtaBuild step from groovy to go. Co-authored-by: Stephan Aßmus <stephan.assmus@sap.com>
This commit is contained in:
		
							
								
								
									
										390
									
								
								cmd/mtaBuild.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										390
									
								
								cmd/mtaBuild.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,390 @@ | |||||||
|  | package cmd | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/command" | ||||||
|  | 	piperhttp "github.com/SAP/jenkins-library/pkg/http" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/log" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/maven" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/piperutils" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/telemetry" | ||||||
|  | 	"gopkg.in/yaml.v2" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | 	"text/template" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const templateMtaYml = `_schema-version: "3.1" | ||||||
|  | ID: "{{.ID}}" | ||||||
|  | version: {{.Version}} | ||||||
|  |  | ||||||
|  | parameters: | ||||||
|  |   hcp-deployer-version: "1.1.0" | ||||||
|  |  | ||||||
|  | modules: | ||||||
|  |   - name: {{.ApplicationName}} | ||||||
|  |     type: html5 | ||||||
|  |     path: . | ||||||
|  |     parameters: | ||||||
|  |        version: {{.Version}}-${timestamp} | ||||||
|  |        name: {{.ApplicationName}} | ||||||
|  |     build-parameters: | ||||||
|  |       builder: grunt | ||||||
|  |       build-result: dist` | ||||||
|  |  | ||||||
|  | // for mocking | ||||||
|  | var getSettingsFile = maven.GetSettingsFile | ||||||
|  |  | ||||||
|  | // MTABuildTarget ... | ||||||
|  | type MTABuildTarget int | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	// NEO ... | ||||||
|  | 	NEO MTABuildTarget = iota | ||||||
|  | 	// CF ... | ||||||
|  | 	CF MTABuildTarget = iota | ||||||
|  | 	//XSA ... | ||||||
|  | 	XSA MTABuildTarget = iota | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // ValueOfBuildTarget ... | ||||||
|  | func ValueOfBuildTarget(str string) (MTABuildTarget, error) { | ||||||
|  | 	switch str { | ||||||
|  | 	case "NEO": | ||||||
|  | 		return NEO, nil | ||||||
|  | 	case "CF": | ||||||
|  | 		return CF, nil | ||||||
|  | 	case "XSA": | ||||||
|  | 		return XSA, nil | ||||||
|  | 	default: | ||||||
|  | 		return -1, fmt.Errorf("Unknown BuildTarget/Platform: '%s'", str) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // String ... | ||||||
|  | func (m MTABuildTarget) String() string { | ||||||
|  | 	return [...]string{ | ||||||
|  | 		"NEO", | ||||||
|  | 		"CF", | ||||||
|  | 		"XSA", | ||||||
|  | 	}[m] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func mtaBuild(config mtaBuildOptions, | ||||||
|  | 	telemetryData *telemetry.CustomData, | ||||||
|  | 	commonPipelineEnvironment *mtaBuildCommonPipelineEnvironment) { | ||||||
|  | 	log.Entry().Debugf("Launching mta build") | ||||||
|  | 	files := piperutils.Files{} | ||||||
|  | 	httpClient := piperhttp.Client{} | ||||||
|  | 	err := runMtaBuild(config, commonPipelineEnvironment, &command.Command{}, &files, &httpClient) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Entry(). | ||||||
|  | 			WithError(err). | ||||||
|  | 			Fatal("failed to execute mta build") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func runMtaBuild(config mtaBuildOptions, | ||||||
|  | 	commonPipelineEnvironment *mtaBuildCommonPipelineEnvironment, | ||||||
|  | 	e envExecRunner, | ||||||
|  | 	p piperutils.FileUtils, | ||||||
|  | 	httpClient piperhttp.Downloader) error { | ||||||
|  |  | ||||||
|  | 	e.Stdout(log.Entry().Writer()) // not sure if using the logging framework here is a suitable approach. We handover already log formatted | ||||||
|  | 	e.Stderr(log.Entry().Writer()) // entries to a logging framwork again. But this is considered to be some kind of project standard. | ||||||
|  |  | ||||||
|  | 	var err error | ||||||
|  |  | ||||||
|  | 	handleSettingsFiles(config, p, httpClient) | ||||||
|  |  | ||||||
|  | 	handleDefaultNpmRegistry(config, e) | ||||||
|  |  | ||||||
|  | 	mtaYamlFile := "mta.yaml" | ||||||
|  | 	mtaYamlFileExists, err := p.FileExists(mtaYamlFile) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !mtaYamlFileExists { | ||||||
|  |  | ||||||
|  | 		if err = createMtaYamlFile(mtaYamlFile, config.ApplicationName, p); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	} else { | ||||||
|  | 		log.Entry().Infof("\"%s\" file found in project sources", mtaYamlFile) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err = setTimeStamp(mtaYamlFile, p); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	mtarName, err := getMtarName(config, mtaYamlFile, p) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var call []string | ||||||
|  |  | ||||||
|  | 	switch config.MtaBuildTool { | ||||||
|  |  | ||||||
|  | 	case "classic": | ||||||
|  |  | ||||||
|  | 		mtaJar := getMarJarName(config) | ||||||
|  |  | ||||||
|  | 		buildTarget, err := ValueOfBuildTarget(config.BuildTarget) | ||||||
|  |  | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		call = append(call, "java", "-jar", mtaJar, "--mtar", mtarName, fmt.Sprintf("--build-target=%s", buildTarget), "build") | ||||||
|  | 		if len(config.Extensions) != 0 { | ||||||
|  | 			call = append(call, fmt.Sprintf("--extension=%s", config.Extensions)) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	case "cloudMbt": | ||||||
|  |  | ||||||
|  | 		platform, err := ValueOfBuildTarget(config.Platform) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		call = append(call, "mbt", "build", "--mtar", mtarName, "--platform", platform.String()) | ||||||
|  | 		if len(config.Extensions) != 0 { | ||||||
|  | 			call = append(call, fmt.Sprintf("--extensions=%s", config.Extensions)) | ||||||
|  | 		} | ||||||
|  | 		call = append(call, "--target", "./") | ||||||
|  |  | ||||||
|  | 	default: | ||||||
|  |  | ||||||
|  | 		return fmt.Errorf("Unknown mta build tool: \"%s\"", config.MtaBuildTool) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if err = addNpmBinToPath(e); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	log.Entry().Infof("Executing mta build call: \"%s\"", strings.Join(call, " ")) | ||||||
|  |  | ||||||
|  | 	if err := e.RunExecutable(call[0], call[1:]...); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	commonPipelineEnvironment.mtarFilePath = mtarName | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getMarJarName(config mtaBuildOptions) string { | ||||||
|  |  | ||||||
|  | 	mtaJar := "mta.jar" | ||||||
|  |  | ||||||
|  | 	if len(config.MtaJarLocation) > 0 { | ||||||
|  | 		mtaJar = config.MtaJarLocation | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return mtaJar | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func addNpmBinToPath(e envExecRunner) error { | ||||||
|  | 	path := "./node_modules/.bin" | ||||||
|  | 	oldPath := os.Getenv("PATH") | ||||||
|  | 	if len(oldPath) > 0 { | ||||||
|  | 		path = path + ":" + oldPath | ||||||
|  | 	} | ||||||
|  | 	e.Env(append(os.Environ(), "PATH="+path)) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getMtarName(config mtaBuildOptions, mtaYamlFile string, p piperutils.FileUtils) (string, error) { | ||||||
|  |  | ||||||
|  | 	mtarName := config.MtarName | ||||||
|  | 	if len(mtarName) == 0 { | ||||||
|  |  | ||||||
|  | 		log.Entry().Debugf("mtar name not provided via config. Extracting from file \"%s\"", mtaYamlFile) | ||||||
|  |  | ||||||
|  | 		mtaID, err := getMtaID(mtaYamlFile, p) | ||||||
|  |  | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if len(mtaID) == 0 { | ||||||
|  | 			return "", fmt.Errorf("Invalid mtar name. Was empty") | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		log.Entry().Debugf("mtar name extracted from file \"%s\": \"%s\"", mtaYamlFile, mtaID) | ||||||
|  |  | ||||||
|  | 		mtarName = mtaID | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return mtarName + ".mtar", nil | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func setTimeStamp(mtaYamlFile string, p piperutils.FileUtils) error { | ||||||
|  |  | ||||||
|  | 	mtaYaml, err := p.FileRead(mtaYamlFile) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	mtaYamlStr := string(mtaYaml) | ||||||
|  |  | ||||||
|  | 	timestampVar := "${timestamp}" | ||||||
|  | 	if strings.Contains(mtaYamlStr, timestampVar) { | ||||||
|  |  | ||||||
|  | 		if err := p.FileWrite(mtaYamlFile, []byte(strings.ReplaceAll(mtaYamlStr, timestampVar, getTimestamp())), 0644); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		log.Entry().Infof("Timestamp replaced in \"%s\"", mtaYamlFile) | ||||||
|  | 	} else { | ||||||
|  | 		log.Entry().Infof("No timestap contained in \"%s\". File has not been modified.", mtaYamlFile) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getTimestamp() string { | ||||||
|  | 	t := time.Now() | ||||||
|  | 	return fmt.Sprintf("%d%02d%02d%02d%02d%02d\n", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func createMtaYamlFile(mtaYamlFile, applicationName string, p piperutils.FileUtils) error { | ||||||
|  |  | ||||||
|  | 	log.Entry().Debugf("mta yaml file not found in project sources.") | ||||||
|  |  | ||||||
|  | 	if len(applicationName) == 0 { | ||||||
|  | 		return fmt.Errorf("'%[1]s' not found in project sources and 'applicationName' not provided as parameter - cannot generate '%[1]s' file", mtaYamlFile) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	packageFileExists, err := p.FileExists("package.json") | ||||||
|  | 	if !packageFileExists { | ||||||
|  | 		return fmt.Errorf("package.json file does not exist") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var result map[string]interface{} | ||||||
|  | 	pContent, err := p.FileRead("package.json") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	json.Unmarshal(pContent, &result) | ||||||
|  |  | ||||||
|  | 	version, ok := result["version"].(string) | ||||||
|  | 	if !ok { | ||||||
|  | 		return fmt.Errorf("Version not found in \"package.json\" (or wrong type)") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	name, ok := result["name"].(string) | ||||||
|  | 	if !ok { | ||||||
|  | 		return fmt.Errorf("Name not found in \"package.json\" (or wrong type)") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	mtaConfig, err := generateMta(name, applicationName, version) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	p.FileWrite(mtaYamlFile, []byte(mtaConfig), 0644) | ||||||
|  | 	log.Entry().Infof("\"%s\" created.", mtaYamlFile) | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func handleDefaultNpmRegistry(config mtaBuildOptions, e envExecRunner) error { | ||||||
|  |  | ||||||
|  | 	if len(config.DefaultNpmRegistry) > 0 { | ||||||
|  |  | ||||||
|  | 		log.Entry().Debugf("Setting default npm registry to \"%s\"", config.DefaultNpmRegistry) | ||||||
|  | 		if err := e.RunExecutable("npm", "config", "set", "registry", config.DefaultNpmRegistry); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		log.Entry().Debugf("No default npm registry provided via configuration. Leaving npm config untouched.") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func handleSettingsFiles(config mtaBuildOptions, | ||||||
|  | 	p piperutils.FileUtils, | ||||||
|  | 	httpClient piperhttp.Downloader) error { | ||||||
|  |  | ||||||
|  | 	if len(config.ProjectSettingsFile) > 0 { | ||||||
|  |  | ||||||
|  | 		if err := getSettingsFile(maven.ProjectSettingsFile, config.ProjectSettingsFile, p, httpClient); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	} else { | ||||||
|  |  | ||||||
|  | 		log.Entry().Debugf("Project settings file not provided via configuation.") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(config.GlobalSettingsFile) > 0 { | ||||||
|  |  | ||||||
|  | 		if err := getSettingsFile(maven.GlobalSettingsFile, config.GlobalSettingsFile, p, httpClient); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  |  | ||||||
|  | 		log.Entry().Debugf("Global settings file not provided via configuation.") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func generateMta(id, applicationName, version string) (string, error) { | ||||||
|  |  | ||||||
|  | 	if len(id) == 0 { | ||||||
|  | 		return "", fmt.Errorf("Generating mta file: ID not provided") | ||||||
|  | 	} | ||||||
|  | 	if len(applicationName) == 0 { | ||||||
|  | 		return "", fmt.Errorf("Generating mta file: ApplicationName not provided") | ||||||
|  | 	} | ||||||
|  | 	if len(version) == 0 { | ||||||
|  | 		return "", fmt.Errorf("Generating mta file: Version not provided") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	tmpl, e := template.New("mta.yaml").Parse(templateMtaYml) | ||||||
|  | 	if e != nil { | ||||||
|  | 		return "", e | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	type properties struct { | ||||||
|  | 		ID              string | ||||||
|  | 		ApplicationName string | ||||||
|  | 		Version         string | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	props := properties{ID: id, ApplicationName: applicationName, Version: version} | ||||||
|  |  | ||||||
|  | 	var script bytes.Buffer | ||||||
|  | 	tmpl.Execute(&script, props) | ||||||
|  | 	return script.String(), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getMtaID(mtaYamlFile string, fileUtils piperutils.FileUtils) (string, error) { | ||||||
|  |  | ||||||
|  | 	var result map[string]interface{} | ||||||
|  | 	p, err := fileUtils.FileRead(mtaYamlFile) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	err = yaml.Unmarshal(p, &result) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	id, ok := result["ID"].(string) | ||||||
|  | 	if !ok || len(id) == 0 { | ||||||
|  | 		fmt.Errorf("Id not found in mta yaml file (or wrong type)") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return id, nil | ||||||
|  | } | ||||||
							
								
								
									
										199
									
								
								cmd/mtaBuild_generated.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								cmd/mtaBuild_generated.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | |||||||
|  | // Code generated by piper's step-generator. DO NOT EDIT. | ||||||
|  |  | ||||||
|  | package cmd | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/config" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/log" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/piperenv" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/telemetry" | ||||||
|  | 	"github.com/spf13/cobra" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type mtaBuildOptions struct { | ||||||
|  | 	BuildTarget         string `json:"buildTarget,omitempty"` | ||||||
|  | 	MtaBuildTool        string `json:"mtaBuildTool,omitempty"` | ||||||
|  | 	MtarName            string `json:"mtarName,omitempty"` | ||||||
|  | 	MtaJarLocation      string `json:"mtaJarLocation,omitempty"` | ||||||
|  | 	Extensions          string `json:"extensions,omitempty"` | ||||||
|  | 	Platform            string `json:"platform,omitempty"` | ||||||
|  | 	ApplicationName     string `json:"applicationName,omitempty"` | ||||||
|  | 	DefaultNpmRegistry  string `json:"defaultNpmRegistry,omitempty"` | ||||||
|  | 	ProjectSettingsFile string `json:"projectSettingsFile,omitempty"` | ||||||
|  | 	GlobalSettingsFile  string `json:"globalSettingsFile,omitempty"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type mtaBuildCommonPipelineEnvironment struct { | ||||||
|  | 	mtarFilePath string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *mtaBuildCommonPipelineEnvironment) persist(path, resourceName string) { | ||||||
|  | 	content := []struct { | ||||||
|  | 		category string | ||||||
|  | 		name     string | ||||||
|  | 		value    string | ||||||
|  | 	}{ | ||||||
|  | 		{category: "", name: "mtarFilePath", value: p.mtarFilePath}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	errCount := 0 | ||||||
|  | 	for _, param := range content { | ||||||
|  | 		err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(param.category, param.name), param.value) | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Entry().WithError(err).Error("Error persisting piper environment.") | ||||||
|  | 			errCount++ | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if errCount > 0 { | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // MtaBuildCommand Performs an mta build | ||||||
|  | func MtaBuildCommand() *cobra.Command { | ||||||
|  | 	metadata := mtaBuildMetadata() | ||||||
|  | 	var stepConfig mtaBuildOptions | ||||||
|  | 	var startTime time.Time | ||||||
|  | 	var commonPipelineEnvironment mtaBuildCommonPipelineEnvironment | ||||||
|  |  | ||||||
|  | 	var createMtaBuildCmd = &cobra.Command{ | ||||||
|  | 		Use:   "mtaBuild", | ||||||
|  | 		Short: "Performs an mta build", | ||||||
|  | 		Long:  `Executes the SAP Multitarget Application Archive Builder to create an mtar archive of the application.`, | ||||||
|  | 		PreRunE: func(cmd *cobra.Command, args []string) error { | ||||||
|  | 			startTime = time.Now() | ||||||
|  | 			log.SetStepName("mtaBuild") | ||||||
|  | 			log.SetVerbose(GeneralConfig.Verbose) | ||||||
|  | 			return PrepareConfig(cmd, &metadata, "mtaBuild", &stepConfig, config.OpenPiperFile) | ||||||
|  | 		}, | ||||||
|  | 		Run: func(cmd *cobra.Command, args []string) { | ||||||
|  | 			telemetryData := telemetry.CustomData{} | ||||||
|  | 			telemetryData.ErrorCode = "1" | ||||||
|  | 			handler := func() { | ||||||
|  | 				commonPipelineEnvironment.persist(GeneralConfig.EnvRootPath, "commonPipelineEnvironment") | ||||||
|  | 				telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds()) | ||||||
|  | 				telemetry.Send(&telemetryData) | ||||||
|  | 			} | ||||||
|  | 			log.DeferExitHandler(handler) | ||||||
|  | 			defer handler() | ||||||
|  | 			telemetry.Initialize(GeneralConfig.NoTelemetry, "mtaBuild") | ||||||
|  | 			mtaBuild(stepConfig, &telemetryData, &commonPipelineEnvironment) | ||||||
|  | 			telemetryData.ErrorCode = "0" | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	addMtaBuildFlags(createMtaBuildCmd, &stepConfig) | ||||||
|  | 	return createMtaBuildCmd | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func addMtaBuildFlags(cmd *cobra.Command, stepConfig *mtaBuildOptions) { | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.BuildTarget, "buildTarget", os.Getenv("PIPER_buildTarget"), "mtaBuildTool 'classic' only: The target platform to which the mtar can be deployed. Valid values: 'CF', 'NEO', 'XSA'.") | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.MtaBuildTool, "mtaBuildTool", "cloudMbt", "Tool to use when building the MTA. Valid values: 'classic', 'cloudMbt'.") | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.MtarName, "mtarName", os.Getenv("PIPER_mtarName"), "The name of the generated mtar file including its extension.") | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.MtaJarLocation, "mtaJarLocation", os.Getenv("PIPER_mtaJarLocation"), "mtaBuildTool 'classic' only: The location of the SAP Multitarget Application Archive Builder jar file, including file name and extension. If you run on Docker, this must match the location of the jar file in the container as well.") | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.Extensions, "extensions", os.Getenv("PIPER_extensions"), "The path to the extension descriptor file.") | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.Platform, "platform", os.Getenv("PIPER_platform"), "mtaBuildTool 'cloudMbt' only: The target platform to which the mtar can be deployed.") | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.ApplicationName, "applicationName", os.Getenv("PIPER_applicationName"), "The name of the application which is being built. If the parameter has been provided and no `mta.yaml` exists, the `mta.yaml` will be automatically generated using this parameter and the information (`name` and `version`) from 'package.json` before the actual build starts.") | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.DefaultNpmRegistry, "defaultNpmRegistry", os.Getenv("PIPER_defaultNpmRegistry"), "Url to the npm registry that should be used for installing npm dependencies.") | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.ProjectSettingsFile, "projectSettingsFile", os.Getenv("PIPER_projectSettingsFile"), "Path or url to the mvn settings file that should be used as project settings file.") | ||||||
|  | 	cmd.Flags().StringVar(&stepConfig.GlobalSettingsFile, "globalSettingsFile", os.Getenv("PIPER_globalSettingsFile"), "Path or url to the mvn settings file that should be used as global settings file") | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // retrieve step metadata | ||||||
|  | func mtaBuildMetadata() config.StepData { | ||||||
|  | 	var theMetaData = config.StepData{ | ||||||
|  | 		Spec: config.StepSpec{ | ||||||
|  | 			Inputs: config.StepInputs{ | ||||||
|  | 				Parameters: []config.StepParameters{ | ||||||
|  | 					{ | ||||||
|  | 						Name:        "buildTarget", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:        "mtaBuildTool", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:        "mtarName", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:        "mtaJarLocation", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:        "extensions", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:        "platform", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:        "applicationName", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:        "defaultNpmRegistry", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:        "projectSettingsFile", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:        "globalSettingsFile", | ||||||
|  | 						ResourceRef: []config.ResourceReference{}, | ||||||
|  | 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||||
|  | 						Type:        "string", | ||||||
|  | 						Mandatory:   false, | ||||||
|  | 						Aliases:     []config.Alias{}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	return theMetaData | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								cmd/mtaBuild_generated_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								cmd/mtaBuild_generated_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | package cmd | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestMtaBuildCommand(t *testing.T) { | ||||||
|  |  | ||||||
|  | 	testCmd := MtaBuildCommand() | ||||||
|  |  | ||||||
|  | 	// only high level testing performed - details are tested in step generation procudure | ||||||
|  | 	assert.Equal(t, "mtaBuild", testCmd.Use, "command name incorrect") | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										336
									
								
								cmd/mtaBuild_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										336
									
								
								cmd/mtaBuild_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,336 @@ | |||||||
|  | package cmd | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	piperhttp "github.com/SAP/jenkins-library/pkg/http" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/maven" | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/piperutils" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"gopkg.in/yaml.v2" | ||||||
|  | 	"os" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestMarBuild(t *testing.T) { | ||||||
|  |  | ||||||
|  | 	cpe := mtaBuildCommonPipelineEnvironment{} | ||||||
|  | 	httpClient := piperhttp.Client{} | ||||||
|  |  | ||||||
|  | 	t.Run("Application name not set", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{} | ||||||
|  |  | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{} | ||||||
|  |  | ||||||
|  | 		err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.NotNil(t, err) | ||||||
|  | 		assert.Equal(t, "'mta.yaml' not found in project sources and 'applicationName' not provided as parameter - cannot generate 'mta.yaml' file", err.Error()) | ||||||
|  |  | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Provide default npm registry", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", DefaultNpmRegistry: "https://example.org/npm", MtarName: "myName"} | ||||||
|  |  | ||||||
|  | 		existingFiles := make(map[string]string) | ||||||
|  | 		existingFiles["package.json"] = "{\"name\": \"myName\", \"version\": \"1.2.3\"}" | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{existingFiles: existingFiles} | ||||||
|  |  | ||||||
|  | 		err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.Nil(t, err) | ||||||
|  |  | ||||||
|  | 		if assert.Len(t, e.calls, 2) { // the second (unchecked) entry is the mta call | ||||||
|  | 			assert.Equal(t, "npm", e.calls[0].exec) | ||||||
|  | 			assert.Equal(t, []string{"config", "set", "registry", "https://example.org/npm"}, e.calls[0].params) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Package json does not exist", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{ApplicationName: "myApp"} | ||||||
|  |  | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{} | ||||||
|  |  | ||||||
|  | 		err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.NotNil(t, err) | ||||||
|  |  | ||||||
|  | 		assert.Equal(t, "package.json file does not exist", err.Error()) | ||||||
|  |  | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Write yaml file", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", MtarName: "myName"} | ||||||
|  |  | ||||||
|  | 		existingFiles := make(map[string]string) | ||||||
|  | 		existingFiles["package.json"] = "{\"name\": \"myName\", \"version\": \"1.2.3\"}" | ||||||
|  |  | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{existingFiles: existingFiles} | ||||||
|  |  | ||||||
|  | 		err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.Nil(t, err) | ||||||
|  |  | ||||||
|  | 		type MtaResult struct { | ||||||
|  | 			Version    string | ||||||
|  | 			ID         string `yaml:"ID,omitempty"` | ||||||
|  | 			Parameters map[string]string | ||||||
|  | 			Modules    []struct { | ||||||
|  | 				Name       string | ||||||
|  | 				Type       string | ||||||
|  | 				Parameters map[string]interface{} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		assert.NotEmpty(t, fileUtils.writtenFiles["mta.yaml"]) | ||||||
|  |  | ||||||
|  | 		var result MtaResult | ||||||
|  | 		yaml.Unmarshal([]byte(fileUtils.writtenFiles["mta.yaml"]), &result) | ||||||
|  |  | ||||||
|  | 		assert.Equal(t, "myName", result.ID) | ||||||
|  | 		assert.Equal(t, "1.2.3", result.Version) | ||||||
|  | 		assert.Equal(t, "myApp", result.Modules[0].Name) | ||||||
|  | 		assert.Equal(t, result.Modules[0].Parameters["version"], "1.2.3-${timestamp}") | ||||||
|  | 		assert.Equal(t, "myApp", result.Modules[0].Parameters["name"]) | ||||||
|  |  | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Dont write mta yaml file when already present no timestamp placeholder", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF"} | ||||||
|  |  | ||||||
|  | 		existingFiles := make(map[string]string) | ||||||
|  | 		existingFiles["package.json"] = "{\"name\": \"myName\", \"version\": \"1.2.3\"}" | ||||||
|  | 		existingFiles["mta.yaml"] = "already there" | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{existingFiles: existingFiles} | ||||||
|  |  | ||||||
|  | 		runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.Empty(t, fileUtils.writtenFiles) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Write mta yaml file when already present with timestamp placeholder", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF"} | ||||||
|  |  | ||||||
|  | 		existingFiles := make(map[string]string) | ||||||
|  | 		existingFiles["package.json"] = "{\"name\": \"myName\", \"version\": \"1.2.3\"}" | ||||||
|  | 		existingFiles["mta.yaml"] = "already there with-${timestamp}" | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{existingFiles: existingFiles} | ||||||
|  |  | ||||||
|  | 		runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.NotEmpty(t, fileUtils.writtenFiles["mta.yaml"]) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Test mta build classic toolset", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", MtarName: "myName"} | ||||||
|  |  | ||||||
|  | 		cpe.mtarFilePath = "" | ||||||
|  |  | ||||||
|  | 		existingFiles := make(map[string]string) | ||||||
|  | 		existingFiles["package.json"] = "{\"name\": \"myName\", \"version\": \"1.2.3\"}" | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{existingFiles: existingFiles} | ||||||
|  |  | ||||||
|  | 		err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.Nil(t, err) | ||||||
|  |  | ||||||
|  | 		if assert.Len(t, e.calls, 1) { | ||||||
|  | 			assert.Equal(t, "java", e.calls[0].exec) | ||||||
|  | 			assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.calls[0].params) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		assert.Equal(t, "myName.mtar", cpe.mtarFilePath) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Test mta build classic toolset, mtarName from already existing mta.yaml", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF"} | ||||||
|  |  | ||||||
|  | 		cpe.mtarFilePath = "" | ||||||
|  |  | ||||||
|  | 		existingFiles := make(map[string]string) | ||||||
|  | 		existingFiles["package.json"] = "{\"name\": \"myName\", \"version\": \"1.2.3\"}" | ||||||
|  | 		existingFiles["mta.yaml"] = "ID: \"myNameFromMtar\"" | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{existingFiles: existingFiles} | ||||||
|  |  | ||||||
|  | 		err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.Nil(t, err) | ||||||
|  |  | ||||||
|  | 		if assert.Len(t, e.calls, 1) { | ||||||
|  | 			assert.Equal(t, "java", e.calls[0].exec) | ||||||
|  | 			assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myNameFromMtar.mtar", "--build-target=CF", "build"}, e.calls[0].params) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Test mta build classic toolset with configured mta jar", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", MtaJarLocation: "/opt/sap/mta/lib/mta.jar", MtarName: "myName"} | ||||||
|  |  | ||||||
|  | 		existingFiles := make(map[string]string) | ||||||
|  | 		existingFiles["package.json"] = "{\"name\": \"myName\", \"version\": \"1.2.3\"}" | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{existingFiles: existingFiles} | ||||||
|  |  | ||||||
|  | 		err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.Nil(t, err) | ||||||
|  |  | ||||||
|  | 		if assert.Len(t, e.calls, 1) { | ||||||
|  | 			assert.Equal(t, "java", e.calls[0].exec) | ||||||
|  | 			assert.Equal(t, []string{"-jar", "/opt/sap/mta/lib/mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.calls[0].params) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Mta build mbt toolset", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 		cpe.mtarFilePath = "" | ||||||
|  |  | ||||||
|  | 		options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "cloudMbt", Platform: "CF", MtarName: "myName"} | ||||||
|  |  | ||||||
|  | 		existingFiles := make(map[string]string) | ||||||
|  | 		existingFiles["package.json"] = "{\"name\": \"myName\", \"version\": \"1.2.3\"}" | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{existingFiles: existingFiles} | ||||||
|  |  | ||||||
|  | 		err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 		assert.Nil(t, err) | ||||||
|  |  | ||||||
|  | 		if assert.Len(t, e.calls, 1) { | ||||||
|  | 			assert.Equal(t, "mbt", e.calls[0].exec) | ||||||
|  | 			assert.Equal(t, []string{"build", "--mtar", "myName.mtar", "--platform", "CF", "--target", "./"}, e.calls[0].params) | ||||||
|  | 		} | ||||||
|  | 		assert.Equal(t, "myName.mtar", cpe.mtarFilePath) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("Settings file releatd tests", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 		var settingsFile string | ||||||
|  | 		var settingsFileType maven.SettingsFileType | ||||||
|  |  | ||||||
|  | 		defer func() { | ||||||
|  | 			getSettingsFile = maven.GetSettingsFile | ||||||
|  | 		}() | ||||||
|  |  | ||||||
|  | 		getSettingsFile = func( | ||||||
|  | 			sfType maven.SettingsFileType, | ||||||
|  | 			src string, | ||||||
|  | 			fileUtilsMock piperutils.FileUtils, | ||||||
|  | 			httpClientMock piperhttp.Downloader) error { | ||||||
|  | 			settingsFile = src | ||||||
|  | 			settingsFileType = sfType | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		fileUtils := MtaTestFileUtilsMock{} | ||||||
|  | 		fileUtils.existingFiles = make(map[string]string) | ||||||
|  | 		fileUtils.existingFiles["package.json"] = "{\"name\": \"myName\", \"version\": \"1.2.3\"}" | ||||||
|  |  | ||||||
|  | 		t.Run("Copy global settings file", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 			defer func() { | ||||||
|  | 				settingsFile = "" | ||||||
|  | 				settingsFileType = -1 | ||||||
|  | 			}() | ||||||
|  |  | ||||||
|  | 			e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 			options := mtaBuildOptions{ApplicationName: "myApp", GlobalSettingsFile: "/opt/maven/settings.xml", MtaBuildTool: "cloudMbt", Platform: "CF", MtarName: "myName"} | ||||||
|  |  | ||||||
|  | 			err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 			assert.Nil(t, err) | ||||||
|  |  | ||||||
|  | 			assert.Equal(t, settingsFile, "/opt/maven/settings.xml") | ||||||
|  | 			assert.Equal(t, settingsFileType, maven.GlobalSettingsFile) | ||||||
|  | 		}) | ||||||
|  |  | ||||||
|  | 		t.Run("Copy project settings file", func(t *testing.T) { | ||||||
|  |  | ||||||
|  | 			defer func() { | ||||||
|  | 				settingsFile = "" | ||||||
|  | 				settingsFileType = -1 | ||||||
|  | 			}() | ||||||
|  |  | ||||||
|  | 			e := execMockRunner{} | ||||||
|  |  | ||||||
|  | 			options := mtaBuildOptions{ApplicationName: "myApp", ProjectSettingsFile: "/my/project/settings.xml", MtaBuildTool: "cloudMbt", Platform: "CF", MtarName: "myName"} | ||||||
|  |  | ||||||
|  | 			err := runMtaBuild(options, &cpe, &e, &fileUtils, &httpClient) | ||||||
|  |  | ||||||
|  | 			assert.Nil(t, err) | ||||||
|  |  | ||||||
|  | 			assert.Equal(t, "/my/project/settings.xml", settingsFile) | ||||||
|  | 			assert.Equal(t, maven.ProjectSettingsFile, settingsFileType) | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type MtaTestFileUtilsMock struct { | ||||||
|  | 	existingFiles map[string]string | ||||||
|  | 	writtenFiles  map[string]string | ||||||
|  | 	copiedFiles   map[string]string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *MtaTestFileUtilsMock) FileExists(path string) (bool, error) { | ||||||
|  |  | ||||||
|  | 	if _, ok := f.existingFiles[path]; ok { | ||||||
|  | 		return true, nil | ||||||
|  | 	} | ||||||
|  | 	return false, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *MtaTestFileUtilsMock) Copy(src, dest string) (int64, error) { | ||||||
|  |  | ||||||
|  | 	if f.copiedFiles == nil { | ||||||
|  | 		f.copiedFiles = make(map[string]string) | ||||||
|  | 	} | ||||||
|  | 	f.copiedFiles[src] = dest | ||||||
|  |  | ||||||
|  | 	return 0, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *MtaTestFileUtilsMock) FileRead(path string) ([]byte, error) { | ||||||
|  | 	return []byte(f.existingFiles[path]), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *MtaTestFileUtilsMock) FileWrite(path string, content []byte, perm os.FileMode) error { | ||||||
|  |  | ||||||
|  | 	if f.writtenFiles == nil { | ||||||
|  | 		f.writtenFiles = make(map[string]string) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if _, ok := f.writtenFiles[path]; ok { | ||||||
|  | 		delete(f.writtenFiles, path) | ||||||
|  | 	} | ||||||
|  | 	f.writtenFiles[path] = string(content) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *MtaTestFileUtilsMock) MkdirAll(path string, perm os.FileMode) error { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
| @@ -56,6 +56,7 @@ func Execute() { | |||||||
| 	rootCmd.AddCommand(CloudFoundryDeleteServiceCommand()) | 	rootCmd.AddCommand(CloudFoundryDeleteServiceCommand()) | ||||||
| 	rootCmd.AddCommand(AbapEnvironmentPullGitRepoCommand()) | 	rootCmd.AddCommand(AbapEnvironmentPullGitRepoCommand()) | ||||||
| 	rootCmd.AddCommand(CheckmarxExecuteScanCommand()) | 	rootCmd.AddCommand(CheckmarxExecuteScanCommand()) | ||||||
|  | 	rootCmd.AddCommand(MtaBuildCommand()) | ||||||
| 	rootCmd.AddCommand(ProtecodeExecuteScanCommand()) | 	rootCmd.AddCommand(ProtecodeExecuteScanCommand()) | ||||||
|  |  | ||||||
| 	addRootFlags(rootCmd) | 	addRootFlags(rootCmd) | ||||||
|   | |||||||
| @@ -110,7 +110,8 @@ xs {{.Mode.GetDeployCommand}} -i {{.OperationID}} -a {{.Action.GetAction}} | |||||||
|  |  | ||||||
| func xsDeploy(config xsDeployOptions, telemetryData *telemetry.CustomData) { | func xsDeploy(config xsDeployOptions, telemetryData *telemetry.CustomData) { | ||||||
| 	c := command.Command{} | 	c := command.Command{} | ||||||
| 	err := runXsDeploy(config, &c, piperutils.FileExists, piperutils.Copy, os.Remove, os.Stdout) | 	fileUtils := piperutils.Files{} | ||||||
|  | 	err := runXsDeploy(config, &c, fileUtils, os.Remove, os.Stdout) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Entry(). | 		log.Entry(). | ||||||
| 			WithError(err). | 			WithError(err). | ||||||
| @@ -119,8 +120,7 @@ func xsDeploy(config xsDeployOptions, telemetryData *telemetry.CustomData) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func runXsDeploy(XsDeployOptions xsDeployOptions, s shellRunner, | func runXsDeploy(XsDeployOptions xsDeployOptions, s shellRunner, | ||||||
| 	fExists func(string) (bool, error), | 	fileUtils piperutils.FileUtils, | ||||||
| 	fCopy func(string, string) (int64, error), |  | ||||||
| 	fRemove func(string) error, | 	fRemove func(string) error, | ||||||
| 	stdout io.Writer) error { | 	stdout io.Writer) error { | ||||||
|  |  | ||||||
| @@ -150,7 +150,7 @@ func runXsDeploy(XsDeployOptions xsDeployOptions, s shellRunner, | |||||||
| 	log.Entry().Debugf("performLogin: %t, performLogout: %t", performLogin, performLogout) | 	log.Entry().Debugf("performLogin: %t, performLogout: %t", performLogin, performLogout) | ||||||
|  |  | ||||||
| 	{ | 	{ | ||||||
| 		exists, e := fExists(XsDeployOptions.MtaPath) | 		exists, e := fileUtils.FileExists(XsDeployOptions.MtaPath) | ||||||
| 		if e != nil { | 		if e != nil { | ||||||
| 			return e | 			return e | ||||||
| 		} | 		} | ||||||
| @@ -200,14 +200,14 @@ func runXsDeploy(XsDeployOptions xsDeployOptions, s shellRunner, | |||||||
| 	if performLogin { | 	if performLogin { | ||||||
| 		loginErr = xsLogin(XsDeployOptions, s) | 		loginErr = xsLogin(XsDeployOptions, s) | ||||||
| 		if loginErr == nil { | 		if loginErr == nil { | ||||||
| 			err = copyFileFromHomeToPwd(xsSessionFile, fCopy) | 			err = copyFileFromHomeToPwd(xsSessionFile, fileUtils) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if loginErr == nil && err == nil { | 	if loginErr == nil && err == nil { | ||||||
|  |  | ||||||
| 		{ | 		{ | ||||||
| 			exists, e := fExists(xsSessionFile) | 			exists, e := fileUtils.FileExists(xsSessionFile) | ||||||
| 			if e != nil { | 			if e != nil { | ||||||
| 				return e | 				return e | ||||||
| 			} | 			} | ||||||
| @@ -216,7 +216,7 @@ func runXsDeploy(XsDeployOptions xsDeployOptions, s shellRunner, | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		copyFileFromPwdToHome(xsSessionFile, fCopy) | 		copyFileFromPwdToHome(xsSessionFile, fileUtils) | ||||||
|  |  | ||||||
| 		switch action { | 		switch action { | ||||||
| 		case Resume, Abort, Retry: | 		case Resume, Abort, Retry: | ||||||
| @@ -435,20 +435,17 @@ func executeCmd(templateID string, commandPattern string, properties interface{} | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func copyFileFromHomeToPwd(xsSessionFile string, fCopy func(string, string) (int64, error)) error { | func copyFileFromHomeToPwd(xsSessionFile string, fileUtils piperutils.FileUtils) error { | ||||||
| 	if fCopy == nil { |  | ||||||
| 		fCopy = piperutils.Copy |  | ||||||
| 	} |  | ||||||
| 	src, dest := fmt.Sprintf("%s/%s", os.Getenv("HOME"), xsSessionFile), fmt.Sprintf("%s", xsSessionFile) | 	src, dest := fmt.Sprintf("%s/%s", os.Getenv("HOME"), xsSessionFile), fmt.Sprintf("%s", xsSessionFile) | ||||||
| 	log.Entry().Debugf("Copying xs session file from home directory ('%s') to workspace ('%s')", src, dest) | 	log.Entry().Debugf("Copying xs session file from home directory ('%s') to workspace ('%s')", src, dest) | ||||||
| 	if _, err := fCopy(src, dest); err != nil { | 	if _, err := fileUtils.Copy(src, dest); err != nil { | ||||||
| 		return errors.Wrapf(err, "Cannot copy xssession file from home directory ('%s') to workspace ('%s')", src, dest) | 		return errors.Wrapf(err, "Cannot copy xssession file from home directory ('%s') to workspace ('%s')", src, dest) | ||||||
| 	} | 	} | ||||||
| 	log.Entry().Debugf("xs session file copied from home directory ('%s') to workspace ('%s')", src, dest) | 	log.Entry().Debugf("xs session file copied from home directory ('%s') to workspace ('%s')", src, dest) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func copyFileFromPwdToHome(xsSessionFile string, fCopy func(string, string) (int64, error)) error { | func copyFileFromPwdToHome(xsSessionFile string, fileUtils piperutils.FileUtils) error { | ||||||
|  |  | ||||||
| 	// | 	// | ||||||
| 	// We rely on running inside a docker container which is discarded after a single use. | 	// We rely on running inside a docker container which is discarded after a single use. | ||||||
| @@ -457,12 +454,9 @@ func copyFileFromPwdToHome(xsSessionFile string, fCopy func(string, string) (int | |||||||
| 	// affects also other builds. | 	// affects also other builds. | ||||||
| 	// | 	// | ||||||
|  |  | ||||||
| 	if fCopy == nil { |  | ||||||
| 		fCopy = piperutils.Copy |  | ||||||
| 	} |  | ||||||
| 	src, dest := fmt.Sprintf("%s", xsSessionFile), fmt.Sprintf("%s/%s", os.Getenv("HOME"), xsSessionFile) | 	src, dest := fmt.Sprintf("%s", xsSessionFile), fmt.Sprintf("%s/%s", os.Getenv("HOME"), xsSessionFile) | ||||||
| 	log.Entry().Debugf("Copying xs session file from workspace ('%s') to home directory ('%s')", src, dest) | 	log.Entry().Debugf("Copying xs session file from workspace ('%s') to home directory ('%s')", src, dest) | ||||||
| 	if _, err := fCopy(src, dest); err != nil { | 	if _, err := fileUtils.Copy(src, dest); err != nil { | ||||||
| 		return errors.Wrapf(err, "Cannot copy xssession file from workspace ('%s') to home directory ('%s')", src, dest) | 		return errors.Wrapf(err, "Cannot copy xssession file from workspace ('%s') to home directory ('%s')", src, dest) | ||||||
| 	} | 	} | ||||||
| 	log.Entry().Debugf("xs session file copied from workspace ('%s') to home directory ('%s')", src, dest) | 	log.Entry().Debugf("xs session file copied from workspace ('%s') to home directory ('%s')", src, dest) | ||||||
|   | |||||||
| @@ -7,11 +7,37 @@ import ( | |||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| 	"io" | 	"io" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"testing" | 	"testing" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | type FileUtilsMock struct { | ||||||
|  | 	copiedFiles []string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *FileUtilsMock) FileExists(path string) (bool, error) { | ||||||
|  | 	return path == "dummy.mtar" || path == ".xs_session", nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *FileUtilsMock) Copy(src, dest string) (int64, error) { | ||||||
|  | 	f.copiedFiles = append(f.copiedFiles, fmt.Sprintf("%s->%s", src, dest)) | ||||||
|  | 	return 0, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *FileUtilsMock) FileRead(path string) ([]byte, error) { | ||||||
|  | 	return []byte{}, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *FileUtilsMock) FileWrite(path string, content []byte, perm os.FileMode) error { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (f *FileUtilsMock) MkdirAll(path string, perm os.FileMode) error { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestDeploy(t *testing.T) { | func TestDeploy(t *testing.T) { | ||||||
| 	myXsDeployOptions := xsDeployOptions{ | 	myXsDeployOptions := xsDeployOptions{ | ||||||
| 		APIURL:                "https://example.org:12345", | 		APIURL:                "https://example.org:12345", | ||||||
| @@ -30,17 +56,9 @@ func TestDeploy(t *testing.T) { | |||||||
|  |  | ||||||
| 	s := shellMockRunner{} | 	s := shellMockRunner{} | ||||||
|  |  | ||||||
| 	var copiedFiles []string |  | ||||||
| 	var removedFiles []string | 	var removedFiles []string | ||||||
|  |  | ||||||
| 	fExists := func(path string) (bool, error) { | 	fileUtilsMock := FileUtilsMock{} | ||||||
| 		return path == "dummy.mtar" || path == ".xs_session", nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	fCopy := func(src, dest string) (int64, error) { |  | ||||||
| 		copiedFiles = append(copiedFiles, fmt.Sprintf("%s->%s", src, dest)) |  | ||||||
| 		return 0, nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	fRemove := func(path string) error { | 	fRemove := func(path string) error { | ||||||
| 		removedFiles = append(removedFiles, path) | 		removedFiles = append(removedFiles, path) | ||||||
| @@ -52,7 +70,7 @@ func TestDeploy(t *testing.T) { | |||||||
| 	t.Run("Standard deploy succeeds", func(t *testing.T) { | 	t.Run("Standard deploy succeeds", func(t *testing.T) { | ||||||
|  |  | ||||||
| 		defer func() { | 		defer func() { | ||||||
| 			copiedFiles = nil | 			fileUtilsMock.copiedFiles = nil | ||||||
| 			removedFiles = nil | 			removedFiles = nil | ||||||
| 			s.calls = nil | 			s.calls = nil | ||||||
| 			stdout = "" | 			stdout = "" | ||||||
| @@ -70,7 +88,7 @@ func TestDeploy(t *testing.T) { | |||||||
| 			wg.Done() | 			wg.Done() | ||||||
| 		}() | 		}() | ||||||
|  |  | ||||||
| 		e := runXsDeploy(myXsDeployOptions, &s, fExists, fCopy, fRemove, wStdout) | 		e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, wStdout) | ||||||
|  |  | ||||||
| 		wStdout.Close() | 		wStdout.Close() | ||||||
| 		wg.Wait() | 		wg.Wait() | ||||||
| @@ -88,14 +106,14 @@ func TestDeploy(t *testing.T) { | |||||||
| 			assert.Len(t, removedFiles, 1) | 			assert.Len(t, removedFiles, 1) | ||||||
| 			assert.Contains(t, removedFiles, ".xs_session") | 			assert.Contains(t, removedFiles, ".xs_session") | ||||||
|  |  | ||||||
| 			assert.Len(t, copiedFiles, 2) | 			assert.Len(t, fileUtilsMock.copiedFiles, 2) | ||||||
| 			// We copy the xs session file to the workspace in order to be able to use the file later. | 			// We copy the xs session file to the workspace in order to be able to use the file later. | ||||||
| 			// This happens directly after login | 			// This happens directly after login | ||||||
| 			// We copy the xs session file from the workspace to the home folder in order to be able to | 			// We copy the xs session file from the workspace to the home folder in order to be able to | ||||||
| 			// use that file. This is important in case we rely on a login which happend e | 			// use that file. This is important in case we rely on a login which happend e | ||||||
| 			assert.Contains(t, copiedFiles[0], "/.xs_session->.xs_session") | 			assert.Contains(t, fileUtilsMock.copiedFiles[0], "/.xs_session->.xs_session") | ||||||
| 			assert.Contains(t, copiedFiles[1], ".xs_session->") | 			assert.Contains(t, fileUtilsMock.copiedFiles[1], ".xs_session->") | ||||||
| 			assert.Contains(t, copiedFiles[1], "/.xs_session") | 			assert.Contains(t, fileUtilsMock.copiedFiles[1], "/.xs_session") | ||||||
| 		}) | 		}) | ||||||
|  |  | ||||||
| 		t.Run("Password not exposed", func(t *testing.T) { | 		t.Run("Password not exposed", func(t *testing.T) { | ||||||
| @@ -107,7 +125,7 @@ func TestDeploy(t *testing.T) { | |||||||
| 	t.Run("Standard deploy fails, deployable missing", func(t *testing.T) { | 	t.Run("Standard deploy fails, deployable missing", func(t *testing.T) { | ||||||
|  |  | ||||||
| 		defer func() { | 		defer func() { | ||||||
| 			copiedFiles = nil | 			fileUtilsMock.copiedFiles = nil | ||||||
| 			removedFiles = nil | 			removedFiles = nil | ||||||
| 			s.calls = nil | 			s.calls = nil | ||||||
| 		}() | 		}() | ||||||
| @@ -121,14 +139,14 @@ func TestDeploy(t *testing.T) { | |||||||
| 		// this file is not denoted in the file exists mock | 		// this file is not denoted in the file exists mock | ||||||
| 		myXsDeployOptions.MtaPath = "doesNotExist" | 		myXsDeployOptions.MtaPath = "doesNotExist" | ||||||
|  |  | ||||||
| 		e := runXsDeploy(myXsDeployOptions, &s, fExists, fCopy, fRemove, ioutil.Discard) | 		e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, ioutil.Discard) | ||||||
| 		checkErr(t, e, "Deployable 'doesNotExist' does not exist") | 		checkErr(t, e, "Deployable 'doesNotExist' does not exist") | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("Standard deploy fails, action provided", func(t *testing.T) { | 	t.Run("Standard deploy fails, action provided", func(t *testing.T) { | ||||||
|  |  | ||||||
| 		defer func() { | 		defer func() { | ||||||
| 			copiedFiles = nil | 			fileUtilsMock.copiedFiles = nil | ||||||
| 			removedFiles = nil | 			removedFiles = nil | ||||||
| 			s.calls = nil | 			s.calls = nil | ||||||
| 		}() | 		}() | ||||||
| @@ -138,14 +156,14 @@ func TestDeploy(t *testing.T) { | |||||||
| 			myXsDeployOptions.Action = "NONE" | 			myXsDeployOptions.Action = "NONE" | ||||||
| 		}() | 		}() | ||||||
|  |  | ||||||
| 		e := runXsDeploy(myXsDeployOptions, &s, fExists, fCopy, fRemove, ioutil.Discard) | 		e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, ioutil.Discard) | ||||||
| 		checkErr(t, e, "Cannot perform action 'RETRY' in mode 'DEPLOY'. Only action 'NONE' is allowed.") | 		checkErr(t, e, "Cannot perform action 'RETRY' in mode 'DEPLOY'. Only action 'NONE' is allowed.") | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("Standard deploy fails, error from underlying process", func(t *testing.T) { | 	t.Run("Standard deploy fails, error from underlying process", func(t *testing.T) { | ||||||
|  |  | ||||||
| 		defer func() { | 		defer func() { | ||||||
| 			copiedFiles = nil | 			fileUtilsMock.copiedFiles = nil | ||||||
| 			removedFiles = nil | 			removedFiles = nil | ||||||
| 			s.calls = nil | 			s.calls = nil | ||||||
| 			s.shouldFailOnCommand = nil | 			s.shouldFailOnCommand = nil | ||||||
| @@ -153,14 +171,14 @@ func TestDeploy(t *testing.T) { | |||||||
|  |  | ||||||
| 		s.shouldFailOnCommand = map[string]error{"#!/bin/bash\nxs login -a https://example.org:12345 -u me -p 'secretPassword' -o myOrg -s mySpace --skip-ssl-validation\n": errors.New("Error from underlying process")} | 		s.shouldFailOnCommand = map[string]error{"#!/bin/bash\nxs login -a https://example.org:12345 -u me -p 'secretPassword' -o myOrg -s mySpace --skip-ssl-validation\n": errors.New("Error from underlying process")} | ||||||
|  |  | ||||||
| 		e := runXsDeploy(myXsDeployOptions, &s, fExists, fCopy, fRemove, ioutil.Discard) | 		e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, ioutil.Discard) | ||||||
| 		checkErr(t, e, "Error from underlying process") | 		checkErr(t, e, "Error from underlying process") | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("BG deploy succeeds", func(t *testing.T) { | 	t.Run("BG deploy succeeds", func(t *testing.T) { | ||||||
|  |  | ||||||
| 		defer func() { | 		defer func() { | ||||||
| 			copiedFiles = nil | 			fileUtilsMock.copiedFiles = nil | ||||||
| 			removedFiles = nil | 			removedFiles = nil | ||||||
| 			s.calls = nil | 			s.calls = nil | ||||||
| 		}() | 		}() | ||||||
| @@ -173,7 +191,7 @@ func TestDeploy(t *testing.T) { | |||||||
|  |  | ||||||
| 		myXsDeployOptions.Mode = "BG_DEPLOY" | 		myXsDeployOptions.Mode = "BG_DEPLOY" | ||||||
|  |  | ||||||
| 		e := runXsDeploy(myXsDeployOptions, &s, fExists, fCopy, fRemove, ioutil.Discard) | 		e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, ioutil.Discard) | ||||||
| 		checkErr(t, e, "") | 		checkErr(t, e, "") | ||||||
|  |  | ||||||
| 		assert.Contains(t, s.calls[0], "xs login") | 		assert.Contains(t, s.calls[0], "xs login") | ||||||
| @@ -184,7 +202,7 @@ func TestDeploy(t *testing.T) { | |||||||
| 	t.Run("BG deploy abort succeeds", func(t *testing.T) { | 	t.Run("BG deploy abort succeeds", func(t *testing.T) { | ||||||
|  |  | ||||||
| 		defer func() { | 		defer func() { | ||||||
| 			copiedFiles = nil | 			fileUtilsMock.copiedFiles = nil | ||||||
| 			removedFiles = nil | 			removedFiles = nil | ||||||
| 			s.calls = nil | 			s.calls = nil | ||||||
| 		}() | 		}() | ||||||
| @@ -202,7 +220,7 @@ func TestDeploy(t *testing.T) { | |||||||
| 		myXsDeployOptions.Action = "ABORT" | 		myXsDeployOptions.Action = "ABORT" | ||||||
| 		myXsDeployOptions.OperationID = "12345" | 		myXsDeployOptions.OperationID = "12345" | ||||||
|  |  | ||||||
| 		e := runXsDeploy(myXsDeployOptions, &s, fExists, fCopy, fRemove, ioutil.Discard) | 		e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, ioutil.Discard) | ||||||
| 		checkErr(t, e, "") | 		checkErr(t, e, "") | ||||||
|  |  | ||||||
| 		assert.Contains(t, s.calls[0], "xs bg-deploy -i 12345 -a abort") | 		assert.Contains(t, s.calls[0], "xs bg-deploy -i 12345 -a abort") | ||||||
| @@ -213,7 +231,7 @@ func TestDeploy(t *testing.T) { | |||||||
| 	t.Run("BG deploy abort fails due to missing operationId", func(t *testing.T) { | 	t.Run("BG deploy abort fails due to missing operationId", func(t *testing.T) { | ||||||
|  |  | ||||||
| 		defer func() { | 		defer func() { | ||||||
| 			copiedFiles = nil | 			fileUtilsMock.copiedFiles = nil | ||||||
| 			removedFiles = nil | 			removedFiles = nil | ||||||
| 			s.calls = nil | 			s.calls = nil | ||||||
| 		}() | 		}() | ||||||
| @@ -229,7 +247,7 @@ func TestDeploy(t *testing.T) { | |||||||
| 		myXsDeployOptions.Mode = "BG_DEPLOY" | 		myXsDeployOptions.Mode = "BG_DEPLOY" | ||||||
| 		myXsDeployOptions.Action = "ABORT" | 		myXsDeployOptions.Action = "ABORT" | ||||||
|  |  | ||||||
| 		e := runXsDeploy(myXsDeployOptions, &s, fExists, fCopy, fRemove, ioutil.Discard) | 		e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, ioutil.Discard) | ||||||
| 		checkErr(t, e, "OperationID was not provided") | 		checkErr(t, e, "OperationID was not provided") | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @@ -20,4 +20,5 @@ require ( | |||||||
| 	github.com/testcontainers/testcontainers-go v0.1.0 | 	github.com/testcontainers/testcontainers-go v0.1.0 | ||||||
| 	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 | 	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 | ||||||
| 	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect | 	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect | ||||||
|  | 	gopkg.in/yaml.v2 v2.2.4 | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										111
									
								
								resources/metadata/mtaBuild.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								resources/metadata/mtaBuild.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | metadata: | ||||||
|  |   name: mtaBuild | ||||||
|  |   description: Performs an mta build | ||||||
|  |   longDescription: | | ||||||
|  |     Executes the SAP Multitarget Application Archive Builder to create an mtar archive of the application. | ||||||
|  | spec: | ||||||
|  |   inputs: | ||||||
|  |     params: | ||||||
|  |       - name: buildTarget | ||||||
|  |         type: string | ||||||
|  |         description: "mtaBuildTool 'classic' only: The target platform to which the mtar can be deployed. Valid values: 'CF', 'NEO', 'XSA'." | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: | ||||||
|  |       - name: mtaBuildTool | ||||||
|  |         type: string | ||||||
|  |         description: "Tool to use when building the MTA. Valid values: 'classic', 'cloudMbt'." | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: cloudMbt | ||||||
|  |       - name: mtarName | ||||||
|  |         type: string | ||||||
|  |         description: "The name of the generated mtar file including its extension." | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: | ||||||
|  |       - name: mtaJarLocation | ||||||
|  |         type: string | ||||||
|  |         description: "mtaBuildTool 'classic' only: The location of the SAP Multitarget Application Archive Builder jar file, including file name and extension. If you run on Docker, this must match the location of the jar file in the container as well." | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: | ||||||
|  |       - name: extensions | ||||||
|  |         type: string | ||||||
|  |         description: "The path to the extension descriptor file." | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: | ||||||
|  |       - name: platform | ||||||
|  |         type: string | ||||||
|  |         description: "mtaBuildTool 'cloudMbt' only: The target platform to which the mtar can be deployed." | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: | ||||||
|  |       - name: applicationName | ||||||
|  |         type: string | ||||||
|  |         description: "The name of the application which is being built. If the parameter has been provided and no `mta.yaml` exists, the `mta.yaml` will be automatically generated using this parameter and the information (`name` and `version`) from 'package.json` before the actual build starts." | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: | ||||||
|  |       - name: defaultNpmRegistry | ||||||
|  |         type: string | ||||||
|  |         description: "Url to the npm registry that should be used for installing npm dependencies." | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: | ||||||
|  |       - name: projectSettingsFile | ||||||
|  |         type: string | ||||||
|  |         description: "Path or url to the mvn settings file that should be used as project settings file." | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: | ||||||
|  |       - name: globalSettingsFile | ||||||
|  |         type: string | ||||||
|  |         description: "Path or url to the mvn settings file that should be used as global settings file" | ||||||
|  |         scope: | ||||||
|  |         - PARAMETERS | ||||||
|  |         - STAGES | ||||||
|  |         - STEPS | ||||||
|  |         mandatory: false | ||||||
|  |         default: | ||||||
|  |  | ||||||
|  |   outputs: | ||||||
|  |     resources: | ||||||
|  |       - name: commonPipelineEnvironment | ||||||
|  |         type: piperEnvironment | ||||||
|  |         params: | ||||||
|  |           - name: mtarFilePath | ||||||
|  |             fields: | ||||||
|  |               - name: mtarFilePath | ||||||
|  |   containers: | ||||||
|  |     - name: mta | ||||||
|  |       image: devxci/mbtci | ||||||
|  |       imagePullPolicy: Always | ||||||
		Reference in New Issue
	
	Block a user