1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-11-06 09:09:19 +02:00

Generic build step (#3323)

* new step abapEnvironmentBuild

* Update piper.go

* Update abapEnvironmentBuild.go

* update yaml file

* Logging for debugging

* Update abaputils.go

* Update connector.go

* assigning connector

* delete debugging logging

* Update abapEnvironmentBuild.go

* certificate to yaml

* Update abapEnvironmentBuild.go

* add scope

* Update abapEnvironmentBuild.go

* Update abapEnvironmentBuild.yaml

* change certificate name in yaml

* test my new gitscript

* logging for debugging

* debugging...

* adding options to client.

* skip verification

* debugging

* debugging...

* switch of transportskipverification

* changing connector return

* deleting additional set options

* fixed timeout error

* adding certificate

* testing without certificate set

* testing with certificate set

* download, publish and value logic

* write values to cpe

* logging

* adding condition on string length

* change publishmethod and some logging

* change download method -> using references

* evaluation of parameter for download

* add case for empty string

* adding unittests

* Update mockClient.go

* make abapEnvironmentBuildUtilsBundle powerful

* refactor abapEnvironmentBuild into pieces

* check error message

* check error message 2

* check error message 3

* check error message 4

* remove check error message

* cleanup

* adding unittests

* unittests and docu

* docu

* docu

* Update abapEnvironmentBuild.md

* removing trailing spaces and adding empty lines in docu

* Update abapEnvironmentBuild.md

* fixing unittest and PR recommen

* Update abapEnvironmentPipelineStageBuild.groovy

* Update abapEnvironmentPipelineStageBuild.groovy

* Update abapEnvironmentPipelineStageBuild.groovy

* Update abapEnvironmentPipelineStageBuild.groovy

* changes derived from pull request

Co-authored-by: tiloKo <70266685+tiloKo@users.noreply.github.com>
This commit is contained in:
rosemarieB
2021-12-06 14:43:37 +01:00
committed by GitHub
parent 24d8584c3f
commit e90856d5bf
16 changed files with 1824 additions and 24 deletions

270
cmd/abapEnvironmentBuild.go Normal file
View File

@@ -0,0 +1,270 @@
package cmd
import (
"encoding/json"
"time"
abapbuild "github.com/SAP/jenkins-library/pkg/abap/build"
"github.com/SAP/jenkins-library/pkg/abaputils"
"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/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/pkg/errors"
)
type abapEnvironmentBuildUtils interface {
command.ExecRunner
abaputils.Communication
abapbuild.Publish
abapbuild.HTTPSendLoader
getMaxRuntime() time.Duration
getPollingIntervall() time.Duration
}
type abapEnvironmentBuildUtilsBundle struct {
*command.Command
*piperhttp.Client
*abaputils.AbapUtils
maxRuntime time.Duration
pollingIntervall time.Duration
}
func (aEBUB *abapEnvironmentBuildUtilsBundle) getMaxRuntime() time.Duration {
return aEBUB.maxRuntime
}
func (aEBUB *abapEnvironmentBuildUtilsBundle) getPollingIntervall() time.Duration {
return aEBUB.pollingIntervall
}
func (aEBUB *abapEnvironmentBuildUtilsBundle) PersistReportsAndLinks(stepName, workspace string, reports, links []piperutils.Path) {
abapbuild.PersistReportsAndLinks(stepName, workspace, reports, links)
}
func newAbapEnvironmentBuildUtils(maxRuntime time.Duration, pollingIntervall time.Duration) abapEnvironmentBuildUtils {
utils := abapEnvironmentBuildUtilsBundle{
Command: &command.Command{},
Client: &piperhttp.Client{},
AbapUtils: &abaputils.AbapUtils{
Exec: &command.Command{},
},
maxRuntime: maxRuntime * time.Minute,
pollingIntervall: pollingIntervall * time.Second,
}
// Reroute command output to logging framework
utils.Stdout(log.Writer())
utils.Stderr(log.Writer())
return &utils
}
func abapEnvironmentBuild(config abapEnvironmentBuildOptions, telemetryData *telemetry.CustomData, cpe *abapEnvironmentBuildCommonPipelineEnvironment) {
utils := newAbapEnvironmentBuildUtils(time.Duration(config.MaxRuntimeInMinutes), time.Duration(config.PollingIntervallInSeconds))
if err := runAbapEnvironmentBuild(&config, telemetryData, &utils, cpe); err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runAbapEnvironmentBuild(config *abapEnvironmentBuildOptions, telemetryData *telemetry.CustomData, utils *abapEnvironmentBuildUtils, cpe *abapEnvironmentBuildCommonPipelineEnvironment) error {
values, err := generateValues(config)
if err != nil {
return errors.Wrap(err, "Generating the values from config failed")
}
conn := new(abapbuild.Connector)
if err := initConnection(conn, config, utils); err != nil {
return errors.Wrap(err, "Connector initialization for communication with the ABAP system failed")
}
finalValues, err := runBuild(conn, config, utils, values)
if err != nil {
return errors.Wrap(err, "Error during execution of build framework")
}
cpe.abap.buildValues = finalValues
return nil
}
func initConnection(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, utils *abapEnvironmentBuildUtils) error {
var connConfig abapbuild.ConnectorConfiguration
connConfig.CfAPIEndpoint = config.CfAPIEndpoint
connConfig.CfOrg = config.CfOrg
connConfig.CfSpace = config.CfSpace
connConfig.CfServiceInstance = config.CfServiceInstance
connConfig.CfServiceKeyName = config.CfServiceKeyName
connConfig.Host = config.Host
connConfig.Username = config.Username
connConfig.Password = config.Password
connConfig.MaxRuntimeInMinutes = config.MaxRuntimeInMinutes
connConfig.CertificateNames = config.CertificateNames
if err := conn.InitBuildFramework(connConfig, *utils, *utils); err != nil {
return err
}
conn.MaxRuntime = (*utils).getMaxRuntime()
conn.PollingInterval = (*utils).getPollingIntervall()
return nil
}
// ***********************************Run Build***************************************************************
func runBuild(conn *abapbuild.Connector, config *abapEnvironmentBuildOptions, utils *abapEnvironmentBuildUtils, values abapbuild.Values) (string, error) {
build := myBuild{
Build: abapbuild.Build{
Connector: *conn,
},
abapEnvironmentBuildOptions: config,
}
if err := build.Start(values); err != nil {
return "", err
}
if err := build.Poll(); err != nil {
return "", errors.Wrap(err, "Error during the polling for the final state of the build run")
}
if err := build.PrintLogs(); err != nil {
return "", errors.Wrap(err, "Error printing the logs")
}
if err := build.EvaluteIfBuildSuccessful(); err != nil {
return "", err
}
if err := build.Download(); err != nil {
return "", err
}
if err := build.Publish(utils); err != nil {
return "", err
}
finalValues, err := build.GetFinalValues()
if err != nil {
return "", err
}
return finalValues, nil
}
type myBuild struct {
abapbuild.Build
*abapEnvironmentBuildOptions
}
func (b *myBuild) Start(values abapbuild.Values) error {
if err := b.Build.Start(b.abapEnvironmentBuildOptions.Phase, values); err != nil {
return errors.Wrap(err, "Error starting the build framework")
}
return nil
}
func (b *myBuild) EvaluteIfBuildSuccessful() error {
if err := b.Build.EvaluteIfBuildSuccessful(b.TreatWarningsAsError); err != nil {
return errors.Wrap(err, "Build ended without success")
}
return nil
}
func (b *myBuild) Download() error {
if b.DownloadAllResultFiles {
if err := b.DownloadAllResults(b.SubDirectoryForDownload, b.FilenamePrefixForDownload); err != nil {
return errors.Wrap(err, "Error during the download of the result files")
}
} else {
if err := b.DownloadResults(b.DownloadResultFilenames, b.SubDirectoryForDownload, b.FilenamePrefixForDownload); err != nil {
return errors.Wrapf(err, "Error during the download of the result files %s", b.DownloadResultFilenames)
}
}
return nil
}
func (b *myBuild) Publish(utils *abapEnvironmentBuildUtils) error {
if b.PublishAllDownloadedResultFiles {
b.PublishAllDownloadedResults("abapEnvironmentBuild", *utils)
} else {
if err := b.PublishDownloadedResults("abapEnvironmentBuild", b.PublishResultFilenames, *utils); err != nil {
return errors.Wrapf(err, "Error during the publish of the result files %s", b.PublishResultFilenames)
}
}
return nil
}
func (b *myBuild) GetFinalValues() (string, error) {
type cpeValue struct {
ValueID string `json:"value_id"`
Value string `json:"value"`
}
if err := b.GetValues(); err != nil {
return "", errors.Wrapf(err, "Error getting the values from build framework")
}
var cpeValues []cpeValue
byt, err := json.Marshal(&b.Build.Values)
if err != nil {
return "", errors.Wrapf(err, "Error converting the values from the build framework")
}
if err := json.Unmarshal(byt, &cpeValues); err != nil {
return "", errors.Wrapf(err, "Error converting the values from the build framework into the structure for the commonPipelineEnvironment")
}
jsonBytes, err := json.Marshal(cpeValues)
if err != nil {
return "", errors.Wrapf(err, "Error converting the converted values")
}
return string(jsonBytes), nil
}
// **********************************Generate Values**************************************************************
func generateValues(config *abapEnvironmentBuildOptions) (abapbuild.Values, error) {
var values abapbuild.Values
vE := valuesEvaluator{}
if err := vE.initialize(config.Values); err != nil {
return values, err
}
if err := vE.appendValues(config.CpeValues); err != nil {
return values, err
}
values.Values = vE.values
return values, nil
}
type valuesEvaluator struct {
values []abapbuild.Value
m map[string]string
}
func (vE *valuesEvaluator) initialize(stringValues string) error {
if err := json.Unmarshal([]byte(stringValues), &vE.values); err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrapf(err, "Could not convert the values %s from the config", stringValues)
}
vE.m = make(map[string]string)
for _, value := range vE.values {
if (len(value.ValueID) == 0) || (len(value.Value) == 0) {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Errorf("Values %s from config have not the right format", stringValues)
}
_, present := vE.m[value.ValueID]
if present {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Errorf("Value_id %s is not unique in the config", value.ValueID)
}
vE.m[value.ValueID] = value.Value
}
return nil
}
func (vE *valuesEvaluator) appendValues(stringValues string) error {
var values []abapbuild.Value
if len(stringValues) > 0 {
if err := json.Unmarshal([]byte(stringValues), &values); err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return errors.Wrapf(err, "Could not convert the values %s from the commonPipelineEnvironment", stringValues)
}
for i := len(values) - 1; i >= 0; i-- {
_, present := vE.m[values[i].ValueID]
if present || (values[i].ValueID == "PHASE") {
log.Entry().Infof("Value %s already exists in config -> discard this value", values[i])
values = append(values[:i], values[i+1:]...)
}
}
vE.values = append(vE.values, values...)
}
return nil
}

