From de6c002be443f01e7896fbc2a3ac66726e1e6b19 Mon Sep 17 00:00:00 2001
From: Akramdzhon Azamov <MY_NAME@example.com>
Date: Thu, 21 Sep 2023 00:00:35 +0500
Subject: [PATCH 1/8] added logic of fetching golang private packages for
 whitesource step and detectExecuteScan step

---
 cmd/detectExecuteScan.go                      |  8 +++++
 cmd/detectExecuteScan_generated.go            | 36 +++++++++++++++++++
 cmd/golangBuild_generated.go                  |  2 +-
 cmd/utils.go                                  | 24 +++++++++++++
 cmd/whitesourceExecuteScan.go                 |  7 ++++
 cmd/whitesourceExecuteScan_generated.go       | 36 +++++++++++++++++++
 resources/metadata/detectExecuteScan.yaml     | 29 +++++++++++++++
 resources/metadata/golangBuild.yaml           |  1 +
 .../metadata/whitesourceExecuteScan.yaml      | 29 +++++++++++++++
 vars/detectExecuteScan.groovy                 |  3 +-
 vars/whitesourceExecuteScan.groovy            |  1 +
 11 files changed, 174 insertions(+), 2 deletions(-)

diff --git a/cmd/detectExecuteScan.go b/cmd/detectExecuteScan.go
index 5527b28ed8..7e62549ab9 100644
--- a/cmd/detectExecuteScan.go
+++ b/cmd/detectExecuteScan.go
@@ -138,6 +138,14 @@ func detectExecuteScan(config detectExecuteScanOptions, _ *telemetry.CustomData,
 	if err != nil {
 		log.Entry().WithError(err).Warning("Failed to get GitHub client")
 	}
+
+	if config.BuildTool == golangBuildTool {
+		//configuring go private packages
+		if err := prepareGolangPrivatePackages(config.PrivateModules, config.PrivateModulesGitToken); err != nil {
+			log.Entry().Warningf("couldn't set private packages for golang, error: %s", err.Error())
+		}
+	}
+
 	utils := newDetectUtils(client)
 	if err := runDetect(ctx, config, utils, influx); err != nil {
 		log.Entry().
diff --git a/cmd/detectExecuteScan_generated.go b/cmd/detectExecuteScan_generated.go
index f4cb28a62f..2b4a424cff 100644
--- a/cmd/detectExecuteScan_generated.go
+++ b/cmd/detectExecuteScan_generated.go
@@ -62,6 +62,8 @@ type detectExecuteScanOptions struct {
 	ExcludedDirectories         []string `json:"excludedDirectories,omitempty"`
 	NpmDependencyTypesExcluded  []string `json:"npmDependencyTypesExcluded,omitempty" validate:"possible-values=NONE DEV PEER"`
 	NpmArguments                []string `json:"npmArguments,omitempty"`
+	PrivateModules              string   `json:"privateModules,omitempty"`
+	PrivateModulesGitToken      string   `json:"privateModulesGitToken,omitempty"`
 }
 
 type detectExecuteScanInflux struct {
@@ -195,6 +197,7 @@ Please configure your BlackDuck server Url using the serverUrl parameter and the
 			}
 			log.RegisterSecret(stepConfig.Token)
 			log.RegisterSecret(stepConfig.GithubToken)
+			log.RegisterSecret(stepConfig.PrivateModulesGitToken)
 
 			if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
 				sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
@@ -305,6 +308,8 @@ func addDetectExecuteScanFlags(cmd *cobra.Command, stepConfig *detectExecuteScan
 	cmd.Flags().StringSliceVar(&stepConfig.ExcludedDirectories, "excludedDirectories", []string{}, "List of directories which should be excluded from the scan.")
 	cmd.Flags().StringSliceVar(&stepConfig.NpmDependencyTypesExcluded, "npmDependencyTypesExcluded", []string{}, "List of npm dependency types which Detect should exclude from the BOM.")
 	cmd.Flags().StringSliceVar(&stepConfig.NpmArguments, "npmArguments", []string{}, "List of additional arguments that Detect will add at then end of the npm ls command line when Detect executes the NPM CLI Detector on an NPM project.")
+	cmd.Flags().StringVar(&stepConfig.PrivateModules, "privateModules", os.Getenv("PIPER_privateModules"), "Tells go which modules shall be considered to be private (by setting [GOPRIVATE](https://pkg.go.dev/cmd/go#hdr-Configuration_for_downloading_non_public_code)).")
+	cmd.Flags().StringVar(&stepConfig.PrivateModulesGitToken, "privateModulesGitToken", os.Getenv("PIPER_privateModulesGitToken"), "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line.")
 
 	cmd.MarkFlagRequired("token")
 	cmd.MarkFlagRequired("projectName")
@@ -324,6 +329,7 @@ func detectExecuteScanMetadata() config.StepData {
 				Secrets: []config.StepSecrets{
 					{Name: "detectTokenCredentialsId", Description: "Jenkins 'Secret text' credentials ID containing the API token used to authenticate with the Synopsis Detect (formerly BlackDuck) Server.", Type: "jenkins", Aliases: []config.Alias{{Name: "apiTokenCredentialsId", Deprecated: false}}},
 					{Name: "githubTokenCredentialsId", Description: "Jenkins 'Secret text' credentials ID containing token to authenticate to GitHub.", Type: "jenkins"},
+					{Name: "golangPrivateModulesGitTokenCredentialsId", Description: "Jenkins 'Username with password' credentials ID containing username/password for http access to your git repos where your go private modules are stored.", Type: "jenkins"},
 				},
 				Resources: []config.StepResources{
 					{Name: "buildDescriptor", Type: "stash"},
@@ -737,6 +743,36 @@ func detectExecuteScanMetadata() config.StepData {
 						Aliases:     []config.Alias{{Name: "detect/npmArguments"}},
 						Default:     []string{},
 					},
+					{
+						Name:        "privateModules",
+						ResourceRef: []config.ResourceReference{},
+						Scope:       []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
+						Type:        "string",
+						Mandatory:   false,
+						Aliases:     []config.Alias{},
+						Default:     os.Getenv("PIPER_privateModules"),
+					},
+					{
+						Name: "privateModulesGitToken",
+						ResourceRef: []config.ResourceReference{
+							{
+								Name:  "golangPrivateModulesGitTokenCredentialsId",
+								Param: "password",
+								Type:  "secret",
+							},
+
+							{
+								Name:    "golangPrivateModulesGitTokenVaultSecret",
+								Type:    "vaultSecret",
+								Default: "golang",
+							},
+						},
+						Scope:     []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
+						Type:      "string",
+						Mandatory: false,
+						Aliases:   []config.Alias{},
+						Default:   os.Getenv("PIPER_privateModulesGitToken"),
+					},
 				},
 			},
 			Containers: []config.Container{
diff --git a/cmd/golangBuild_generated.go b/cmd/golangBuild_generated.go
index 676a0539ea..6ef805e447 100644
--- a/cmd/golangBuild_generated.go
+++ b/cmd/golangBuild_generated.go
@@ -498,7 +498,7 @@ func golangBuildMetadata() config.StepData {
 					{
 						Name:        "privateModules",
 						ResourceRef: []config.ResourceReference{},
-						Scope:       []string{"STEPS", "STAGES", "PARAMETERS"},
+						Scope:       []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
 						Type:        "string",
 						Mandatory:   false,
 						Aliases:     []config.Alias{},
diff --git a/cmd/utils.go b/cmd/utils.go
index 685b043bd7..9c148e1f08 100644
--- a/cmd/utils.go
+++ b/cmd/utils.go
@@ -12,3 +12,27 @@ func fileExists(filename string) bool {
 	}
 	return !info.IsDir()
 }
+
+const golangBuildTool = "golang"
+
+// prepare golang private packages for whitesource and blackduck(detectExecuteScan)
+func prepareGolangPrivatePackages(privateModules, privateModulesGitToken string) error {
+
+	goConfig := golangBuildOptions{
+		PrivateModules:         privateModules,
+		PrivateModulesGitToken: privateModulesGitToken,
+	} // only these parameters are enough to configure
+
+	utils := newGolangBuildUtils(goConfig)
+
+	goModFile, err := readGoModFile(utils) // returns nil if go.mod doesnt exist
+	if err != nil {
+		return err
+	}
+
+	if err = prepareGolangEnvironment(&goConfig, goModFile, utils); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/cmd/whitesourceExecuteScan.go b/cmd/whitesourceExecuteScan.go
index 11b1c42051..9169dd34e1 100644
--- a/cmd/whitesourceExecuteScan.go
+++ b/cmd/whitesourceExecuteScan.go
@@ -157,6 +157,13 @@ func whitesourceExecuteScan(config ScanOptions, _ *telemetry.CustomData, commonP
 }
 
 func runWhitesourceExecuteScan(ctx context.Context, config *ScanOptions, scan *ws.Scan, utils whitesourceUtils, sys whitesource, commonPipelineEnvironment *whitesourceExecuteScanCommonPipelineEnvironment, influx *whitesourceExecuteScanInflux) error {
+	if config.BuildTool == golangBuildTool && config != nil {
+		//configuring go private packages
+		if err := prepareGolangPrivatePackages(config.PrivateModules, config.PrivateModulesGitToken); err != nil {
+			log.Entry().Warningf("couldn't set private packages for golang, error: %s", err.Error())
+		}
+	}
+
 	if err := resolveAggregateProjectName(config, scan, sys); err != nil {
 		return errors.Wrapf(err, "failed to resolve and aggregate project name")
 	}
diff --git a/cmd/whitesourceExecuteScan_generated.go b/cmd/whitesourceExecuteScan_generated.go
index 673f7ee6d0..cf8a78700c 100644
--- a/cmd/whitesourceExecuteScan_generated.go
+++ b/cmd/whitesourceExecuteScan_generated.go
@@ -74,6 +74,8 @@ type whitesourceExecuteScanOptions struct {
 	Repository                           string   `json:"repository,omitempty"`
 	Assignees                            []string `json:"assignees,omitempty"`
 	CustomTLSCertificateLinks            []string `json:"customTlsCertificateLinks,omitempty"`
+	PrivateModules                       string   `json:"privateModules,omitempty"`
+	PrivateModulesGitToken               string   `json:"privateModulesGitToken,omitempty"`
 }
 
 type whitesourceExecuteScanCommonPipelineEnvironment struct {
@@ -243,6 +245,7 @@ The step uses the so-called Mend Unified Agent. For details please refer to the
 			log.RegisterSecret(stepConfig.OrgToken)
 			log.RegisterSecret(stepConfig.UserToken)
 			log.RegisterSecret(stepConfig.GithubToken)
+			log.RegisterSecret(stepConfig.PrivateModulesGitToken)
 
 			if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
 				sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
@@ -366,6 +369,8 @@ func addWhitesourceExecuteScanFlags(cmd *cobra.Command, stepConfig *whitesourceE
 	cmd.Flags().StringVar(&stepConfig.Repository, "repository", os.Getenv("PIPER_repository"), "Set the GitHub repository.")
 	cmd.Flags().StringSliceVar(&stepConfig.Assignees, "assignees", []string{``}, "Defines the assignees for the Github Issue created/updated with the results of the scan as a list of login names.")
 	cmd.Flags().StringSliceVar(&stepConfig.CustomTLSCertificateLinks, "customTlsCertificateLinks", []string{}, "List of download links to custom TLS certificates. This is required to ensure trusted connections to instances with repositories (like nexus) when publish flag is set to true.")
+	cmd.Flags().StringVar(&stepConfig.PrivateModules, "privateModules", os.Getenv("PIPER_privateModules"), "Tells go which modules shall be considered to be private (by setting [GOPRIVATE](https://pkg.go.dev/cmd/go#hdr-Configuration_for_downloading_non_public_code)).")
+	cmd.Flags().StringVar(&stepConfig.PrivateModulesGitToken, "privateModulesGitToken", os.Getenv("PIPER_privateModulesGitToken"), "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line.")
 
 	cmd.MarkFlagRequired("buildTool")
 	cmd.MarkFlagRequired("orgToken")
@@ -387,6 +392,7 @@ func whitesourceExecuteScanMetadata() config.StepData {
 					{Name: "orgAdminUserTokenCredentialsId", Description: "Jenkins 'Secret text' credentials ID containing Whitesource org admin token.", Type: "jenkins", Aliases: []config.Alias{{Name: "whitesourceOrgAdminUserTokenCredentialsId", Deprecated: false}, {Name: "whitesource/orgAdminUserTokenCredentialsId", Deprecated: true}}},
 					{Name: "dockerConfigJsonCredentialsId", Description: "Jenkins 'Secret file' credentials ID containing Docker config.json (with registry credential(s)). You can find more details about the Docker credentials in the [Docker documentation](https://docs.docker.com/engine/reference/commandline/login/).", Type: "jenkins", Aliases: []config.Alias{{Name: "dockerCredentialsId", Deprecated: true}}},
 					{Name: "githubTokenCredentialsId", Description: "Jenkins 'Secret text' credentials ID containing token to authenticate to GitHub.", Type: "jenkins"},
+					{Name: "golangPrivateModulesGitTokenCredentialsId", Description: "Jenkins 'Username with password' credentials ID containing username/password for http access to your git repos where your go private modules are stored.", Type: "jenkins"},
 				},
 				Resources: []config.StepResources{
 					{Name: "buildDescriptor", Type: "stash"},
@@ -967,6 +973,36 @@ func whitesourceExecuteScanMetadata() config.StepData {
 						Aliases:     []config.Alias{},
 						Default:     []string{},
 					},
+					{
+						Name:        "privateModules",
+						ResourceRef: []config.ResourceReference{},
+						Scope:       []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
+						Type:        "string",
+						Mandatory:   false,
+						Aliases:     []config.Alias{},
+						Default:     os.Getenv("PIPER_privateModules"),
+					},
+					{
+						Name: "privateModulesGitToken",
+						ResourceRef: []config.ResourceReference{
+							{
+								Name:  "golangPrivateModulesGitTokenCredentialsId",
+								Param: "password",
+								Type:  "secret",
+							},
+
+							{
+								Name:    "golangPrivateModulesGitTokenVaultSecret",
+								Type:    "vaultSecret",
+								Default: "golang",
+							},
+						},
+						Scope:     []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
+						Type:      "string",
+						Mandatory: false,
+						Aliases:   []config.Alias{},
+						Default:   os.Getenv("PIPER_privateModulesGitToken"),
+					},
 				},
 			},
 			Containers: []config.Container{
diff --git a/resources/metadata/detectExecuteScan.yaml b/resources/metadata/detectExecuteScan.yaml
index 35c10a9f90..06cd929967 100644
--- a/resources/metadata/detectExecuteScan.yaml
+++ b/resources/metadata/detectExecuteScan.yaml
@@ -21,6 +21,9 @@ spec:
       - name: githubTokenCredentialsId
         description: Jenkins 'Secret text' credentials ID containing token to authenticate to GitHub.
         type: jenkins
+      - name: golangPrivateModulesGitTokenCredentialsId
+        description: Jenkins 'Username with password' credentials ID containing username/password for http access to your git repos where your go private modules are stored.
+        type: jenkins
     params:
       - name: token
         aliases:
@@ -489,6 +492,32 @@ spec:
           - PARAMETERS
           - STAGES
           - STEPS
+      - name: privateModules
+        type: "string"
+        description: Tells go which modules shall be considered to be private (by setting [GOPRIVATE](https://pkg.go.dev/cmd/go#hdr-Configuration_for_downloading_non_public_code)).
+        scope:
+          - GENERAL
+          - STEPS
+          - STAGES
+          - PARAMETERS
+        alias:
+          - goprivate
+      - name: privateModulesGitToken
+        description: GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line.
+        scope:
+          - GENERAL
+          - PARAMETERS
+          - STAGES
+          - STEPS
+        type: string
+        secret: true
+        resourceRef:
+          - name: golangPrivateModulesGitTokenCredentialsId
+            type: secret
+            param: password
+          - type: vaultSecret
+            name: golangPrivateModulesGitTokenVaultSecret
+            default: golang
   outputs:
     resources:
       - name: influx
diff --git a/resources/metadata/golangBuild.yaml b/resources/metadata/golangBuild.yaml
index 58bedb1f8f..6eb6ebe1c1 100644
--- a/resources/metadata/golangBuild.yaml
+++ b/resources/metadata/golangBuild.yaml
@@ -209,6 +209,7 @@ spec:
         type: "string"
         description: Tells go which modules shall be considered to be private (by setting [GOPRIVATE](https://pkg.go.dev/cmd/go#hdr-Configuration_for_downloading_non_public_code)).
         scope:
+          - GENERAL
           - STEPS
           - STAGES
           - PARAMETERS
diff --git a/resources/metadata/whitesourceExecuteScan.yaml b/resources/metadata/whitesourceExecuteScan.yaml
index 1b450e3ffa..2be99d7ecb 100644
--- a/resources/metadata/whitesourceExecuteScan.yaml
+++ b/resources/metadata/whitesourceExecuteScan.yaml
@@ -38,6 +38,9 @@ spec:
       - name: githubTokenCredentialsId
         description: Jenkins 'Secret text' credentials ID containing token to authenticate to GitHub.
         type: jenkins
+      - name: golangPrivateModulesGitTokenCredentialsId
+        description: Jenkins 'Username with password' credentials ID containing username/password for http access to your git repos where your go private modules are stored.
+        type: jenkins
     params:
       - name: agentDownloadUrl
         type: string
@@ -597,6 +600,32 @@ spec:
           - PARAMETERS
           - STAGES
           - STEPS
+      - name: privateModules
+        type: "string"
+        description: Tells go which modules shall be considered to be private (by setting [GOPRIVATE](https://pkg.go.dev/cmd/go#hdr-Configuration_for_downloading_non_public_code)).
+        scope:
+          - GENERAL
+          - STEPS
+          - STAGES
+          - PARAMETERS
+        alias:
+          - goprivate
+      - name: privateModulesGitToken
+        description: GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line.
+        scope:
+          - GENERAL
+          - PARAMETERS
+          - STAGES
+          - STEPS
+        type: string
+        secret: true
+        resourceRef:
+          - name: golangPrivateModulesGitTokenCredentialsId
+            type: secret
+            param: password
+          - type: vaultSecret
+            name: golangPrivateModulesGitTokenVaultSecret
+            default: golang
     resources:
       - name: buildDescriptor
         type: stash
diff --git a/vars/detectExecuteScan.groovy b/vars/detectExecuteScan.groovy
index 6587c18ba7..3bb58fb3d4 100644
--- a/vars/detectExecuteScan.groovy
+++ b/vars/detectExecuteScan.groovy
@@ -12,7 +12,8 @@ void call(Map parameters = [:]) {
     parameters = DownloadCacheUtils.injectDownloadCacheInParameters(script, parameters, BuildTool.MAVEN)
     List credentials = [
         [type: 'token', id: 'detectTokenCredentialsId', env: ['PIPER_token']],
-        [type: 'token', id: 'githubTokenCredentialsId', env: ['PIPER_githubToken']]
+        [type: 'token', id: 'githubTokenCredentialsId', env: ['PIPER_githubToken']],
+        [type: 'usernamePassword', id: 'golangPrivateModulesGitTokenCredentialsId', env: ['PIPER_privateModulesGitUsername', 'PIPER_privateModulesGitToken']]
     ]
     piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
 }
diff --git a/vars/whitesourceExecuteScan.groovy b/vars/whitesourceExecuteScan.groovy
index 818c4004a6..36cf2321ba 100644
--- a/vars/whitesourceExecuteScan.groovy
+++ b/vars/whitesourceExecuteScan.groovy
@@ -18,6 +18,7 @@ void call(Map parameters = [:]) {
         [type: 'token', id: 'userTokenCredentialsId', env: ['PIPER_userToken']],
         [type: 'token', id: 'githubTokenCredentialsId', env: ['PIPER_githubToken']],
         [type: 'file', id: 'dockerConfigJsonCredentialsId', env: ['PIPER_dockerConfigJSON']],
+        [type: 'usernamePassword', id: 'golangPrivateModulesGitTokenCredentialsId', env: ['PIPER_privateModulesGitUsername', 'PIPER_privateModulesGitToken']]
     ]
     piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
 }

From 3787de677961de4ed4e54d92b88dc4c78bc7ee0e Mon Sep 17 00:00:00 2001
From: akram8008 <900658008.akram@gmail.com>
Date: Wed, 4 Oct 2023 12:47:50 +0500
Subject: [PATCH 2/8] changed logic of checking by
 config.PrivateModulesGitToken

---
 cmd/detectExecuteScan.go      | 2 +-
 cmd/utils.go                  | 2 --
 cmd/whitesourceExecuteScan.go | 2 +-
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/cmd/detectExecuteScan.go b/cmd/detectExecuteScan.go
index 7e62549ab9..6eb858e052 100644
--- a/cmd/detectExecuteScan.go
+++ b/cmd/detectExecuteScan.go
@@ -139,7 +139,7 @@ func detectExecuteScan(config detectExecuteScanOptions, _ *telemetry.CustomData,
 		log.Entry().WithError(err).Warning("Failed to get GitHub client")
 	}
 
-	if config.BuildTool == golangBuildTool {
+	if config.PrivateModulesGitToken != "" {
 		//configuring go private packages
 		if err := prepareGolangPrivatePackages(config.PrivateModules, config.PrivateModulesGitToken); err != nil {
 			log.Entry().Warningf("couldn't set private packages for golang, error: %s", err.Error())
diff --git a/cmd/utils.go b/cmd/utils.go
index 9c148e1f08..b81a7b3d44 100644
--- a/cmd/utils.go
+++ b/cmd/utils.go
@@ -13,8 +13,6 @@ func fileExists(filename string) bool {
 	return !info.IsDir()
 }
 
-const golangBuildTool = "golang"
-
 // prepare golang private packages for whitesource and blackduck(detectExecuteScan)
 func prepareGolangPrivatePackages(privateModules, privateModulesGitToken string) error {
 
diff --git a/cmd/whitesourceExecuteScan.go b/cmd/whitesourceExecuteScan.go
index 9169dd34e1..65f7f68b0f 100644
--- a/cmd/whitesourceExecuteScan.go
+++ b/cmd/whitesourceExecuteScan.go
@@ -157,7 +157,7 @@ func whitesourceExecuteScan(config ScanOptions, _ *telemetry.CustomData, commonP
 }
 
 func runWhitesourceExecuteScan(ctx context.Context, config *ScanOptions, scan *ws.Scan, utils whitesourceUtils, sys whitesource, commonPipelineEnvironment *whitesourceExecuteScanCommonPipelineEnvironment, influx *whitesourceExecuteScanInflux) error {
-	if config.BuildTool == golangBuildTool && config != nil {
+	if config != nil && config.PrivateModulesGitToken != "" {
 		//configuring go private packages
 		if err := prepareGolangPrivatePackages(config.PrivateModules, config.PrivateModulesGitToken); err != nil {
 			log.Entry().Warningf("couldn't set private packages for golang, error: %s", err.Error())

From e3045d1fc5f53eb3fa007c11ebd92ab0a9587a5a Mon Sep 17 00:00:00 2001
From: akram8008 <900658008.akram@gmail.com>
Date: Thu, 5 Oct 2023 13:57:21 +0500
Subject: [PATCH 3/8] moved func prepareGolangPrivatePackages to golangBuild.go

---
 cmd/golangBuild.go | 22 ++++++++++++++++++++++
 cmd/utils.go       | 22 ----------------------
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/cmd/golangBuild.go b/cmd/golangBuild.go
index 8d3cf68783..22fec60ca2 100644
--- a/cmd/golangBuild.go
+++ b/cmd/golangBuild.go
@@ -600,3 +600,25 @@ func gitConfigurationForPrivateModules(privateMod string, token string, utils go
 
 	return nil
 }
+
+// prepare golang private packages for whitesource and blackduck(detectExecuteScan)
+func prepareGolangPrivatePackages(privateModules, privateModulesGitToken string) error {
+
+	goConfig := golangBuildOptions{
+		PrivateModules:         privateModules,
+		PrivateModulesGitToken: privateModulesGitToken,
+	} // only these parameters are enough to configure
+
+	utils := newGolangBuildUtils(goConfig)
+
+	goModFile, err := readGoModFile(utils) // returns nil if go.mod doesnt exist
+	if err != nil {
+		return err
+	}
+
+	if err = prepareGolangEnvironment(&goConfig, goModFile, utils); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/cmd/utils.go b/cmd/utils.go
index b81a7b3d44..685b043bd7 100644
--- a/cmd/utils.go
+++ b/cmd/utils.go
@@ -12,25 +12,3 @@ func fileExists(filename string) bool {
 	}
 	return !info.IsDir()
 }
-
-// prepare golang private packages for whitesource and blackduck(detectExecuteScan)
-func prepareGolangPrivatePackages(privateModules, privateModulesGitToken string) error {
-
-	goConfig := golangBuildOptions{
-		PrivateModules:         privateModules,
-		PrivateModulesGitToken: privateModulesGitToken,
-	} // only these parameters are enough to configure
-
-	utils := newGolangBuildUtils(goConfig)
-
-	goModFile, err := readGoModFile(utils) // returns nil if go.mod doesnt exist
-	if err != nil {
-		return err
-	}
-
-	if err = prepareGolangEnvironment(&goConfig, goModFile, utils); err != nil {
-		return err
-	}
-
-	return nil
-}

From aa09f5b5d3cf85af647ec11da4cb34e275094379 Mon Sep 17 00:00:00 2001
From: Anil Keshav <anil.keshav@sap.com>
Date: Thu, 28 Sep 2023 11:31:51 +0200
Subject: [PATCH 4/8] fix (gitOpsUpdateDeployment) add CA bundle options to
 plain clone and commit to trust enterprise github instances (#4602)

* downloading ca cert bundle when added as config

* adding logging statements

* allowing bats test to handle ca cert

* adding info message

* hard coding file names

* including correct http client util bundle

* removing logging message not needed

* adding cert bundle to commit and push

* improving the condition to add ca cert in commit and push

* fixing unit test

* fixing unit test

* fixing unit test

* fixing unit test

* fixing unit test
---
 cmd/batsExecuteTests.go                       |  4 +-
 cmd/gitopsUpdateDeployment.go                 | 90 +++++++++++++++----
 cmd/gitopsUpdateDeployment_generated.go       | 39 +++++---
 cmd/gitopsUpdateDeployment_test.go            | 12 ++-
 pkg/git/git.go                                | 24 +++--
 pkg/git/git_test.go                           |  8 +-
 .../metadata/gitopsUpdateDeployment.yaml      |  7 ++
 7 files changed, 138 insertions(+), 46 deletions(-)

diff --git a/cmd/batsExecuteTests.go b/cmd/batsExecuteTests.go
index 6bd28f704f..aa4251ebfa 100644
--- a/cmd/batsExecuteTests.go
+++ b/cmd/batsExecuteTests.go
@@ -108,7 +108,9 @@ func runBatsExecuteTests(config *batsExecuteTestsOptions, telemetryData *telemet
 }
 
 func (b *batsExecuteTestsUtilsBundle) CloneRepo(URL string) error {
-	_, err := pipergit.PlainClone("", "", URL, "bats-core")
+	// ToDo: BatsExecute test needs to check if the repo can come from a
+	// enterprise github instance and needs ca-cert handelling seperately
+	_, err := pipergit.PlainClone("", "", URL, "bats-core", []byte{})
 	return err
 
 }
diff --git a/cmd/gitopsUpdateDeployment.go b/cmd/gitopsUpdateDeployment.go
index 6695019418..7220025de8 100644
--- a/cmd/gitopsUpdateDeployment.go
+++ b/cmd/gitopsUpdateDeployment.go
@@ -3,9 +3,19 @@ package cmd
 import (
 	"bytes"
 	"fmt"
+	"io"
+	"net/http"
+	"os"
+	"path"
+	"path/filepath"
+	"regexp"
+	"strings"
+	"time"
+
 	"github.com/SAP/jenkins-library/pkg/command"
 	"github.com/SAP/jenkins-library/pkg/docker"
 	gitUtil "github.com/SAP/jenkins-library/pkg/git"
+	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"
@@ -13,12 +23,6 @@ import (
 	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
 	"github.com/pkg/errors"
-	"io"
-	"os"
-	"path/filepath"
-	"regexp"
-	"strings"
-	"time"
 )
 
 const toolKubectl = "kubectl"
@@ -27,8 +31,8 @@ const toolKustomize = "kustomize"
 
 type iGitopsUpdateDeploymentGitUtils interface {
 	CommitFiles(filePaths []string, commitMessage, author string) (plumbing.Hash, error)
-	PushChangesToRepository(username, password string, force *bool) error
-	PlainClone(username, password, serverURL, directory string) error
+	PushChangesToRepository(username, password string, force *bool, caCerts []byte) error
+	PlainClone(username, password, serverURL, directory string, caCerts []byte) error
 	ChangeBranch(branchName string) error
 }
 
@@ -36,6 +40,7 @@ type gitopsUpdateDeploymentFileUtils interface {
 	TempDir(dir, pattern string) (name string, err error)
 	RemoveAll(path string) error
 	FileWrite(path string, content []byte, perm os.FileMode) error
+	FileRead(path string) ([]byte, error)
 	Glob(pattern string) ([]string, error)
 }
 
@@ -51,6 +56,25 @@ type gitopsUpdateDeploymentGitUtils struct {
 	repository *git.Repository
 }
 
+type gitopsUpdateDeploymentUtilsBundle struct {
+	*piperhttp.Client
+}
+
+type gitopsUpdateDeploymentUtils interface {
+	DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error
+}
+
+func newGitopsUpdateDeploymentUtilsBundle() gitopsUpdateDeploymentUtils {
+	utils := gitopsUpdateDeploymentUtilsBundle{
+		Client: &piperhttp.Client{},
+	}
+	return &utils
+}
+
+func (g *gitopsUpdateDeploymentUtilsBundle) DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error {
+	return g.Client.DownloadFile(url, filename, header, cookies)
+}
+
 func (g *gitopsUpdateDeploymentGitUtils) CommitFiles(filePaths []string, commitMessage, author string) (plumbing.Hash, error) {
 	for _, path := range filePaths {
 		_, err := g.worktree.Add(path)
@@ -71,13 +95,13 @@ func (g *gitopsUpdateDeploymentGitUtils) CommitFiles(filePaths []string, commitM
 	return commit, nil
 }
 
-func (g *gitopsUpdateDeploymentGitUtils) PushChangesToRepository(username, password string, force *bool) error {
-	return gitUtil.PushChangesToRepository(username, password, force, g.repository)
+func (g *gitopsUpdateDeploymentGitUtils) PushChangesToRepository(username, password string, force *bool, caCerts []byte) error {
+	return gitUtil.PushChangesToRepository(username, password, force, g.repository, caCerts)
 }
 
-func (g *gitopsUpdateDeploymentGitUtils) PlainClone(username, password, serverURL, directory string) error {
+func (g *gitopsUpdateDeploymentGitUtils) PlainClone(username, password, serverURL, directory string, caCerts []byte) error {
 	var err error
-	g.repository, err = gitUtil.PlainClone(username, password, serverURL, directory)
+	g.repository, err = gitUtil.PlainClone(username, password, serverURL, directory, caCerts)
 	if err != nil {
 		return errors.Wrapf(err, "plain clone failed '%s'", serverURL)
 	}
@@ -126,7 +150,12 @@ func runGitopsUpdateDeployment(config *gitopsUpdateDeploymentOptions, command gi
 		}
 	}()
 
-	err = cloneRepositoryAndChangeBranch(config, gitUtils, temporaryFolder)
+	certs, err := downloadCACertbunde(config.CustomTLSCertificateLinks, gitUtils, fileUtils)
+	if err != nil {
+		return err
+	}
+
+	err = cloneRepositoryAndChangeBranch(config, gitUtils, fileUtils, temporaryFolder, certs)
 	if err != nil {
 		return errors.Wrap(err, "repository could not get prepared")
 	}
@@ -190,7 +219,7 @@ func runGitopsUpdateDeployment(config *gitopsUpdateDeploymentOptions, command gi
 		}
 	}
 
-	commit, err := commitAndPushChanges(config, gitUtils, allFiles)
+	commit, err := commitAndPushChanges(config, gitUtils, allFiles, certs)
 	if err != nil {
 		return errors.Wrap(err, "failed to commit and push changes")
 	}
@@ -292,8 +321,9 @@ func logNotRequiredButFilledFieldForKustomize(config *gitopsUpdateDeploymentOpti
 	}
 }
 
-func cloneRepositoryAndChangeBranch(config *gitopsUpdateDeploymentOptions, gitUtils iGitopsUpdateDeploymentGitUtils, temporaryFolder string) error {
-	err := gitUtils.PlainClone(config.Username, config.Password, config.ServerURL, temporaryFolder)
+func cloneRepositoryAndChangeBranch(config *gitopsUpdateDeploymentOptions, gitUtils iGitopsUpdateDeploymentGitUtils, fileUtils gitopsUpdateDeploymentFileUtils, temporaryFolder string, certs []byte) error {
+
+	err := gitUtils.PlainClone(config.Username, config.Password, config.ServerURL, temporaryFolder, certs)
 	if err != nil {
 		return errors.Wrap(err, "failed to plain clone repository")
 	}
@@ -305,6 +335,30 @@ func cloneRepositoryAndChangeBranch(config *gitopsUpdateDeploymentOptions, gitUt
 	return nil
 }
 
+func downloadCACertbunde(customTlsCertificateLinks []string, gitUtils iGitopsUpdateDeploymentGitUtils, fileUtils gitopsUpdateDeploymentFileUtils) ([]byte, error) {
+	certs := []byte{}
+	utils := newGitopsUpdateDeploymentUtilsBundle()
+	if len(customTlsCertificateLinks) > 0 {
+		for _, customTlsCertificateLink := range customTlsCertificateLinks {
+			log.Entry().Infof("Downloading CA certs %s into file '%s'", customTlsCertificateLink, path.Base(customTlsCertificateLink))
+			err := utils.DownloadFile(customTlsCertificateLink, path.Base(customTlsCertificateLink), nil, nil)
+			if err != nil {
+				return certs, nil
+			}
+
+			content, err := fileUtils.FileRead(path.Base(customTlsCertificateLink))
+			if err != nil {
+				return certs, nil
+			}
+			log.Entry().Infof("CA certs added successfully to cert pool")
+
+			certs = append(certs, content...)
+		}
+	}
+
+	return certs, nil
+}
+
 func executeKubectl(config *gitopsUpdateDeploymentOptions, command gitopsUpdateDeploymentExecRunner, filePath string) ([]byte, error) {
 	var outputBytes []byte
 	registryImage, err := buildRegistryPlusImage(config)
@@ -444,7 +498,7 @@ func buildRegistryPlusImageAndTagSeparately(config *gitopsUpdateDeploymentOption
 
 }
 
-func commitAndPushChanges(config *gitopsUpdateDeploymentOptions, gitUtils iGitopsUpdateDeploymentGitUtils, filePaths []string) (plumbing.Hash, error) {
+func commitAndPushChanges(config *gitopsUpdateDeploymentOptions, gitUtils iGitopsUpdateDeploymentGitUtils, filePaths []string, certs []byte) (plumbing.Hash, error) {
 	commitMessage := config.CommitMessage
 
 	if commitMessage == "" {
@@ -456,7 +510,7 @@ func commitAndPushChanges(config *gitopsUpdateDeploymentOptions, gitUtils iGitop
 		return [20]byte{}, errors.Wrap(err, "committing changes failed")
 	}
 
-	err = gitUtils.PushChangesToRepository(config.Username, config.Password, &config.ForcePush)
+	err = gitUtils.PushChangesToRepository(config.Username, config.Password, &config.ForcePush, certs)
 	if err != nil {
 		return [20]byte{}, errors.Wrap(err, "pushing changes failed")
 	}
diff --git a/cmd/gitopsUpdateDeployment_generated.go b/cmd/gitopsUpdateDeployment_generated.go
index 97eb254291..ca1c926643 100644
--- a/cmd/gitopsUpdateDeployment_generated.go
+++ b/cmd/gitopsUpdateDeployment_generated.go
@@ -16,20 +16,21 @@ import (
 )
 
 type gitopsUpdateDeploymentOptions struct {
-	BranchName            string   `json:"branchName,omitempty"`
-	CommitMessage         string   `json:"commitMessage,omitempty"`
-	ServerURL             string   `json:"serverUrl,omitempty"`
-	ForcePush             bool     `json:"forcePush,omitempty"`
-	Username              string   `json:"username,omitempty"`
-	Password              string   `json:"password,omitempty"`
-	FilePath              string   `json:"filePath,omitempty"`
-	ContainerName         string   `json:"containerName,omitempty"`
-	ContainerRegistryURL  string   `json:"containerRegistryUrl,omitempty"`
-	ContainerImageNameTag string   `json:"containerImageNameTag,omitempty"`
-	ChartPath             string   `json:"chartPath,omitempty"`
-	HelmValues            []string `json:"helmValues,omitempty"`
-	DeploymentName        string   `json:"deploymentName,omitempty"`
-	Tool                  string   `json:"tool,omitempty" validate:"possible-values=kubectl helm kustomize"`
+	BranchName                string   `json:"branchName,omitempty"`
+	CommitMessage             string   `json:"commitMessage,omitempty"`
+	ServerURL                 string   `json:"serverUrl,omitempty"`
+	ForcePush                 bool     `json:"forcePush,omitempty"`
+	Username                  string   `json:"username,omitempty"`
+	Password                  string   `json:"password,omitempty"`
+	FilePath                  string   `json:"filePath,omitempty"`
+	ContainerName             string   `json:"containerName,omitempty"`
+	ContainerRegistryURL      string   `json:"containerRegistryUrl,omitempty"`
+	ContainerImageNameTag     string   `json:"containerImageNameTag,omitempty"`
+	ChartPath                 string   `json:"chartPath,omitempty"`
+	HelmValues                []string `json:"helmValues,omitempty"`
+	DeploymentName            string   `json:"deploymentName,omitempty"`
+	Tool                      string   `json:"tool,omitempty" validate:"possible-values=kubectl helm kustomize"`
+	CustomTLSCertificateLinks []string `json:"customTlsCertificateLinks,omitempty"`
 }
 
 // GitopsUpdateDeploymentCommand Updates Kubernetes Deployment Manifest in an Infrastructure Git Repository
@@ -155,6 +156,7 @@ func addGitopsUpdateDeploymentFlags(cmd *cobra.Command, stepConfig *gitopsUpdate
 	cmd.Flags().StringSliceVar(&stepConfig.HelmValues, "helmValues", []string{}, "List of helm values as YAML file reference or URL (as per helm parameter description for `-f` / `--values`)")
 	cmd.Flags().StringVar(&stepConfig.DeploymentName, "deploymentName", os.Getenv("PIPER_deploymentName"), "Defines the name of the deployment. In case of `kustomize` this is the name or alias of the image in the `kustomization.yaml`")
 	cmd.Flags().StringVar(&stepConfig.Tool, "tool", `kubectl`, "Defines the tool which should be used to update the deployment description.")
+	cmd.Flags().StringSliceVar(&stepConfig.CustomTLSCertificateLinks, "customTlsCertificateLinks", []string{}, "List containing download links of custom TLS certificates. This is required to ensure trusted connections to registries with custom certificates.")
 
 	cmd.MarkFlagRequired("branchName")
 	cmd.MarkFlagRequired("serverUrl")
@@ -343,6 +345,15 @@ func gitopsUpdateDeploymentMetadata() config.StepData {
 						Aliases:     []config.Alias{},
 						Default:     `kubectl`,
 					},
+					{
+						Name:        "customTlsCertificateLinks",
+						ResourceRef: []config.ResourceReference{},
+						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
+						Type:        "[]string",
+						Mandatory:   false,
+						Aliases:     []config.Alias{},
+						Default:     []string{},
+					},
 				},
 			},
 			Containers: []config.Container{
diff --git a/cmd/gitopsUpdateDeployment_test.go b/cmd/gitopsUpdateDeployment_test.go
index 2d05f1ce39..a776fdb83c 100644
--- a/cmd/gitopsUpdateDeployment_test.go
+++ b/cmd/gitopsUpdateDeployment_test.go
@@ -772,6 +772,7 @@ type filesMock struct {
 	failOnCreation bool
 	failOnDeletion bool
 	failOnWrite    bool
+	failOnRead     bool
 	failOnGlob     bool
 	path           string
 }
@@ -783,6 +784,13 @@ func (f filesMock) FileWrite(path string, content []byte, perm os.FileMode) erro
 	return piperutils.Files{}.FileWrite(path, content, perm)
 }
 
+func (f filesMock) FileRead(path string) ([]byte, error) {
+	if f.failOnRead {
+		return []byte{}, errors.New("error appeared")
+	}
+	return piperutils.Files{}.FileRead(path)
+}
+
 func (f filesMock) TempDir(dir string, pattern string) (name string, err error) {
 	if f.failOnCreation {
 		return "", errors.New("error appeared")
@@ -848,7 +856,7 @@ func (v *gitUtilsMock) CommitFiles(newFiles []string, commitMessage string, _ st
 	return [20]byte{123}, nil
 }
 
-func (v gitUtilsMock) PushChangesToRepository(_ string, _ string, force *bool) error {
+func (v gitUtilsMock) PushChangesToRepository(_ string, _ string, force *bool, caCerts []byte) error {
 	if v.failOnPush {
 		return errors.New("error on push")
 	}
@@ -858,7 +866,7 @@ func (v gitUtilsMock) PushChangesToRepository(_ string, _ string, force *bool) e
 	return nil
 }
 
-func (v *gitUtilsMock) PlainClone(_, _, _, directory string) error {
+func (v *gitUtilsMock) PlainClone(_, _, _, directory string, caCerts []byte) error {
 	if v.skipClone {
 		return nil
 	}
diff --git a/pkg/git/git.go b/pkg/git/git.go
index f843d1ee36..c5758f281a 100644
--- a/pkg/git/git.go
+++ b/pkg/git/git.go
@@ -1,13 +1,14 @@
 package git
 
 import (
+	"time"
+
 	"github.com/SAP/jenkins-library/pkg/log"
 	"github.com/go-git/go-git/v5"
 	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/object"
 	"github.com/go-git/go-git/v5/plumbing/transport/http"
 	"github.com/pkg/errors"
-	"time"
 )
 
 // utilsWorkTree interface abstraction of git.Worktree to enable tests
@@ -53,14 +54,18 @@ func commitSingleFile(filePath, commitMessage, author string, worktree utilsWork
 }
 
 // PushChangesToRepository Pushes all committed changes in the repository to the remote repository
-func PushChangesToRepository(username, password string, force *bool, repository *git.Repository) error {
-	return pushChangesToRepository(username, password, force, repository)
+func PushChangesToRepository(username, password string, force *bool, repository *git.Repository, caCerts []byte) error {
+	return pushChangesToRepository(username, password, force, repository, caCerts)
 }
 
-func pushChangesToRepository(username, password string, force *bool, repository utilsRepository) error {
+func pushChangesToRepository(username, password string, force *bool, repository utilsRepository, caCerts []byte) error {
 	pushOptions := &git.PushOptions{
 		Auth: &http.BasicAuth{Username: username, Password: password},
 	}
+
+	if len(caCerts) > 0 {
+		pushOptions.CABundle = caCerts
+	}
 	if force != nil {
 		pushOptions.Force = *force
 	}
@@ -72,16 +77,21 @@ func pushChangesToRepository(username, password string, force *bool, repository
 }
 
 // PlainClone Clones a non-bare repository to the provided directory
-func PlainClone(username, password, serverURL, directory string) (*git.Repository, error) {
+func PlainClone(username, password, serverURL, directory string, caCerts []byte) (*git.Repository, error) {
 	abstractedGit := &abstractionGit{}
-	return plainClone(username, password, serverURL, directory, abstractedGit)
+	return plainClone(username, password, serverURL, directory, abstractedGit, caCerts)
 }
 
-func plainClone(username, password, serverURL, directory string, abstractionGit utilsGit) (*git.Repository, error) {
+func plainClone(username, password, serverURL, directory string, abstractionGit utilsGit, caCerts []byte) (*git.Repository, error) {
 	gitCloneOptions := git.CloneOptions{
 		Auth: &http.BasicAuth{Username: username, Password: password},
 		URL:  serverURL,
 	}
+
+	if len(caCerts) > 0 {
+		gitCloneOptions.CABundle = caCerts
+	}
+
 	repository, err := abstractionGit.plainClone(directory, false, &gitCloneOptions)
 	if err != nil {
 		return nil, errors.Wrap(err, "failed to clone git")
diff --git a/pkg/git/git_test.go b/pkg/git/git_test.go
index 39e50e3348..f5cf660db4 100644
--- a/pkg/git/git_test.go
+++ b/pkg/git/git_test.go
@@ -51,13 +51,13 @@ func TestPushChangesToRepository(t *testing.T) {
 		t.Parallel()
 		err := pushChangesToRepository("user", "password", nil, RepositoryMock{
 			test: t,
-		})
+		}, []byte{})
 		assert.NoError(t, err)
 	})
 
 	t.Run("error pushing", func(t *testing.T) {
 		t.Parallel()
-		err := pushChangesToRepository("user", "password", nil, RepositoryMockError{})
+		err := pushChangesToRepository("user", "password", nil, RepositoryMockError{}, []byte{})
 		assert.EqualError(t, err, "failed to push commit: error on push commits")
 	})
 }
@@ -67,7 +67,7 @@ func TestPlainClone(t *testing.T) {
 	t.Run("successful clone", func(t *testing.T) {
 		t.Parallel()
 		abstractedGit := &UtilsGitMock{}
-		_, err := plainClone("user", "password", "URL", "directory", abstractedGit)
+		_, err := plainClone("user", "password", "URL", "directory", abstractedGit, []byte{})
 		assert.NoError(t, err)
 		assert.Equal(t, "directory", abstractedGit.path)
 		assert.False(t, abstractedGit.isBare)
@@ -78,7 +78,7 @@ func TestPlainClone(t *testing.T) {
 	t.Run("error on cloning", func(t *testing.T) {
 		t.Parallel()
 		abstractedGit := UtilsGitMockError{}
-		_, err := plainClone("user", "password", "URL", "directory", abstractedGit)
+		_, err := plainClone("user", "password", "URL", "directory", abstractedGit, []byte{})
 		assert.EqualError(t, err, "failed to clone git: error during clone")
 	})
 }
diff --git a/resources/metadata/gitopsUpdateDeployment.yaml b/resources/metadata/gitopsUpdateDeployment.yaml
index 22bceee9bf..5349e2e74b 100644
--- a/resources/metadata/gitopsUpdateDeployment.yaml
+++ b/resources/metadata/gitopsUpdateDeployment.yaml
@@ -190,6 +190,13 @@ spec:
           - kubectl
           - helm
           - kustomize
+      - name: customTlsCertificateLinks
+        type: "[]string"
+        description: List containing download links of custom TLS certificates. This is required to ensure trusted connections to registries with custom certificates.
+        scope:
+          - PARAMETERS
+          - STAGES
+          - STEPS
   containers:
     - image: dtzar/helm-kubectl:3.8.0
       workingDir: /config

From 8c9beb98c60bd3097da9647455825563a10c2c99 Mon Sep 17 00:00:00 2001
From: Egor Balakin <14162703+m1ron0xFF@users.noreply.github.com>
Date: Thu, 28 Sep 2023 16:14:35 +0400
Subject: [PATCH 5/8] feat(kanikoExecute): add dockerfilePath param to
 multipleImages (#4569)

* add containerDockerfilePath param to multipleImages

* rename ContainerDockerfilePath param to DockerfilePath

* Fix trailing spaces

---------

Co-authored-by: Egor Balakin <egor.balakin@sap.com>
Co-authored-by: Vyacheslav Starostin <32613074+vstarostin@users.noreply.github.com>
---
 cmd/kanikoExecute.go                  | 17 +++++++++++++++--
 resources/metadata/kanikoExecute.yaml |  1 +
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/cmd/kanikoExecute.go b/cmd/kanikoExecute.go
index 91469991ce..645682b594 100644
--- a/cmd/kanikoExecute.go
+++ b/cmd/kanikoExecute.go
@@ -226,7 +226,13 @@ func runKanikoExecute(config *kanikoExecuteOptions, telemetryData *telemetry.Cus
 					"--context-sub-path", entry.ContextSubPath,
 					"--destination", fmt.Sprintf("%v/%v", containerRegistry, containerImageNameAndTag),
 				)
-				if err = runKaniko(config.DockerfilePath, buildOptions, config.ReadImageDigest, execRunner, fileUtils, commonPipelineEnvironment); err != nil {
+
+				dockerfilePath := config.DockerfilePath
+				if entry.DockerfilePath != "" {
+					dockerfilePath = entry.DockerfilePath
+				}
+
+				if err = runKaniko(dockerfilePath, buildOptions, config.ReadImageDigest, execRunner, fileUtils, commonPipelineEnvironment); err != nil {
 					return fmt.Errorf("multipleImages: failed to build image '%v' using '%v': %w", entry.ContainerImageName, config.DockerfilePath, err)
 				}
 
@@ -251,7 +257,13 @@ func runKanikoExecute(config *kanikoExecuteOptions, telemetryData *telemetry.Cus
 					"--context-sub-path", entry.ContextSubPath,
 					"--destination", entry.ContainerImage,
 				)
-				if err = runKaniko(config.DockerfilePath, buildOptions, config.ReadImageDigest, execRunner, fileUtils, commonPipelineEnvironment); err != nil {
+
+				dockerfilePath := config.DockerfilePath
+				if entry.DockerfilePath != "" {
+					dockerfilePath = entry.DockerfilePath
+				}
+
+				if err = runKaniko(dockerfilePath, buildOptions, config.ReadImageDigest, execRunner, fileUtils, commonPipelineEnvironment); err != nil {
 					return fmt.Errorf("multipleImages: failed to build image '%v' using '%v': %w", containerImageName, config.DockerfilePath, err)
 				}
 
@@ -405,6 +417,7 @@ func runKaniko(dockerFilepath string, buildOptions []string, readDigest bool, ex
 
 type multipleImageConf struct {
 	ContextSubPath     string `json:"contextSubPath,omitempty"`
+	DockerfilePath     string `json:"dockerfilePath,omitempty"`
 	ContainerImageName string `json:"containerImageName,omitempty"`
 	ContainerImageTag  string `json:"containerImageTag,omitempty"`
 	ContainerImage     string `json:"containerImage,omitempty"`
diff --git a/resources/metadata/kanikoExecute.yaml b/resources/metadata/kanikoExecute.yaml
index 18a241c42b..f8acefba0b 100644
--- a/resources/metadata/kanikoExecute.yaml
+++ b/resources/metadata/kanikoExecute.yaml
@@ -158,6 +158,7 @@ spec:
 
           Array keys:
             contextSubPath - Set a context subpath.
+            dockerfilePath - Dockerfile path (optional). If empty, root will be used.
             containerImageName - Name of the container which will be built.
             containerImageTag - Tag of the container which will be built. If empty - root containerImageTag will be used.
             containerImage - Defines the full name of the Docker image to be created including registry.

From ac083606f027e0b958b485ae78e51aa9a417d601 Mon Sep 17 00:00:00 2001
From: Marcus Holl <marcus.holl@sap.com>
Date: Fri, 29 Sep 2023 13:59:56 +0200
Subject: [PATCH 6/8] fix(helm): forward sourceRepositoryCredentialsId from
 groovy to go layer (#4604)

forward sourceRepositoryCredentialsId from groovy to go layer in the same way how this is done for the targetRepositoryCredentialsId
---
 cmd/helmExecute_generated.go        | 3 ++-
 resources/metadata/helmExecute.yaml | 5 ++++-
 vars/helmExecute.groovy             | 1 +
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/cmd/helmExecute_generated.go b/cmd/helmExecute_generated.go
index 516b471cbc..84a6c253a9 100644
--- a/cmd/helmExecute_generated.go
+++ b/cmd/helmExecute_generated.go
@@ -255,7 +255,8 @@ func helmExecuteMetadata() config.StepData {
 				Secrets: []config.StepSecrets{
 					{Name: "kubeConfigFileCredentialsId", Description: "Jenkins 'Secret file' credentials ID containing kubeconfig file. Details can be found in the [Kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/).", Type: "jenkins", Aliases: []config.Alias{{Name: "kubeCredentialsId", Deprecated: true}}},
 					{Name: "dockerConfigJsonCredentialsId", Description: "Jenkins 'Secret file' credentials ID containing Docker config.json (with registry credential(s)).", Type: "jenkins"},
-					{Name: "targetRepositoryCredentialsId", Description: "Jenkins 'Username Password' credentials ID containing username and password for the Helm Repository authentication", Type: "jenkins"},
+					{Name: "sourceRepositoryCredentialsId", Description: "Jenkins 'Username Password' credentials ID containing username and password for the Helm Repository authentication (source repo)", Type: "jenkins"},
+					{Name: "targetRepositoryCredentialsId", Description: "Jenkins 'Username Password' credentials ID containing username and password for the Helm Repository authentication (target repo)", Type: "jenkins"},
 				},
 				Resources: []config.StepResources{
 					{Name: "deployDescriptor", Type: "stash"},
diff --git a/resources/metadata/helmExecute.yaml b/resources/metadata/helmExecute.yaml
index f91c755a78..ccae717d7f 100644
--- a/resources/metadata/helmExecute.yaml
+++ b/resources/metadata/helmExecute.yaml
@@ -36,8 +36,11 @@ spec:
       - name: dockerConfigJsonCredentialsId
         description: Jenkins 'Secret file' credentials ID containing Docker config.json (with registry credential(s)).
         type: jenkins
+      - name: sourceRepositoryCredentialsId
+        description: Jenkins 'Username Password' credentials ID containing username and password for the Helm Repository authentication (source repo)
+        type: jenkins
       - name: targetRepositoryCredentialsId
-        description: Jenkins 'Username Password' credentials ID containing username and password for the Helm Repository authentication
+        description: Jenkins 'Username Password' credentials ID containing username and password for the Helm Repository authentication (target repo)
         type: jenkins
     resources:
       - name: deployDescriptor
diff --git a/vars/helmExecute.groovy b/vars/helmExecute.groovy
index ef729cd237..89c8ee202a 100644
--- a/vars/helmExecute.groovy
+++ b/vars/helmExecute.groovy
@@ -7,6 +7,7 @@ void call(Map parameters = [:]) {
     List credentials = [
         [type: 'file', id: 'kubeConfigFileCredentialsId', env: ['PIPER_kubeConfig']],
         [type: 'file', id: 'dockerConfigJsonCredentialsId', env: ['PIPER_dockerConfigJSON']],
+        [type: 'usernamePassword', id: 'sourceRepositoryCredentialsId', env: ['PIPER_sourceRepositoryUser', 'PIPER_sourceRepositoryPassword']],
         [type: 'usernamePassword', id: 'targetRepositoryCredentialsId', env: ['PIPER_targetRepositoryUser', 'PIPER_targetRepositoryPassword']],
     ]
     piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)

From 3c24cae62776aadbe82e6533d7eead714d35b7cf Mon Sep 17 00:00:00 2001
From: Jk1484 <35270240+Jk1484@users.noreply.github.com>
Date: Wed, 4 Oct 2023 15:44:48 +0500
Subject: [PATCH 7/8] feat(config): exporting generateConfig function and
 applying minor changes (#4605)

* exporting generateConfig function and applying minor changes

* Added setConfigOptions to set configOptions variable.
Added possibility to set format output, json or yaml for now.

* Correcting mistake on cmd/getDefaults.go

Co-authored-by: Jordi van Liempt <35920075+jliempt@users.noreply.github.com>

---------

Co-authored-by: Jordi van Liempt <35920075+jliempt@users.noreply.github.com>
---
 cmd/cnbBuild_test.go      |   2 +-
 cmd/getConfig.go          | 121 +++++++++++++++++++++++---------------
 cmd/getConfig_test.go     |   8 +--
 cmd/getDefaults.go        |   2 +-
 cmd/kanikoExecute_test.go |   6 +-
 5 files changed, 82 insertions(+), 57 deletions(-)

diff --git a/cmd/cnbBuild_test.go b/cmd/cnbBuild_test.go
index 75ba12e4a0..24dd2331d3 100644
--- a/cmd/cnbBuild_test.go
+++ b/cmd/cnbBuild_test.go
@@ -105,7 +105,7 @@ func assetBuildEnv(t *testing.T, utils cnbutils.MockUtils, key, value string) bo
 }
 
 func TestRunCnbBuild(t *testing.T) {
-	configOptions.openFile = piperconf.OpenPiperFile
+	configOptions.OpenFile = piperconf.OpenPiperFile
 
 	t.Run("prefers direct configuration", func(t *testing.T) {
 		t.Parallel()
diff --git a/cmd/getConfig.go b/cmd/getConfig.go
index 6ea45de881..aa4734a75c 100644
--- a/cmd/getConfig.go
+++ b/cmd/getConfig.go
@@ -6,6 +6,7 @@ import (
 	"os"
 	"path"
 	"path/filepath"
+	"strings"
 
 	"github.com/SAP/jenkins-library/pkg/config"
 	"github.com/SAP/jenkins-library/pkg/log"
@@ -16,19 +17,31 @@ import (
 	"github.com/spf13/cobra"
 )
 
-type configCommandOptions struct {
-	output                        string // output format, so far only JSON
-	outputFile                    string // if set: path to file where the output should be written to
-	parametersJSON                string // parameters to be considered in JSON format
-	stageConfig                   bool
-	stageConfigAcceptedParameters []string
-	stepMetadata                  string // metadata to be considered, can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR'
-	stepName                      string
-	contextConfig                 bool
-	openFile                      func(s string, t map[string]string) (io.ReadCloser, error)
+type ConfigCommandOptions struct {
+	Output                        string // output format, so far only JSON, YAML
+	OutputFile                    string // if set: path to file where the output should be written to
+	ParametersJSON                string // parameters to be considered in JSON format
+	StageConfig                   bool
+	StageConfigAcceptedParameters []string
+	StepMetadata                  string // metadata to be considered, can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR'
+	StepName                      string
+	ContextConfig                 bool
+	OpenFile                      func(s string, t map[string]string) (io.ReadCloser, error)
 }
 
-var configOptions configCommandOptions
+var configOptions ConfigCommandOptions
+
+func SetConfigOptions(c ConfigCommandOptions) {
+	configOptions.ContextConfig = c.ContextConfig
+	configOptions.OpenFile = c.OpenFile
+	configOptions.Output = c.Output
+	configOptions.OutputFile = c.OutputFile
+	configOptions.ParametersJSON = c.ParametersJSON
+	configOptions.StageConfig = c.StageConfig
+	configOptions.StageConfigAcceptedParameters = c.StageConfigAcceptedParameters
+	configOptions.StepMetadata = c.StepMetadata
+	configOptions.StepName = c.StepName
+}
 
 type getConfigUtils interface {
 	FileExists(filename string) (bool, error)
@@ -41,16 +54,17 @@ type getConfigUtilsBundle struct {
 }
 
 func newGetConfigUtilsUtils() getConfigUtils {
-	utils := getConfigUtilsBundle{
+	return &getConfigUtilsBundle{
 		Files: &piperutils.Files{},
 	}
-	return &utils
 }
 
 // ConfigCommand is the entry command for loading the configuration of a pipeline step
 func ConfigCommand() *cobra.Command {
+	SetConfigOptions(ConfigCommandOptions{
+		OpenFile: config.OpenPiperFile,
+	})
 
-	configOptions.openFile = config.OpenPiperFile
 	var createConfigCmd = &cobra.Command{
 		Use:   "getConfig",
 		Short: "Loads the project 'Piper' configuration respecting defaults and parameters.",
@@ -62,9 +76,7 @@ func ConfigCommand() *cobra.Command {
 			GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens)
 		},
 		Run: func(cmd *cobra.Command, _ []string) {
-			utils := newGetConfigUtilsUtils()
-			err := generateConfig(utils)
-			if err != nil {
+			if err := generateConfigWrapper(); err != nil {
 				log.SetErrorCategory(log.ErrorConfiguration)
 				log.Entry().WithError(err).Fatal("failed to retrieve configuration")
 			}
@@ -77,8 +89,8 @@ func ConfigCommand() *cobra.Command {
 
 // GetDockerImageValue provides Piper commands additional access to configuration of step execution image if required
 func GetDockerImageValue(stepName string) (string, error) {
-	configOptions.contextConfig = true
-	configOptions.stepName = stepName
+	configOptions.ContextConfig = true
+	configOptions.StepName = stepName
 	stepConfig, err := getConfig()
 	if err != nil {
 		return "", err
@@ -94,8 +106,8 @@ func GetDockerImageValue(stepName string) (string, error) {
 }
 
 func getBuildToolFromStageConfig(stepName string) (string, error) {
-	configOptions.contextConfig = true
-	configOptions.stepName = stepName
+	configOptions.ContextConfig = true
+	configOptions.StepName = stepName
 	stageConfig, err := GetStageConfig()
 	if err != nil {
 		return "", err
@@ -116,7 +128,7 @@ func GetStageConfig() (config.StepConfig, error) {
 	stepConfig := config.StepConfig{}
 	projectConfigFile := getProjectConfigFile(GeneralConfig.CustomConfig)
 
-	customConfig, err := configOptions.openFile(projectConfigFile, GeneralConfig.GitHubAccessTokens)
+	customConfig, err := configOptions.OpenFile(projectConfigFile, GeneralConfig.GitHubAccessTokens)
 	if err != nil {
 		if !errors.Is(err, os.ErrNotExist) {
 			return stepConfig, errors.Wrapf(err, "config: open configuration file '%v' failed", projectConfigFile)
@@ -126,7 +138,7 @@ func GetStageConfig() (config.StepConfig, error) {
 
 	defaultConfig := []io.ReadCloser{}
 	for _, f := range GeneralConfig.DefaultConfig {
-		fc, err := configOptions.openFile(f, GeneralConfig.GitHubAccessTokens)
+		fc, err := configOptions.OpenFile(f, GeneralConfig.GitHubAccessTokens)
 		// only create error for non-default values
 		if err != nil && f != ".pipeline/defaults.yaml" {
 			return stepConfig, errors.Wrapf(err, "config: getting defaults failed: '%v'", f)
@@ -136,7 +148,7 @@ func GetStageConfig() (config.StepConfig, error) {
 		}
 	}
 
-	return myConfig.GetStageConfig(GeneralConfig.ParametersJSON, customConfig, defaultConfig, GeneralConfig.IgnoreCustomDefaults, configOptions.stageConfigAcceptedParameters, GeneralConfig.StageName)
+	return myConfig.GetStageConfig(GeneralConfig.ParametersJSON, customConfig, defaultConfig, GeneralConfig.IgnoreCustomDefaults, configOptions.StageConfigAcceptedParameters, GeneralConfig.StageName)
 }
 
 func getConfig() (config.StepConfig, error) {
@@ -144,17 +156,17 @@ func getConfig() (config.StepConfig, error) {
 	var stepConfig config.StepConfig
 	var err error
 
-	if configOptions.stageConfig {
+	if configOptions.StageConfig {
 		stepConfig, err = GetStageConfig()
 		if err != nil {
 			return stepConfig, errors.Wrap(err, "getting stage config failed")
 		}
 	} else {
-		log.Entry().Infof("Printing stepName %s", configOptions.stepName)
+		log.Entry().Infof("Printing stepName %s", configOptions.StepName)
 		if GeneralConfig.MetaDataResolver == nil {
 			GeneralConfig.MetaDataResolver = GetAllStepMetadata
 		}
-		metadata, err := config.ResolveMetadata(GeneralConfig.GitHubAccessTokens, GeneralConfig.MetaDataResolver, configOptions.stepMetadata, configOptions.stepName)
+		metadata, err := config.ResolveMetadata(GeneralConfig.GitHubAccessTokens, GeneralConfig.MetaDataResolver, configOptions.StepMetadata, configOptions.StepName)
 		if err != nil {
 			return stepConfig, errors.Wrapf(err, "failed to resolve metadata")
 		}
@@ -172,7 +184,7 @@ func getConfig() (config.StepConfig, error) {
 
 		projectConfigFile := getProjectConfigFile(GeneralConfig.CustomConfig)
 
-		customConfig, err := configOptions.openFile(projectConfigFile, GeneralConfig.GitHubAccessTokens)
+		customConfig, err := configOptions.OpenFile(projectConfigFile, GeneralConfig.GitHubAccessTokens)
 		if err != nil {
 			if !errors.Is(err, os.ErrNotExist) {
 				return stepConfig, errors.Wrapf(err, "config: open configuration file '%v' failed", projectConfigFile)
@@ -186,7 +198,7 @@ func getConfig() (config.StepConfig, error) {
 		}
 
 		for _, f := range GeneralConfig.DefaultConfig {
-			fc, err := configOptions.openFile(f, GeneralConfig.GitHubAccessTokens)
+			fc, err := configOptions.OpenFile(f, GeneralConfig.GitHubAccessTokens)
 			// only create error for non-default values
 			if err != nil && f != ".pipeline/defaults.yaml" {
 				return stepConfig, errors.Wrapf(err, "config: getting defaults failed: '%v'", f)
@@ -198,7 +210,7 @@ func getConfig() (config.StepConfig, error) {
 
 		var flags map[string]interface{}
 
-		if configOptions.contextConfig {
+		if configOptions.ContextConfig {
 			metadata.Spec.Inputs.Parameters = []config.StepParameters{}
 		}
 
@@ -208,33 +220,46 @@ func getConfig() (config.StepConfig, error) {
 		}
 
 		// apply context conditions if context configuration is requested
-		if configOptions.contextConfig {
+		if configOptions.ContextConfig {
 			applyContextConditions(metadata, &stepConfig)
 		}
 	}
 	return stepConfig, nil
 }
 
-func generateConfig(utils getConfigUtils) error {
+func generateConfigWrapper() error {
+	var formatter func(interface{}) (string, error)
+	switch strings.ToLower(configOptions.Output) {
+	case "yaml", "yml":
+		formatter = config.GetYAML
+	case "json":
+		formatter = config.GetJSON
+	default:
+		formatter = config.GetJSON
+	}
+	return GenerateConfig(formatter)
+}
+
+func GenerateConfig(formatter func(interface{}) (string, error)) error {
+	utils := newGetConfigUtilsUtils()
 
 	stepConfig, err := getConfig()
 	if err != nil {
 		return err
 	}
 
-	myConfigJSON, err := config.GetJSON(stepConfig.Config)
+	myConfig, err := formatter(stepConfig.Config)
 	if err != nil {
-		return fmt.Errorf("failed to get JSON from config: %w", err)
+		return fmt.Errorf("failed to marshal config: %w", err)
 	}
 
-	if len(configOptions.outputFile) > 0 {
-		err := utils.FileWrite(configOptions.outputFile, []byte(myConfigJSON), 0666)
-		if err != nil {
-			return fmt.Errorf("failed to write output file %v: %w", configOptions.outputFile, err)
+	if len(configOptions.OutputFile) > 0 {
+		if err := utils.FileWrite(configOptions.OutputFile, []byte(myConfig), 0666); err != nil {
+			return fmt.Errorf("failed to write output file %v: %w", configOptions.OutputFile, err)
 		}
 		return nil
 	}
-	fmt.Println(myConfigJSON)
+	fmt.Println(myConfig)
 
 	return nil
 }
@@ -242,20 +267,20 @@ func generateConfig(utils getConfigUtils) error {
 func addConfigFlags(cmd *cobra.Command) {
 
 	// ToDo: support more output options, like https://kubernetes.io/docs/reference/kubectl/overview/#formatting-output
-	cmd.Flags().StringVar(&configOptions.output, "output", "json", "Defines the output format")
-	cmd.Flags().StringVar(&configOptions.outputFile, "outputFile", "", "Defines a file path. f set, the output will be written to the defines file")
+	cmd.Flags().StringVar(&configOptions.Output, "output", "json", "Defines the output format")
+	cmd.Flags().StringVar(&configOptions.OutputFile, "outputFile", "", "Defines a file path. f set, the output will be written to the defines file")
 
-	cmd.Flags().StringVar(&configOptions.parametersJSON, "parametersJSON", os.Getenv("PIPER_parametersJSON"), "Parameters to be considered in JSON format")
-	cmd.Flags().BoolVar(&configOptions.stageConfig, "stageConfig", false, "Defines if step stage configuration should be loaded and no step-specific config")
-	cmd.Flags().StringArrayVar(&configOptions.stageConfigAcceptedParameters, "stageConfigAcceptedParams", []string{}, "Defines the parameters used for filtering stage/general configuration when accessing stage config")
-	cmd.Flags().StringVar(&configOptions.stepMetadata, "stepMetadata", "", "Step metadata, passed as path to yaml")
-	cmd.Flags().StringVar(&configOptions.stepName, "stepName", "", "Step name, used to get step metadata if yaml path is not set")
-	cmd.Flags().BoolVar(&configOptions.contextConfig, "contextConfig", false, "Defines if step context configuration should be loaded instead of step config")
+	cmd.Flags().StringVar(&configOptions.ParametersJSON, "parametersJSON", os.Getenv("PIPER_parametersJSON"), "Parameters to be considered in JSON format")
+	cmd.Flags().BoolVar(&configOptions.StageConfig, "stageConfig", false, "Defines if step stage configuration should be loaded and no step-specific config")
+	cmd.Flags().StringArrayVar(&configOptions.StageConfigAcceptedParameters, "stageConfigAcceptedParams", []string{}, "Defines the parameters used for filtering stage/general configuration when accessing stage config")
+	cmd.Flags().StringVar(&configOptions.StepMetadata, "stepMetadata", "", "Step metadata, passed as path to yaml")
+	cmd.Flags().StringVar(&configOptions.StepName, "stepName", "", "Step name, used to get step metadata if yaml path is not set")
+	cmd.Flags().BoolVar(&configOptions.ContextConfig, "contextConfig", false, "Defines if step context configuration should be loaded instead of step config")
 
 }
 
 func defaultsAndFilters(metadata *config.StepData, stepName string) ([]io.ReadCloser, config.StepFilters, error) {
-	if configOptions.contextConfig {
+	if configOptions.ContextConfig {
 		defaults, err := metadata.GetContextDefaults(stepName)
 		if err != nil {
 			return nil, config.StepFilters{}, errors.Wrap(err, "metadata: getting context defaults failed")
diff --git a/cmd/getConfig_test.go b/cmd/getConfig_test.go
index 327a5dc57d..f2acdbf561 100644
--- a/cmd/getConfig_test.go
+++ b/cmd/getConfig_test.go
@@ -56,8 +56,8 @@ func TestConfigCommand(t *testing.T) {
 
 	t.Run("Run", func(t *testing.T) {
 		t.Run("Success case", func(t *testing.T) {
-			configOptions.openFile = configOpenFileMock
-			configOptions.stepName = "githubCreateIssue"
+			configOptions.OpenFile = configOpenFileMock
+			configOptions.StepName = "githubCreateIssue"
 			cmd.Run(cmd, []string{})
 		})
 	})
@@ -75,8 +75,8 @@ func TestDefaultsAndFilters(t *testing.T) {
 	}
 
 	t.Run("Context config", func(t *testing.T) {
-		configOptions.contextConfig = true
-		defer func() { configOptions.contextConfig = false }()
+		configOptions.ContextConfig = true
+		defer func() { configOptions.ContextConfig = false }()
 		defaults, filters, err := defaultsAndFilters(&metadata, "stepName")
 
 		assert.Equal(t, 1, len(defaults), "getting defaults failed")
diff --git a/cmd/getDefaults.go b/cmd/getDefaults.go
index 9930764fee..98b2bd998a 100644
--- a/cmd/getDefaults.go
+++ b/cmd/getDefaults.go
@@ -128,7 +128,7 @@ func generateDefaults(utils getDefaultsUtils) ([]byte, error) {
 	if len(defaultsOptions.outputFile) > 0 {
 		err := utils.FileWrite(defaultsOptions.outputFile, []byte(jsonOutput), 0666)
 		if err != nil {
-			return jsonOutput, fmt.Errorf("failed to write output file %v: %w", configOptions.outputFile, err)
+			return jsonOutput, fmt.Errorf("failed to write output file %v: %w", defaultsOptions.outputFile, err)
 		}
 		return jsonOutput, nil
 	}
diff --git a/cmd/kanikoExecute_test.go b/cmd/kanikoExecute_test.go
index 0571b4be77..b8aa6483ce 100644
--- a/cmd/kanikoExecute_test.go
+++ b/cmd/kanikoExecute_test.go
@@ -50,12 +50,12 @@ func TestRunKanikoExecute(t *testing.T) {
 
 	// required due to config resolution during build settings retrieval
 	// ToDo: proper mocking
-	openFileBak := configOptions.openFile
+	openFileBak := configOptions.OpenFile
 	defer func() {
-		configOptions.openFile = openFileBak
+		configOptions.OpenFile = openFileBak
 	}()
 
-	configOptions.openFile = configOpenFileMock
+	configOptions.OpenFile = configOpenFileMock
 
 	t.Run("success case", func(t *testing.T) {
 		config := &kanikoExecuteOptions{

From f3c70df939d2de67b4a134cc780441e004e02b7b Mon Sep 17 00:00:00 2001
From: akram8008 <900658008.akram@gmail.com>
Date: Thu, 5 Oct 2023 20:34:33 +0500
Subject: [PATCH 8/8] moved func prepareGolangPrivatePackages to pkg/golang

---
 cmd/detectExecuteScan.go      |  5 ++--
 cmd/golangBuild.go            | 22 ------------------
 cmd/whitesourceExecuteScan.go |  5 ++--
 pkg/golang/golang.go          | 43 +++++++++++++++++++++++++++++++++++
 4 files changed, 49 insertions(+), 26 deletions(-)
 create mode 100644 pkg/golang/golang.go

diff --git a/cmd/detectExecuteScan.go b/cmd/detectExecuteScan.go
index faf6a07205..eeb5099181 100644
--- a/cmd/detectExecuteScan.go
+++ b/cmd/detectExecuteScan.go
@@ -15,6 +15,7 @@ import (
 	bd "github.com/SAP/jenkins-library/pkg/blackduck"
 	"github.com/SAP/jenkins-library/pkg/command"
 	piperGithub "github.com/SAP/jenkins-library/pkg/github"
+	"github.com/SAP/jenkins-library/pkg/golang"
 	piperhttp "github.com/SAP/jenkins-library/pkg/http"
 	"github.com/SAP/jenkins-library/pkg/log"
 	"github.com/SAP/jenkins-library/pkg/maven"
@@ -139,9 +140,9 @@ func detectExecuteScan(config detectExecuteScanOptions, _ *telemetry.CustomData,
 		log.Entry().WithError(err).Warning("Failed to get GitHub client")
 	}
 
-	if config.PrivateModulesGitToken != "" {
+	if config.PrivateModules == "" && config.PrivateModulesGitToken != "" {
 		//configuring go private packages
-		if err := prepareGolangPrivatePackages(config.PrivateModules, config.PrivateModulesGitToken); err != nil {
+		if err := golang.PrepareGolangPrivatePackages("detectExecuteStep", config.PrivateModules, config.PrivateModulesGitToken); err != nil {
 			log.Entry().Warningf("couldn't set private packages for golang, error: %s", err.Error())
 		}
 	}
diff --git a/cmd/golangBuild.go b/cmd/golangBuild.go
index 22fec60ca2..8d3cf68783 100644
--- a/cmd/golangBuild.go
+++ b/cmd/golangBuild.go
@@ -600,25 +600,3 @@ func gitConfigurationForPrivateModules(privateMod string, token string, utils go
 
 	return nil
 }
-
-// prepare golang private packages for whitesource and blackduck(detectExecuteScan)
-func prepareGolangPrivatePackages(privateModules, privateModulesGitToken string) error {
-
-	goConfig := golangBuildOptions{
-		PrivateModules:         privateModules,
-		PrivateModulesGitToken: privateModulesGitToken,
-	} // only these parameters are enough to configure
-
-	utils := newGolangBuildUtils(goConfig)
-
-	goModFile, err := readGoModFile(utils) // returns nil if go.mod doesnt exist
-	if err != nil {
-		return err
-	}
-
-	if err = prepareGolangEnvironment(&goConfig, goModFile, utils); err != nil {
-		return err
-	}
-
-	return nil
-}
diff --git a/cmd/whitesourceExecuteScan.go b/cmd/whitesourceExecuteScan.go
index 65f7f68b0f..1f00d7d767 100644
--- a/cmd/whitesourceExecuteScan.go
+++ b/cmd/whitesourceExecuteScan.go
@@ -18,6 +18,7 @@ import (
 
 	"github.com/SAP/jenkins-library/pkg/command"
 	"github.com/SAP/jenkins-library/pkg/format"
+	"github.com/SAP/jenkins-library/pkg/golang"
 	"github.com/SAP/jenkins-library/pkg/log"
 	"github.com/SAP/jenkins-library/pkg/npm"
 	"github.com/SAP/jenkins-library/pkg/piperutils"
@@ -157,9 +158,9 @@ func whitesourceExecuteScan(config ScanOptions, _ *telemetry.CustomData, commonP
 }
 
 func runWhitesourceExecuteScan(ctx context.Context, config *ScanOptions, scan *ws.Scan, utils whitesourceUtils, sys whitesource, commonPipelineEnvironment *whitesourceExecuteScanCommonPipelineEnvironment, influx *whitesourceExecuteScanInflux) error {
-	if config != nil && config.PrivateModulesGitToken != "" {
+	if config != nil && config.PrivateModules != "" && config.PrivateModulesGitToken != "" {
 		//configuring go private packages
-		if err := prepareGolangPrivatePackages(config.PrivateModules, config.PrivateModulesGitToken); err != nil {
+		if err := golang.PrepareGolangPrivatePackages("WhitesourceExecuteStep", config.PrivateModules, config.PrivateModulesGitToken); err != nil {
 			log.Entry().Warningf("couldn't set private packages for golang, error: %s", err.Error())
 		}
 	}
diff --git a/pkg/golang/golang.go b/pkg/golang/golang.go
new file mode 100644
index 0000000000..8ff5d2f4df
--- /dev/null
+++ b/pkg/golang/golang.go
@@ -0,0 +1,43 @@
+package golang
+
+import (
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/SAP/jenkins-library/pkg/command"
+)
+
+type utilsBundle struct {
+	command.Command
+}
+
+// prepare golang private packages for whitesource and blackduck(detectExecuteScan)
+func PrepareGolangPrivatePackages(stepName, privateModules, privateModulesGitToken string) error {
+	utils := &utilsBundle{
+		Command: command.Command{
+			StepName: stepName,
+		},
+	}
+	os.Setenv("GOPRIVATE", privateModules)
+	err := gitConfigurationForPrivateModules(privateModules, privateModulesGitToken, utils)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func gitConfigurationForPrivateModules(privateMod string, token string, utils *utilsBundle) error {
+	privateMod = strings.ReplaceAll(privateMod, "/*", "")
+	privateMod = strings.ReplaceAll(privateMod, "*.", "")
+	modules := strings.Split(privateMod, ",")
+	for _, v := range modules {
+		authenticatedRepoURL := fmt.Sprintf("https://%s@%s", token, v)
+		repoBaseURL := fmt.Sprintf("https://%s", v)
+		err := utils.RunExecutable("git", "config", "--global", fmt.Sprintf("url.%s.insteadOf", authenticatedRepoURL), repoBaseURL)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}