github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/cmd/abapEnvironmentAssembleConfirm.go (about)

     1  package cmd
     2  
     3  import (
     4  	"encoding/json"
     5  	"time"
     6  
     7  	abapbuild "github.com/SAP/jenkins-library/pkg/abap/build"
     8  	"github.com/SAP/jenkins-library/pkg/abaputils"
     9  	"github.com/SAP/jenkins-library/pkg/command"
    10  	piperhttp "github.com/SAP/jenkins-library/pkg/http"
    11  	"github.com/SAP/jenkins-library/pkg/log"
    12  	"github.com/SAP/jenkins-library/pkg/telemetry"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  func abapEnvironmentAssembleConfirm(config abapEnvironmentAssembleConfirmOptions, telemetryData *telemetry.CustomData, cpe *abapEnvironmentAssembleConfirmCommonPipelineEnvironment) {
    17  	// for command execution use Command
    18  	c := command.Command{}
    19  	// reroute command output to logging framework
    20  	c.Stdout(log.Writer())
    21  	c.Stderr(log.Writer())
    22  
    23  	var autils = abaputils.AbapUtils{
    24  		Exec: &c,
    25  	}
    26  
    27  	client := piperhttp.Client{}
    28  	err := runAbapEnvironmentAssembleConfirm(&config, telemetryData, &autils, &client, cpe)
    29  	if err != nil {
    30  		log.Entry().WithError(err).Fatal("step execution failed")
    31  	}
    32  }
    33  
    34  func runAbapEnvironmentAssembleConfirm(config *abapEnvironmentAssembleConfirmOptions, telemetryData *telemetry.CustomData, com abaputils.Communication, client abapbuild.HTTPSendLoader, cpe *abapEnvironmentAssembleConfirmCommonPipelineEnvironment) error {
    35  	conn := new(abapbuild.Connector)
    36  	var connConfig abapbuild.ConnectorConfiguration
    37  	connConfig.CfAPIEndpoint = config.CfAPIEndpoint
    38  	connConfig.CfOrg = config.CfOrg
    39  	connConfig.CfSpace = config.CfSpace
    40  	connConfig.CfServiceInstance = config.CfServiceInstance
    41  	connConfig.CfServiceKeyName = config.CfServiceKeyName
    42  	connConfig.Host = config.Host
    43  	connConfig.Username = config.Username
    44  	connConfig.Password = config.Password
    45  	connConfig.AddonDescriptor = config.AddonDescriptor
    46  	connConfig.MaxRuntimeInMinutes = config.MaxRuntimeInMinutes
    47  	connConfig.CertificateNames = config.CertificateNames
    48  
    49  	err := conn.InitBuildFramework(connConfig, com, client)
    50  	if err != nil {
    51  		return err
    52  	}
    53  	var addonDescriptor abaputils.AddonDescriptor
    54  	err = json.Unmarshal([]byte(config.AddonDescriptor), &addonDescriptor)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	delayBetweenPosts := time.Duration(3 * time.Second)
    59  	builds, err := startingConfirm(addonDescriptor.Repositories, *conn, delayBetweenPosts)
    60  	if err != nil {
    61  		return err
    62  	}
    63  	maxRuntimeInMinutes := time.Duration(config.MaxRuntimeInMinutes) * time.Minute
    64  	pollInterval := time.Duration(60 * time.Second)
    65  	err = polling(builds, maxRuntimeInMinutes, pollInterval)
    66  	if err != nil {
    67  		return err
    68  	}
    69  	err = checkIfFailedAndPrintLogs(builds)
    70  	if err != nil {
    71  		return err
    72  	}
    73  	return nil
    74  }
    75  
    76  func startingConfirm(repos []abaputils.Repository, conn abapbuild.Connector, delayBetweenPosts time.Duration) ([]buildWithRepository, error) {
    77  	var confirmedBuilds []buildWithRepository
    78  	var releasePackagesFailed error = nil
    79  	for _, repo := range repos {
    80  		assemblyBuild := abapbuild.Build{
    81  			Connector: conn,
    82  		}
    83  		buildRepo := buildWithRepository{
    84  			build: assemblyBuild,
    85  			repo:  repo,
    86  		}
    87  		if repo.InBuildScope && repo.Status == "R" {
    88  			err := buildRepo.startConfirm()
    89  			if err != nil {
    90  				return confirmedBuilds, err
    91  			}
    92  			confirmedBuilds = append(confirmedBuilds, buildRepo)
    93  		} else if repo.InBuildScope && repo.Status != "R" {
    94  			errormessage := "Release of package '" + repo.PackageName + "' must have failed as still in status: '" + repo.Status + "'"
    95  			if releasePackagesFailed == nil {
    96  				releasePackagesFailed = errors.New(errormessage)
    97  			} else {
    98  				releasePackagesFailed = errors.Wrapf(releasePackagesFailed, errormessage)
    99  			}
   100  		} else {
   101  			log.Entry().Infof("Packages %s was not assembled in this pipeline run, thus no need to confirm", repo.PackageName)
   102  		}
   103  
   104  		//as batch events in the ABAP Backend need a little time
   105  		time.Sleep(delayBetweenPosts)
   106  	}
   107  	return confirmedBuilds, releasePackagesFailed
   108  }
   109  
   110  func polling(builds []buildWithRepository, maxRuntimeInMinutes time.Duration, pollInterval time.Duration) error {
   111  	timeout := time.After(maxRuntimeInMinutes)
   112  	ticker := time.Tick(pollInterval)
   113  	for {
   114  		select {
   115  		case <-timeout:
   116  			return errors.New("Timed out")
   117  		case <-ticker:
   118  			var allFinished bool = true
   119  			for i := range builds {
   120  				if err := builds[i].build.Get(); err != nil {
   121  					return err
   122  				}
   123  				if !builds[i].build.IsFinished() {
   124  					log.Entry().Infof("Assembly of %s is not yet finished, check again in %s", builds[i].repo.PackageName, pollInterval)
   125  					allFinished = false
   126  				}
   127  			}
   128  			if allFinished {
   129  				return nil
   130  			}
   131  		}
   132  	}
   133  }
   134  
   135  func (b *buildWithRepository) startConfirm() error {
   136  	if b.repo.Name == "" || b.repo.PackageName == "" {
   137  		return errors.New("Parameters missing. Please provide software component name, namespace and packagename")
   138  	}
   139  	valuesInput := abapbuild.Values{
   140  		Values: []abapbuild.Value{
   141  			{
   142  				ValueID: "SWC",
   143  				Value:   b.repo.Name,
   144  			},
   145  		},
   146  	}
   147  	if b.repo.Namespace != "" {
   148  		// Steampunk Use Case, Namespace provided by AAKaaS
   149  		valuesInput.Values = append(valuesInput.Values,
   150  			abapbuild.Value{ValueID: "SSDC-delta",
   151  				Value: b.repo.Namespace + b.repo.PackageName})
   152  	} else {
   153  		// Traditional SWCs, Namespace to be provided in assembly system via build script
   154  		valuesInput.Values = append(valuesInput.Values,
   155  			abapbuild.Value{ValueID: "PACKAGE_TYPE",
   156  				Value: b.repo.PackageType})
   157  		valuesInput.Values = append(valuesInput.Values,
   158  			abapbuild.Value{ValueID: "PACKAGE_NAME_" + b.repo.PackageType,
   159  				Value: b.repo.PackageName})
   160  	}
   161  
   162  	phase := "BUILD_CONFIRM"
   163  	log.Entry().Infof("Starting confirmation of package %s", b.repo.PackageName)
   164  	return b.build.Start(phase, valuesInput)
   165  }