From f41ad1272e6951b2f395bc1636f9b80c456ccf03 Mon Sep 17 00:00:00 2001 From: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Sun, 8 Mar 2026 18:30:37 +0530 Subject: [PATCH 1/9] - Added DA_MIGRATION FLAG implementation --- internal/commands/root.go | 1 + internal/commands/scan.go | 10 +++++++++- internal/services/applications.go | 26 +++++++++++++++++++++++--- internal/services/projects.go | 3 ++- internal/wrappers/feature-flags.go | 1 + 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/internal/commands/root.go b/internal/commands/root.go index 4ecebedb3..6f3503036 100644 --- a/internal/commands/root.go +++ b/internal/commands/root.go @@ -197,6 +197,7 @@ func NewAstCLI( featureFlagsWrapper, containerResolverWrapper, realTimeWrapper, + tenantWrapper, ) projectCmd := NewProjectCommand(applicationsWrapper, projectsWrapper, groupsWrapper, accessManagementWrapper, featureFlagsWrapper) dastEnvironmentsCmd := dast.NewDastEnvironmentsCommand(dastEnvironmentsWrapper) diff --git a/internal/commands/scan.go b/internal/commands/scan.go index 47de5b3fa..c534b7cc6 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -187,6 +187,7 @@ func NewScanCommand( featureFlagsWrapper wrappers.FeatureFlagsWrapper, containerResolverWrapper wrappers.ContainerResolverWrapper, realtimeScannerWrapper wrappers.RealtimeScannerWrapper, + tenantWrapper wrappers.TenantConfigurationWrapper, ) *cobra.Command { scanCmd := &cobra.Command{ Use: "scan", @@ -217,6 +218,7 @@ func NewScanCommand( accessManagementWrapper, applicationsWrapper, featureFlagsWrapper, + tenantWrapper, ) containerResolver = containerResolverWrapper @@ -674,6 +676,7 @@ func scanCreateSubCommand( accessManagementWrapper wrappers.AccessManagementWrapper, applicationsWrapper wrappers.ApplicationsWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, + tenantWrapper wrappers.TenantConfigurationWrapper, ) *cobra.Command { createScanCmd := &cobra.Command{ Use: "create", @@ -945,6 +948,7 @@ func setupScanTypeProjectAndConfig( accessManagementWrapper wrappers.AccessManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, jwtWrapper wrappers.JWTWrapper, + tenantWrapper wrappers.TenantConfigurationWrapper, ) error { userAllowedEngines, _ := jwtWrapper.GetAllowedEngines(featureFlagsWrapper) var info map[string]interface{} @@ -973,6 +977,7 @@ func setupScanTypeProjectAndConfig( accessManagementWrapper, applicationsWrapper, featureFlagsWrapper, + tenantWrapper, ) if findProjectErr != nil { return findProjectErr @@ -2391,6 +2396,7 @@ func runCreateScanCommand( accessManagementWrapper wrappers.AccessManagementWrapper, applicationsWrapper wrappers.ApplicationsWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, + tenantWrapper wrappers.TenantConfigurationWrapper, ) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { err := validateScanTypes(cmd, jwtWrapper, featureFlagsWrapper) @@ -2440,6 +2446,7 @@ func runCreateScanCommand( applicationsWrapper, featureFlagsWrapper, jwtWrapper, + tenantWrapper, ) defer cleanUpTempZip(zipFilePath) if err != nil { @@ -2538,11 +2545,12 @@ func createScanModel( applicationsWrapper wrappers.ApplicationsWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, jwtWrapper wrappers.JWTWrapper, + tenantWrapper wrappers.TenantConfigurationWrapper, ) (*wrappers.Scan, string, error) { var input = []byte("{}") // Define type, project and config in scan model - err := setupScanTypeProjectAndConfig(&input, cmd, projectsWrapper, groupsWrapper, scansWrapper, applicationsWrapper, accessManagementWrapper, featureFlagsWrapper, jwtWrapper) + err := setupScanTypeProjectAndConfig(&input, cmd, projectsWrapper, groupsWrapper, scansWrapper, applicationsWrapper, accessManagementWrapper, featureFlagsWrapper, jwtWrapper, tenantWrapper) if err != nil { return nil, "", err } diff --git a/internal/services/applications.go b/internal/services/applications.go index 10e533c40..d51bba4a9 100644 --- a/internal/services/applications.go +++ b/internal/services/applications.go @@ -9,7 +9,8 @@ import ( ) const ( - ApplicationRuleType = "project.name.in" + ApplicationRuleType = "project.name.in" + DirectAssociationKey = "scan.config.applications.directAssociations" ) func createApplicationIds(applicationID, existingApplicationIds []string) []string { @@ -64,7 +65,7 @@ func verifyApplicationNameExactMatch(applicationName string, resp *wrappers.Appl return application } -func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappers.ApplicationsWrapper, projectName, projectID string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { +func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappers.ApplicationsWrapper, projectName, projectID string, featureFlagsWrapper wrappers.FeatureFlagsWrapper, tenantWrapper wrappers.TenantConfigurationHTTPWrapper) error { if applicationName == "" { logger.PrintfIfVerbose("No application name provided. Skipping application update") return nil @@ -78,7 +79,26 @@ func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappe } directAssociationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DirectAssociationEnabled) - if directAssociationEnabled.Status { + daMigrationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DA_MIGRATION_ENABLED) + var isDAConfigurationEnabled bool + // TODO: Relevant Error message to be added + Testing + if daMigrationEnabled.Status { + tenantConfigurationResponse, errorModel, err := tenantWrapper.GetTenantConfiguration() + if err != nil { + return err + } + if errorModel != nil { + return errors.New(errorModel.Message) + } + if tenantConfigurationResponse != nil { + for _, resp := range *tenantConfigurationResponse { + if resp.Key == DirectAssociationKey && resp.Value == "true" { + isDAConfigurationEnabled = true + } + } + } + } + if (daMigrationEnabled.Status && isDAConfigurationEnabled) || directAssociationEnabled.Status { err = associateProjectToApplication(applicationResp.ID, projectID, applicationResp.ProjectIds, applicationsWrapper) if err != nil { return err diff --git a/internal/services/projects.go b/internal/services/projects.go index 3d34cc110..a8df680ac 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -32,6 +32,7 @@ func FindProject( accessManagementWrapper wrappers.AccessManagementWrapper, applicationWrapper wrappers.ApplicationsWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, + tenantWrapper wrappers.TenantConfigurationHTTPWrapper, ) (string, error) { var isBranchPrimary bool resp, err := GetProjectsCollectionByProjectName(projectName, projectsWrapper) @@ -44,7 +45,7 @@ func FindProject( for i := 0; i < len(resp.Projects); i++ { project := resp.Projects[i] if project.Name == projectName { - err = findApplicationAndUpdate(applicationName, applicationWrapper, projectName, project.ID, featureFlagsWrapper) + err = findApplicationAndUpdate(applicationName, applicationWrapper, projectName, project.ID, featureFlagsWrapper, tenantWrapper) if err != nil { return "", err } diff --git a/internal/wrappers/feature-flags.go b/internal/wrappers/feature-flags.go index 8b2579b27..0c8120fcf 100644 --- a/internal/wrappers/feature-flags.go +++ b/internal/wrappers/feature-flags.go @@ -17,6 +17,7 @@ const OssRealtimeEnabled = "OSS_REALTIME_ENABLED" const ScsLicensingV2Enabled = "SSCS_NEW_LICENSING_ENABLED" const SscsCommitHistoryEnabled = "SSCS_COMMIT_HISTORY_ENABLED" const DirectAssociationEnabled = "DIRECT_APP_ASSOCIATION_ENABLED" +const DA_MIGRATION_ENABLED = "DA_MIGRATION_ENABLED" const maxRetries = 3 const IncreaseFileUploadLimit = "INCREASE_FILE_UPLOAD_LIMIT" const ScaDeltaScanEnabled = "SCA_DELTASCAN_ENABLED" From 42a360b96805518315b2009c744df1815900042e Mon Sep 17 00:00:00 2001 From: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Mon, 9 Mar 2026 15:47:15 +0530 Subject: [PATCH 2/9] - Changed the Wrapper name --- internal/commands/scan.go | 1 + internal/commands/util/import.go | 8 ++++---- internal/commands/util/utils.go | 2 +- internal/services/applications.go | 4 ++-- internal/services/projects.go | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/internal/commands/scan.go b/internal/commands/scan.go index c534b7cc6..b0d346a6d 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -710,6 +710,7 @@ func scanCreateSubCommand( accessManagementWrapper, applicationsWrapper, featureFlagsWrapper, + tenantWrapper, ), } createScanCmd.PersistentFlags().Bool(commonParams.AsyncFlag, false, "Do not wait for scan completion") diff --git a/internal/commands/util/import.go b/internal/commands/util/import.go index ea0d18dfe..e4ef88efb 100644 --- a/internal/commands/util/import.go +++ b/internal/commands/util/import.go @@ -21,7 +21,7 @@ func NewImportCommand( accessManagementWrapper wrappers.AccessManagementWrapper, byorWrapper wrappers.ByorWrapper, applicationsWrapper wrappers.ApplicationsWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper) *cobra.Command { + featureFlagsWrapper wrappers.FeatureFlagsWrapper, tenantWrapper wrappers.TenantConfigurationWrapper) *cobra.Command { cmd := &cobra.Command{ Use: "import", Short: "Import SAST scan results", @@ -37,7 +37,7 @@ func NewImportCommand( `, ), }, - RunE: runImportCommand(projectsWrapper, uploadsWrapper, groupsWrapper, accessManagementWrapper, applicationsWrapper, byorWrapper, featureFlagsWrapper), + RunE: runImportCommand(projectsWrapper, uploadsWrapper, groupsWrapper, accessManagementWrapper, applicationsWrapper, byorWrapper, featureFlagsWrapper, tenantWrapper), } cmd.PersistentFlags().String(commonParams.ImportFilePath, "", "Path to the import file (sarif file or zip archive containing sarif files)") @@ -53,7 +53,7 @@ func runImportCommand( accessManagementWrapper wrappers.AccessManagementWrapper, applicationsWrapper wrappers.ApplicationsWrapper, byorWrapper wrappers.ByorWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper) func(cmd *cobra.Command, args []string) error { + featureFlagsWrapper wrappers.FeatureFlagsWrapper, tenantWrapper wrappers.TenantConfigurationWrapper) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { importFilePath, err := validateFilePath(cmd) if err != nil { @@ -65,7 +65,7 @@ func runImportCommand( return errors.Errorf(errorConstants.ProjectNameIsRequired) } - projectID, err := services.FindProject(projectName, cmd, projectsWrapper, groupsWrapper, accessManagementWrapper, applicationsWrapper, featureFlagsWrapper) + projectID, err := services.FindProject(projectName, cmd, projectsWrapper, groupsWrapper, accessManagementWrapper, applicationsWrapper, featureFlagsWrapper, tenantWrapper) if err != nil { return err } diff --git a/internal/commands/util/utils.go b/internal/commands/util/utils.go index c16db6f93..cbc2b2c10 100644 --- a/internal/commands/util/utils.go +++ b/internal/commands/util/utils.go @@ -65,7 +65,7 @@ func NewUtilsCommand( }, } - importCmd := NewImportCommand(projectsWrapper, uploadsWrapper, groupsWrapper, accessManagementWrapper, byorWrapper, applicationsWrapper, featureFlagsWrapper) + importCmd := NewImportCommand(projectsWrapper, uploadsWrapper, groupsWrapper, accessManagementWrapper, byorWrapper, applicationsWrapper, featureFlagsWrapper, tenantWrapper) envCheckCmd := NewEnvCheckCommand() diff --git a/internal/services/applications.go b/internal/services/applications.go index d51bba4a9..1ceaf0987 100644 --- a/internal/services/applications.go +++ b/internal/services/applications.go @@ -65,7 +65,7 @@ func verifyApplicationNameExactMatch(applicationName string, resp *wrappers.Appl return application } -func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappers.ApplicationsWrapper, projectName, projectID string, featureFlagsWrapper wrappers.FeatureFlagsWrapper, tenantWrapper wrappers.TenantConfigurationHTTPWrapper) error { +func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappers.ApplicationsWrapper, projectName, projectID string, featureFlagsWrapper wrappers.FeatureFlagsWrapper, tenantWrapper wrappers.TenantConfigurationWrapper) error { if applicationName == "" { logger.PrintfIfVerbose("No application name provided. Skipping application update") return nil @@ -81,7 +81,7 @@ func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappe directAssociationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DirectAssociationEnabled) daMigrationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DA_MIGRATION_ENABLED) var isDAConfigurationEnabled bool - // TODO: Relevant Error message to be added + Testing + if daMigrationEnabled.Status { tenantConfigurationResponse, errorModel, err := tenantWrapper.GetTenantConfiguration() if err != nil { diff --git a/internal/services/projects.go b/internal/services/projects.go index a8df680ac..4d65e1b68 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -32,7 +32,7 @@ func FindProject( accessManagementWrapper wrappers.AccessManagementWrapper, applicationWrapper wrappers.ApplicationsWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, - tenantWrapper wrappers.TenantConfigurationHTTPWrapper, + tenantWrapper wrappers.TenantConfigurationWrapper, ) (string, error) { var isBranchPrimary bool resp, err := GetProjectsCollectionByProjectName(projectName, projectsWrapper) From eebdbc9e91caff9566dd0c355daaeadbd223710c Mon Sep 17 00:00:00 2001 From: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Mon, 9 Mar 2026 16:16:07 +0530 Subject: [PATCH 3/9] - Added additional unit tests --- internal/commands/scan_test.go | 22 ++++++++++++++++++++-- internal/wrappers/mock/tenant-mock.go | 4 ++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 1c20053f5..1b43b3826 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -4470,11 +4470,29 @@ func Test_CreateScanWithExistingProjectAndAssign_FailedApplication_DoesNot_Exist func Test_CreateScanWithExistingProjectAssign_to_Application_FF_DirectAssociationEnabledShouldPass(t *testing.T) { file := createOutputFile(t, outputFileName) - defer deleteOutputFile(file) + //defer deleteOutputFile(file) defer logger.SetOutput(os.Stdout) mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DirectAssociationEnabled, Status: true} - baseArgs := []string{"scan", "create", "--project-name", "MOCK", "-s", ".", "--branch", "main", "--debug", "--application-name", mock.ExistingApplication} + baseArgs := []string{"scan", "create", "--project-name", "MOCK2", "-s", ".", "--branch", "main", "--debug", "--application-name", mock.ExistingApplication} + execCmdNilAssertion( + t, + baseArgs..., + ) + stdoutString, err := util.ReadFileAsString(file.Name()) + if err != nil { + t.Fatalf("Failed to read log file: %v", err) + } + assert.Equal(t, strings.Contains(stdoutString, "Successfully updated the application"), true, "Expected output: %s", "Successfully updated the application") +} + +func Test_Create_Scan_With_DA_MIGRATION_And_Configuration_ShouldPass(t *testing.T) { + file := createOutputFile(t, outputFileName) + defer deleteOutputFile(file) + defer logger.SetOutput(os.Stdout) + + mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DA_MIGRATION_ENABLED, Status: true} + baseArgs := []string{"scan", "create", "--project-name", "MOCK5", "-s", ".", "--branch", "main", "--debug", "--application-name", mock.ExistingApplication} execCmdNilAssertion( t, baseArgs..., diff --git a/internal/wrappers/mock/tenant-mock.go b/internal/wrappers/mock/tenant-mock.go index 4cacbd990..840a7b2a0 100644 --- a/internal/wrappers/mock/tenant-mock.go +++ b/internal/wrappers/mock/tenant-mock.go @@ -26,6 +26,10 @@ func (t TenantConfigurationMockWrapper) GetTenantConfiguration() ( Key: "scan.config.plugins.aiGuidedRemediationAiEngine", Value: "azureai", }, + { + Key: "scan.config.applications.directAssociations", + Value: "true", + }, } } return &TenantConfiguration, nil, nil From 6805875ff731370e22acc3af5e87153ba4c7dd4b Mon Sep 17 00:00:00 2001 From: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Mon, 9 Mar 2026 16:17:59 +0530 Subject: [PATCH 4/9] - Added defer output file --- internal/commands/scan_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 1b43b3826..b58711f62 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -4470,7 +4470,7 @@ func Test_CreateScanWithExistingProjectAndAssign_FailedApplication_DoesNot_Exist func Test_CreateScanWithExistingProjectAssign_to_Application_FF_DirectAssociationEnabledShouldPass(t *testing.T) { file := createOutputFile(t, outputFileName) - //defer deleteOutputFile(file) + defer deleteOutputFile(file) defer logger.SetOutput(os.Stdout) mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DirectAssociationEnabled, Status: true} From 1939d759282032fb7bf2e28a99cfa248b24db15f Mon Sep 17 00:00:00 2001 From: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:42:44 +0530 Subject: [PATCH 5/9] - Fixed Unit tests --- internal/commands/util/import_test.go | 8 ++++++++ internal/services/projects_test.go | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/internal/commands/util/import_test.go b/internal/commands/util/import_test.go index 571b49dc0..97bfa15dd 100644 --- a/internal/commands/util/import_test.go +++ b/internal/commands/util/import_test.go @@ -20,6 +20,7 @@ func TestImport_ImportSarifFileWithCorrectFlags_CreateImportSuccessfully(t *test &mock.ByorMockWrapper{}, mock.ApplicationsMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, + &mock.TenantConfigurationMockWrapper{}, ) cmd.SetArgs([]string{"utils", "import", "--project-name", "my-project", "--import-file-path", "my-path.sarif"}) err := cmd.Execute() @@ -36,6 +37,7 @@ func TestImport_ImportSarifFileProjectDoesntExist_CreateImportWithProvidedNewNam &mock.ByorMockWrapper{}, mock.ApplicationsMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, + &mock.TenantConfigurationMockWrapper{}, ) cmd.SetArgs([]string{"utils", "import", "--project-name", "MOCK-PROJECT-NOT-EXIST", "--import-file-path", "my-path.sarif"}) err := cmd.Execute() @@ -52,6 +54,7 @@ func TestImport_ImportSarifFileMissingImportFilePath_CreateImportReturnsErrorWit &mock.ByorMockWrapper{}, mock.ApplicationsMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, + &mock.TenantConfigurationMockWrapper{}, ) cmd.SetArgs([]string{"utils", "import", "--project-name", "my-project"}) err := cmd.Execute() @@ -67,6 +70,7 @@ func TestImport_ImportSarifFileEmptyImportFilePathValue_CreateImportReturnsError &mock.ByorMockWrapper{}, mock.ApplicationsMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, + &mock.TenantConfigurationMockWrapper{}, ) cmd.SetArgs([]string{"utils", "import", "--project-name", "my-project", "--import-file-path", ""}) err := cmd.Execute() @@ -82,6 +86,7 @@ func TestImport_ImportSarifFileMissingImportProjectName_CreateImportReturnsError &mock.ByorMockWrapper{}, mock.ApplicationsMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, + &mock.TenantConfigurationMockWrapper{}, ) cmd.SetArgs([]string{"utils", "import", "--import-file-path", "my-path.zip"}) err := cmd.Execute() @@ -97,6 +102,7 @@ func TestImport_ImportSarifFileProjectNameNotProvided_CreateImportWithProvidedNe &mock.ByorMockWrapper{}, mock.ApplicationsMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, + &mock.TenantConfigurationMockWrapper{}, ) cmd.SetArgs([]string{"utils", "import", "--project-name", "", "--import-file-path", "my-path.sarif"}) err := cmd.Execute() @@ -112,6 +118,7 @@ func TestImport_ImportSarifFileUnacceptedFileExtension_CreateImportReturnsErrorW &mock.ByorMockWrapper{}, mock.ApplicationsMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, + &mock.TenantConfigurationMockWrapper{}, ) cmd.SetArgs([]string{"utils", "import", "--project-name", "MOCK-PROJECT-NOT-EXIST", "--import-file-path", "my-path.txt"}) err := cmd.Execute() @@ -127,6 +134,7 @@ func TestImport_ImportSarifFileMissingExtension_CreateImportReturnsErrorWithCorr &mock.ByorMockWrapper{}, mock.ApplicationsMockWrapper{}, &mock.FeatureFlagsMockWrapper{}, + &mock.TenantConfigurationMockWrapper{}, ) cmd.SetArgs([]string{"utils", "import", "--project-name", "MOCK-PROJECT-NOT-EXIST", "--import-file-path", "some/path/no/extension/my-path"}) err := cmd.Execute() diff --git a/internal/services/projects_test.go b/internal/services/projects_test.go index 5d959f5d3..700e28138 100644 --- a/internal/services/projects_test.go +++ b/internal/services/projects_test.go @@ -19,6 +19,7 @@ func TestFindProject(t *testing.T) { accessManagementWrapper wrappers.AccessManagementWrapper applicationsWrapper wrappers.ApplicationsWrapper featureFlagsWrapper wrappers.FeatureFlagsWrapper + tenantWrapper wrappers.TenantConfigurationWrapper } tests := []struct { name string @@ -37,6 +38,7 @@ func TestFindProject(t *testing.T) { accessManagementWrapper: &mock.AccessManagementMockWrapper{}, applicationsWrapper: &mock.ApplicationsMockWrapper{}, featureFlagsWrapper: &mock.FeatureFlagsMockWrapper{}, + tenantWrapper: &mock.TenantConfigurationMockWrapper{}, }, want: "MOCK", wantErr: false, @@ -51,6 +53,7 @@ func TestFindProject(t *testing.T) { accessManagementWrapper: &mock.AccessManagementMockWrapper{}, applicationsWrapper: &mock.ApplicationsMockWrapper{}, featureFlagsWrapper: &mock.FeatureFlagsMockWrapper{}, + tenantWrapper: &mock.TenantConfigurationMockWrapper{}, }, want: "ID-new-MOCK", wantErr: false, @@ -66,7 +69,8 @@ func TestFindProject(t *testing.T) { ttt.args.groupsWrapper, ttt.args.accessManagementWrapper, ttt.args.applicationsWrapper, - ttt.args.featureFlagsWrapper) + ttt.args.featureFlagsWrapper, + ttt.args.tenantWrapper) if (err != nil) != ttt.wantErr { t.Errorf("FindProject() error = %v, wantErr %v", err, ttt.wantErr) return From 7dff2fac2d86acf5b689140c96ee90d47da20f8d Mon Sep 17 00:00:00 2001 From: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Mon, 9 Mar 2026 19:37:55 +0530 Subject: [PATCH 6/9] - Fixed Lint issues --- internal/services/applications.go | 47 ++++++++++++++++++------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/internal/services/applications.go b/internal/services/applications.go index 1ceaf0987..fc07f1430 100644 --- a/internal/services/applications.go +++ b/internal/services/applications.go @@ -11,6 +11,7 @@ import ( const ( ApplicationRuleType = "project.name.in" DirectAssociationKey = "scan.config.applications.directAssociations" + trueString = "true" ) func createApplicationIds(applicationID, existingApplicationIds []string) []string { @@ -78,27 +79,11 @@ func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappe return errors.Errorf("%s: %s", errorConstants.ApplicationNotFound, applicationName) } - directAssociationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DirectAssociationEnabled) - daMigrationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DA_MIGRATION_ENABLED) - var isDAConfigurationEnabled bool - - if daMigrationEnabled.Status { - tenantConfigurationResponse, errorModel, err := tenantWrapper.GetTenantConfiguration() - if err != nil { - return err - } - if errorModel != nil { - return errors.New(errorModel.Message) - } - if tenantConfigurationResponse != nil { - for _, resp := range *tenantConfigurationResponse { - if resp.Key == DirectAssociationKey && resp.Value == "true" { - isDAConfigurationEnabled = true - } - } - } + isEnabled, err := checkDirectAssociationEnabled(featureFlagsWrapper, tenantWrapper) + if err != nil { + return errors.Wrap(err, "error while checking if direct association is enabled") } - if (daMigrationEnabled.Status && isDAConfigurationEnabled) || directAssociationEnabled.Status { + if isEnabled { err = associateProjectToApplication(applicationResp.ID, projectID, applicationResp.ProjectIds, applicationsWrapper) if err != nil { return err @@ -127,6 +112,28 @@ func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappe return nil } +func checkDirectAssociationEnabled(featureFlagsWrapper wrappers.FeatureFlagsWrapper, tenantWrapper wrappers.TenantConfigurationWrapper) (bool, error) { + directAssociationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DirectAssociationEnabled) + daMigrationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DA_MIGRATION_ENABLED) + var isDAConfigurationEnabled bool + if daMigrationEnabled.Status { + tenantConfigurationResponse, errorModel, err := tenantWrapper.GetTenantConfiguration() + if err != nil { + return false, err + } + if errorModel != nil { + return false, errors.New(errorModel.Message) + } + if tenantConfigurationResponse != nil { + for _, resp := range *tenantConfigurationResponse { + if resp.Key == DirectAssociationKey && resp.Value == trueString { + isDAConfigurationEnabled = true + } + } + } + } + return (daMigrationEnabled.Status && isDAConfigurationEnabled) || directAssociationEnabled.Status, nil +} func updateApplication(applicationModel *wrappers.ApplicationConfiguration, applicationWrapper wrappers.ApplicationsWrapper, applicationID string) error { errorModel, err := applicationWrapper.Update(applicationID, applicationModel) return handleApplicationUpdateResponse(errorModel, err) From fc5f90b663da215b6ccb31efcdbdd9d4f9700ff7 Mon Sep 17 00:00:00 2001 From: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Mon, 9 Mar 2026 19:46:05 +0530 Subject: [PATCH 7/9] - Fixed test issues --- internal/commands/scan_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index b58711f62..c2bd8d72b 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -4472,9 +4472,9 @@ func Test_CreateScanWithExistingProjectAssign_to_Application_FF_DirectAssociatio file := createOutputFile(t, outputFileName) defer deleteOutputFile(file) defer logger.SetOutput(os.Stdout) - + mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DA_MIGRATION_ENABLED, Status: false} mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DirectAssociationEnabled, Status: true} - baseArgs := []string{"scan", "create", "--project-name", "MOCK2", "-s", ".", "--branch", "main", "--debug", "--application-name", mock.ExistingApplication} + baseArgs := []string{"scan", "create", "--project-name", "MOCK", "-s", ".", "--branch", "main", "--debug", "--application-name", mock.ExistingApplication} execCmdNilAssertion( t, baseArgs..., @@ -4492,7 +4492,7 @@ func Test_Create_Scan_With_DA_MIGRATION_And_Configuration_ShouldPass(t *testing. defer logger.SetOutput(os.Stdout) mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DA_MIGRATION_ENABLED, Status: true} - baseArgs := []string{"scan", "create", "--project-name", "MOCK5", "-s", ".", "--branch", "main", "--debug", "--application-name", mock.ExistingApplication} + baseArgs := []string{"scan", "create", "--project-name", "MOCK", "-s", ".", "--branch", "main", "--debug", "--application-name", mock.ExistingApplication} execCmdNilAssertion( t, baseArgs..., From 0820f0b0e90ae846436b98a808baf3087ecb20a4 Mon Sep 17 00:00:00 2001 From: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Mon, 9 Mar 2026 20:35:48 +0530 Subject: [PATCH 8/9] - Fixed test issues --- internal/commands/scan_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index c2bd8d72b..4f8fcda34 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -4486,7 +4486,7 @@ func Test_CreateScanWithExistingProjectAssign_to_Application_FF_DirectAssociatio assert.Equal(t, strings.Contains(stdoutString, "Successfully updated the application"), true, "Expected output: %s", "Successfully updated the application") } -func Test_Create_Scan_With_DA_MIGRATION_And_Configuration_ShouldPass(t *testing.T) { +func Test_Create_Scan_With_DA_MIGRATION_And_ConfigurationEnabled_ShouldPass(t *testing.T) { file := createOutputFile(t, outputFileName) defer deleteOutputFile(file) defer logger.SetOutput(os.Stdout) From 5df99f400359918c7ad9e053357dd315ef979e34 Mon Sep 17 00:00:00 2001 From: anjali-deore <200181980+cx-anjali-deore@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:07:37 +0530 Subject: [PATCH 9/9] - Changed FF name --- internal/commands/scan_test.go | 4 ++-- internal/services/applications.go | 2 +- internal/wrappers/feature-flags.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/commands/scan_test.go b/internal/commands/scan_test.go index 4f8fcda34..6d029bb34 100644 --- a/internal/commands/scan_test.go +++ b/internal/commands/scan_test.go @@ -4472,7 +4472,7 @@ func Test_CreateScanWithExistingProjectAssign_to_Application_FF_DirectAssociatio file := createOutputFile(t, outputFileName) defer deleteOutputFile(file) defer logger.SetOutput(os.Stdout) - mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DA_MIGRATION_ENABLED, Status: false} + mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DaMigrationEnabled, Status: false} mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DirectAssociationEnabled, Status: true} baseArgs := []string{"scan", "create", "--project-name", "MOCK", "-s", ".", "--branch", "main", "--debug", "--application-name", mock.ExistingApplication} execCmdNilAssertion( @@ -4491,7 +4491,7 @@ func Test_Create_Scan_With_DA_MIGRATION_And_ConfigurationEnabled_ShouldPass(t *t defer deleteOutputFile(file) defer logger.SetOutput(os.Stdout) - mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DA_MIGRATION_ENABLED, Status: true} + mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.DaMigrationEnabled, Status: true} baseArgs := []string{"scan", "create", "--project-name", "MOCK", "-s", ".", "--branch", "main", "--debug", "--application-name", mock.ExistingApplication} execCmdNilAssertion( t, diff --git a/internal/services/applications.go b/internal/services/applications.go index fc07f1430..19880f529 100644 --- a/internal/services/applications.go +++ b/internal/services/applications.go @@ -114,7 +114,7 @@ func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappe func checkDirectAssociationEnabled(featureFlagsWrapper wrappers.FeatureFlagsWrapper, tenantWrapper wrappers.TenantConfigurationWrapper) (bool, error) { directAssociationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DirectAssociationEnabled) - daMigrationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DA_MIGRATION_ENABLED) + daMigrationEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.DaMigrationEnabled) var isDAConfigurationEnabled bool if daMigrationEnabled.Status { tenantConfigurationResponse, errorModel, err := tenantWrapper.GetTenantConfiguration() diff --git a/internal/wrappers/feature-flags.go b/internal/wrappers/feature-flags.go index 0c8120fcf..798256a4b 100644 --- a/internal/wrappers/feature-flags.go +++ b/internal/wrappers/feature-flags.go @@ -17,7 +17,7 @@ const OssRealtimeEnabled = "OSS_REALTIME_ENABLED" const ScsLicensingV2Enabled = "SSCS_NEW_LICENSING_ENABLED" const SscsCommitHistoryEnabled = "SSCS_COMMIT_HISTORY_ENABLED" const DirectAssociationEnabled = "DIRECT_APP_ASSOCIATION_ENABLED" -const DA_MIGRATION_ENABLED = "DA_MIGRATION_ENABLED" +const DaMigrationEnabled = "DA_MIGRATION_ENABLED" const maxRetries = 3 const IncreaseFileUploadLimit = "INCREASE_FILE_UPLOAD_LIMIT" const ScaDeltaScanEnabled = "SCA_DELTASCAN_ENABLED"