You've already forked sap-jenkins-library
mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-11-06 09:09:19 +02:00
Add easy mode for AUnit & ATC (#3389)
* remove mandatory flag from config files * Enable repo.yml as config * Adapt to merge * Refactoring * Refactoring * avoid panic * Add comments * Add easy mode for atc * Add tests * Add test * Refactor * Add test for MPS * Updates * Rename functions * Add files to gitignore * Rename * Renaming * Renaming * Renaming * Improve error messages * Update documentation * Add logging * Rename * Extend gitignore
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -40,3 +40,9 @@ debug.test
|
||||
*errorDetails.json
|
||||
*_links.json
|
||||
*_reports.json
|
||||
|
||||
# Result files
|
||||
ATCResults.xml
|
||||
AUnitResults.xml
|
||||
ATCResults.html
|
||||
AUnitResults.html
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -19,7 +18,6 @@ import (
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/piperutils"
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -61,10 +59,10 @@ func abapEnvironmentRunATCCheck(options abapEnvironmentRunATCCheckOptions, telem
|
||||
details.XCsrfToken, err = fetchXcsrfToken("GET", details, nil, &client)
|
||||
}
|
||||
if err == nil {
|
||||
resp, err = triggerATCrun(options, details, &client)
|
||||
resp, err = triggerATCRun(options, details, &client)
|
||||
}
|
||||
if err == nil {
|
||||
err = handleATCresults(resp, details, &client, options.AtcResultsFileName, options.GenerateHTML)
|
||||
err = fetchAndPersistATCResults(resp, details, &client, options.AtcResultsFileName, options.GenerateHTML)
|
||||
}
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Fatal("step execution failed")
|
||||
@@ -73,7 +71,7 @@ func abapEnvironmentRunATCCheck(options abapEnvironmentRunATCCheckOptions, telem
|
||||
log.Entry().Info("ATC run completed successfully. If there are any results from the respective run they will be listed in the logs above as well as being saved in the output .xml file")
|
||||
}
|
||||
|
||||
func handleATCresults(resp *http.Response, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, atcResultFileName string, generateHTML bool) error {
|
||||
func fetchAndPersistATCResults(resp *http.Response, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, atcResultFileName string, generateHTML bool) error {
|
||||
var err error
|
||||
var abapEndpoint string
|
||||
abapEndpoint = details.URL
|
||||
@@ -91,7 +89,7 @@ func handleATCresults(resp *http.Response, details abaputils.ConnectionDetailsHT
|
||||
}
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
err = parseATCResult(body, atcResultFileName, generateHTML)
|
||||
err = logAndPersistATCResult(body, atcResultFileName, generateHTML)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("Handling ATC result failed: %w", err)
|
||||
@@ -99,83 +97,107 @@ func handleATCresults(resp *http.Response, details abaputils.ConnectionDetailsHT
|
||||
return nil
|
||||
}
|
||||
|
||||
func triggerATCrun(config abapEnvironmentRunATCCheckOptions, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender) (*http.Response, error) {
|
||||
var atcConfigyamlFile []byte
|
||||
abapEndpoint := details.URL
|
||||
filelocation, err := filepath.Glob(config.AtcConfig)
|
||||
//Parse YAML ATC run configuration as body for ATC run trigger
|
||||
if err == nil {
|
||||
filename, err := filepath.Abs(filelocation[0])
|
||||
if err == nil {
|
||||
atcConfigyamlFile, err = ioutil.ReadFile(filename)
|
||||
}
|
||||
}
|
||||
var ATCConfig ATCconfig
|
||||
if err == nil {
|
||||
var result []byte
|
||||
result, err = yaml.YAMLToJSON(atcConfigyamlFile)
|
||||
json.Unmarshal(result, &ATCConfig)
|
||||
}
|
||||
var checkVariantString, packageString, softwareComponentString string
|
||||
if err == nil {
|
||||
checkVariantString, packageString, softwareComponentString, err = buildATCCheckBody(ATCConfig)
|
||||
}
|
||||
func triggerATCRun(config abapEnvironmentRunATCCheckOptions, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender) (*http.Response, error) {
|
||||
|
||||
//Trigger ATC run
|
||||
bodyString, err := buildATCRequestBody(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp *http.Response
|
||||
var bodyString = `<?xml version="1.0" encoding="UTF-8"?><atc:runparameters xmlns:atc="http://www.sap.com/adt/atc" xmlns:obj="http://www.sap.com/adt/objectset"` + checkVariantString + `><obj:objectSet>` + softwareComponentString + packageString + `</obj:objectSet></atc:runparameters>`
|
||||
abapEndpoint := details.URL
|
||||
|
||||
log.Entry().Debugf("Request Body: %s", bodyString)
|
||||
var body = []byte(bodyString)
|
||||
if err == nil {
|
||||
details.URL = abapEndpoint + "/sap/bc/adt/api/atc/runs?clientWait=false"
|
||||
resp, err = runATC("POST", details, body, client)
|
||||
}
|
||||
if err != nil {
|
||||
return resp, fmt.Errorf("Triggering ATC run failed: %w", err)
|
||||
}
|
||||
return resp, nil
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func buildATCCheckBody(ATCConfig ATCconfig) (checkVariantString string, packageString string, softwareComponentString string, err error) {
|
||||
func buildATCRequestBody(config abapEnvironmentRunATCCheckOptions) (bodyString string, err error) {
|
||||
|
||||
atcConfig, err := resolveATCConfiguration(config)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Create string for the run parameters
|
||||
variant := "ABAP_CLOUD_DEVELOPMENT_DEFAULT"
|
||||
if atcConfig.CheckVariant != "" {
|
||||
variant = atcConfig.CheckVariant
|
||||
}
|
||||
log.Entry().Infof("ATC Check Variant: %s", variant)
|
||||
runParameters := ` checkVariant="` + variant + `"`
|
||||
if atcConfig.Configuration != "" {
|
||||
runParameters += ` configuration="` + atcConfig.Configuration + `"`
|
||||
}
|
||||
|
||||
objectSet, err := getATCObjectSet(atcConfig)
|
||||
|
||||
bodyString = `<?xml version="1.0" encoding="UTF-8"?><atc:runparameters xmlns:atc="http://www.sap.com/adt/atc" xmlns:obj="http://www.sap.com/adt/objectset"` + runParameters + `>` + objectSet + `</atc:runparameters>`
|
||||
return bodyString, err
|
||||
}
|
||||
|
||||
func resolveATCConfiguration(config abapEnvironmentRunATCCheckOptions) (atcConfig ATCConfiguration, err error) {
|
||||
|
||||
if config.AtcConfig != "" {
|
||||
// Configuration defaults to AUnitConfig
|
||||
log.Entry().Infof("ATC Configuration: %s", config.AtcConfig)
|
||||
atcConfigFile, err := abaputils.ReadConfigFile(config.AtcConfig)
|
||||
if err != nil {
|
||||
return atcConfig, err
|
||||
}
|
||||
json.Unmarshal(atcConfigFile, &atcConfig)
|
||||
return atcConfig, err
|
||||
|
||||
} else if config.Repositories != "" {
|
||||
// Fallback / EasyMode is the Repositories configuration
|
||||
log.Entry().Infof("ATC Configuration derived from: %s", config.Repositories)
|
||||
repositories, err := abaputils.GetRepositories((&abaputils.RepositoriesConfig{Repositories: config.Repositories}))
|
||||
if err != nil {
|
||||
return atcConfig, err
|
||||
}
|
||||
for _, repository := range repositories {
|
||||
atcConfig.Objects.SoftwareComponent = append(atcConfig.Objects.SoftwareComponent, SoftwareComponent{Name: repository.Name})
|
||||
}
|
||||
return atcConfig, nil
|
||||
} else {
|
||||
// Fail if no configuration is provided
|
||||
return atcConfig, errors.New("No configuration provided - please provide either an ATC configuration file or a repository configuration file")
|
||||
}
|
||||
}
|
||||
|
||||
func getATCObjectSet(ATCConfig ATCConfiguration) (objectSet string, err error) {
|
||||
if len(ATCConfig.Objects.Package) == 0 && len(ATCConfig.Objects.SoftwareComponent) == 0 {
|
||||
log.SetErrorCategory(log.ErrorConfiguration)
|
||||
return "", "", "", fmt.Errorf("Error while parsing ATC run config. Please provide the packages and/or the software components to be checked! %w", errors.New("No Package or Software Component specified. Please provide either one or both of them"))
|
||||
return "", fmt.Errorf("Error while parsing ATC run config. Please provide the packages and/or the software components to be checked! %w", errors.New("No Package or Software Component specified. Please provide either one or both of them"))
|
||||
}
|
||||
|
||||
//Build Check Variant and Configuration XML Body
|
||||
if len(ATCConfig.CheckVariant) != 0 {
|
||||
checkVariantString += ` checkVariant="` + ATCConfig.CheckVariant + `"`
|
||||
log.Entry().Infof("ATC Check Variant: %s", ATCConfig.CheckVariant)
|
||||
if len(ATCConfig.Configuration) != 0 {
|
||||
checkVariantString += ` configuration="` + ATCConfig.Configuration + `"`
|
||||
objectSet += `<obj:objectSet>`
|
||||
|
||||
//Build SC XML body
|
||||
if len(ATCConfig.Objects.SoftwareComponent) != 0 {
|
||||
objectSet += "<obj:softwarecomponents>"
|
||||
for _, s := range ATCConfig.Objects.SoftwareComponent {
|
||||
objectSet += `<obj:softwarecomponent value="` + s.Name + `"/>`
|
||||
}
|
||||
} else {
|
||||
const defaultCheckVariant = "ABAP_CLOUD_DEVELOPMENT_DEFAULT"
|
||||
checkVariantString += ` checkVariant="` + defaultCheckVariant + `"`
|
||||
log.Entry().Infof("ATC Check Variant: %s", checkVariantString)
|
||||
objectSet += "</obj:softwarecomponents>"
|
||||
}
|
||||
|
||||
//Build Package XML body
|
||||
if len(ATCConfig.Objects.Package) != 0 {
|
||||
packageString += "<obj:packages>"
|
||||
objectSet += "<obj:packages>"
|
||||
for _, s := range ATCConfig.Objects.Package {
|
||||
packageString += `<obj:package value="` + s.Name + `" includeSubpackages="` + strconv.FormatBool(s.IncludeSubpackages) + `"/>`
|
||||
objectSet += `<obj:package value="` + s.Name + `" includeSubpackages="` + strconv.FormatBool(s.IncludeSubpackages) + `"/>`
|
||||
}
|
||||
packageString += "</obj:packages>"
|
||||
objectSet += "</obj:packages>"
|
||||
}
|
||||
|
||||
//Build SC XML body
|
||||
if len(ATCConfig.Objects.SoftwareComponent) != 0 {
|
||||
softwareComponentString += "<obj:softwarecomponents>"
|
||||
for _, s := range ATCConfig.Objects.SoftwareComponent {
|
||||
softwareComponentString += `<obj:softwarecomponent value="` + s.Name + `"/>`
|
||||
}
|
||||
softwareComponentString += "</obj:softwarecomponents>"
|
||||
}
|
||||
return checkVariantString, packageString, softwareComponentString, nil
|
||||
objectSet += `</obj:objectSet>`
|
||||
|
||||
return objectSet, nil
|
||||
}
|
||||
|
||||
func parseATCResult(body []byte, atcResultFileName string, generateHTML bool) (err error) {
|
||||
func logAndPersistATCResult(body []byte, atcResultFileName string, generateHTML bool) (err error) {
|
||||
if len(body) == 0 {
|
||||
return fmt.Errorf("Parsing ATC result failed: %w", errors.New("Body is empty, can't parse empty body"))
|
||||
}
|
||||
@@ -253,9 +275,6 @@ func fetchXcsrfToken(requestType string, details abaputils.ConnectionDetailsHTTP
|
||||
}
|
||||
defer req.Body.Close()
|
||||
|
||||
// workaround until golang version 1.16 is used
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
token := req.Header.Get("X-Csrf-Token")
|
||||
return token, err
|
||||
}
|
||||
@@ -293,8 +312,6 @@ func pollATCRun(details abaputils.ConnectionDetailsHTTP, body []byte, client pip
|
||||
|
||||
func getHTTPResponseATCRun(requestType string, details abaputils.ConnectionDetailsHTTP, body []byte, client piperhttp.Sender) (*http.Response, error) {
|
||||
|
||||
log.Entry().WithField("ABAP Endpoint: ", details.URL).Info("Polling ATC run status")
|
||||
|
||||
header := make(map[string][]string)
|
||||
header["Accept"] = []string{"application/vnd.sap.atc.run.v1+xml"}
|
||||
|
||||
@@ -364,8 +381,8 @@ func generateHTMLDocument(parsedXML *Result) (htmlDocumentString string) {
|
||||
return htmlDocumentString
|
||||
}
|
||||
|
||||
//ATCconfig object for parsing yaml config of software components and packages
|
||||
type ATCconfig struct {
|
||||
//ATCConfiguration object for parsing yaml config of software components and packages
|
||||
type ATCConfiguration struct {
|
||||
CheckVariant string `json:"checkvariant,omitempty"`
|
||||
Configuration string `json:"configuration,omitempty"`
|
||||
Objects ATCObjects `json:"atcobjects"`
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
type abapEnvironmentRunATCCheckOptions struct {
|
||||
AtcConfig string `json:"atcConfig,omitempty"`
|
||||
Repositories string `json:"repositories,omitempty"`
|
||||
CfAPIEndpoint string `json:"cfApiEndpoint,omitempty"`
|
||||
CfOrg string `json:"cfOrg,omitempty"`
|
||||
CfServiceInstance string `json:"cfServiceInstance,omitempty"`
|
||||
@@ -128,6 +129,7 @@ Regardless of the option you chose, please make sure to provide the configuratio
|
||||
|
||||
func addAbapEnvironmentRunATCCheckFlags(cmd *cobra.Command, stepConfig *abapEnvironmentRunATCCheckOptions) {
|
||||
cmd.Flags().StringVar(&stepConfig.AtcConfig, "atcConfig", os.Getenv("PIPER_atcConfig"), "Path to a YAML configuration file for Packages and/or Software Components to be checked during ATC run")
|
||||
cmd.Flags().StringVar(&stepConfig.Repositories, "repositories", os.Getenv("PIPER_repositories"), "Specifies a YAML file containing the repositories configuration")
|
||||
cmd.Flags().StringVar(&stepConfig.CfAPIEndpoint, "cfApiEndpoint", os.Getenv("PIPER_cfApiEndpoint"), "Cloud Foundry API endpoint")
|
||||
cmd.Flags().StringVar(&stepConfig.CfOrg, "cfOrg", os.Getenv("PIPER_cfOrg"), "CF org")
|
||||
cmd.Flags().StringVar(&stepConfig.CfServiceInstance, "cfServiceInstance", os.Getenv("PIPER_cfServiceInstance"), "Parameter of ServiceInstance Name to delete CloudFoundry Service")
|
||||
@@ -139,7 +141,6 @@ func addAbapEnvironmentRunATCCheckFlags(cmd *cobra.Command, stepConfig *abapEnvi
|
||||
cmd.Flags().StringVar(&stepConfig.AtcResultsFileName, "atcResultsFileName", `ATCResults.xml`, "Specifies output file name for the results from the ATC run. This file name will also be used for generating the HTML file")
|
||||
cmd.Flags().BoolVar(&stepConfig.GenerateHTML, "generateHTML", false, "Specifies whether the ATC results should also be generated as an HTML document")
|
||||
|
||||
cmd.MarkFlagRequired("atcConfig")
|
||||
cmd.MarkFlagRequired("username")
|
||||
cmd.MarkFlagRequired("password")
|
||||
}
|
||||
@@ -163,10 +164,19 @@ func abapEnvironmentRunATCCheckMetadata() config.StepData {
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Default: os.Getenv("PIPER_atcConfig"),
|
||||
},
|
||||
{
|
||||
Name: "repositories",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Default: os.Getenv("PIPER_repositories"),
|
||||
},
|
||||
{
|
||||
Name: "cfApiEndpoint",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
|
||||
@@ -248,7 +248,7 @@ func TestParseATCResult(t *testing.T) {
|
||||
</file>
|
||||
</checkstyle>`
|
||||
body := []byte(bodyString)
|
||||
err = parseATCResult(body, "ATCResults.xml", false)
|
||||
err = logAndPersistATCResult(body, "ATCResults.xml", false)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
t.Run("succes case: test parsing empty XML result", func(t *testing.T) {
|
||||
@@ -267,14 +267,14 @@ func TestParseATCResult(t *testing.T) {
|
||||
<checkstyle>
|
||||
</checkstyle>`
|
||||
body := []byte(bodyString)
|
||||
err = parseATCResult(body, "ATCResults.xml", false)
|
||||
err = logAndPersistATCResult(body, "ATCResults.xml", false)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
t.Run("failure case: parsing empty xml", func(t *testing.T) {
|
||||
var bodyString string
|
||||
body := []byte(bodyString)
|
||||
|
||||
err := parseATCResult(body, "ATCResults.xml", false)
|
||||
err := logAndPersistATCResult(body, "ATCResults.xml", false)
|
||||
assert.EqualError(t, err, "Parsing ATC result failed: Body is empty, can't parse empty body")
|
||||
})
|
||||
t.Run("failure case: html response", func(t *testing.T) {
|
||||
@@ -291,37 +291,27 @@ func TestParseATCResult(t *testing.T) {
|
||||
}()
|
||||
bodyString := `<html><head><title>HTMLTestResponse</title</head></html>`
|
||||
body := []byte(bodyString)
|
||||
err = parseATCResult(body, "ATCResults.xml", false)
|
||||
err = logAndPersistATCResult(body, "ATCResults.xml", false)
|
||||
assert.EqualError(t, err, "The Software Component could not be checked. Please make sure the respective Software Component has been cloned successfully on the system")
|
||||
})
|
||||
}
|
||||
|
||||
func TestBuildATCCheckBody(t *testing.T) {
|
||||
t.Run("Test build body with no software component and package", func(t *testing.T) {
|
||||
expectedpackagestring := ""
|
||||
expectedsoftwarecomponentstring := ""
|
||||
expectedcheckvariantstring := ""
|
||||
expectedObjectSet := ""
|
||||
|
||||
var err error
|
||||
var config ATCconfig
|
||||
var checkVariantString, packageString, softwarecomponentString string
|
||||
var config ATCConfiguration
|
||||
|
||||
checkVariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
|
||||
objectSet, err := getATCObjectSet(config)
|
||||
|
||||
assert.Equal(t, expectedcheckvariantstring, checkVariantString)
|
||||
assert.Equal(t, expectedpackagestring, packageString)
|
||||
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
|
||||
assert.Equal(t, expectedObjectSet, objectSet)
|
||||
assert.EqualError(t, err, "Error while parsing ATC run config. Please provide the packages and/or the software components to be checked! No Package or Software Component specified. Please provide either one or both of them")
|
||||
})
|
||||
t.Run("success case: Test build body with example yaml config", func(t *testing.T) {
|
||||
expectedcheckvariantstring := " checkVariant=\"ABAP_CLOUD_DEVELOPMENT_DEFAULT\""
|
||||
expectedpackagestring := "<obj:packages><obj:package value=\"testPackage\" includeSubpackages=\"true\"/><obj:package value=\"testPackage2\" includeSubpackages=\"false\"/></obj:packages>"
|
||||
expectedsoftwarecomponentstring := "<obj:softwarecomponents><obj:softwarecomponent value=\"testSoftwareComponent\"/><obj:softwarecomponent value=\"testSoftwareComponent2\"/></obj:softwarecomponents>"
|
||||
|
||||
var err error
|
||||
var config ATCconfig
|
||||
expectedObjectSet := "<obj:objectSet><obj:softwarecomponents><obj:softwarecomponent value=\"testSoftwareComponent\"/><obj:softwarecomponent value=\"testSoftwareComponent2\"/></obj:softwarecomponents><obj:packages><obj:package value=\"testPackage\" includeSubpackages=\"true\"/><obj:package value=\"testPackage2\" includeSubpackages=\"false\"/></obj:packages></obj:objectSet>"
|
||||
|
||||
config = ATCconfig{
|
||||
config := ATCConfiguration{
|
||||
"",
|
||||
"",
|
||||
ATCObjects{
|
||||
@@ -336,24 +326,19 @@ func TestBuildATCCheckBody(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
var checkvariantString, packageString, softwarecomponentString string
|
||||
objectSet, err := getATCObjectSet(config)
|
||||
|
||||
checkvariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
|
||||
|
||||
assert.Equal(t, expectedcheckvariantstring, checkvariantString)
|
||||
assert.Equal(t, expectedpackagestring, packageString)
|
||||
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
|
||||
assert.Equal(t, expectedObjectSet, objectSet)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
t.Run("failure case: Test build body with example yaml config with only packages and no software components", func(t *testing.T) {
|
||||
expectedcheckvariantstring := " checkVariant=\"ABAP_CLOUD_DEVELOPMENT_DEFAULT\""
|
||||
expectedpackagestring := `<obj:packages><obj:package value="testPackage" includeSubpackages="true"/><obj:package value="testPackage2" includeSubpackages="false"/></obj:packages>`
|
||||
expectedsoftwarecomponentstring := ""
|
||||
|
||||
expectedObjectSet := `<obj:objectSet><obj:packages><obj:package value="testPackage" includeSubpackages="true"/><obj:package value="testPackage2" includeSubpackages="false"/></obj:packages></obj:objectSet>`
|
||||
|
||||
var err error
|
||||
var config ATCconfig
|
||||
var config ATCConfiguration
|
||||
|
||||
config = ATCconfig{
|
||||
config = ATCConfiguration{
|
||||
"",
|
||||
"",
|
||||
ATCObjects{
|
||||
@@ -364,25 +349,17 @@ func TestBuildATCCheckBody(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
var checkvariantString, packageString, softwarecomponentString string
|
||||
objectSet, err := getATCObjectSet(config)
|
||||
|
||||
checkvariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
|
||||
|
||||
assert.Equal(t, expectedcheckvariantstring, checkvariantString)
|
||||
assert.Equal(t, expectedpackagestring, packageString)
|
||||
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
|
||||
assert.Equal(t, expectedObjectSet, objectSet)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
})
|
||||
t.Run("success case: Test build body with example yaml config with no packages and only software components", func(t *testing.T) {
|
||||
expectedcheckvariantstring := " checkVariant=\"ABAP_CLOUD_DEVELOPMENT_DEFAULT\""
|
||||
expectedpackagestring := ""
|
||||
expectedsoftwarecomponentstring := `<obj:softwarecomponents><obj:softwarecomponent value="testSoftwareComponent"/><obj:softwarecomponent value="testSoftwareComponent2"/></obj:softwarecomponents>`
|
||||
|
||||
var err error
|
||||
var config ATCconfig
|
||||
expectedObjectSet := `<obj:objectSet><obj:softwarecomponents><obj:softwarecomponent value="testSoftwareComponent"/><obj:softwarecomponent value="testSoftwareComponent2"/></obj:softwarecomponents></obj:objectSet>`
|
||||
|
||||
config = ATCconfig{
|
||||
config := ATCConfiguration{
|
||||
"",
|
||||
"",
|
||||
ATCObjects{
|
||||
@@ -393,45 +370,9 @@ func TestBuildATCCheckBody(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
var checkvariantString, packageString, softwarecomponentString string
|
||||
objectSet, err := getATCObjectSet(config)
|
||||
|
||||
checkvariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
|
||||
|
||||
assert.Equal(t, expectedcheckvariantstring, checkvariantString)
|
||||
assert.Equal(t, expectedpackagestring, packageString)
|
||||
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
t.Run("success case: Test build body with example yaml config with check variant configuration", func(t *testing.T) {
|
||||
expectedcheckvariantstring := ` checkVariant="TestVariant" configuration="TestConfiguration"`
|
||||
expectedpackagestring := `<obj:packages><obj:package value="testPackage" includeSubpackages="true"/><obj:package value="testPackage2" includeSubpackages="false"/></obj:packages>`
|
||||
expectedsoftwarecomponentstring := `<obj:softwarecomponents><obj:softwarecomponent value="testSoftwareComponent"/><obj:softwarecomponent value="testSoftwareComponent2"/></obj:softwarecomponents>`
|
||||
|
||||
var err error
|
||||
var config ATCconfig
|
||||
|
||||
config = ATCconfig{
|
||||
"TestVariant",
|
||||
"TestConfiguration",
|
||||
ATCObjects{
|
||||
SoftwareComponent: []SoftwareComponent{
|
||||
{Name: "testSoftwareComponent"},
|
||||
{Name: "testSoftwareComponent2"},
|
||||
},
|
||||
Package: []Package{
|
||||
{Name: "testPackage", IncludeSubpackages: true},
|
||||
{Name: "testPackage2", IncludeSubpackages: false},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var checkvariantString, packageString, softwarecomponentString string
|
||||
|
||||
checkvariantString, packageString, softwarecomponentString, err = buildATCCheckBody(config)
|
||||
|
||||
assert.Equal(t, expectedcheckvariantstring, checkvariantString)
|
||||
assert.Equal(t, expectedpackagestring, packageString)
|
||||
assert.Equal(t, expectedsoftwarecomponentstring, softwarecomponentString)
|
||||
assert.Equal(t, expectedObjectSet, objectSet)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
}
|
||||
@@ -463,3 +404,99 @@ func TestGenerateHTMLDocument(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestResolveConfiguration(t *testing.T) {
|
||||
|
||||
t.Run("resolve atcConfig-yml", func(t *testing.T) {
|
||||
|
||||
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><atc:runparameters xmlns:atc=\"http://www.sap.com/adt/atc\" xmlns:obj=\"http://www.sap.com/adt/objectset\" checkVariant=\"MY_TEST\" configuration=\"MY_CONFIG\"><obj:objectSet><obj:softwarecomponents><obj:softwarecomponent value=\"Z_TEST\"/><obj:softwarecomponent value=\"/DMO/SWC\"/></obj:softwarecomponents><obj:packages><obj:package value=\"Z_TEST\" includeSubpackages=\"false\"/></obj:packages></obj:objectSet></atc:runparameters>"
|
||||
config := abapEnvironmentRunATCCheckOptions{
|
||||
AtcConfig: "atc.yml",
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "atcDir")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
oldCWD, _ := os.Getwd()
|
||||
_ = os.Chdir(dir)
|
||||
// clean up tmp dir
|
||||
defer func() {
|
||||
_ = os.Chdir(oldCWD)
|
||||
_ = os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
yamlBody := `checkvariant: MY_TEST
|
||||
configuration: MY_CONFIG
|
||||
atcobjects:
|
||||
package:
|
||||
- name: Z_TEST
|
||||
softwarecomponent:
|
||||
- name: Z_TEST
|
||||
- name: /DMO/SWC
|
||||
`
|
||||
|
||||
err = ioutil.WriteFile(config.AtcConfig, []byte(yamlBody), 0644)
|
||||
if assert.Equal(t, err, nil) {
|
||||
bodyString, err := buildATCRequestBody(config)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, expectedBodyString, bodyString)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
t.Run("resolve repo-yml", func(t *testing.T) {
|
||||
|
||||
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><atc:runparameters xmlns:atc=\"http://www.sap.com/adt/atc\" xmlns:obj=\"http://www.sap.com/adt/objectset\" checkVariant=\"ABAP_CLOUD_DEVELOPMENT_DEFAULT\"><obj:objectSet><obj:softwarecomponents><obj:softwarecomponent value=\"Z_TEST\"/><obj:softwarecomponent value=\"/DMO/SWC\"/></obj:softwarecomponents></obj:objectSet></atc:runparameters>"
|
||||
config := abapEnvironmentRunATCCheckOptions{
|
||||
Repositories: "repo.yml",
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "test parse AUnit yaml config2")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
oldCWD, _ := os.Getwd()
|
||||
_ = os.Chdir(dir)
|
||||
// clean up tmp dir
|
||||
defer func() {
|
||||
_ = os.Chdir(oldCWD)
|
||||
_ = os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
yamlBody := `repositories:
|
||||
- name: Z_TEST
|
||||
- name: /DMO/SWC
|
||||
`
|
||||
|
||||
err = ioutil.WriteFile(config.Repositories, []byte(yamlBody), 0644)
|
||||
if assert.Equal(t, err, nil) {
|
||||
bodyString, err := buildATCRequestBody(config)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, expectedBodyString, bodyString)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
t.Run("Missing config files", func(t *testing.T) {
|
||||
|
||||
config := abapEnvironmentRunATCCheckOptions{
|
||||
AtcConfig: "atc.yml",
|
||||
}
|
||||
|
||||
bodyString, err := buildATCRequestBody(config)
|
||||
assert.Equal(t, "Could not find atc.yml", err.Error())
|
||||
assert.Equal(t, "", bodyString)
|
||||
|
||||
})
|
||||
|
||||
t.Run("Config file not specified", func(t *testing.T) {
|
||||
|
||||
config := abapEnvironmentRunATCCheckOptions{}
|
||||
|
||||
bodyString, err := buildATCRequestBody(config)
|
||||
assert.Equal(t, "No configuration provided - please provide either an ATC configuration file or a repository configuration file", err.Error())
|
||||
assert.Equal(t, "", bodyString)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -19,7 +18,6 @@ import (
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/piperutils"
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -96,7 +94,7 @@ func runAbapEnvironmentRunAUnitTest(config *abapEnvironmentRunAUnitTestOptions,
|
||||
resp, err = triggerAUnitrun(*config, details, client)
|
||||
}
|
||||
if err == nil {
|
||||
err = handleAUnitResults(resp, details, client, config.AUnitResultsFileName, config.GenerateHTML)
|
||||
err = fetchAndPersistAUnitResults(resp, details, client, config.AUnitResultsFileName, config.GenerateHTML)
|
||||
}
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Fatal("step execution failed")
|
||||
@@ -106,40 +104,51 @@ func runAbapEnvironmentRunAUnitTest(config *abapEnvironmentRunAUnitTestOptions,
|
||||
}
|
||||
|
||||
func triggerAUnitrun(config abapEnvironmentRunAUnitTestOptions, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender) (*http.Response, error) {
|
||||
var aUnitConfigYamlFile []byte
|
||||
|
||||
abapEndpoint := details.URL
|
||||
filelocation, err := filepath.Glob(config.AUnitConfig)
|
||||
//Parse YAML AUnit run configuration as body for AUnit run trigger
|
||||
if err == nil {
|
||||
filename, err := filepath.Abs(filelocation[0])
|
||||
if err == nil {
|
||||
aUnitConfigYamlFile, err = ioutil.ReadFile(filename)
|
||||
}
|
||||
}
|
||||
var AUnitConfig AUnitConfig
|
||||
if err == nil {
|
||||
var result []byte
|
||||
result, err = yaml.YAMLToJSON(aUnitConfigYamlFile)
|
||||
json.Unmarshal(result, &AUnitConfig)
|
||||
}
|
||||
var metadataString, optionsString, objectSetString string
|
||||
if err == nil {
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(AUnitConfig)
|
||||
bodyString, err := buildAUnitRequestBody(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Trigger AUnit run
|
||||
var resp *http.Response
|
||||
var bodyString = `<?xml version="1.0" encoding="UTF-8"?>` + metadataString + optionsString + objectSetString
|
||||
|
||||
var body = []byte(bodyString)
|
||||
if err == nil {
|
||||
log.Entry().Debugf("Request Body: %s", bodyString)
|
||||
details.URL = abapEndpoint + "/sap/bc/adt/api/abapunit/runs"
|
||||
resp, err = runAUnit("POST", details, body, client)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func resolveAUnitConfiguration(config abapEnvironmentRunAUnitTestOptions) (aUnitConfig AUnitConfig, err error) {
|
||||
|
||||
if config.AUnitConfig != "" {
|
||||
// Configuration defaults to AUnitConfig
|
||||
log.Entry().Infof("AUnit Configuration: %s", config.AUnitConfig)
|
||||
result, err := abaputils.ReadConfigFile(config.AUnitConfig)
|
||||
if err != nil {
|
||||
return resp, fmt.Errorf("Triggering AUnit test run failed: %w", err)
|
||||
return aUnitConfig, err
|
||||
}
|
||||
err = json.Unmarshal(result, &aUnitConfig)
|
||||
return aUnitConfig, err
|
||||
|
||||
} else if config.Repositories != "" {
|
||||
// Fallback / EasyMode is the Repositories configuration
|
||||
log.Entry().Infof("AUnit Configuration derived from: %s", config.Repositories)
|
||||
repos, err := abaputils.GetRepositories((&abaputils.RepositoriesConfig{Repositories: config.Repositories}))
|
||||
if err != nil {
|
||||
return aUnitConfig, err
|
||||
}
|
||||
for _, repo := range repos {
|
||||
aUnitConfig.ObjectSet.SoftwareComponents = append(aUnitConfig.ObjectSet.SoftwareComponents, SoftwareComponents{Name: repo.Name})
|
||||
}
|
||||
aUnitConfig.Title = "AUnit Test Run"
|
||||
return aUnitConfig, nil
|
||||
} else {
|
||||
// Fail if no configuration is provided
|
||||
return aUnitConfig, errors.New("No configuration provided - please provide either an AUnit configuration file or a repository configuration file")
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func convertAUnitOptions(options *abapEnvironmentRunAUnitTestOptions) abaputils.AbapEnvironmentOptions {
|
||||
@@ -157,7 +166,7 @@ func convertAUnitOptions(options *abapEnvironmentRunAUnitTestOptions) abaputils.
|
||||
return subOptions
|
||||
}
|
||||
|
||||
func handleAUnitResults(resp *http.Response, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, aunitResultFileName string, generateHTML bool) error {
|
||||
func fetchAndPersistAUnitResults(resp *http.Response, details abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, aunitResultFileName string, generateHTML bool) error {
|
||||
var err error
|
||||
var abapEndpoint string
|
||||
abapEndpoint = details.URL
|
||||
@@ -166,7 +175,7 @@ func handleAUnitResults(resp *http.Response, details abaputils.ConnectionDetails
|
||||
location, err = pollAUnitRun(details, nil, client)
|
||||
if err == nil {
|
||||
details.URL = abapEndpoint + location
|
||||
resp, err = getResultAUnitRun("GET", details, nil, client)
|
||||
resp, err = getAUnitResults("GET", details, nil, client)
|
||||
}
|
||||
//Parse response
|
||||
var body []byte
|
||||
@@ -175,7 +184,7 @@ func handleAUnitResults(resp *http.Response, details abaputils.ConnectionDetails
|
||||
}
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
err = parseAUnitResult(body, aunitResultFileName, generateHTML)
|
||||
err = persistAUnitResult(body, aunitResultFileName, generateHTML)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("Handling AUnit result failed: %w", err)
|
||||
@@ -183,29 +192,35 @@ func handleAUnitResults(resp *http.Response, details abaputils.ConnectionDetails
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildAUnitTestBody(AUnitConfig AUnitConfig) (metadataString string, optionsString string, objectSetString string, err error) {
|
||||
func buildAUnitRequestBody(config abapEnvironmentRunAUnitTestOptions) (bodyString string, err error) {
|
||||
|
||||
bodyString = ""
|
||||
AUnitConfig, err := resolveAUnitConfiguration(config)
|
||||
if err != nil {
|
||||
return bodyString, err
|
||||
}
|
||||
|
||||
//Checks before building the XML body
|
||||
if AUnitConfig.Title == "" {
|
||||
return "", "", "", fmt.Errorf("Error while parsing AUnit test run config. No title for the AUnit run has been provided. Please configure an appropriate title for the respective test run")
|
||||
return bodyString, fmt.Errorf("Error while parsing AUnit test run config. No title for the AUnit run has been provided. Please configure an appropriate title for the respective test run")
|
||||
}
|
||||
if AUnitConfig.Context == "" {
|
||||
AUnitConfig.Context = "ABAP Environment Pipeline"
|
||||
}
|
||||
if reflect.DeepEqual(ObjectSet{}, AUnitConfig.ObjectSet) {
|
||||
return "", "", "", fmt.Errorf("Error while parsing AUnit test run object set config. No object set has been provided. Please configure the objects you want to be checked for the respective test run")
|
||||
return bodyString, fmt.Errorf("Error while parsing AUnit test run object set config. No object set has been provided. Please configure the objects you want to be checked for the respective test run")
|
||||
}
|
||||
|
||||
//Build Options
|
||||
optionsString += buildAUnitOptionsString(AUnitConfig)
|
||||
optionsString := buildAUnitOptionsString(AUnitConfig)
|
||||
//Build metadata string
|
||||
metadataString += `<aunit:run title="` + AUnitConfig.Title + `" context="` + AUnitConfig.Context + `" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
|
||||
|
||||
metadataString := `<aunit:run title="` + AUnitConfig.Title + `" context="` + AUnitConfig.Context + `" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
|
||||
//Build Object Set
|
||||
objectSetString += buildAUnitObjectSetString(AUnitConfig)
|
||||
objectSetString += `</aunit:run>`
|
||||
objectSetString := buildAUnitObjectSetString(AUnitConfig)
|
||||
|
||||
return metadataString, optionsString, objectSetString, nil
|
||||
bodyString += `<?xml version="1.0" encoding="UTF-8"?>` + metadataString + optionsString + objectSetString + `</aunit:run>`
|
||||
|
||||
return bodyString, nil
|
||||
}
|
||||
|
||||
func runAUnit(requestType string, details abaputils.ConnectionDetailsHTTP, body []byte, client piperhttp.Sender) (*http.Response, error) {
|
||||
@@ -282,11 +297,6 @@ func buildAUnitOptionsString(AUnitConfig AUnitConfig) (optionsString string) {
|
||||
return optionsString
|
||||
}
|
||||
|
||||
func buildOSLObjectSets(multipropertyset MultiPropertySet) (objectSetString string) {
|
||||
objectSetString += writeObjectSetProperties(multipropertyset)
|
||||
return objectSetString
|
||||
}
|
||||
|
||||
func writeObjectSetProperties(set MultiPropertySet) (objectSetString string) {
|
||||
for _, packages := range set.PackageNames {
|
||||
objectSetString += `<osl:package name="` + packages.Name + `"/>`
|
||||
@@ -342,10 +352,10 @@ func buildAUnitObjectSetString(AUnitConfig AUnitConfig) (objectSetString string)
|
||||
PackageNames: s.PackageNames,
|
||||
SoftwareComponents: s.SoftwareComponents,
|
||||
}
|
||||
objectSetString += buildOSLObjectSets(mps)
|
||||
objectSetString += writeObjectSetProperties(mps)
|
||||
}
|
||||
|
||||
objectSetString += buildOSLObjectSets(s.MultiPropertySet)
|
||||
objectSetString += writeObjectSetProperties(s.MultiPropertySet)
|
||||
|
||||
if !(reflect.DeepEqual(s.MultiPropertySet, MultiPropertySet{})) {
|
||||
log.Entry().Info("Wrong configuration has been detected: MultiPropertySet has been used. Please note that there is no official documentation for this usage. Please check the step documentation for more information")
|
||||
@@ -422,7 +432,7 @@ func getHTTPResponseAUnitRun(requestType string, details abaputils.ConnectionDet
|
||||
return req, err
|
||||
}
|
||||
|
||||
func getResultAUnitRun(requestType string, details abaputils.ConnectionDetailsHTTP, body []byte, client piperhttp.Sender) (*http.Response, error) {
|
||||
func getAUnitResults(requestType string, details abaputils.ConnectionDetailsHTTP, body []byte, client piperhttp.Sender) (*http.Response, error) {
|
||||
|
||||
log.Entry().WithField("ABAP Endpoint: ", details.URL).Info("Getting AUnit results")
|
||||
|
||||
@@ -437,7 +447,7 @@ func getResultAUnitRun(requestType string, details abaputils.ConnectionDetailsHT
|
||||
return req, err
|
||||
}
|
||||
|
||||
func parseAUnitResult(body []byte, aunitResultFileName string, generateHTML bool) (err error) {
|
||||
func persistAUnitResult(body []byte, aunitResultFileName string, generateHTML bool) (err error) {
|
||||
if len(body) == 0 {
|
||||
return fmt.Errorf("Parsing AUnit result failed: %w", errors.New("Body is empty, can't parse empty body"))
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
type abapEnvironmentRunAUnitTestOptions struct {
|
||||
AUnitConfig string `json:"aUnitConfig,omitempty"`
|
||||
Repositories string `json:"repositories,omitempty"`
|
||||
CfAPIEndpoint string `json:"cfApiEndpoint,omitempty"`
|
||||
CfOrg string `json:"cfOrg,omitempty"`
|
||||
CfServiceInstance string `json:"cfServiceInstance,omitempty"`
|
||||
@@ -128,6 +129,7 @@ Regardless of the option you chose, please make sure to provide the object set c
|
||||
|
||||
func addAbapEnvironmentRunAUnitTestFlags(cmd *cobra.Command, stepConfig *abapEnvironmentRunAUnitTestOptions) {
|
||||
cmd.Flags().StringVar(&stepConfig.AUnitConfig, "aUnitConfig", os.Getenv("PIPER_aUnitConfig"), "Path to a YAML configuration file for the object set to be checked during the AUnit test run")
|
||||
cmd.Flags().StringVar(&stepConfig.Repositories, "repositories", os.Getenv("PIPER_repositories"), "Specifies a YAML file containing the repositories configuration")
|
||||
cmd.Flags().StringVar(&stepConfig.CfAPIEndpoint, "cfApiEndpoint", os.Getenv("PIPER_cfApiEndpoint"), "Cloud Foundry API endpoint")
|
||||
cmd.Flags().StringVar(&stepConfig.CfOrg, "cfOrg", os.Getenv("PIPER_cfOrg"), "Cloud Foundry org")
|
||||
cmd.Flags().StringVar(&stepConfig.CfServiceInstance, "cfServiceInstance", os.Getenv("PIPER_cfServiceInstance"), "Parameter of ServiceInstance Name to delete Cloud Foundry Service")
|
||||
@@ -139,7 +141,6 @@ func addAbapEnvironmentRunAUnitTestFlags(cmd *cobra.Command, stepConfig *abapEnv
|
||||
cmd.Flags().StringVar(&stepConfig.AUnitResultsFileName, "aUnitResultsFileName", `AUnitResults.xml`, "Specifies output file name for the results from the AUnit run.")
|
||||
cmd.Flags().BoolVar(&stepConfig.GenerateHTML, "generateHTML", false, "Specifies whether the AUnit results should also be generated as an HTML document")
|
||||
|
||||
cmd.MarkFlagRequired("aUnitConfig")
|
||||
cmd.MarkFlagRequired("username")
|
||||
cmd.MarkFlagRequired("password")
|
||||
}
|
||||
@@ -163,10 +164,19 @@ func abapEnvironmentRunAUnitTestMetadata() config.StepData {
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Default: os.Getenv("PIPER_aUnitConfig"),
|
||||
},
|
||||
{
|
||||
Name: "repositories",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Default: os.Getenv("PIPER_repositories"),
|
||||
},
|
||||
{
|
||||
Name: "cfApiEndpoint",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
|
||||
@@ -27,40 +27,29 @@ func newAbapEnvironmentRunAUnitTestTestsUtils() abapEnvironmentRunAUnitTestMockU
|
||||
return utils
|
||||
}
|
||||
|
||||
func TestBuildAUnitTestBody(t *testing.T) {
|
||||
|
||||
func TestBuildAUnitRequestBody(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("Test AUnit test run body with no data", func(t *testing.T) {
|
||||
|
||||
t.Parallel()
|
||||
|
||||
expectedmetadataString := ""
|
||||
expectedoptionsString := ""
|
||||
expectedobjectSetString := ""
|
||||
var config abapEnvironmentRunAUnitTestOptions
|
||||
|
||||
var err error
|
||||
var config AUnitConfig
|
||||
var metadataString, optionsString, objectSetString string
|
||||
bodyString, err := buildAUnitRequestBody(config)
|
||||
expectedBodyString := ""
|
||||
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
|
||||
|
||||
assert.Equal(t, expectedmetadataString, metadataString)
|
||||
assert.Equal(t, expectedoptionsString, optionsString)
|
||||
assert.Equal(t, expectedobjectSetString, objectSetString)
|
||||
assert.EqualError(t, err, "Error while parsing AUnit test run config. No title for the AUnit run has been provided. Please configure an appropriate title for the respective test run")
|
||||
assert.Equal(t, expectedBodyString, bodyString)
|
||||
assert.EqualError(t, err, "No configuration provided - please provide either an AUnit configuration file or a repository configuration file")
|
||||
})
|
||||
|
||||
t.Run("Test AUnit test run body with example yaml config of not supported Object Sets", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
expectedmetadataString := `<aunit:run title="Test Title" context="Test Context" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
|
||||
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="false" foreignTests="false"/><aunit:riskLevel harmless="false" dangerous="false" critical="false"/><aunit:duration short="false" medium="false" long="false"/></aunit:options>`
|
||||
expectedobjectSetString := `</aunit:run>`
|
||||
expectedobjectSetString := ``
|
||||
|
||||
var err error
|
||||
var config AUnitConfig
|
||||
|
||||
config = AUnitConfig{
|
||||
config := AUnitConfig{
|
||||
Title: "Test Title",
|
||||
Context: "Test Context",
|
||||
Options: AUnitOptions{
|
||||
@@ -110,27 +99,20 @@ func TestBuildAUnitTestBody(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
var metadataString, optionsString, objectSetString string
|
||||
objectSetString := buildAUnitObjectSetString(config)
|
||||
optionsString := buildAUnitOptionsString(config)
|
||||
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
|
||||
|
||||
assert.Equal(t, expectedmetadataString, metadataString)
|
||||
assert.Equal(t, expectedoptionsString, optionsString)
|
||||
assert.Equal(t, expectedobjectSetString, objectSetString)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
|
||||
t.Run("Test AUnit test run body with example yaml config of only Multi Property Set", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
expectedmetadataString := `<aunit:run title="Test Title" context="Test Context" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
|
||||
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="false" foreignTests="false"/><aunit:riskLevel harmless="false" dangerous="false" critical="false"/><aunit:duration short="false" medium="false" long="false"/></aunit:options>`
|
||||
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet></aunit:run>`
|
||||
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet>`
|
||||
|
||||
var err error
|
||||
var config AUnitConfig
|
||||
|
||||
config = AUnitConfig{
|
||||
config := AUnitConfig{
|
||||
Title: "Test Title",
|
||||
Context: "Test Context",
|
||||
Options: AUnitOptions{
|
||||
@@ -165,27 +147,20 @@ func TestBuildAUnitTestBody(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
var metadataString, optionsString, objectSetString string
|
||||
objectSetString := buildAUnitObjectSetString(config)
|
||||
optionsString := buildAUnitOptionsString(config)
|
||||
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
|
||||
|
||||
assert.Equal(t, expectedmetadataString, metadataString)
|
||||
assert.Equal(t, expectedoptionsString, optionsString)
|
||||
assert.Equal(t, expectedobjectSetString, objectSetString)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
|
||||
t.Run("Test AUnit test run body with example yaml config of only Multi Property Set but empty type", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
expectedmetadataString := `<aunit:run title="Test Title" context="Test Context" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
|
||||
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="false" foreignTests="false"/><aunit:riskLevel harmless="false" dangerous="false" critical="false"/><aunit:duration short="false" medium="false" long="false"/></aunit:options>`
|
||||
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet></aunit:run>`
|
||||
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet>`
|
||||
|
||||
var err error
|
||||
var config AUnitConfig
|
||||
|
||||
config = AUnitConfig{
|
||||
config := AUnitConfig{
|
||||
Title: "Test Title",
|
||||
Context: "Test Context",
|
||||
Options: AUnitOptions{
|
||||
@@ -220,27 +195,20 @@ func TestBuildAUnitTestBody(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
var metadataString, optionsString, objectSetString string
|
||||
objectSetString := buildAUnitObjectSetString(config)
|
||||
optionsString := buildAUnitOptionsString(config)
|
||||
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
|
||||
|
||||
assert.Equal(t, expectedmetadataString, metadataString)
|
||||
assert.Equal(t, expectedoptionsString, optionsString)
|
||||
assert.Equal(t, expectedobjectSetString, objectSetString)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
|
||||
t.Run("Test AUnit test run body with example yaml config of only Multi Property Set with scomps & packages on top level", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
expectedmetadataString := `<aunit:run title="Test Title" context="Test Context" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
|
||||
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="false" foreignTests="false"/><aunit:riskLevel harmless="false" dangerous="false" critical="false"/><aunit:duration short="false" medium="false" long="false"/></aunit:options>`
|
||||
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:package name="testPackage1"/><osl:package name="testPackage2"/><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet></aunit:run>`
|
||||
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:package name="testPackage1"/><osl:package name="testPackage2"/><osl:softwareComponent name="testComponent1"/><osl:softwareComponent name="testComponent2"/></osl:objectSet>`
|
||||
|
||||
var err error
|
||||
var config AUnitConfig
|
||||
|
||||
config = AUnitConfig{
|
||||
config := AUnitConfig{
|
||||
Title: "Test Title",
|
||||
Context: "Test Context",
|
||||
Options: AUnitOptions{
|
||||
@@ -274,79 +242,18 @@ func TestBuildAUnitTestBody(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
var metadataString, optionsString, objectSetString string
|
||||
objectSetString := buildAUnitObjectSetString(config)
|
||||
optionsString := buildAUnitOptionsString(config)
|
||||
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
|
||||
|
||||
assert.Equal(t, expectedmetadataString, metadataString)
|
||||
assert.Equal(t, expectedoptionsString, optionsString)
|
||||
assert.Equal(t, expectedobjectSetString, objectSetString)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
|
||||
t.Run("Test AUnit test run body with example yaml config fail: no Title", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
expectedmetadataString := ""
|
||||
expectedoptionsString := ""
|
||||
expectedobjectSetString := ""
|
||||
|
||||
var err error
|
||||
var config AUnitConfig
|
||||
|
||||
config = AUnitConfig{}
|
||||
|
||||
var metadataString, optionsString, objectSetString string
|
||||
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
|
||||
|
||||
assert.Equal(t, expectedmetadataString, metadataString)
|
||||
assert.Equal(t, expectedoptionsString, optionsString)
|
||||
assert.Equal(t, expectedobjectSetString, objectSetString)
|
||||
assert.EqualError(t, err, "Error while parsing AUnit test run config. No title for the AUnit run has been provided. Please configure an appropriate title for the respective test run")
|
||||
})
|
||||
|
||||
t.Run("Test AUnit test run body with example yaml config: no Context", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
expectedmetadataString := `<aunit:run title="Test" context="ABAP Environment Pipeline" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
|
||||
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="true" foreignTests="true"/><aunit:riskLevel harmless="true" dangerous="true" critical="true"/><aunit:duration short="true" medium="true" long="true"/></aunit:options>`
|
||||
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:package name="testPackage1"/><osl:softwareComponent name="testComponent1"/></osl:objectSet></aunit:run>`
|
||||
|
||||
var err error
|
||||
var config AUnitConfig
|
||||
|
||||
config = AUnitConfig{Title: "Test",
|
||||
ObjectSet: ObjectSet{
|
||||
PackageNames: []AUnitPackage{{
|
||||
Name: "testPackage1",
|
||||
}},
|
||||
SoftwareComponents: []SoftwareComponents{{
|
||||
Name: "testComponent1",
|
||||
}},
|
||||
}}
|
||||
|
||||
var metadataString, optionsString, objectSetString string
|
||||
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
|
||||
|
||||
assert.Equal(t, expectedmetadataString, metadataString)
|
||||
assert.Equal(t, expectedoptionsString, optionsString)
|
||||
assert.Equal(t, expectedobjectSetString, objectSetString)
|
||||
assert.Equal(t, err, nil)
|
||||
})
|
||||
|
||||
t.Run("Test AUnit test run body with example yaml config: no Options", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
expectedmetadataString := `<aunit:run title="Test" context="Test" xmlns:aunit="http://www.sap.com/adt/api/aunit">`
|
||||
expectedoptionsString := `<aunit:options><aunit:measurements type="none"/><aunit:scope ownTests="true" foreignTests="true"/><aunit:riskLevel harmless="true" dangerous="true" critical="true"/><aunit:duration short="true" medium="true" long="true"/></aunit:options>`
|
||||
expectedobjectSetString := `<osl:objectSet xsi:type="multiPropertySet" xmlns:osl="http://www.sap.com/api/osl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><osl:package name="testPackage1"/><osl:softwareComponent name="testComponent1"/></osl:objectSet></aunit:run>`
|
||||
|
||||
var err error
|
||||
var config AUnitConfig
|
||||
|
||||
config = AUnitConfig{Title: "Test", Context: "Test",
|
||||
config := AUnitConfig{Title: "Test", Context: "Test",
|
||||
ObjectSet: ObjectSet{
|
||||
PackageNames: []AUnitPackage{{
|
||||
Name: "testPackage1",
|
||||
@@ -356,36 +263,134 @@ func TestBuildAUnitTestBody(t *testing.T) {
|
||||
}},
|
||||
}}
|
||||
|
||||
var metadataString, optionsString, objectSetString string
|
||||
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
|
||||
|
||||
assert.Equal(t, expectedmetadataString, metadataString)
|
||||
optionsString := buildAUnitOptionsString(config)
|
||||
assert.Equal(t, expectedoptionsString, optionsString)
|
||||
assert.Equal(t, expectedobjectSetString, objectSetString)
|
||||
assert.Equal(t, err, nil)
|
||||
})
|
||||
|
||||
t.Run("Test AUnit test run body with example yaml config fail: no ObjectSet", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Config with repository-yml", func(t *testing.T) {
|
||||
|
||||
expectedmetadataString := ""
|
||||
expectedoptionsString := ""
|
||||
expectedobjectSetString := ""
|
||||
config := abapEnvironmentRunAUnitTestOptions{
|
||||
AUnitResultsFileName: "aUnitResults.xml",
|
||||
Repositories: "repositories.yml",
|
||||
}
|
||||
|
||||
var err error
|
||||
var config AUnitConfig
|
||||
dir, err := ioutil.TempDir("", "test parse AUnit yaml config2")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
oldCWD, _ := os.Getwd()
|
||||
_ = os.Chdir(dir)
|
||||
// clean up tmp dir
|
||||
defer func() {
|
||||
_ = os.Chdir(oldCWD)
|
||||
_ = os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
config = AUnitConfig{Title: "Test", Context: "Test", Options: AUnitOptions{Measurements: "Test"}}
|
||||
repositories := `repositories:
|
||||
- name: /DMO/REPO
|
||||
branch: main
|
||||
`
|
||||
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aunit:run title=\"AUnit Test Run\" context=\"ABAP Environment Pipeline\" xmlns:aunit=\"http://www.sap.com/adt/api/aunit\"><aunit:options><aunit:measurements type=\"none\"/><aunit:scope ownTests=\"true\" foreignTests=\"true\"/><aunit:riskLevel harmless=\"true\" dangerous=\"true\" critical=\"true\"/><aunit:duration short=\"true\" medium=\"true\" long=\"true\"/></aunit:options><osl:objectSet xsi:type=\"multiPropertySet\" xmlns:osl=\"http://www.sap.com/api/osl\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><osl:softwareComponent name=\"/DMO/REPO\"/></osl:objectSet></aunit:run>"
|
||||
err = ioutil.WriteFile(config.Repositories, []byte(repositories), 0644)
|
||||
if assert.Equal(t, err, nil) {
|
||||
bodyString, err := buildAUnitRequestBody(config)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, expectedBodyString, bodyString)
|
||||
}
|
||||
})
|
||||
|
||||
var metadataString, optionsString, objectSetString string
|
||||
t.Run("Config with aunitconfig-yml", func(t *testing.T) {
|
||||
|
||||
metadataString, optionsString, objectSetString, err = buildAUnitTestBody(config)
|
||||
config := abapEnvironmentRunAUnitTestOptions{
|
||||
AUnitResultsFileName: "aUnitResults.xml",
|
||||
AUnitConfig: "aunit.yml",
|
||||
}
|
||||
|
||||
assert.Equal(t, expectedmetadataString, metadataString)
|
||||
assert.Equal(t, expectedoptionsString, optionsString)
|
||||
assert.Equal(t, expectedobjectSetString, objectSetString)
|
||||
assert.EqualError(t, err, "Error while parsing AUnit test run object set config. No object set has been provided. Please configure the objects you want to be checked for the respective test run")
|
||||
dir, err := ioutil.TempDir("", "test parse AUnit yaml config2")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
oldCWD, _ := os.Getwd()
|
||||
_ = os.Chdir(dir)
|
||||
// clean up tmp dir
|
||||
defer func() {
|
||||
_ = os.Chdir(oldCWD)
|
||||
_ = os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
yamlBody := `title: My AUnit run
|
||||
objectset:
|
||||
packages:
|
||||
- name: Z_TEST
|
||||
softwarecomponents:
|
||||
- name: Z_TEST
|
||||
- name: /DMO/SWC
|
||||
`
|
||||
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aunit:run title=\"My AUnit run\" context=\"ABAP Environment Pipeline\" xmlns:aunit=\"http://www.sap.com/adt/api/aunit\"><aunit:options><aunit:measurements type=\"none\"/><aunit:scope ownTests=\"true\" foreignTests=\"true\"/><aunit:riskLevel harmless=\"true\" dangerous=\"true\" critical=\"true\"/><aunit:duration short=\"true\" medium=\"true\" long=\"true\"/></aunit:options><osl:objectSet xsi:type=\"multiPropertySet\" xmlns:osl=\"http://www.sap.com/api/osl\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><osl:package name=\"Z_TEST\"/><osl:softwareComponent name=\"Z_TEST\"/><osl:softwareComponent name=\"/DMO/SWC\"/></osl:objectSet></aunit:run>"
|
||||
err = ioutil.WriteFile(config.AUnitConfig, []byte(yamlBody), 0644)
|
||||
if assert.Equal(t, err, nil) {
|
||||
bodyString, err := buildAUnitRequestBody(config)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, expectedBodyString, bodyString)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Config with aunitconfig-yml mps", func(t *testing.T) {
|
||||
|
||||
config := abapEnvironmentRunAUnitTestOptions{
|
||||
AUnitResultsFileName: "aUnitResults.xml",
|
||||
AUnitConfig: "aunit.yml",
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "test parse AUnit yaml config2")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create temporary directory")
|
||||
}
|
||||
oldCWD, _ := os.Getwd()
|
||||
_ = os.Chdir(dir)
|
||||
// clean up tmp dir
|
||||
defer func() {
|
||||
_ = os.Chdir(oldCWD)
|
||||
_ = os.RemoveAll(dir)
|
||||
}()
|
||||
|
||||
yamlBody := `title: My AUnit run
|
||||
objectset:
|
||||
type: multiPropertySet
|
||||
multipropertyset:
|
||||
packages:
|
||||
- name: Z_TEST
|
||||
softwarecomponents:
|
||||
- name: Z_TEST
|
||||
- name: /DMO/SWC
|
||||
`
|
||||
expectedBodyString := "<?xml version=\"1.0\" encoding=\"UTF-8\"?><aunit:run title=\"My AUnit run\" context=\"ABAP Environment Pipeline\" xmlns:aunit=\"http://www.sap.com/adt/api/aunit\"><aunit:options><aunit:measurements type=\"none\"/><aunit:scope ownTests=\"true\" foreignTests=\"true\"/><aunit:riskLevel harmless=\"true\" dangerous=\"true\" critical=\"true\"/><aunit:duration short=\"true\" medium=\"true\" long=\"true\"/></aunit:options><osl:objectSet xsi:type=\"multiPropertySet\" xmlns:osl=\"http://www.sap.com/api/osl\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><osl:package name=\"Z_TEST\"/><osl:softwareComponent name=\"Z_TEST\"/><osl:softwareComponent name=\"/DMO/SWC\"/></osl:objectSet></aunit:run>"
|
||||
err = ioutil.WriteFile(config.AUnitConfig, []byte(yamlBody), 0644)
|
||||
if assert.Equal(t, err, nil) {
|
||||
bodyString, err := buildAUnitRequestBody(config)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, expectedBodyString, bodyString)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("No AUnit config file - expect no panic", func(t *testing.T) {
|
||||
|
||||
config := abapEnvironmentRunAUnitTestOptions{
|
||||
AUnitConfig: "aunit.yml",
|
||||
}
|
||||
|
||||
_, err := buildAUnitRequestBody(config)
|
||||
assert.Equal(t, "Could not find aunit.yml", err.Error())
|
||||
})
|
||||
|
||||
t.Run("No Repo config file - expect no panic", func(t *testing.T) {
|
||||
|
||||
config := abapEnvironmentRunAUnitTestOptions{
|
||||
Repositories: "repo.yml",
|
||||
}
|
||||
|
||||
_, err := buildAUnitRequestBody(config)
|
||||
assert.Equal(t, "Could not find repo.yml", err.Error())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -528,7 +533,7 @@ func TestParseAUnitResult(t *testing.T) {
|
||||
}()
|
||||
bodyString := `<?xml version="1.0" encoding="utf-8"?><testsuites title="My AUnit run" system="TST" client="100" executedBy="TESTUSER" time="000.000" timestamp="2021-01-01T00:00:00Z" failures="2" errors="2" skipped="0" asserts="0" tests="2"><testsuite name="" tests="2" failures="2" errors="0" skipped="0" asserts="0" package="testpackage" timestamp="2021-01-01T00:00:00ZZ" time="0.000" hostname="test"><testcase classname="test" name="execute" time="0.000" asserts="2"><failure message="testMessage1" type="Assert Failure">Test1</failure><failure message="testMessage2" type="Assert Failure">Test2</failure></testcase></testsuite></testsuites>`
|
||||
body := []byte(bodyString)
|
||||
err = parseAUnitResult(body, "AUnitResults.xml", false)
|
||||
err = persistAUnitResult(body, "AUnitResults.xml", false)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
|
||||
@@ -547,7 +552,7 @@ func TestParseAUnitResult(t *testing.T) {
|
||||
}()
|
||||
bodyString := `<?xml version="1.0" encoding="UTF-8"?>`
|
||||
body := []byte(bodyString)
|
||||
err = parseAUnitResult(body, "AUnitResults.xml", false)
|
||||
err = persistAUnitResult(body, "AUnitResults.xml", false)
|
||||
assert.Equal(t, nil, err)
|
||||
})
|
||||
|
||||
@@ -556,7 +561,7 @@ func TestParseAUnitResult(t *testing.T) {
|
||||
var bodyString string
|
||||
body := []byte(bodyString)
|
||||
|
||||
err := parseAUnitResult(body, "AUnitResults.xml", false)
|
||||
err := persistAUnitResult(body, "AUnitResults.xml", false)
|
||||
assert.EqualError(t, err, "Parsing AUnit result failed: Body is empty, can't parse empty body")
|
||||
})
|
||||
}
|
||||
@@ -576,7 +581,7 @@ func TestGetResultAUnitRun(t *testing.T) {
|
||||
Password: "Test",
|
||||
URL: "https://api.endpoint.com/Entity/",
|
||||
}
|
||||
resp, err := getResultAUnitRun("GET", con, []byte(client.Body), client)
|
||||
resp, err := getAUnitResults("GET", con, []byte(client.Body), client)
|
||||
defer resp.Body.Close()
|
||||
if assert.Equal(t, nil, err) {
|
||||
buf := new(bytes.Buffer)
|
||||
@@ -603,7 +608,7 @@ func TestGetResultAUnitRun(t *testing.T) {
|
||||
Password: "Test",
|
||||
URL: "https://api.endpoint.com/Entity/",
|
||||
}
|
||||
resp, err := getResultAUnitRun("GET", con, []byte(client.Body), client)
|
||||
resp, err := getAUnitResults("GET", con, []byte(client.Body), client)
|
||||
defer resp.Body.Close()
|
||||
if assert.EqualError(t, err, "Getting AUnit run results failed: Test fail") {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
@@ -20,11 +20,11 @@ You can have a look at different pipeline configurations in our [SAP-samples rep
|
||||
|
||||
## 1. Prerequisites
|
||||
|
||||
* Configure your Jenkins Server according to the [documentation](https://sap.github.io/jenkins-library/guidedtour/).
|
||||
* Create a git repository on a host reachable by the Jenkins server (e.g. GitHub.com). The pipeline will be configured in this repository. Create a GitHub User with read access.
|
||||
* Configure your Jenkins server according to the [documentation](https://sap.github.io/jenkins-library/guidedtour/).
|
||||
* Create a git repository on a host reachable by the Jenkins server (e.g. GitHub.com). The pipeline will be configured in this repository. Create a GitHub user with read access.
|
||||
* The entitlements for the ABAP environment system are available in the SAP BTP global account and assigned to the subaccount.
|
||||
* A Cloud Foundry Organization & Space with the allocated entitlements are available.
|
||||
* A Cloud Foundry User & Password with the required authorization ("Space Developer") in the Organization and Space are available. User and Password were saved in the Jenkins Credentials Store.
|
||||
* A Cloud Foundry organization & space with the allocated entitlements are available.
|
||||
* A Cloud Foundry user & password with the required authorization ("Space Developer") in the organization and space are available. User and password were saved in the Jenkins Credentials Store.
|
||||
|
||||
## 2. Jenkinsfile
|
||||
|
||||
@@ -46,7 +46,7 @@ An Overview of the releases of the project "Piper" library can be found [here](h
|
||||
|
||||
## 3. Configuration for Cloning the repositories
|
||||
|
||||
If you have specified the `Clone Repositories` Stage you can make use of a dedicated configuration file containing the repositories to be pulled and the branches to be switched on. The `repositories` flag makes use of such a configuration file and helps executing a Pull, Clone and Checkout of the Branches of the Repositores. Create the file `repositories.yml` with the following structure containing your repositories including the branches for this stage.
|
||||
If you have specified the `Clone Repositories` stage you can make use of a dedicated configuration file containing the repositories to be pulled and the branches to be switched on. The `repositories` flag makes use of such a configuration file and helps executing a `Pull`, `Clone` and `Checkout` of the branches of the repositores. Create the file `repositories.yml` with the following structure containing your repositories including the branches for this stage.
|
||||
|
||||
```yml
|
||||
repositories:
|
||||
@@ -56,11 +56,16 @@ repositories:
|
||||
branch: 'master'
|
||||
```
|
||||
|
||||
You can later use the `repositories.yml` file for the `repositories` parameter in the `Clone Repositories` stage used in chapter [7. Technical Pipeline Configuration](#7-technical-pipeline-configuration).
|
||||
You can later use the `repositories.yml` file for the `repositories` parameter in the `Clone Repositories` stage used in chapter [5. Technical Pipeline Configuration](#5-technical-pipeline-configuration).
|
||||
|
||||
## 4. Configuration for ATC
|
||||
## 4. Optional: Configuration for the ABAP Test Cockpit (ATC) and ABAP Unit Tests (AUnit)
|
||||
|
||||
Create a file `atcConfig.yml` to store the configuration for the ATC run. In this file, you can specify which packages or software components shall be checked. Please have a look at the step documentation for more details. Here is an example of the configuration:
|
||||
As a default, a configuration for ATC and AUnit is generated out of the `repositories.yml` file. This default configuration checks the listed repositories using the default ATC check variant and with no AUnit restrictions regarding `duration` and `risk level`.
|
||||
If you want to configure these tools yourself, you can create a tool specific configuration.
|
||||
|
||||
### ATC
|
||||
|
||||
Create a file `atcConfig.yml` to store the configuration for the ATC run. In this file, you can specify which packages or software components shall be checked. Please have a look at the [step documentation](https://sap.github.io/jenkins-library/steps/abapEnvironmentRunATCCheck/) for more details. You have to pass the filename `atcConfig.yml` to the `atcConfig` parameter in the [5. Technical Pipeline Configuration](#5-technical-pipeline-configuration). Here is an example of the configuration:
|
||||
|
||||
```yml
|
||||
atcobjects:
|
||||
@@ -68,7 +73,17 @@ atcobjects:
|
||||
- name: "/DMO/REPO"
|
||||
```
|
||||
|
||||
Please have a look at the [step documentation](https://sap.github.io/jenkins-library/steps/abapEnvironmentRunATCCheck/) for more details.
|
||||
### AUnit
|
||||
|
||||
Create a file `aunitConfig.yml` to store the configuration for the AUnit run. In this file, you can specify which packages or software components shall be checked. Please have a look at the [step documentation](https://sap.github.io/jenkins-library/steps/abapEnvironmentRunAUnitTest/) for more details. You have to pass the filename `aunitConfig.yml` to the `aunitConfig` parameter in the [5. Technical Pipeline Configuration](#5-technical-pipeline-configuration). Here is an example of the configuration:
|
||||
|
||||
```yml
|
||||
title: My AUnit run
|
||||
objectSet:
|
||||
softwarecomponents:
|
||||
- name: Z_TEST_SC
|
||||
- name: Z_TEST_SC2
|
||||
```
|
||||
|
||||
## 5. Technical Pipeline Configuration
|
||||
|
||||
@@ -95,7 +110,9 @@ stages:
|
||||
strategy: 'Clone'
|
||||
repositories: 'repositories.yml'
|
||||
ATC:
|
||||
atcConfig: 'atcConfig.yml'
|
||||
active: true
|
||||
AUnit:
|
||||
active: true
|
||||
Post:
|
||||
cfDeleteServiceKeys: true
|
||||
```
|
||||
@@ -118,7 +135,11 @@ If the `Clone Repositories` stage is configured, you can specify the `strategy`
|
||||
|
||||
Note that you can use the `repositories.yml` file with the `repositories` parameter consistently for all strategies.
|
||||
|
||||
The values for `cfApiEndpoint`,`cfOrg` and `cfSpace` can be found in the respective overview pages in the SAP BTP cockpit. The Cloud Foundry credentials, saved in the Jenkins credentials store with the ID `cfCredentialsId`, must refer to a user with the required authorizations ("Space Developer") for the Cloud Foundry organization and space.
|
||||
The values for `cfApiEndpoint`,`cfOrg` and `cfSpace` can be found in the respective overview pages in the SAP BTP cockpit. The SAP BTP / Cloud Foundry credentials, saved in the Jenkins credentials store with the ID `cfCredentialsId`, must refer to a user with the required authorizations ("Space Developer") for the SAP BTP / Cloud Foundry organization and space.
|
||||
|
||||
### ATC & AUnit
|
||||
|
||||
The ATC and AUnit stage will be executed, if the `config.yml` file contains an entry for the respective stage. If you are using the default configuration a placeholder entry `active: true` has to be added in order to activate the stages. If you are using a dedicated configuration file - `atcConfig.yml` and `aunitConfig.yml` - this is not necessary.
|
||||
|
||||
## 7. Create a Jenkins Pipeline
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ There are no specifc stage parameters.
|
||||
|
||||
### Stage Activation
|
||||
|
||||
This stage will be active, if the stage configuration in the `config.yml` contains entries for this stage..
|
||||
This stage will be active, if the stage configuration in the `config.yml` contains entries for this stage.
|
||||
|
||||
### Configuration Example
|
||||
|
||||
|
||||
@@ -82,6 +82,8 @@ To trigger the ATC run an ATC config file `atcconfig.yml` will be needed. Check
|
||||
|
||||
### ATC config file example
|
||||
|
||||
Providing a specifc ATC configuration is optional. If you are using a `repositories.yml` file for the `Clone` stage of the ABAP environment pipeline, a default ATC configuration will be derived if no explicit ATC configuration is available.
|
||||
|
||||
The following section contains an example of an `atcconfig.yml` file.
|
||||
This file must be stored in the same Git folder where the `Jenkinsfile` is stored to run the pipeline. This folder must be taken as a SCM in the Jenkins pipeline to run the pipeline.
|
||||
|
||||
|
||||
@@ -83,6 +83,8 @@ To trigger the AUnit run an AUnit config file `aUnitConfig.yml` will be needed.
|
||||
|
||||
### AUnit config file example
|
||||
|
||||
Providing a specifc AUnit configuration is optional. If you are using a `repositories.yml` file for the `Clone` stage of the ABAP environment pipeline, a default AUnit configuration will be derived if no explicit AUnit configuration is available.
|
||||
|
||||
The following section contains an example of an `aUnitConfig.yml` file.
|
||||
This file must be stored in the same Git folder where the `Jenkinsfile` is stored to run the pipeline. This repository containing the `Jenkinsfile` must be taken as a SCM in the Jenkins pipeline to run the pipeline.
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -16,6 +17,7 @@ import (
|
||||
"github.com/SAP/jenkins-library/pkg/command"
|
||||
piperhttp "github.com/SAP/jenkins-library/pkg/http"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -119,6 +121,30 @@ func (abaputils *AbapUtils) GetPollIntervall() time.Duration {
|
||||
return 10 * time.Second
|
||||
}
|
||||
|
||||
/*
|
||||
ReadCOnfigFile reads a file from a specific path and returns the json string as []byte
|
||||
*/
|
||||
func ReadConfigFile(path string) (file []byte, err error) {
|
||||
filelocation, err := filepath.Glob(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(filelocation) == 0 {
|
||||
return nil, errors.New("Could not find " + path)
|
||||
}
|
||||
filename, err := filepath.Abs(filelocation[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
yamlFile, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var jsonFile []byte
|
||||
jsonFile, err = yaml.YAMLToJSON(yamlFile)
|
||||
return jsonFile, err
|
||||
}
|
||||
|
||||
// GetHTTPResponse wraps the SendRequest function of piperhttp
|
||||
func GetHTTPResponse(requestType string, connectionDetails ConnectionDetailsHTTP, body []byte, client piperhttp.Sender) (*http.Response, error) {
|
||||
|
||||
|
||||
@@ -26,7 +26,15 @@ spec:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
mandatory: true
|
||||
mandatory: false
|
||||
- name: repositories
|
||||
type: string
|
||||
description: Specifies a YAML file containing the repositories configuration
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: cfApiEndpoint
|
||||
type: string
|
||||
description: Cloud Foundry API endpoint
|
||||
|
||||
@@ -26,7 +26,15 @@ spec:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
mandatory: true
|
||||
mandatory: false
|
||||
- name: repositories
|
||||
type: string
|
||||
description: Specifies a YAML file containing the repositories configuration
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: cfApiEndpoint
|
||||
type: string
|
||||
description: Cloud Foundry API endpoint
|
||||
|
||||
Reference in New Issue
Block a user