From 7504a5e7e1b1d0f807ad6d9fb967840cb076442e Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Wed, 19 Nov 2025 14:55:17 +0000 Subject: [PATCH 01/12] feat: Add git-commit-history flag for Secret Detection scans --- internal/commands/scan.go | 85 ++++++++++++++++++++++++++++++++++++++ internal/params/flags.go | 4 ++ internal/wrappers/scans.go | 9 ++-- 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/internal/commands/scan.go b/internal/commands/scan.go index 9dc28ff85..d5ae4ae26 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -864,6 +864,7 @@ func scanCreateSubCommand( createScanCmd.PersistentFlags().String(commonParams.SCSRepoTokenFlag, "", "Provide a token with read permission for the repo that you are scanning (for scorecard scans)") createScanCmd.PersistentFlags().String(commonParams.SCSRepoURLFlag, "", "The URL of the repo that you are scanning with scs (for scorecard scans)") createScanCmd.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "Specify which scs engines will run (default: all licensed engines)") + createScanCmd.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagUsage) createScanCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) // Container config flags @@ -1403,6 +1404,11 @@ func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, scsLicensi if scsSecretDetectionSelected && scsSecretDetectionAllowed { scsConfig.Twoms = trueString + + // Set git commit history if enabled and all validations pass + if shouldEnableGitCommitHistory(cmd) { + scsConfig.GitCommitHistory = trueString + } } isScsEnginesFlagSet := scsEngines != "" @@ -3466,6 +3472,13 @@ func validateCreateScanFlags(cmd *cobra.Command) error { } } } + + // Validate git-commit-history flag + err = validateGitCommitHistoryFlag(cmd) + if err != nil { + return err + } + return nil } @@ -3729,6 +3742,78 @@ func validateBooleanString(value string) error { return nil } +// validateGitCommitHistoryFlag validates the git-commit-history flag (needed for Secret Detection) +func validateGitCommitHistoryFlag(cmd *cobra.Command) error { + gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag) + + err := validateBooleanString(gitCommitHistory) + if err != nil { + return errors.Errorf("Invalid value for --git-commit-history. Use 'true' or 'false'.") + } + + return nil +} + +// shouldEnableGitCommitHistory checks if the git-commit-history flag should be enabled +func shouldEnableGitCommitHistory(cmd *cobra.Command) bool { + gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag) + + // If flag is not set to true, return false + if strings.ToLower(strings.TrimSpace(gitCommitHistory)) != trueString { + return false + } + + userScanTypes, _ := cmd.Flags().GetString(commonParams.ScanTypes) + if !strings.Contains(strings.ToLower(userScanTypes), commonParams.ScsType) { + fmt.Println("Warning: '--git-commit-history' was provided, but SCS is not selected. Ignoring this flag.") + return false + } + + // Check if only scorecard is enabled (no secret detection) + scsEngines, _ := cmd.Flags().GetString(commonParams.SCSEnginesFlag) + scsScoreCardSelected, scsSecretDetectionSelected := getSCSEnginesSelected(scsEngines) + if scsScoreCardSelected && !scsSecretDetectionSelected { + fmt.Println("Warning: Commit History applies only to Secret Detection. The flag will be ignored.") + return false + } + + // Check if there's a git repository context + source, _ := cmd.Flags().GetString(commonParams.SourcesFlag) + + hasGitContext := false + + // Check if source directory has .git folder (in root or subdirectories) + if source != "" && !hasGitContext { + sourceTrimmed := strings.TrimSpace(source) + info, statErr := os.Stat(sourceTrimmed) + if statErr == nil && info != nil && info.IsDir() { + gitPath := filepath.Join(sourceTrimmed, ".git") + if _, err := os.Stat(gitPath); err == nil { + hasGitContext = true + } else { + // If not found in root, search subdirectories + _ = filepath.Walk(sourceTrimmed, func(path string, info os.FileInfo, err error) error { + if err != nil || hasGitContext { + return nil + } + if info.IsDir() && info.Name() == ".git" { + hasGitContext = true + return filepath.SkipAll + } + return nil + }) + } + } + } + + if !hasGitContext { + fmt.Println("Warning: No Git history found. Secret Detection will scan the working tree only.") + return false + } + + return true +} + func parseArgs(input string) []string { var args []string var current strings.Builder diff --git a/internal/params/flags.go b/internal/params/flags.go index 2eb507d52..04af5d967 100644 --- a/internal/params/flags.go +++ b/internal/params/flags.go @@ -237,6 +237,10 @@ const ( SCSRepoTokenFlag = "scs-repo-token" SCSRepoURLFlag = "scs-repo-url" + // Secret Detection Git Commit History + GitCommitHistoryFlag = "git-commit-history" + GitCommitHistoryFlagUsage = "Enable or disable commit history scan for Secret Detection (default: false)" + // Containers Config Flags ContainersFileFolderFilterFlag = "containers-file-folder-filter" ContainersImageTagFilterFlag = "containers-image-tag-filter" diff --git a/internal/wrappers/scans.go b/internal/wrappers/scans.go index b1dc5a028..71c878a0b 100644 --- a/internal/wrappers/scans.go +++ b/internal/wrappers/scans.go @@ -157,8 +157,9 @@ type APISecConfig struct { } type SCSConfig struct { - Twoms string `json:"2ms,omitempty"` - Scorecard string `json:"scorecard,omitempty"` - RepoURL string `json:"repoUrl,omitempty"` - RepoToken string `json:"repoToken,omitempty"` + Twoms string `json:"2ms,omitempty"` + Scorecard string `json:"scorecard,omitempty"` + RepoURL string `json:"repoUrl,omitempty"` + RepoToken string `json:"repoToken,omitempty"` + GitCommitHistory string `json:"gitCommitHistory,omitempty"` } From 00789f3ab8a9eab579f02d4380dfd720bc3c4a7c Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Wed, 19 Nov 2025 14:56:13 +0000 Subject: [PATCH 02/12] test: add UTs for flag validation and enabling logic --- internal/commands/scan_test.go | 182 +++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 3062da8ba..5b4e45c7f 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -4249,3 +4249,185 @@ func TestEnforceLocalResolutionForTarFiles_Integration(t *testing.T) { }) } } + +func TestValidateGitCommitHistoryFlag(t *testing.T) { + tests := []struct { + name string + flagValue string + expectedErrorMsg string + }{ + { + name: "Valid true value", + flagValue: "true", + }, + { + name: "Valid false value", + flagValue: "false", + }, + { + name: "Valid TRUE value (case insensitive)", + flagValue: "TRUE", + }, + { + name: "Valid FALSE value (case insensitive)", + flagValue: "FALSE", + }, + { + name: "Invalid value 'maybe'", + flagValue: "maybe", + expectedErrorMsg: "Invalid value for --git-commit-history. Use 'true' or 'false'.", + }, + { + name: "Empty value", + flagValue: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmdCommand := &cobra.Command{} + cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagUsage) + _ = cmdCommand.Flags().Set(commonParams.GitCommitHistoryFlag, tt.flagValue) + + err := validateGitCommitHistoryFlag(cmdCommand) + if err != nil { + assert.Assert(t, err.Error() == tt.expectedErrorMsg, "Expected error: %v, got: %v", tt.expectedErrorMsg, err) + } else { + assert.NilError(t, err, "Expected no error, got: %v", err) + } + }) + } +} + +func TestShouldEnableGitCommitHistory(t *testing.T) { + // Create a temporary directory with .git for testing + tempDir := t.TempDir() + gitDir := filepath.Join(tempDir, ".git") + _ = os.Mkdir(gitDir, 0755) + + // Create a directory without .git + tempDirNoGit := t.TempDir() + + // Create a directory with .git in a subdirectory + tempDirWithSubGit := t.TempDir() + subDir := filepath.Join(tempDirWithSubGit, "project1") + _ = os.Mkdir(subDir, 0755) + gitDirSub := filepath.Join(subDir, ".git") + _ = os.Mkdir(gitDirSub, 0755) + + tests := []struct { + name string + flagValue string + scanTypes string + scsEngines string + source string + expectEnabled bool + expectWarnings []string + }{ + { + name: "Flag set to false - disabled", + flagValue: "false", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDir, + expectEnabled: false, + }, + { + name: "Flag set to true with SCS not in scan types - warning and disabled", + flagValue: "true", + scanTypes: "sast", + scsEngines: "secret-detection", + source: tempDir, + expectEnabled: false, + expectWarnings: []string{"--git-commit-history' was provided, but SCS is not selected"}, + }, + { + name: "Flag set to true with only scorecard - warning and disabled", + flagValue: "true", + scanTypes: "scs", + scsEngines: "scorecard", + source: tempDir, + expectEnabled: false, + expectWarnings: []string{"Commit History applies only to Secret Detection"}, + }, + { + name: "Flag set to true without git context - warning and disabled", + flagValue: "true", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDirNoGit, + expectEnabled: false, + expectWarnings: []string{"No Git history found"}, + }, + { + name: "Flag set to true with git context (directory) - enabled", + flagValue: "true", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDir, + expectEnabled: true, + }, + { + name: "Flag set to true with git in subdirectory - enabled", + flagValue: "true", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDirWithSubGit, + expectEnabled: true, + }, + { + name: "Flag set to true with both secret-detection and scorecard - enabled", + flagValue: "true", + scanTypes: "scs", + scsEngines: "secret-detection,scorecard", + source: tempDir, + expectEnabled: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create command with flags + cmdCommand := &cobra.Command{ + Use: "scan", + Short: "Scan a project with git commit history", + } + cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagUsage) + cmdCommand.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") + cmdCommand.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "SCS engines") + cmdCommand.PersistentFlags().String(commonParams.SourcesFlag, "", "Sources") + + _ = cmdCommand.Execute() + + _ = cmdCommand.Flags().Set(commonParams.GitCommitHistoryFlag, tt.flagValue) + _ = cmdCommand.Flags().Set(commonParams.ScanTypes, tt.scanTypes) + _ = cmdCommand.Flags().Set(commonParams.SCSEnginesFlag, tt.scsEngines) + _ = cmdCommand.Flags().Set(commonParams.SourcesFlag, tt.source) + + // Capture output for warnings (fmt.Println goes to stdout) + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + result := shouldEnableGitCommitHistory(cmdCommand) + + w.Close() + os.Stdout = oldStdout + + // Read captured output + var buf bytes.Buffer + _, _ = io.Copy(&buf, r) + r.Close() + output := buf.String() + + // Check result + assert.Equal(t, tt.expectEnabled, result, "Expected enabled=%v, got=%v", tt.expectEnabled, result) + + // Check warnings + for _, expectedWarning := range tt.expectWarnings { + assert.Assert(t, strings.Contains(output, expectedWarning), + "Expected warning containing '%s' not found in output: %s", expectedWarning, output) + } + }) + } +} From 87ae9d56f77de85450ab57f086c39bf2bbd4d9ba Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:37:49 +0000 Subject: [PATCH 03/12] refactor: update git-commit-history flag description for clarity --- internal/commands/scan.go | 2 +- internal/commands/scan_test.go | 4 ++-- internal/params/flags.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/commands/scan.go b/internal/commands/scan.go index d5ae4ae26..210656a45 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -864,7 +864,7 @@ func scanCreateSubCommand( createScanCmd.PersistentFlags().String(commonParams.SCSRepoTokenFlag, "", "Provide a token with read permission for the repo that you are scanning (for scorecard scans)") createScanCmd.PersistentFlags().String(commonParams.SCSRepoURLFlag, "", "The URL of the repo that you are scanning with scs (for scorecard scans)") createScanCmd.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "Specify which scs engines will run (default: all licensed engines)") - createScanCmd.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagUsage) + createScanCmd.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagDescription) createScanCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) // Container config flags diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 5b4e45c7f..74e6b8ee6 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -4286,7 +4286,7 @@ func TestValidateGitCommitHistoryFlag(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cmdCommand := &cobra.Command{} - cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagUsage) + cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagDescription) _ = cmdCommand.Flags().Set(commonParams.GitCommitHistoryFlag, tt.flagValue) err := validateGitCommitHistoryFlag(cmdCommand) @@ -4392,7 +4392,7 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { Use: "scan", Short: "Scan a project with git commit history", } - cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagUsage) + cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagDescription) cmdCommand.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") cmdCommand.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "SCS engines") cmdCommand.PersistentFlags().String(commonParams.SourcesFlag, "", "Sources") diff --git a/internal/params/flags.go b/internal/params/flags.go index 04af5d967..02f5fc55a 100644 --- a/internal/params/flags.go +++ b/internal/params/flags.go @@ -238,8 +238,8 @@ const ( SCSRepoURLFlag = "scs-repo-url" // Secret Detection Git Commit History - GitCommitHistoryFlag = "git-commit-history" - GitCommitHistoryFlagUsage = "Enable or disable commit history scan for Secret Detection (default: false)" + GitCommitHistoryFlag = "git-commit-history" + GitCommitHistoryFlagDescription = "Enable or disable commit history scan for Secret Detection" // Containers Config Flags ContainersFileFolderFilterFlag = "containers-file-folder-filter" From c7f6bd4c5fef4ce855e762d5638bfc8816cfa439 Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:49:33 +0000 Subject: [PATCH 04/12] refactor: reduce cyclomatic complexity --- internal/commands/scan.go | 63 +++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/internal/commands/scan.go b/internal/commands/scan.go index 210656a45..14cdc5f5e 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -3779,39 +3779,50 @@ func shouldEnableGitCommitHistory(cmd *cobra.Command) bool { // Check if there's a git repository context source, _ := cmd.Flags().GetString(commonParams.SourcesFlag) + if !hasGitRepository(source) { + fmt.Println("Warning: No Git history found. Secret Detection will scan the working tree only.") + return false + } - hasGitContext := false + return true +} - // Check if source directory has .git folder (in root or subdirectories) - if source != "" && !hasGitContext { - sourceTrimmed := strings.TrimSpace(source) - info, statErr := os.Stat(sourceTrimmed) - if statErr == nil && info != nil && info.IsDir() { - gitPath := filepath.Join(sourceTrimmed, ".git") - if _, err := os.Stat(gitPath); err == nil { - hasGitContext = true - } else { - // If not found in root, search subdirectories - _ = filepath.Walk(sourceTrimmed, func(path string, info os.FileInfo, err error) error { - if err != nil || hasGitContext { - return nil - } - if info.IsDir() && info.Name() == ".git" { - hasGitContext = true - return filepath.SkipAll - } - return nil - }) - } - } +// hasGitRepository checks if the source directory contains a Git repository +func hasGitRepository(source string) bool { + if source == "" { + return false } - if !hasGitContext { - fmt.Println("Warning: No Git history found. Secret Detection will scan the working tree only.") + sourceTrimmed := strings.TrimSpace(source) + info, err := os.Stat(sourceTrimmed) + if err != nil || !info.IsDir() { return false } - return true + // Check if .git exists in the root directory + gitPath := filepath.Join(sourceTrimmed, ".git") + if _, err := os.Stat(gitPath); err == nil { + return true + } + + // fallback: search for .git in subdirectories + return searchGitInSubdirectories(sourceTrimmed) +} + +// searchGitInSubdirectories walks through subdirectories to find a .git folder +func searchGitInSubdirectories(sourcePath string) bool { + found := false + _ = filepath.Walk(sourcePath, func(path string, info os.FileInfo, err error) error { + if err != nil || found { + return nil + } + if info.IsDir() && info.Name() == ".git" { + found = true + return filepath.SkipAll + } + return nil + }) + return found } func parseArgs(input string) []string { From f19cf797bd3bcd70f6321f417713b54db99edd0c Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:46:31 +0000 Subject: [PATCH 05/12] refactor: enhance functionality with feature flag integration for commit history --- internal/commands/scan.go | 24 +++++++++++++++--------- internal/wrappers/feature-flags.go | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/internal/commands/scan.go b/internal/commands/scan.go index 14cdc5f5e..ec523655f 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -991,9 +991,8 @@ func setupScanTypeProjectAndConfig( configArr = append(configArr, containersConfig) } - scsLicensingV2Flag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.ScsLicensingV2Enabled) - var SCSConfig, scsErr = addSCSScan(cmd, resubmitConfig, scsLicensingV2Flag.Status, userAllowedEngines[commonParams.RepositoryHealthType], - userAllowedEngines[commonParams.SecretDetectionType], userAllowedEngines[commonParams.EnterpriseSecretsType]) + var SCSConfig, scsErr = addSCSScan(cmd, resubmitConfig, userAllowedEngines[commonParams.RepositoryHealthType], + userAllowedEngines[commonParams.SecretDetectionType], userAllowedEngines[commonParams.EnterpriseSecretsType], featureFlagsWrapper) if scsErr != nil { return scsErr } else if SCSConfig != nil { @@ -1369,11 +1368,12 @@ func isScorecardRunnable(isScsEnginesFlagSet, scsScorecardSelected bool, scsRepo return isURLSupportedByScorecard(scsRepoURL), nil } -func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, scsLicensingV2, hasRepositoryHealthLicense, - hasSecretDetectionLicense, hasEnterpriseSecretsLicense bool) (map[string]interface{}, error) { +func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, hasRepositoryHealthLicense, + hasSecretDetectionLicense, hasEnterpriseSecretsLicense bool, featureFlagsWrapper wrappers.FeatureFlagsWrapper) (map[string]interface{}, error) { scsEnabled := scanTypeEnabled(commonParams.ScsType) - scsScorecardAllowed := isScsScorecardAllowed(scsLicensingV2, hasRepositoryHealthLicense, scsEnabled) - scsSecretDetectionAllowed := isScsSecretDetectionAllowed(scsLicensingV2, hasSecretDetectionLicense, hasEnterpriseSecretsLicense, scsEnabled) + scsLicensingV2Flag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.ScsLicensingV2Enabled) + scsScorecardAllowed := isScsScorecardAllowed(scsLicensingV2Flag.Status, hasRepositoryHealthLicense, scsEnabled) + scsSecretDetectionAllowed := isScsSecretDetectionAllowed(scsLicensingV2Flag.Status, hasSecretDetectionLicense, hasEnterpriseSecretsLicense, scsEnabled) if !scsScorecardAllowed && !scsSecretDetectionAllowed { return nil, nil } @@ -1406,7 +1406,8 @@ func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, scsLicensi scsConfig.Twoms = trueString // Set git commit history if enabled and all validations pass - if shouldEnableGitCommitHistory(cmd) { + commitHistoryFlag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.SscsCommitHistoryEnabled) + if shouldEnableGitCommitHistory(cmd, commitHistoryFlag.Status) { scsConfig.GitCommitHistory = trueString } } @@ -3755,7 +3756,12 @@ func validateGitCommitHistoryFlag(cmd *cobra.Command) error { } // shouldEnableGitCommitHistory checks if the git-commit-history flag should be enabled -func shouldEnableGitCommitHistory(cmd *cobra.Command) bool { +func shouldEnableGitCommitHistory(cmd *cobra.Command, commitHistoryFlag bool) bool { + if !commitHistoryFlag { + fmt.Println("Warning: Git commit history scanning is not available. The flag will be ignored.") + return false + } + gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag) // If flag is not set to true, return false diff --git a/internal/wrappers/feature-flags.go b/internal/wrappers/feature-flags.go index 8f92b8cef..a3f85152e 100644 --- a/internal/wrappers/feature-flags.go +++ b/internal/wrappers/feature-flags.go @@ -15,6 +15,7 @@ const SastCustomStateEnabled = "SAST_CUSTOM_STATES_ENABLED" const RiskManagementEnabled = "RISK_MANAGEMENT_IDES_PROJECT_RESULTS_SCORES_API_ENABLED" const OssRealtimeEnabled = "OSS_REALTIME_ENABLED" const ScsLicensingV2Enabled = "SSCS_NEW_LICENSING_ENABLED" +const SscsCommitHistoryEnabled = "SSCS_COMMIT_HISTORY_ENABLED" const DirectAssociationEnabled = "DIRECT_APP_ASSOCIATION_ENABLED" const maxRetries = 3 From 8f1624c1e46b9a3462d40719bf7705abe5c11c53 Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:59:08 +0000 Subject: [PATCH 06/12] test: add and update UTs considering commit history FF --- internal/commands/scan_test.go | 270 ++++++++++++++++--- internal/wrappers/mock/feature-flags-mock.go | 15 ++ 2 files changed, 249 insertions(+), 36 deletions(-) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 74e6b8ee6..17de84155 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -832,6 +832,7 @@ func TestAddSCSScan_ResubmitWithoutScorecardFlags_ShouldPass(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() cmdCommand := &cobra.Command{ Use: "scan", Short: "Scan a project", @@ -856,8 +857,14 @@ func TestAddSCSScan_ResubmitWithoutScorecardFlags_ShouldPass(t *testing.T) { }, } - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) expectedConfig := wrappers.SCSConfig{ Twoms: trueString, @@ -901,6 +908,7 @@ func TestAddSCSScan_ResubmitWithScorecardFlags_ShouldPass(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() cmdCommand := &cobra.Command{ Use: "scan", Short: "Scan a project", @@ -925,8 +933,14 @@ func TestAddSCSScan_ResubmitWithScorecardFlags_ShouldPass(t *testing.T) { }, } - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) expectedConfig := wrappers.SCSConfig{ Twoms: "true", @@ -1185,6 +1199,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecard_scsMapHasBoth(t *testing. for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1199,8 +1214,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecard_scsMapHasBoth(t *testing. _ = cmdCommand.Flags().Set(commonParams.SCSRepoTokenFlag, dummyToken) _ = cmdCommand.Flags().Set(commonParams.SCSRepoURLFlag, dummyRepo) - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) scsConfig := wrappers.SCSConfig{ Twoms: "true", @@ -1245,6 +1266,7 @@ func TestAddSCSScan_WithoutSCSSecretDetection_scsMapNoSecretDetection(t *testing for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1259,8 +1281,14 @@ func TestAddSCSScan_WithoutSCSSecretDetection_scsMapNoSecretDetection(t *testing _ = cmdCommand.Flags().Set(commonParams.SCSRepoTokenFlag, dummyToken) _ = cmdCommand.Flags().Set(commonParams.SCSRepoURLFlag, dummyRepo) - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) scsConfig := wrappers.SCSConfig{ Twoms: "", @@ -1305,6 +1333,7 @@ func TestAddSCSScan_WithSCSSecretDetection_scsMapHasSecretDetection(t *testing.T for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1315,8 +1344,14 @@ func TestAddSCSScan_WithSCSSecretDetection_scsMapHasSecretDetection(t *testing.T _ = cmdCommand.Execute() _ = cmdCommand.Flags().Set(commonParams.SCSEnginesFlag, "secret-detection") - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) scsConfig := wrappers.SCSConfig{ Twoms: "true", @@ -1332,6 +1367,88 @@ func TestAddSCSScan_WithSCSSecretDetection_scsMapHasSecretDetection(t *testing.T } } +func TestAddSCSScan_WithSCSSecretDetectionAndGitCommitHistoryFlag_scsMapHasSecretDetection(t *testing.T) { + tests := []struct { + name string + scsLicensingV2 bool + hasRepositoryHealthLicense bool + hasSecretDetectionLicense bool + hasEnterpriseSecretsLicense bool + }{ + { + name: "scsLicensingV2 disabled", + scsLicensingV2: false, + hasRepositoryHealthLicense: false, + hasSecretDetectionLicense: false, + hasEnterpriseSecretsLicense: true, + }, + { + name: "scsLicensingV2 enabled", + scsLicensingV2: true, + hasRepositoryHealthLicense: true, + hasSecretDetectionLicense: true, + hasEnterpriseSecretsLicense: false, + }, + } + + // Create a temporary directory with .git for testing + tempDir := t.TempDir() + gitDir := filepath.Join(tempDir, ".git") + _ = os.Mkdir(gitDir, 0755) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() + var resubmitConfig []wrappers.Config + cmdCommand := &cobra.Command{ + Use: "scan", + Short: "Scan a project", + Long: `Scan a project`, + } + cmdCommand.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "SCS Engine flag") + cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagDescription) + cmdCommand.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") + cmdCommand.PersistentFlags().String(commonParams.SourcesFlag, "", "Sources") + + _ = cmdCommand.Execute() + _ = cmdCommand.Flags().Set(commonParams.SCSEnginesFlag, "secret-detection") + _ = cmdCommand.Flags().Set(commonParams.GitCommitHistoryFlag, "true") + _ = cmdCommand.Flags().Set(commonParams.ScanTypes, "scs") + _ = cmdCommand.Flags().Set(commonParams.SourcesFlag, tempDir) + + mock.Flags = wrappers.FeatureFlagsResponseModel{ + { + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + }, + { + Name: wrappers.SscsCommitHistoryEnabled, + Status: true, + }, + } + defer func() { + mock.Flags = wrappers.FeatureFlagsResponseModel{} + }() + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) + + scsConfig := wrappers.SCSConfig{ + Twoms: "true", + GitCommitHistory: "true", + } + scsMapConfig := make(map[string]interface{}) + scsMapConfig[resultsMapType] = commonParams.MicroEnginesType + scsMapConfig[resultsMapValue] = &scsConfig + + if !reflect.DeepEqual(result, scsMapConfig) { + t.Errorf("Expected %+v, but got %+v", scsMapConfig, result) + } + }) + } +} + func TestAddSCSScan_WithSCSSecretDetectionAndScorecardWithScanTypesAndNoScorecardFlags_scsMapHasSecretDetection(t *testing.T) { tests := []struct { name string @@ -1358,6 +1475,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardWithScanTypesAndNoScorecar for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1374,8 +1492,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardWithScanTypesAndNoScorecar _ = cmdCommand.Execute() _ = cmdCommand.Flags().Set(commonParams.ScanTypeFlag, "scs") - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) scsConfig := wrappers.SCSConfig{ Twoms: "true", @@ -1433,6 +1557,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndWithoutScanTypes_scsMapHasSecretDet for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1440,8 +1565,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndWithoutScanTypes_scsMapHasSecretDet Long: `Scan a project`, } - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) scsConfig := wrappers.SCSConfig{ Twoms: "true", @@ -1484,6 +1615,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepo_scsMap for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1504,8 +1636,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepo_scsMap _ = cmdCommand.Flags().Set(commonParams.SCSRepoTokenFlag, dummyToken) _ = cmdCommand.Flags().Set(commonParams.SCSRepoURLFlag, dummyShortenedGithubRepo) - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) // Close the writer to signal that we are done capturing the output w.Close() @@ -1565,6 +1703,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1585,8 +1724,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok _ = cmdCommand.Flags().Set(commonParams.SCSRepoTokenFlag, dummyToken) _ = cmdCommand.Flags().Set(commonParams.SCSRepoURLFlag, dummyShortenedRepoWithToken) - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) // Close the writer to signal that we are done capturing the output w.Close() @@ -1646,6 +1791,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenInURL_s for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1666,8 +1812,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenInURL_s _ = cmdCommand.Flags().Set(commonParams.SCSRepoTokenFlag, dummyToken) _ = cmdCommand.Flags().Set(commonParams.SCSRepoURLFlag, dummyRepoWithToken) - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) // Close the writer to signal that we are done capturing the output w.Close() @@ -1726,6 +1878,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenAndUser } for _, tt := range tests { + wrappers.ClearCache() t.Run(tt.name, func(t *testing.T) { // Create a pipe for capturing stdout r, w, _ := os.Pipe() @@ -1747,8 +1900,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenAndUser _ = cmdCommand.Flags().Set(commonParams.SCSRepoTokenFlag, dummyToken) _ = cmdCommand.Flags().Set(commonParams.SCSRepoURLFlag, dummyRepoWithTokenAndUsername) - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) // Close the writer to signal that we are done capturing the output w.Close() @@ -1807,6 +1966,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok } for _, tt := range tests { + wrappers.ClearCache() t.Run(tt.name, func(t *testing.T) { // Create a pipe for capturing stdout r, w, _ := os.Pipe() @@ -1828,8 +1988,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok _ = cmdCommand.Flags().Set(commonParams.SCSRepoTokenFlag, dummyToken) _ = cmdCommand.Flags().Set(commonParams.SCSRepoURLFlag, dummyShortenedRepoWithTokenAndUsername) - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) // Close the writer to signal that we are done capturing the output w.Close() @@ -1888,6 +2054,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitLabRepo_scsMapHasSecret } for _, tt := range tests { + wrappers.ClearCache() t.Run(tt.name, func(t *testing.T) { // Create a pipe for capturing stdout r, w, _ := os.Pipe() @@ -1909,8 +2076,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitLabRepo_scsMapHasSecret _ = cmdCommand.Flags().Set(commonParams.SCSRepoTokenFlag, dummyToken) _ = cmdCommand.Flags().Set(commonParams.SCSRepoURLFlag, dummyGitlabRepo) - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) // Close the writer to signal that we are done capturing the output w.Close() @@ -1970,6 +2143,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitSSHRepo_scsMapHasSecret for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1990,8 +2164,14 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitSSHRepo_scsMapHasSecret _ = cmdCommand.Flags().Set(commonParams.SCSRepoTokenFlag, dummyToken) _ = cmdCommand.Flags().Set(commonParams.SCSRepoURLFlag, dummySSHRepo) - result, _ := addSCSScan(cmdCommand, resubmitConfig, tt.scsLicensingV2, - tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense) + mock.Flag = wrappers.FeatureFlagResponseModel{ + Name: wrappers.ScsLicensingV2Enabled, + Status: tt.scsLicensingV2, + } + + featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} + result, _ := addSCSScan(cmdCommand, resubmitConfig, + tt.hasRepositoryHealthLicense, tt.hasSecretDetectionLicense, tt.hasEnterpriseSecretsLicense, featureFlagsWrapper) // Close the writer to signal that we are done capturing the output w.Close() @@ -4322,8 +4502,19 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { scsEngines string source string expectEnabled bool - expectWarnings []string + expectWarnings string + ffEnabled bool }{ + { + name: "Feature flag disabled - disabled", + flagValue: "true", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDir, + expectEnabled: false, + expectWarnings: "Git commit history scanning is not available", + ffEnabled: false, + }, { name: "Flag set to false - disabled", flagValue: "false", @@ -4331,6 +4522,7 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { scsEngines: "secret-detection", source: tempDir, expectEnabled: false, + ffEnabled: true, }, { name: "Flag set to true with SCS not in scan types - warning and disabled", @@ -4339,7 +4531,8 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { scsEngines: "secret-detection", source: tempDir, expectEnabled: false, - expectWarnings: []string{"--git-commit-history' was provided, but SCS is not selected"}, + expectWarnings: "--git-commit-history' was provided, but SCS is not selected", + ffEnabled: true, }, { name: "Flag set to true with only scorecard - warning and disabled", @@ -4348,7 +4541,8 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { scsEngines: "scorecard", source: tempDir, expectEnabled: false, - expectWarnings: []string{"Commit History applies only to Secret Detection"}, + expectWarnings: "Commit History applies only to Secret Detection", + ffEnabled: true, }, { name: "Flag set to true without git context - warning and disabled", @@ -4357,7 +4551,8 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { scsEngines: "secret-detection", source: tempDirNoGit, expectEnabled: false, - expectWarnings: []string{"No Git history found"}, + expectWarnings: "No Git history found", + ffEnabled: true, }, { name: "Flag set to true with git context (directory) - enabled", @@ -4366,6 +4561,7 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { scsEngines: "secret-detection", source: tempDir, expectEnabled: true, + ffEnabled: true, }, { name: "Flag set to true with git in subdirectory - enabled", @@ -4374,6 +4570,7 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { scsEngines: "secret-detection", source: tempDirWithSubGit, expectEnabled: true, + ffEnabled: true, }, { name: "Flag set to true with both secret-detection and scorecard - enabled", @@ -4382,6 +4579,7 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { scsEngines: "secret-detection,scorecard", source: tempDir, expectEnabled: true, + ffEnabled: true, }, } @@ -4409,7 +4607,7 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { r, w, _ := os.Pipe() os.Stdout = w - result := shouldEnableGitCommitHistory(cmdCommand) + result := shouldEnableGitCommitHistory(cmdCommand, tt.ffEnabled) w.Close() os.Stdout = oldStdout @@ -4424,9 +4622,9 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { assert.Equal(t, tt.expectEnabled, result, "Expected enabled=%v, got=%v", tt.expectEnabled, result) // Check warnings - for _, expectedWarning := range tt.expectWarnings { - assert.Assert(t, strings.Contains(output, expectedWarning), - "Expected warning containing '%s' not found in output: %s", expectedWarning, output) + if tt.expectWarnings != "" { + assert.Assert(t, strings.Contains(output, tt.expectWarnings), + "Expected warning containing '%s' not found in output: %s", tt.expectWarnings, output) } }) } diff --git a/internal/wrappers/mock/feature-flags-mock.go b/internal/wrappers/mock/feature-flags-mock.go index 44eb85db3..b292821b8 100644 --- a/internal/wrappers/mock/feature-flags-mock.go +++ b/internal/wrappers/mock/feature-flags-mock.go @@ -27,6 +27,21 @@ func (f FeatureFlagsMockWrapper) GetSpecificFlag(specificFlag string) (*wrappers fmt.Println(FFErr) return nil, FFErr } + + // If Flags (plural) is set, search for the specific flag by name + if len(Flags) > 0 { + for _, flag := range Flags { + if flag.Name == specificFlag { + fmt.Println("Returning flag from Flags collection:", flag.Status, "for flag name:", flag.Name) + return &wrappers.FeatureFlagResponseModel{Name: flag.Name, Status: flag.Status}, nil + } + } + // If flag not found in collection, return default (false) + fmt.Println("Flag not found in Flags collection, returning default (false) for flag:", specificFlag) + return &wrappers.FeatureFlagResponseModel{Name: specificFlag, Status: false}, nil + } + + // Otherwise, return the single Flag (backward compatibility) fmt.Println("Returning flag:", Flag.Status, "for flag name:", Flag.Name) return &Flag, nil } From e9a647c1e26c38ff58ad4ba58a5f44dcd6120016 Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Thu, 20 Nov 2025 10:45:05 +0000 Subject: [PATCH 07/12] test: add clearFlags() calls for consistency --- internal/commands/groups_test.go | 5 +++++ internal/commands/scan_test.go | 20 +------------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/internal/commands/groups_test.go b/internal/commands/groups_test.go index 4b507908b..5e5d2d65e 100644 --- a/internal/commands/groups_test.go +++ b/internal/commands/groups_test.go @@ -9,6 +9,7 @@ import ( func TestCreateScanAndProjectWithGroupFFTrue(t *testing.T) { mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: true}} + defer clearFlags() execCmdNilAssertion( t, "scan", "create", "--project-name", "new-project", "-b", "dummy_branch", "-s", ".", "--project-groups", "group", @@ -17,6 +18,7 @@ func TestCreateScanAndProjectWithGroupFFTrue(t *testing.T) { func TestCreateScanAndProjectWithGroupFFFalse(t *testing.T) { mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: false}} + defer clearFlags() execCmdNilAssertion( t, "scan", "create", "--project-name", "new-project", "-b", "dummy_branch", "-s", ".", "--project-groups", "group", @@ -24,6 +26,7 @@ func TestCreateScanAndProjectWithGroupFFFalse(t *testing.T) { } func TestCreateProjectWithGroupFFTrue(t *testing.T) { mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: true}} + defer clearFlags() execCmdNilAssertion( t, "project", "create", "--project-name", "new-project", "--groups", "group", ) @@ -31,6 +34,7 @@ func TestCreateProjectWithGroupFFTrue(t *testing.T) { func TestCreateProjectWithGroupFFFalse(t *testing.T) { mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: false}} + defer clearFlags() execCmdNilAssertion( t, "project", "create", "--project-name", "new-project", "--groups", "group", @@ -39,6 +43,7 @@ func TestCreateProjectWithGroupFFFalse(t *testing.T) { func TestCreateScanForExistingProjectWithGroupFFTrue(t *testing.T) { mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: true}} + defer clearFlags() execCmdNilAssertion( t, "scan", "create", "--project-name", "MOCK", "-b", "dummy_branch", "-s", ".", "--project-groups", "group", diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 17de84155..cc265d71c 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -832,7 +832,6 @@ func TestAddSCSScan_ResubmitWithoutScorecardFlags_ShouldPass(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() cmdCommand := &cobra.Command{ Use: "scan", Short: "Scan a project", @@ -908,7 +907,6 @@ func TestAddSCSScan_ResubmitWithScorecardFlags_ShouldPass(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() cmdCommand := &cobra.Command{ Use: "scan", Short: "Scan a project", @@ -1199,7 +1197,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecard_scsMapHasBoth(t *testing. for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1266,7 +1263,6 @@ func TestAddSCSScan_WithoutSCSSecretDetection_scsMapNoSecretDetection(t *testing for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1333,7 +1329,6 @@ func TestAddSCSScan_WithSCSSecretDetection_scsMapHasSecretDetection(t *testing.T for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1398,7 +1393,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndGitCommitHistoryFlag_scsMapHasSecre for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1426,9 +1420,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndGitCommitHistoryFlag_scsMapHasSecre Status: true, }, } - defer func() { - mock.Flags = wrappers.FeatureFlagsResponseModel{} - }() + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1475,7 +1467,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardWithScanTypesAndNoScorecar for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1557,7 +1548,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndWithoutScanTypes_scsMapHasSecretDet for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1615,7 +1605,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepo_scsMap for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1703,7 +1692,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1791,7 +1779,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenInURL_s for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1878,7 +1865,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenAndUser } for _, tt := range tests { - wrappers.ClearCache() t.Run(tt.name, func(t *testing.T) { // Create a pipe for capturing stdout r, w, _ := os.Pipe() @@ -1966,7 +1952,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok } for _, tt := range tests { - wrappers.ClearCache() t.Run(tt.name, func(t *testing.T) { // Create a pipe for capturing stdout r, w, _ := os.Pipe() @@ -2054,7 +2039,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitLabRepo_scsMapHasSecret } for _, tt := range tests { - wrappers.ClearCache() t.Run(tt.name, func(t *testing.T) { // Create a pipe for capturing stdout r, w, _ := os.Pipe() @@ -2143,7 +2127,6 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitSSHRepo_scsMapHasSecret for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -3553,7 +3536,6 @@ func TestValidateScanTypes(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - wrappers.ClearCache() mock.Flag = wrappers.FeatureFlagResponseModel{ Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, From 885dc30871bb821eb9debd2ce109f3f4ab4aa317 Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Thu, 20 Nov 2025 15:10:45 +0000 Subject: [PATCH 08/12] test: add wrappers.ClearCache() calls to clear cache --- internal/commands/scan_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 15770507b..77d8e0e62 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -832,6 +832,7 @@ func TestAddSCSScan_ResubmitWithoutScorecardFlags_ShouldPass(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() cmdCommand := &cobra.Command{ Use: "scan", Short: "Scan a project", @@ -907,6 +908,7 @@ func TestAddSCSScan_ResubmitWithScorecardFlags_ShouldPass(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() cmdCommand := &cobra.Command{ Use: "scan", Short: "Scan a project", @@ -1197,6 +1199,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecard_scsMapHasBoth(t *testing. for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1263,6 +1266,7 @@ func TestAddSCSScan_WithoutSCSSecretDetection_scsMapNoSecretDetection(t *testing for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1329,6 +1333,7 @@ func TestAddSCSScan_WithSCSSecretDetection_scsMapHasSecretDetection(t *testing.T for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1393,6 +1398,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndGitCommitHistoryFlag_scsMapHasSecre for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1467,6 +1473,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardWithScanTypesAndNoScorecar for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1548,6 +1555,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndWithoutScanTypes_scsMapHasSecretDet for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() var resubmitConfig []wrappers.Config cmdCommand := &cobra.Command{ Use: "scan", @@ -1605,6 +1613,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepo_scsMap for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1692,6 +1701,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1779,6 +1789,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenInURL_s for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1866,6 +1877,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenAndUser for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -1953,6 +1965,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -2040,6 +2053,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitLabRepo_scsMapHasSecret for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -2127,6 +2141,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitSSHRepo_scsMapHasSecret for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() // Create a pipe for capturing stdout r, w, _ := os.Pipe() oldStdout := os.Stdout @@ -3567,6 +3582,7 @@ func TestValidateScanTypes(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + wrappers.ClearCache() mock.Flag = wrappers.FeatureFlagResponseModel{ Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, From bb6a103ad97c1c54667a2d508f7715b5cf2b283b Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Fri, 21 Nov 2025 09:36:52 +0000 Subject: [PATCH 09/12] test: ensure that flags are cleared after use --- internal/commands/scan_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 77d8e0e62..f3d1959d7 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -861,6 +861,7 @@ func TestAddSCSScan_ResubmitWithoutScorecardFlags_ShouldPass(t *testing.T) { Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -937,6 +938,7 @@ func TestAddSCSScan_ResubmitWithScorecardFlags_ShouldPass(t *testing.T) { Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1218,6 +1220,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecard_scsMapHasBoth(t *testing. Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1285,6 +1288,7 @@ func TestAddSCSScan_WithoutSCSSecretDetection_scsMapNoSecretDetection(t *testing Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1348,6 +1352,7 @@ func TestAddSCSScan_WithSCSSecretDetection_scsMapHasSecretDetection(t *testing.T Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1494,6 +1499,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardWithScanTypesAndNoScorecar Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1567,6 +1573,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndWithoutScanTypes_scsMapHasSecretDet Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1638,6 +1645,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepo_scsMap Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1726,6 +1734,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1814,6 +1823,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenInURL_s Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1902,6 +1912,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGithubRepoWithTokenAndUser Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -1990,6 +2001,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardShortenedGithubRepoWithTok Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -2078,6 +2090,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitLabRepo_scsMapHasSecret Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -2166,6 +2179,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndScorecardGitSSHRepo_scsMapHasSecret Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() featureFlagsWrapper := &mock.FeatureFlagsMockWrapper{} result, _ := addSCSScan(cmdCommand, resubmitConfig, @@ -3587,6 +3601,7 @@ func TestValidateScanTypes(t *testing.T) { Name: wrappers.ScsLicensingV2Enabled, Status: tt.scsLicensingV2, } + defer clearFlags() cmd := &cobra.Command{} cmd.Flags().String(commonParams.ScanTypes, tt.userScanTypes, "") From 801179e23cc95c5337e57537ca915e1ded786e4a Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:17:45 +0000 Subject: [PATCH 10/12] refactor: set git commit history to false if configured correctly to allow overrides --- internal/commands/scan.go | 29 +++--- internal/commands/scan_test.go | 185 ++++++++++++++++++++++++--------- 2 files changed, 150 insertions(+), 64 deletions(-) diff --git a/internal/commands/scan.go b/internal/commands/scan.go index e077edefa..ea083ab36 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -1406,10 +1406,10 @@ func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, hasReposit if scsSecretDetectionSelected && scsSecretDetectionAllowed { scsConfig.Twoms = trueString - // Set git commit history if enabled and all validations pass + // Set git commit history based on FF and validations commitHistoryFlag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.SscsCommitHistoryEnabled) - if shouldEnableGitCommitHistory(cmd, commitHistoryFlag.Status) { - scsConfig.GitCommitHistory = trueString + if gitCommitHistoryValue := getGitCommitHistoryValue(cmd, commitHistoryFlag.Status); gitCommitHistoryValue != "" { + scsConfig.GitCommitHistory = gitCommitHistoryValue } } @@ -3762,34 +3762,38 @@ func validateGitCommitHistoryFlag(cmd *cobra.Command) error { gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag) err := validateBooleanString(gitCommitHistory) - if err != nil { + if err != nil || gitCommitHistory == "" { return errors.Errorf("Invalid value for --git-commit-history. Use 'true' or 'false'.") } return nil } -// shouldEnableGitCommitHistory checks if the git-commit-history flag should be enabled -func shouldEnableGitCommitHistory(cmd *cobra.Command, commitHistoryFlag bool) bool { - if !commitHistoryFlag { +// getGitCommitHistoryValue determines the value for git commit history config based on flag and validations +func getGitCommitHistoryValue(cmd *cobra.Command, isFeatureFlagEnabled bool) string { + if !isFeatureFlagEnabled { fmt.Println("Warning: Git commit history scanning is not available. The flag will be ignored.") - return false + return "" } gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag) + gitCommitHistoryValue := strings.ToLower(gitCommitHistory) - // If flag is not set to true, return false - if strings.ToLower(strings.TrimSpace(gitCommitHistory)) != trueString { - return false + if !validateGitCommitHistoryContext(cmd) { + return "" } + return gitCommitHistoryValue +} + +// validateGitCommitHistoryContext validates if the context is appropriate for functionality +func validateGitCommitHistoryContext(cmd *cobra.Command) bool { userScanTypes, _ := cmd.Flags().GetString(commonParams.ScanTypes) if !strings.Contains(strings.ToLower(userScanTypes), commonParams.ScsType) { fmt.Println("Warning: '--git-commit-history' was provided, but SCS is not selected. Ignoring this flag.") return false } - // Check if only scorecard is enabled (no secret detection) scsEngines, _ := cmd.Flags().GetString(commonParams.SCSEnginesFlag) scsScoreCardSelected, scsSecretDetectionSelected := getSCSEnginesSelected(scsEngines) if scsScoreCardSelected && !scsSecretDetectionSelected { @@ -3797,7 +3801,6 @@ func shouldEnableGitCommitHistory(cmd *cobra.Command, commitHistoryFlag bool) bo return false } - // Check if there's a git repository context source, _ := cmd.Flags().GetString(commonParams.SourcesFlag) if !hasGitRepository(source) { fmt.Println("Warning: No Git history found. Secret Detection will scan the working tree only.") diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index f3d1959d7..fc5125c25 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -4595,20 +4595,30 @@ func TestValidateGitCommitHistoryFlag(t *testing.T) { expectedErrorMsg: "Invalid value for --git-commit-history. Use 'true' or 'false'.", }, { - name: "Empty value", - flagValue: "", + name: "Empty value", + flagValue: "", + expectedErrorMsg: "Invalid value for --git-commit-history. Use 'true' or 'false'.", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cmdCommand := &cobra.Command{} + cmdCommand := &cobra.Command{ + Use: "scan", + Short: "Test scan command", + } cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagDescription) + + _ = cmdCommand.Execute() + _ = cmdCommand.Flags().Set(commonParams.GitCommitHistoryFlag, tt.flagValue) err := validateGitCommitHistoryFlag(cmdCommand) - if err != nil { - assert.Assert(t, err.Error() == tt.expectedErrorMsg, "Expected error: %v, got: %v", tt.expectedErrorMsg, err) + if tt.expectedErrorMsg != "" { + assert.Assert(t, err != nil, "Expected error but got nil") + if err != nil { + assert.Assert(t, err.Error() == tt.expectedErrorMsg, "Expected error: %v, got: %v", tt.expectedErrorMsg, err) + } } else { assert.NilError(t, err, "Expected no error, got: %v", err) } @@ -4616,7 +4626,7 @@ func TestValidateGitCommitHistoryFlag(t *testing.T) { } } -func TestShouldEnableGitCommitHistory(t *testing.T) { +func TestGetGitCommitHistoryValue(t *testing.T) { // Create a temporary directory with .git for testing tempDir := t.TempDir() gitDir := filepath.Join(tempDir, ".git") @@ -4638,85 +4648,158 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { scanTypes string scsEngines string source string - expectEnabled bool - expectWarnings string ffEnabled bool + expectedValue string + expectWarnings string }{ { - name: "Feature flag disabled - disabled", + name: "Flag true with valid context - returns true", + flagValue: "true", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDir, + ffEnabled: true, + expectedValue: "true", + }, + { + name: "Flag true with FF disabled - returns empty with warning", flagValue: "true", scanTypes: "scs", scsEngines: "secret-detection", source: tempDir, - expectEnabled: false, - expectWarnings: "Git commit history scanning is not available", ffEnabled: false, + expectedValue: "", + expectWarnings: "Git commit history scanning is not available. The flag will be ignored.", }, { - name: "Flag set to false - disabled", - flagValue: "false", - scanTypes: "scs", - scsEngines: "secret-detection", - source: tempDir, - expectEnabled: false, - ffEnabled: true, + name: "Flag false with valid context - returns false", + flagValue: "false", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDir, + ffEnabled: true, + expectedValue: "false", + expectWarnings: "", + }, + { + name: "Flag false with FF disabled - returns empty with warning", + flagValue: "false", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDir, + ffEnabled: false, + expectedValue: "", + expectWarnings: "Git commit history scanning is not available. The flag will be ignored.", }, { - name: "Flag set to true with SCS not in scan types - warning and disabled", + name: "Flag true without SCS scan type - returns empty with warning", flagValue: "true", scanTypes: "sast", scsEngines: "secret-detection", source: tempDir, - expectEnabled: false, - expectWarnings: "--git-commit-history' was provided, but SCS is not selected", ffEnabled: true, + expectedValue: "", + expectWarnings: "--git-commit-history' was provided, but SCS is not selected. Ignoring this flag.", }, { - name: "Flag set to true with only scorecard - warning and disabled", + name: "Flag false without SCS scan type - returns empty with warning", + flagValue: "false", + scanTypes: "sast", + scsEngines: "secret-detection", + source: tempDir, + ffEnabled: true, + expectedValue: "", + expectWarnings: "--git-commit-history' was provided, but SCS is not selected. Ignoring this flag.", + }, + { + name: "Flag true with only scorecard engine - returns empty with warning", flagValue: "true", scanTypes: "scs", scsEngines: "scorecard", source: tempDir, - expectEnabled: false, - expectWarnings: "Commit History applies only to Secret Detection", ffEnabled: true, + expectedValue: "", + expectWarnings: "Commit History applies only to Secret Detection. The flag will be ignored.", }, { - name: "Flag set to true without git context - warning and disabled", + name: "Flag false with only scorecard engine - returns empty with warning", + flagValue: "false", + scanTypes: "scs", + scsEngines: "scorecard", + source: tempDir, + ffEnabled: true, + expectedValue: "", + expectWarnings: "Commit History applies only to Secret Detection. The flag will be ignored.", + }, + { + name: "Flag true without git repository - returns empty with warning", flagValue: "true", scanTypes: "scs", scsEngines: "secret-detection", source: tempDirNoGit, - expectEnabled: false, - expectWarnings: "No Git history found", ffEnabled: true, + expectedValue: "", + expectWarnings: "No Git history found. Secret Detection will scan the working tree only.", }, { - name: "Flag set to true with git context (directory) - enabled", - flagValue: "true", - scanTypes: "scs", - scsEngines: "secret-detection", - source: tempDir, - expectEnabled: true, - ffEnabled: true, + name: "Flag false without git repository - returns empty with warning", + flagValue: "false", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDirNoGit, + ffEnabled: true, + expectedValue: "", + expectWarnings: "No Git history found. Secret Detection will scan the working tree only.", }, { - name: "Flag set to true with git in subdirectory - enabled", - flagValue: "true", - scanTypes: "scs", - scsEngines: "secret-detection", - source: tempDirWithSubGit, - expectEnabled: true, - ffEnabled: true, + name: "Flag true with git in subdirectory - returns true", + flagValue: "true", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDirWithSubGit, + ffEnabled: true, + expectedValue: "true", + expectWarnings: "", }, { - name: "Flag set to true with both secret-detection and scorecard - enabled", - flagValue: "true", - scanTypes: "scs", - scsEngines: "secret-detection,scorecard", - source: tempDir, - expectEnabled: true, - ffEnabled: true, + name: "Flag true with both engines - returns true", + flagValue: "true", + scanTypes: "scs", + scsEngines: "secret-detection,scorecard", + source: tempDir, + ffEnabled: true, + expectedValue: "true", + expectWarnings: "", + }, + { + name: "Flag false with both engines - returns false", + flagValue: "false", + scanTypes: "scs", + scsEngines: "secret-detection,scorecard", + source: tempDir, + ffEnabled: true, + expectedValue: "false", + expectWarnings: "", + }, + { + name: "Case insensitive TRUE - returns true", + flagValue: "TRUE", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDir, + ffEnabled: true, + expectedValue: "true", + expectWarnings: "", + }, + { + name: "Case insensitive FALSE - returns false", + flagValue: "FALSE", + scanTypes: "scs", + scsEngines: "secret-detection", + source: tempDir, + ffEnabled: true, + expectedValue: "false", + expectWarnings: "", }, } @@ -4739,12 +4822,12 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { _ = cmdCommand.Flags().Set(commonParams.SCSEnginesFlag, tt.scsEngines) _ = cmdCommand.Flags().Set(commonParams.SourcesFlag, tt.source) - // Capture output for warnings (fmt.Println goes to stdout) + // Capture output for warnings oldStdout := os.Stdout r, w, _ := os.Pipe() os.Stdout = w - result := shouldEnableGitCommitHistory(cmdCommand, tt.ffEnabled) + result := getGitCommitHistoryValue(cmdCommand, tt.ffEnabled) w.Close() os.Stdout = oldStdout @@ -4756,7 +4839,7 @@ func TestShouldEnableGitCommitHistory(t *testing.T) { output := buf.String() // Check result - assert.Equal(t, tt.expectEnabled, result, "Expected enabled=%v, got=%v", tt.expectEnabled, result) + assert.Equal(t, tt.expectedValue, result, "Expected value=%s, got=%s", tt.expectedValue, result) // Check warnings if tt.expectWarnings != "" { From b62b503b527f47f1170d453daae0142a4a79f363 Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:31:36 +0000 Subject: [PATCH 11/12] test: remove redundant case insensitive TRUE/FALSE tests for flag values --- internal/commands/scan_test.go | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index fc5125c25..72cd9ce9a 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -4781,26 +4781,6 @@ func TestGetGitCommitHistoryValue(t *testing.T) { expectedValue: "false", expectWarnings: "", }, - { - name: "Case insensitive TRUE - returns true", - flagValue: "TRUE", - scanTypes: "scs", - scsEngines: "secret-detection", - source: tempDir, - ffEnabled: true, - expectedValue: "true", - expectWarnings: "", - }, - { - name: "Case insensitive FALSE - returns false", - flagValue: "FALSE", - scanTypes: "scs", - scsEngines: "secret-detection", - source: tempDir, - ffEnabled: true, - expectedValue: "false", - expectWarnings: "", - }, } for _, tt := range tests { From 6b53fee30baba3898a7f48d32cd2c689499b744a Mon Sep 17 00:00:00 2001 From: RuiO <139987905+cx-rui-oliveira@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:09:16 +0000 Subject: [PATCH 12/12] refactor: improve use of warning messages and remove default value --- internal/commands/scan.go | 20 +++++++++++++------- internal/commands/scan_test.go | 27 +++++++++++---------------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/internal/commands/scan.go b/internal/commands/scan.go index 067163d9b..ba271507a 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -124,6 +124,12 @@ const ( "--scs-repo-url your_repo_url --scs-repo-token your_repo_token" ScsScorecardUnsupportedHostWarningMsg = "SCS scan warning: Unable to run Scorecard scanner due to unsupported repo host. Currently, Scorecard can only run on GitHub Cloud repos." + gitCommitHistoryInvalidValueErrorMsg = "Invalid value for --git-commit-history. Use 'true' or 'false'." + gitCommitHistoryNotAvailableWarningMsg = "Secret Detection scan warning: Git commit history scanning is not available. The flag will be ignored." + gitCommitHistoryNotSelectedWarningMsg = "Secret Detection scan warning: '--git-commit-history' was provided, but SCS is not selected. Ignoring this flag." + gitCommitHistoryNotApplicableWarningMsg = "Secret Detection scan warning: Commit History applies only to Secret Detection. The flag will be ignored." + gitCommitHistoryNoGitRepositoryWarningMsg = "Secret Detection scan warning: No Git history found. Secret Detection will scan the working tree only." + jsonExt = ".json" xmlExt = ".xml" sbomScanTypeErrMsg = "The --sbom-only flag can only be used when the scan type is sca" @@ -865,7 +871,7 @@ func scanCreateSubCommand( createScanCmd.PersistentFlags().String(commonParams.SCSRepoTokenFlag, "", "Provide a token with read permission for the repo that you are scanning (for scorecard scans)") createScanCmd.PersistentFlags().String(commonParams.SCSRepoURLFlag, "", "The URL of the repo that you are scanning with scs (for scorecard scans)") createScanCmd.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "Specify which scs engines will run (default: all licensed engines)") - createScanCmd.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagDescription) + createScanCmd.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "", commonParams.GitCommitHistoryFlagDescription) createScanCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) // Container config flags @@ -3762,8 +3768,8 @@ func validateGitCommitHistoryFlag(cmd *cobra.Command) error { gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag) err := validateBooleanString(gitCommitHistory) - if err != nil || gitCommitHistory == "" { - return errors.Errorf("Invalid value for --git-commit-history. Use 'true' or 'false'.") + if err != nil { + return errors.Errorf(gitCommitHistoryInvalidValueErrorMsg) } return nil @@ -3772,7 +3778,7 @@ func validateGitCommitHistoryFlag(cmd *cobra.Command) error { // getGitCommitHistoryValue determines the value for git commit history config based on flag and validations func getGitCommitHistoryValue(cmd *cobra.Command, isFeatureFlagEnabled bool) string { if !isFeatureFlagEnabled { - fmt.Println("Warning: Git commit history scanning is not available. The flag will be ignored.") + fmt.Println(gitCommitHistoryNotAvailableWarningMsg) return "" } @@ -3790,20 +3796,20 @@ func getGitCommitHistoryValue(cmd *cobra.Command, isFeatureFlagEnabled bool) str func validateGitCommitHistoryContext(cmd *cobra.Command) bool { userScanTypes, _ := cmd.Flags().GetString(commonParams.ScanTypes) if !strings.Contains(strings.ToLower(userScanTypes), commonParams.ScsType) { - fmt.Println("Warning: '--git-commit-history' was provided, but SCS is not selected. Ignoring this flag.") + fmt.Println(gitCommitHistoryNotSelectedWarningMsg) return false } scsEngines, _ := cmd.Flags().GetString(commonParams.SCSEnginesFlag) scsScoreCardSelected, scsSecretDetectionSelected := getSCSEnginesSelected(scsEngines) if scsScoreCardSelected && !scsSecretDetectionSelected { - fmt.Println("Warning: Commit History applies only to Secret Detection. The flag will be ignored.") + fmt.Println(gitCommitHistoryNotApplicableWarningMsg) return false } source, _ := cmd.Flags().GetString(commonParams.SourcesFlag) if !hasGitRepository(source) { - fmt.Println("Warning: No Git history found. Secret Detection will scan the working tree only.") + fmt.Println(gitCommitHistoryNoGitRepositoryWarningMsg) return false } diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 72cd9ce9a..c7d30ef97 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -1411,7 +1411,7 @@ func TestAddSCSScan_WithSCSSecretDetectionAndGitCommitHistoryFlag_scsMapHasSecre Long: `Scan a project`, } cmdCommand.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "SCS Engine flag") - cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagDescription) + cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "", commonParams.GitCommitHistoryFlagDescription) cmdCommand.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") cmdCommand.PersistentFlags().String(commonParams.SourcesFlag, "", "Sources") @@ -4592,12 +4592,7 @@ func TestValidateGitCommitHistoryFlag(t *testing.T) { { name: "Invalid value 'maybe'", flagValue: "maybe", - expectedErrorMsg: "Invalid value for --git-commit-history. Use 'true' or 'false'.", - }, - { - name: "Empty value", - flagValue: "", - expectedErrorMsg: "Invalid value for --git-commit-history. Use 'true' or 'false'.", + expectedErrorMsg: gitCommitHistoryInvalidValueErrorMsg, }, } @@ -4669,7 +4664,7 @@ func TestGetGitCommitHistoryValue(t *testing.T) { source: tempDir, ffEnabled: false, expectedValue: "", - expectWarnings: "Git commit history scanning is not available. The flag will be ignored.", + expectWarnings: gitCommitHistoryNotAvailableWarningMsg, }, { name: "Flag false with valid context - returns false", @@ -4689,7 +4684,7 @@ func TestGetGitCommitHistoryValue(t *testing.T) { source: tempDir, ffEnabled: false, expectedValue: "", - expectWarnings: "Git commit history scanning is not available. The flag will be ignored.", + expectWarnings: gitCommitHistoryNotAvailableWarningMsg, }, { name: "Flag true without SCS scan type - returns empty with warning", @@ -4699,7 +4694,7 @@ func TestGetGitCommitHistoryValue(t *testing.T) { source: tempDir, ffEnabled: true, expectedValue: "", - expectWarnings: "--git-commit-history' was provided, but SCS is not selected. Ignoring this flag.", + expectWarnings: gitCommitHistoryNotSelectedWarningMsg, }, { name: "Flag false without SCS scan type - returns empty with warning", @@ -4709,7 +4704,7 @@ func TestGetGitCommitHistoryValue(t *testing.T) { source: tempDir, ffEnabled: true, expectedValue: "", - expectWarnings: "--git-commit-history' was provided, but SCS is not selected. Ignoring this flag.", + expectWarnings: gitCommitHistoryNotSelectedWarningMsg, }, { name: "Flag true with only scorecard engine - returns empty with warning", @@ -4719,7 +4714,7 @@ func TestGetGitCommitHistoryValue(t *testing.T) { source: tempDir, ffEnabled: true, expectedValue: "", - expectWarnings: "Commit History applies only to Secret Detection. The flag will be ignored.", + expectWarnings: gitCommitHistoryNotApplicableWarningMsg, }, { name: "Flag false with only scorecard engine - returns empty with warning", @@ -4729,7 +4724,7 @@ func TestGetGitCommitHistoryValue(t *testing.T) { source: tempDir, ffEnabled: true, expectedValue: "", - expectWarnings: "Commit History applies only to Secret Detection. The flag will be ignored.", + expectWarnings: gitCommitHistoryNotApplicableWarningMsg, }, { name: "Flag true without git repository - returns empty with warning", @@ -4739,7 +4734,7 @@ func TestGetGitCommitHistoryValue(t *testing.T) { source: tempDirNoGit, ffEnabled: true, expectedValue: "", - expectWarnings: "No Git history found. Secret Detection will scan the working tree only.", + expectWarnings: gitCommitHistoryNoGitRepositoryWarningMsg, }, { name: "Flag false without git repository - returns empty with warning", @@ -4749,7 +4744,7 @@ func TestGetGitCommitHistoryValue(t *testing.T) { source: tempDirNoGit, ffEnabled: true, expectedValue: "", - expectWarnings: "No Git history found. Secret Detection will scan the working tree only.", + expectWarnings: gitCommitHistoryNoGitRepositoryWarningMsg, }, { name: "Flag true with git in subdirectory - returns true", @@ -4790,7 +4785,7 @@ func TestGetGitCommitHistoryValue(t *testing.T) { Use: "scan", Short: "Scan a project with git commit history", } - cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagDescription) + cmdCommand.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "", commonParams.GitCommitHistoryFlagDescription) cmdCommand.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") cmdCommand.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "SCS engines") cmdCommand.PersistentFlags().String(commonParams.SourcesFlag, "", "Sources")