2020-09-18 16:40:49 +02:00
package cmd
import (
"encoding/json"
"time"
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
abapbuild "github.com/SAP/jenkins-library/pkg/abap/build"
"github.com/SAP/jenkins-library/pkg/abaputils"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/pkg/errors"
)
func abapAddonAssemblyKitReleasePackages ( config abapAddonAssemblyKitReleasePackagesOptions , telemetryData * telemetry . CustomData , cpe * abapAddonAssemblyKitReleasePackagesCommonPipelineEnvironment ) {
2021-12-09 13:54:18 +02:00
utils := aakaas . NewAakBundleWithTime ( time . Duration ( config . MaxRuntimeInMinutes ) , time . Duration ( config . PollingIntervalInSeconds ) )
2020-09-18 16:40:49 +02:00
// error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end
2021-12-09 13:54:18 +02:00
if err := runAbapAddonAssemblyKitReleasePackages ( & config , telemetryData , & utils , cpe ) ; err != nil {
2020-09-18 16:40:49 +02:00
log . Entry ( ) . WithError ( err ) . Fatal ( "step execution failed" )
}
}
2021-12-09 13:54:18 +02:00
func runAbapAddonAssemblyKitReleasePackages ( config * abapAddonAssemblyKitReleasePackagesOptions , telemetryData * telemetry . CustomData , utils * aakaas . AakUtils ,
cpe * abapAddonAssemblyKitReleasePackagesCommonPipelineEnvironment ) error {
2020-09-18 16:40:49 +02:00
conn := new ( abapbuild . Connector )
2021-12-09 13:54:18 +02:00
if err := conn . InitAAKaaS ( config . AbapAddonAssemblyKitEndpoint , config . Username , config . Password , * utils ) ; err != nil {
return err
}
2020-09-18 16:40:49 +02:00
var addonDescriptor abaputils . AddonDescriptor
2022-07-06 14:29:04 +02:00
if err := json . Unmarshal ( [ ] byte ( config . AddonDescriptor ) , & addonDescriptor ) ; err != nil {
return err
}
2020-09-18 16:40:49 +02:00
err := checkInput ( addonDescriptor . Repositories )
if err != nil {
return err
}
packagesWithReposLocked , packagesWithReposNotLocked := sortByStatus ( addonDescriptor . Repositories , * conn )
2021-12-09 13:54:18 +02:00
packagesWithReposLocked , err = releaseAndPoll ( packagesWithReposLocked , utils )
2020-09-18 16:40:49 +02:00
if err != nil {
2022-08-23 15:33:42 +02:00
var numberOfReleasedPackages int
for i := range packagesWithReposLocked {
if packagesWithReposLocked [ i ] . Package . Status == aakaas . PackageStatusReleased {
numberOfReleasedPackages += 1
}
}
if numberOfReleasedPackages == 0 {
return errors . Wrap ( err , "Release of all packages failed/timed out - Aborting as abapEnvironmentAssembleConfirm step is not needed" )
} else {
log . Entry ( ) . WithError ( err ) . Warn ( "Release of at least one package failed/timed out - Continuing anyway to enable abapEnvironmentAssembleConfirm to run" )
}
2020-09-18 16:40:49 +02:00
}
addonDescriptor . Repositories = sortingBack ( packagesWithReposLocked , packagesWithReposNotLocked )
log . Entry ( ) . Info ( "Writing package status to CommonPipelineEnvironment" )
2021-12-09 13:54:18 +02:00
cpe . abap . addonDescriptor = string ( addonDescriptor . AsJSON ( ) )
2020-09-18 16:40:49 +02:00
return nil
}
func sortingBack ( packagesWithReposLocked [ ] aakaas . PackageWithRepository , packagesWithReposNotLocked [ ] aakaas . PackageWithRepository ) [ ] abaputils . Repository {
var combinedRepos [ ] abaputils . Repository
for i := range packagesWithReposLocked {
packagesWithReposLocked [ i ] . Package . ChangeStatus ( & packagesWithReposLocked [ i ] . Repo )
combinedRepos = append ( combinedRepos , packagesWithReposLocked [ i ] . Repo )
}
for i := range packagesWithReposNotLocked {
combinedRepos = append ( combinedRepos , packagesWithReposNotLocked [ i ] . Repo )
}
return combinedRepos
}
func checkInput ( repos [ ] abaputils . Repository ) error {
for i := range repos {
if repos [ i ] . PackageName == "" {
return errors . New ( "Parameter missing. Please provide the name of the package which should be released" )
}
}
return nil
}
func sortByStatus ( repos [ ] abaputils . Repository , conn abapbuild . Connector ) ( [ ] aakaas . PackageWithRepository , [ ] aakaas . PackageWithRepository ) {
var packagesWithReposLocked [ ] aakaas . PackageWithRepository
var packagesWithReposNotLocked [ ] aakaas . PackageWithRepository
for i := range repos {
var pack aakaas . Package
pack . InitPackage ( repos [ i ] , conn )
pWR := aakaas . PackageWithRepository {
Package : pack ,
Repo : repos [ i ] ,
}
2022-08-23 15:33:42 +02:00
if pack . Status == aakaas . PackageStatusLocked {
2020-09-18 16:40:49 +02:00
packagesWithReposLocked = append ( packagesWithReposLocked , pWR )
} else {
log . Entry ( ) . Infof ( "Package %s has status %s, cannot release this package" , pack . PackageName , pack . Status )
packagesWithReposNotLocked = append ( packagesWithReposNotLocked , pWR )
}
}
return packagesWithReposLocked , packagesWithReposNotLocked
}
2021-12-09 13:54:18 +02:00
func releaseAndPoll ( pckgWR [ ] aakaas . PackageWithRepository , utils * aakaas . AakUtils ) ( [ ] aakaas . PackageWithRepository , error ) {
timeout := time . After ( ( * utils ) . GetMaxRuntime ( ) )
ticker := time . Tick ( ( * utils ) . GetPollingInterval ( ) )
2020-09-18 16:40:49 +02:00
for {
select {
case <- timeout :
return pckgWR , errors . New ( "Timed out" )
case <- ticker :
var allFinished bool = true
for i := range pckgWR {
if pckgWR [ i ] . Package . Status != aakaas . PackageStatusReleased {
err := pckgWR [ i ] . Package . Release ( )
// if there is an error, release is not yet finished
if err != nil {
2022-08-23 15:33:42 +02:00
log . Entry ( ) . Error ( err )
2021-12-09 13:54:18 +02:00
log . Entry ( ) . Infof ( "Release of %s is not yet finished, check again in %s" , pckgWR [ i ] . Package . PackageName , ( * utils ) . GetPollingInterval ( ) )
2020-09-18 16:40:49 +02:00
allFinished = false
}
}
}
if allFinished {
2020-09-24 07:41:06 +02:00
log . Entry ( ) . Infof ( "Release of package(s) was successful" )
2020-09-18 16:40:49 +02:00
return pckgWR , nil
}
}
}
}