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 }