View File

@@ -0,0 +1,424 @@
// 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/splunk"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/SAP/jenkins-library/pkg/validation"
"github.com/spf13/cobra"
)
type abapEnvironmentBuildOptions struct {
CfAPIEndpoint string `json:"cfApiEndpoint,omitempty"`
CfOrg string `json:"cfOrg,omitempty"`
CfSpace string `json:"cfSpace,omitempty"`
CfServiceInstance string `json:"cfServiceInstance,omitempty"`
CfServiceKeyName string `json:"cfServiceKeyName,omitempty"`
Host string `json:"host,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
Phase string `json:"phase,omitempty"`
Values string `json:"values,omitempty"`
DownloadAllResultFiles bool `json:"downloadAllResultFiles,omitempty"`
DownloadResultFilenames []string `json:"downloadResultFilenames,omitempty"`
PublishAllDownloadedResultFiles bool `json:"publishAllDownloadedResultFiles,omitempty"`
PublishResultFilenames []string `json:"publishResultFilenames,omitempty"`
SubDirectoryForDownload string `json:"subDirectoryForDownload,omitempty"`
FilenamePrefixForDownload string `json:"filenamePrefixForDownload,omitempty"`
TreatWarningsAsError bool `json:"treatWarningsAsError,omitempty"`
MaxRuntimeInMinutes int `json:"maxRuntimeInMinutes,omitempty"`
PollingIntervallInSeconds int `json:"pollingIntervallInSeconds,omitempty"`
CertificateNames []string `json:"certificateNames,omitempty"`
CpeValues string `json:"cpeValues,omitempty"`
}
type abapEnvironmentBuildCommonPipelineEnvironment struct {
abap struct {
buildValues string
}
}
func (p *abapEnvironmentBuildCommonPipelineEnvironment) persist(path, resourceName string) {
content := []struct {
category string
name string
value interface{}
}{
{category: "abap", name: "buildValues", value: p.abap.buildValues},
}
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 {
log.Entry().Fatal("failed to persist Piper environment")
}
}
// AbapEnvironmentBuildCommand Executes builds as defined with the build framework
func AbapEnvironmentBuildCommand() *cobra.Command {
const STEP_NAME = "abapEnvironmentBuild"
metadata := abapEnvironmentBuildMetadata()
var stepConfig abapEnvironmentBuildOptions
var startTime time.Time
var commonPipelineEnvironment abapEnvironmentBuildCommonPipelineEnvironment
var logCollector *log.CollectorHook
var splunkClient *splunk.Splunk
telemetryClient := &telemetry.Telemetry{}
var createAbapEnvironmentBuildCmd = &cobra.Command{
Use: STEP_NAME,
Short: "Executes builds as defined with the build framework",
Long: `Executes builds as defined with the build framework. Transaction overview /n/BUILD/OVERVIEW`,
PreRunE: func(cmd *cobra.Command, _ []string) error {
startTime = time.Now()
log.SetStepName(STEP_NAME)
log.SetVerbose(GeneralConfig.Verbose)
GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens)
path, _ := os.Getwd()
fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
log.RegisterHook(fatalHook)
err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return err
}
log.RegisterSecret(stepConfig.Username)
log.RegisterSecret(stepConfig.Password)
if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
log.RegisterHook(&sentryHook)
}
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunkClient = &splunk.Splunk{}
logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID}
log.RegisterHook(logCollector)
}
validation, err := validation.New(validation.WithJSONNamesForStructFields(), validation.WithPredefinedErrorMessages())
if err != nil {
return err
}
if err = validation.ValidateStruct(stepConfig); err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return err
}
return nil
},
Run: func(_ *cobra.Command, _ []string) {
stepTelemetryData := telemetry.CustomData{}
stepTelemetryData.ErrorCode = "1"
handler := func() {
config.RemoveVaultSecretFiles()
commonPipelineEnvironment.persist(GeneralConfig.EnvRootPath, "commonPipelineEnvironment")
stepTelemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
stepTelemetryData.ErrorCategory = log.GetErrorCategory().String()
stepTelemetryData.PiperCommitHash = GitCommit
telemetryClient.SetData(&stepTelemetryData)
telemetryClient.Send()
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunkClient.Send(telemetryClient.GetData(), logCollector)
}
}
log.DeferExitHandler(handler)
defer handler()
telemetryClient.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunkClient.Initialize(GeneralConfig.CorrelationID,
GeneralConfig.HookConfig.SplunkConfig.Dsn,
GeneralConfig.HookConfig.SplunkConfig.Token,
GeneralConfig.HookConfig.SplunkConfig.Index,
GeneralConfig.HookConfig.SplunkConfig.SendLogs)
}
abapEnvironmentBuild(stepConfig, &stepTelemetryData, &commonPipelineEnvironment)
stepTelemetryData.ErrorCode = "0"
log.Entry().Info("SUCCESS")
},
}
addAbapEnvironmentBuildFlags(createAbapEnvironmentBuildCmd, &stepConfig)
return createAbapEnvironmentBuildCmd
}
func addAbapEnvironmentBuildFlags(cmd *cobra.Command, stepConfig *abapEnvironmentBuildOptions) {
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 target organization")
cmd.Flags().StringVar(&stepConfig.CfSpace, "cfSpace", os.Getenv("PIPER_cfSpace"), "Cloud Foundry target space")
cmd.Flags().StringVar(&stepConfig.CfServiceInstance, "cfServiceInstance", os.Getenv("PIPER_cfServiceInstance"), "Cloud Foundry Service Instance")
cmd.Flags().StringVar(&stepConfig.CfServiceKeyName, "cfServiceKeyName", os.Getenv("PIPER_cfServiceKeyName"), "Cloud Foundry Service Key")
cmd.Flags().StringVar(&stepConfig.Host, "host", os.Getenv("PIPER_host"), "Specifies the host address of the SAP Cloud Platform ABAP Environment system")
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password")
cmd.Flags().StringVar(&stepConfig.Phase, "phase", os.Getenv("PIPER_phase"), "Phase as specified in the build script in the backend system")
cmd.Flags().StringVar(&stepConfig.Values, "values", os.Getenv("PIPER_values"), "Input values for the build framework")
cmd.Flags().BoolVar(&stepConfig.DownloadAllResultFiles, "downloadAllResultFiles", false, "If true, all build artefacts are downloaded")
cmd.Flags().StringSliceVar(&stepConfig.DownloadResultFilenames, "downloadResultFilenames", []string{}, "Only the specified files are downloaded, downloadAllResultFiles is true, this parameter is ignored")
cmd.Flags().BoolVar(&stepConfig.PublishAllDownloadedResultFiles, "publishAllDownloadedResultFiles", false, "If true, it publishes all downloaded files")
cmd.Flags().StringSliceVar(&stepConfig.PublishResultFilenames, "publishResultFilenames", []string{}, "Only the specified files get published, in case the file was not downloaded before an error occures")
cmd.Flags().StringVar(&stepConfig.SubDirectoryForDownload, "subDirectoryForDownload", os.Getenv("PIPER_subDirectoryForDownload"), "Target directory to store the downloaded files, {buildID} and {taskID} can be used and will be resolved accordingly")
cmd.Flags().StringVar(&stepConfig.FilenamePrefixForDownload, "filenamePrefixForDownload", os.Getenv("PIPER_filenamePrefixForDownload"), "Filename prefix for the downloaded files, {buildID} and {taskID} can be used and will be resolved accordingly")
cmd.Flags().BoolVar(&stepConfig.TreatWarningsAsError, "treatWarningsAsError", false, "If a warrning occures, the step will be set to unstable")
cmd.Flags().IntVar(&stepConfig.MaxRuntimeInMinutes, "maxRuntimeInMinutes", 360, "maximal runtime of the step in minutes")
cmd.Flags().IntVar(&stepConfig.PollingIntervallInSeconds, "pollingIntervallInSeconds", 60, "wait time in seconds till next status request in the backend system")
cmd.Flags().StringSliceVar(&stepConfig.CertificateNames, "certificateNames", []string{}, "certificates for the backend system, this certificates needs to be stored in .pipeline/trustStore")
cmd.Flags().StringVar(&stepConfig.CpeValues, "cpeValues", os.Getenv("PIPER_cpeValues"), "Values taken from the previous step, if a value was also specified in the config file, the value from cpe will be discarded")
cmd.MarkFlagRequired("username")
cmd.MarkFlagRequired("password")
cmd.MarkFlagRequired("phase")
cmd.MarkFlagRequired("downloadAllResultFiles")
cmd.MarkFlagRequired("publishAllDownloadedResultFiles")
cmd.MarkFlagRequired("treatWarningsAsError")
cmd.MarkFlagRequired("maxRuntimeInMinutes")
cmd.MarkFlagRequired("pollingIntervallInSeconds")
}
// retrieve step metadata
func abapEnvironmentBuildMetadata() config.StepData {
var theMetaData = config.StepData{
Metadata: config.StepMetadata{
Name: "abapEnvironmentBuild",
Aliases: []config.Alias{},
Description: "Executes builds as defined with the build framework",
},
Spec: config.StepSpec{
Inputs: config.StepInputs{
Secrets: []config.StepSecrets{
{Name: "abapCredentialsId", Description: "Jenkins credentials ID containing user and password to authenticate to the Cloud Platform ABAP Environment system or the Cloud Foundry API", Type: "jenkins", Aliases: []config.Alias{{Name: "cfCredentialsId", Deprecated: false}, {Name: "credentialsId", Deprecated: false}}},
},
Parameters: []config.StepParameters{
{
Name: "cfApiEndpoint",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "cloudFoundry/apiEndpoint"}},
Default: os.Getenv("PIPER_cfApiEndpoint"),
},
{
Name: "cfOrg",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "cloudFoundry/org"}},
Default: os.Getenv("PIPER_cfOrg"),
},
{
Name: "cfSpace",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "cloudFoundry/space"}},
Default: os.Getenv("PIPER_cfSpace"),
},
{
Name: "cfServiceInstance",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "cloudFoundry/serviceInstance"}},
Default: os.Getenv("PIPER_cfServiceInstance"),
},
{
Name: "cfServiceKeyName",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "cloudFoundry/serviceKey"}, {Name: "cloudFoundry/serviceKeyName"}, {Name: "cfServiceKey"}},
Default: os.Getenv("PIPER_cfServiceKeyName"),
},
{
Name: "host",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_host"),
},
{
Name: "username",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_username"),
},
{
Name: "password",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_password"),
},
{
Name: "phase",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_phase"),
},
{
Name: "values",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_values"),
},
{
Name: "downloadAllResultFiles",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: true,
Aliases: []config.Alias{},
Default: false,
},
{
Name: "downloadResultFilenames",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "[]string",
Mandatory: false,
Aliases: []config.Alias{},
Default: []string{},
},
{
Name: "publishAllDownloadedResultFiles",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: true,
Aliases: []config.Alias{},
Default: false,
},
{
Name: "publishResultFilenames",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "[]string",
Mandatory: false,
Aliases: []config.Alias{},
Default: []string{},
},
{
Name: "subDirectoryForDownload",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_subDirectoryForDownload"),
},
{
Name: "filenamePrefixForDownload",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_filenamePrefixForDownload"),
},
{
Name: "treatWarningsAsError",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: true,
Aliases: []config.Alias{},
Default: false,
},
{
Name: "maxRuntimeInMinutes",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "int",
Mandatory: true,
Aliases: []config.Alias{},
Default: 360,
},
{
Name: "pollingIntervallInSeconds",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "int",
Mandatory: true,
Aliases: []config.Alias{},
Default: 60,
},
{
Name: "certificateNames",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "[]string",
Mandatory: false,
Aliases: []config.Alias{},
Default: []string{},
},
{
Name: "cpeValues",
ResourceRef: []config.ResourceReference{
{
Name: "commonPipelineEnvironment",
Param: "abap/buildValues",
},
},
Scope: []string{},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_cpeValues"),
},
},
},
Containers: []config.Container{
{Name: "cf", Image: "ppiper/cf-cli:7"},
},
Outputs: config.StepOutputs{
Resources: []config.StepResources{
{
Name: "commonPipelineEnvironment",
Type: "piperEnvironment",
Parameters: []map[string]interface{}{
{"Name": "abap/buildValues"},
},
},
},
},
},
}
return theMetaData
}

View File

@@ -0,0 +1,17 @@
package cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestAbapEnvironmentBuildCommand(t *testing.T) {
t.Parallel()
testCmd := AbapEnvironmentBuildCommand()
// only high level testing performed - details are tested in step generation procedure
assert.Equal(t, "abapEnvironmentBuild", testCmd.Use, "command name incorrect")
}

View File

@@ -0,0 +1,150 @@
package cmd
import (
"testing"
"time"
abapbuild "github.com/SAP/jenkins-library/pkg/abap/build"
"github.com/SAP/jenkins-library/pkg/abaputils"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/stretchr/testify/assert"
)
type abapEnvironmentBuildMockUtils struct {
*mock.ExecMockRunner
*abapbuild.MockClient
}
func newAbapEnvironmentBuildTestsUtils() abapEnvironmentBuildUtils {
mC := abapbuild.GetBuildMockClient()
utils := abapEnvironmentBuildMockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
MockClient: &mC,
}
return &utils
}
func (mB abapEnvironmentBuildMockUtils) PersistReportsAndLinks(stepName, workspace string, reports, links []piperutils.Path) {
}
func (mB abapEnvironmentBuildMockUtils) GetAbapCommunicationArrangementInfo(options abaputils.AbapEnvironmentOptions, oDataURL string) (abaputils.ConnectionDetailsHTTP, error) {
var cd abaputils.ConnectionDetailsHTTP
cd.URL = "/sap/opu/odata/BUILD/CORE_SRV"
return cd, nil
}
func (mB abapEnvironmentBuildMockUtils) GetPollIntervall() time.Duration {
return 1 * time.Microsecond
}
func (mB abapEnvironmentBuildMockUtils) getMaxRuntime() time.Duration {
return 1 * time.Second
}
func (mB abapEnvironmentBuildMockUtils) getPollingIntervall() time.Duration {
return 1 * time.Microsecond
}
func TestRunAbapEnvironmentBuild(t *testing.T) {
t.Parallel()
t.Run("happy path", func(t *testing.T) {
t.Parallel()
// init
cpe := abapEnvironmentBuildCommonPipelineEnvironment{}
config := abapEnvironmentBuildOptions{}
config.Values = `[{"value_id":"PACKAGES","value":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"MyId1","value":"Value1"}]`
config.DownloadAllResultFiles = true
config.PublishAllDownloadedResultFiles = true
utils := newAbapEnvironmentBuildTestsUtils()
// test
err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe)
// assert
finalValues := `[{"value_id":"PHASE","value":"AUNIT"},{"value_id":"PACKAGES","value":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"MyId1","value":"AunitValue1"},{"value_id":"MyId2","value":"AunitValue2"},{"value_id":"BUILD_FRAMEWORK_MODE","value":"P"}]`
assert.NoError(t, err)
assert.Equal(t, finalValues, cpe.abap.buildValues)
})
t.Run("happy path, download only one", func(t *testing.T) {
t.Parallel()
// init
cpe := abapEnvironmentBuildCommonPipelineEnvironment{}
config := abapEnvironmentBuildOptions{}
config.Values = `[{"value_id":"PACKAGES","value":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"MyId1","value":"Value1"}]`
config.DownloadResultFilenames = []string{"SAR_XML"}
config.PublishResultFilenames = []string{"SAR_XML"}
utils := newAbapEnvironmentBuildTestsUtils()
// test
err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe)
// assert
assert.NoError(t, err)
})
t.Run("error path, try to publish file, which was not downloaded", func(t *testing.T) {
t.Parallel()
// init
cpe := abapEnvironmentBuildCommonPipelineEnvironment{}
config := abapEnvironmentBuildOptions{}
config.Values = `[{"value_id":"PACKAGES","value":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"MyId1","value":"Value1"}]`
config.DownloadResultFilenames = []string{"DELIVERY_LOGS.ZIP"}
config.PublishResultFilenames = []string{"SAR_XML"}
utils := newAbapEnvironmentBuildTestsUtils()
// test
err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe)
// assert
assert.Error(t, err)
})
t.Run("error path, try to download file which does not exist", func(t *testing.T) {
t.Parallel()
// init
cpe := abapEnvironmentBuildCommonPipelineEnvironment{}
config := abapEnvironmentBuildOptions{}
config.Values = `[{"value_id":"PACKAGES","value":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"MyId1","value":"Value1"}]`
config.DownloadResultFilenames = []string{"DOES_NOT_EXIST"}
config.PublishAllDownloadedResultFiles = true
utils := newAbapEnvironmentBuildTestsUtils()
// test
err := runAbapEnvironmentBuild(&config, nil, &utils, &cpe)
// assert
assert.Error(t, err)
})
}
func TestGenerateValues(t *testing.T) {
t.Parallel()
t.Run("happy path", func(t *testing.T) {
t.Parallel()
// init
config := abapEnvironmentBuildOptions{}
config.Values = `[{"value_id":"PACKAGES","value":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"MyId1","value":"Value1"}]`
config.CpeValues = `[{"value_id":"PHASE","value":"AUNIT"},{"value_id":"PACKAGES","value":"CPE_PACKAGE"},{"value_id":"MyId2","value":"Value2"}]`
// test
values, err := generateValues(&config)
// assert
assert.NoError(t, err)
assert.Equal(t, 3, len(values.Values))
assert.Equal(t, "/BUILD/AUNIT_DUMMY_TESTS", values.Values[0].Value)
assert.Equal(t, "Value1", values.Values[1].Value)
assert.Equal(t, "Value2", values.Values[2].Value)
})
t.Run("error path - duplicate in config", func(t *testing.T) {
t.Parallel()
// init
config := abapEnvironmentBuildOptions{}
config.Values = `[{"value_id":"PACKAGES","value":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"MyId1","value":"Value1"},{"value_id":"MyId1","value":"Value1"}]`
// test
values, err := generateValues(&config)
// assert
assert.Error(t, err)
assert.Equal(t, 0, len(values.Values))
})
t.Run("error path - bad formating in config.Values", func(t *testing.T) {
t.Parallel()
// init
config := abapEnvironmentBuildOptions{}
config.Values = `[{"task_id":"PACKAGES","task":"/BUILD/AUNIT_DUMMY_TESTS"},{"value_id":"MyId1","value":"Value1"}]`
// test
_, err := generateValues(&config)
// assert
assert.Error(t, err)
})
}

View File

@@ -16,6 +16,7 @@ func GetAllStepMetadata() map[string]config.StepData {
"abapAddonAssemblyKitReserveNextPackages": abapAddonAssemblyKitReserveNextPackagesMetadata(),
"abapEnvironmentAssembleConfirm": abapEnvironmentAssembleConfirmMetadata(),
"abapEnvironmentAssemblePackages": abapEnvironmentAssemblePackagesMetadata(),
"abapEnvironmentBuild": abapEnvironmentBuildMetadata(),
"abapEnvironmentCheckoutBranch": abapEnvironmentCheckoutBranchMetadata(),
"abapEnvironmentCloneGitRepo": abapEnvironmentCloneGitRepoMetadata(),
"abapEnvironmentCreateSystem": abapEnvironmentCreateSystemMetadata(),

View File

@@ -128,6 +128,7 @@ func Execute() {
rootCmd.AddCommand(JsonApplyPatchCommand())
rootCmd.AddCommand(KanikoExecuteCommand())
rootCmd.AddCommand(CnbBuildCommand())
rootCmd.AddCommand(AbapEnvironmentBuildCommand())
rootCmd.AddCommand(AbapEnvironmentAssemblePackagesCommand())
rootCmd.AddCommand(AbapAddonAssemblyKitCheckCVsCommand())
rootCmd.AddCommand(AbapAddonAssemblyKitCheckPVCommand())