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
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:
270
cmd/abapEnvironmentBuild.go
Normal file
270
cmd/abapEnvironmentBuild.go
Normal 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
|
||||
}
|
||||
424
cmd/abapEnvironmentBuild_generated.go
Normal file
424
cmd/abapEnvironmentBuild_generated.go
Normal 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
|
||||
}
|
||||
17
cmd/abapEnvironmentBuild_generated_test.go
Normal file
17
cmd/abapEnvironmentBuild_generated_test.go
Normal 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")
|
||||
|
||||
}
|
||||
150
cmd/abapEnvironmentBuild_test.go
Normal file
150
cmd/abapEnvironmentBuild_test.go
Normal 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)
|
||||
})
|
||||
}
|
||||
@@ -16,6 +16,7 @@ func GetAllStepMetadata() map[string]config.StepData {
|
||||
"abapAddonAssemblyKitReserveNextPackages": abapAddonAssemblyKitReserveNextPackagesMetadata(),
|
||||
"abapEnvironmentAssembleConfirm": abapEnvironmentAssembleConfirmMetadata(),
|
||||
"abapEnvironmentAssemblePackages": abapEnvironmentAssemblePackagesMetadata(),
|
||||
"abapEnvironmentBuild": abapEnvironmentBuildMetadata(),
|
||||
"abapEnvironmentCheckoutBranch": abapEnvironmentCheckoutBranchMetadata(),
|
||||
"abapEnvironmentCloneGitRepo": abapEnvironmentCloneGitRepoMetadata(),
|
||||
"abapEnvironmentCreateSystem": abapEnvironmentCreateSystemMetadata(),
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user