@@ -117,29 +117,66 @@ class OdsComponentStageScanWithSonarSpec extends PipelineSpockTestBase {
117117 assertJobStatusSuccess()
118118 }
119119
120- def " skips scan if not enabled in cluster and project" () {
121- given :
122- def c = config + [environment : ' dev' ]
123- IContext context = new Context (null , c, logger)
124- BitbucketService bitbucketService = Stub (BitbucketService . class)
125- ServiceRegistry . instance. add(BitbucketService , bitbucketService)
126- NexusService nexusService = Mock (NexusService . class)
127- ServiceRegistry . instance. add(NexusService , nexusService)
128- SonarQubeService sonarQubeService = Stub (SonarQubeService . class)
129- ServiceRegistry . instance. add(SonarQubeService , sonarQubeService)
130- def script = loadScript(' vars/odsComponentStageScanWithSonar.groovy' )
131- script. env. OPENSHIFT_BUILD_NAMESPACE = ' test-namespace'
132- helper. registerAllowedMethod(' emailext' , [Map ]) { Map args -> }
133- // Mock sh to return config map with enabled=false
134- helper. registerAllowedMethod(' sh' , [Map ]) { Map args -> ' {"data": {"enabled": "false", "alertEmails": "test@example.com"}}' }
135- when :
136- script. call(context)
137- then :
138- printCallStack()
139- assertCallStackContains(' SonarQube scan not enabled at cluster level' )
140- assertJobStatusSuccess()
120+ @Unroll
121+ def " enable/disable scan: clusterEnabled=#clusterEnabled, projectEnabled=#projectEnabled" () {
122+ // The configmap key for project-level override is "projects.<projectId>.enabled".
123+ // The shared config has projectId='foo', so the key is "projects.foo.enabled".
124+ // Project value always governs when the key is present; cluster value is ignored.
125+ given :
126+ def c = config + [environment : ' dev' ]
127+ IContext context = new Context (null , c, logger)
128+ BitbucketService bitbucketService = Stub (BitbucketService . class)
129+ bitbucketService. findPullRequest(* _) >> [:]
130+ ServiceRegistry . instance. add(BitbucketService , bitbucketService)
131+ NexusService nexusService = Mock (NexusService . class)
132+ ServiceRegistry . instance. add(NexusService , nexusService)
133+ SonarQubeService sonarQubeService = Stub (SonarQubeService . class)
134+ sonarQubeService. readProperties() >> [' sonar.projectKey' : ' foo' ]
135+ sonarQubeService. readTask() >> [' ceTaskId' : ' AXxaAoUSsjAMlIY9kNmn' ]
136+ sonarQubeService. scan(* _) >> null
137+ sonarQubeService. getQualityGateJSON(* _) >> ' {"projectStatus":{"status":"OK"}}'
138+ sonarQubeService. getComputeEngineTaskResult(* _) >> ' SUCCESS'
139+ sonarQubeService. getSonarQubeHostUrl() >> ' https://sonarqube.example.com'
140+ ServiceRegistry . instance. add(SonarQubeService , sonarQubeService)
141+
142+ when :
143+ def script = loadScript(' vars/odsComponentStageScanWithSonar.groovy' )
144+ script. env. WORKSPACE = tempFolder. getRoot(). absolutePath
145+ script. env. OPENSHIFT_BUILD_NAMESPACE = ' test-namespace'
146+ helper. registerAllowedMethod(' archiveArtifacts' , [Map ]) { Map args -> }
147+ helper. registerAllowedMethod(' stash' , [Map ]) { Map args -> }
148+ helper. registerAllowedMethod(' readFile' , [Map ]) { Map args -> ' ' }
149+ helper. registerAllowedMethod(' emailext' , [Map ]) { Map args -> }
150+ helper. registerAllowedMethod(' sh' , [Map ]) { Map args -> configMapJson }
151+ script. call(context)
152+
153+ then :
154+ printCallStack()
155+ assertJobStatusSuccess()
156+ if (shouldScan) {
157+ assertCallStackContains(' SonarQube Analysis' )
158+ } else {
159+ assertCallStackContains(skipReason)
160+ assertCallStackContains(' SonarQube scan not enabled' )
141161 }
142162
163+ where :
164+ // Project value always takes precedence; cluster value is irrelevant when project key is present.
165+ clusterEnabled | projectEnabled || configMapJson | shouldScan | skipReason
166+ ' true' | ' true' || ' {"data": {"enabled": "true", "projects.foo.enabled": "true"}}' | true | ' '
167+ ' true' | ' false' || ' {"data": {"enabled": "true", "projects.foo.enabled": "false"}}' | false | ' Skipping SonarQube scan because project is not enabled'
168+ // Project enabled=true overrides a disabled cluster → scan MUST run
169+ ' false' | ' true' || ' {"data": {"enabled": "false", "projects.foo.enabled": "true"}}' | true | ' '
170+ // Project disabled regardless of cluster state → scan MUST NOT run
171+ ' false' | ' false' || ' {"data": {"enabled": "false", "projects.foo.enabled": "false"}}' | false | ' Skipping SonarQube scan because project is not enabled'
172+ // Cluster enabled not explicitly set (defaults true); project value still governs
173+ ' not set' | ' true' || ' {"data": {"projects.foo.enabled": "true"}}' | true | ' '
174+ ' not set' | ' false' || ' {"data": {"projects.foo.enabled": "false"}}' | false | ' Skipping SonarQube scan because project is not enabled'
175+ // Project not set (empty map) → falls back to cluster configuration
176+ ' true' | ' not set' || ' {"data": {"enabled": "true"}}' | true | ' '
177+ ' false' | ' not set' || ' {"data": {"enabled": "false"}}' | false | ' Skipping SonarQube scan because is not enabled at cluster level'
178+ }
179+
143180 @Unroll
144181 def " checks quality gate" () {
145182 given :
0 commit comments