Versions used:
- SonarQube 8.9.1.44547 Developer Edition
- sonar-scanner-cli:latest Docker container running in GitLab CI
- GitLab 14.0.2 Community Edition (self-hosted)
Setup:
We’re using SonarQube to analyze our code in GitLab merge requests.
Everything seems to be working fine, including login to SonarQube via GitLab. However, there is one issue with merge request decoration.
The GitLab API URL is set to https://git.provider.com/api/v4
in the ALM integration settings (URL changed for privacy reasons), SonarQube successfully validated the configuration.
The GitLab URL in the ALM integration settings is set to https://git.provider.com
Error observed:
When the merge request includes a lot of notes and there are multiple pages to load, the merge request decoration fails as you can see from the SonarQube Compute Engine logs:
2021.07.02 13:53:36 INFO ce[AXpnfwCIV-8YgX-7qfdM][c.s.F.D.E.B] GitLab's instance URL from the scanner ('http://git.provider.com/api/v4') is overridden by the settings ('https://git.provider.com/api/v4')
2021.07.02 13:53:36 INFO ce[AXpnfwCIV-8YgX-7qfdM][c.s.F.D.E.B] GitLab's project ID from the scanner ('21') is overridden by the settings ('21')
2021.07.02 13:53:36 TRACE ce[AXpnfwCIV-8YgX-7qfdM][sql] time=0ms | sql=select pb.uuid as uuid, pb.project_uuid as projectUuid, pb.kee as kee, pb.branch_type as branchType, pb.merge_branch_uuid as mergeBranchUuid, pb.pull_request_binary as pullRequestBinary, pb.exclude_from_purge as excludeFromPurge, pb.need_issue_sync as needIssueSync from project_branches pb where pb.project_uuid = ? and pb.kee = ? and pb.branch_type = ? | params=AXkNazzUIEM8XDb7WpJn, 64, PULL_REQUEST
2021.07.02 13:53:36 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][c.s.F.D.E.D] loading notes from [https://git.provider.com/api/v4/projects/21/merge_requests/64/notes]
2021.07.02 13:53:36 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][c.s.F.D.E.D] get notes : [https://git.provider.com/api/v4/projects/21/merge_requests/64/notes]
2021.07.02 13:53:36 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][o.i.http2.Http2] >> CONNECTION 505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
2021.07.02 13:53:36 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][o.i.http2.Http2] >> 0x00000000 6 SETTINGS
2021.07.02 13:53:36 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][o.i.http2.Http2] >> 0x00000000 4 WINDOW_UPDATE
2021.07.02 13:53:36 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][o.i.c.TaskRunner] Q10073 scheduled after 0 µs: OkHttp git.provider.com
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10073 starting : OkHttp git.provider.com
2021.07.02 13:53:36 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][o.i.c.TaskRunner] Q10005 scheduled after 0 µs: OkHttp ConnectionPool
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10005 starting : OkHttp ConnectionPool
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10005 run again after 300 s : OkHttp ConnectionPool
2021.07.02 13:53:36 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][o.i.http2.Http2] >> 0x00000003 94 HEADERS END_STREAM|END_HEADERS
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10005 finished run in 345 µs: OkHttp ConnectionPool
2021.07.02 13:53:36 DEBUG ce[][o.i.http2.Http2] << 0x00000000 18 SETTINGS
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10070 scheduled after 0 µs: OkHttp git.provider.com applyAndAckSettings
2021.07.02 13:53:36 DEBUG ce[][o.i.http2.Http2] << 0x00000000 4 WINDOW_UPDATE
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10070 starting : OkHttp git.provider.com applyAndAckSettings
2021.07.02 13:53:36 DEBUG ce[][o.i.http2.Http2] << 0x00000000 0 SETTINGS ACK
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10072 scheduled after 0 µs: OkHttp git.provider.com onSettings
2021.07.02 13:53:36 DEBUG ce[][o.i.http2.Http2] >> 0x00000000 0 SETTINGS ACK
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10072 starting : OkHttp git.provider.com onSettings
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10072 finished run in 9 ms: OkHttp git.provider.com onSettings
2021.07.02 13:53:36 DEBUG ce[][o.i.c.TaskRunner] Q10070 finished run in 9 ms: OkHttp git.provider.com applyAndAckSettings
2021.07.02 13:53:37 DEBUG ce[][o.i.http2.Http2] << 0x00000003 898 HEADERS END_HEADERS
2021.07.02 13:53:37 DEBUG ce[][o.i.http2.Http2] << 0x00000003 3210 DATA
2021.07.02 13:53:37 DEBUG ce[][o.i.http2.Http2] << 0x00000003 0 DATA END_STREAM
2021.07.02 13:53:37 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][o.i.c.TaskRunner] Q10005 scheduled after 0 µs: OkHttp ConnectionPool
2021.07.02 13:53:37 DEBUG ce[][o.i.c.TaskRunner] Q10005 starting : OkHttp ConnectionPool
2021.07.02 13:53:37 DEBUG ce[][o.i.c.TaskRunner] Q10005 run again after 300 s : OkHttp ConnectionPool
2021.07.02 13:53:37 DEBUG ce[][o.i.c.TaskRunner] Q10005 finished run in 229 µs: OkHttp ConnectionPool
2021.07.02 13:53:37 TRACE ce[AXpnfwCIV-8YgX-7qfdM][c.s.F.D.E.D] loading notes payload result : [*payload hidden for privacy reasons*]
2021.07.02 13:53:37 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][c.s.F.D.E.D] loading notes from [https://git.provider.com:80/api/v4/projects/21/merge_requests/64/notes?activity_filter=all_notes&id=21¬eable_id=64&order_by=created_at&page=2&per_page=20&sort=desc]
2021.07.02 13:53:37 DEBUG ce[AXpnfwCIV-8YgX-7qfdM][c.s.F.D.E.D] get notes : [https://git.provider.com:80/api/v4/projects/21/merge_requests/64/notes?activity_filter=all_notes&id=21¬eable_id=64&order_by=created_at&page=2&per_page=20&sort=desc]
2021.07.02 13:53:37 ERROR ce[AXpnfwCIV-8YgX-7qfdM][c.s.F.D.E.A] An exception was thrown during Merge Request decoration : Unsupported or unrecognized SSL message
2021.07.02 13:53:37 TRACE ce[AXpnfwCIV-8YgX-7qfdM][sql] time=0ms | sql=insert into ce_task_message ( uuid, task_uuid, message, message_type, created_at ) values ( ?, ?, ?, ?, ? ) | params=AXpnfwvmj9Khos8f3kzO, AXpnfwCIV-8YgX-7qfdM, Merge Request decoration failed. Please check your configuration and the connectivity to GitLab, GENERIC, 1625234017254
2021.07.02 13:53:37 ERROR ce[AXpnfwCIV-8YgX-7qfdM][o.s.c.t.p.a.p.PostProjectAnalysisTasksExecutor] Execution of task class com.sonarsource.F.D.c failed
java.lang.IllegalStateException: Unsupported or unrecognized SSL message
at com.sonarsource.F.D.E.D.getAllNotes(Unknown Source)
at com.sonarsource.F.D.E.D.deleteAllUserNotes(Unknown Source)
at com.sonarsource.F.D.E.A.A(Unknown Source)
at com.sonarsource.F.D.c.A(Unknown Source)
at java.base/java.util.Optional.ifPresent(Unknown Source)
at com.sonarsource.F.D.c.B(Unknown Source)
at com.sonarsource.F.D.c.A(Unknown Source)
at org.sonar.ce.async.SynchronousAsyncExecution.addToQueue(SynchronousAsyncExecution.java:27)
at com.sonarsource.F.D.c.A(Unknown Source)
at java.base/java.util.Optional.ifPresent(Unknown Source)
at com.sonarsource.F.D.c.finished(Unknown Source)
at org.sonar.ce.task.projectanalysis.api.posttask.PostProjectAnalysisTasksExecutor.executeTask(PostProjectAnalysisTasksExecutor.java:118)
at org.sonar.ce.task.projectanalysis.api.posttask.PostProjectAnalysisTasksExecutor.finished(PostProjectAnalysisTasksExecutor.java:109)
at org.sonar.ce.task.step.ComputationStepExecutor.executeListener(ComputationStepExecutor.java:91)
at org.sonar.ce.task.step.ComputationStepExecutor.execute(ComputationStepExecutor.java:63)
at org.sonar.ce.task.projectanalysis.taskprocessor.ReportTaskProcessor.process(ReportTaskProcessor.java:81)
at org.sonar.ce.taskprocessor.CeWorkerImpl$ExecuteTask.executeTask(CeWorkerImpl.java:212)
at org.sonar.ce.taskprocessor.CeWorkerImpl$ExecuteTask.run(CeWorkerImpl.java:194)
at org.sonar.ce.taskprocessor.CeWorkerImpl.findAndProcessTask(CeWorkerImpl.java:160)
at org.sonar.ce.taskprocessor.CeWorkerImpl$TrackRunningState.get(CeWorkerImpl.java:135)
at org.sonar.ce.taskprocessor.CeWorkerImpl.call(CeWorkerImpl.java:87)
at org.sonar.ce.taskprocessor.CeWorkerImpl.call(CeWorkerImpl.java:53)
at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:125)
at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:69)
at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:78)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: javax.net.ssl.SSLException: Unsupported or unrecognized SSL message
at java.base/sun.security.ssl.SSLSocketInputRecord.handleUnknownRecord(Unknown Source)
at java.base/sun.security.ssl.SSLSocketInputRecord.decode(Unknown Source)
at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:379)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:337)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:209)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
... 31 common frames omitted
2021.07.02 13:53:37 INFO ce[AXpnfwCIV-8YgX-7qfdM][o.s.c.t.p.a.p.PostProjectAnalysisTasksExecutor] Pull Request decoration | status=FAILED | time=336ms
As you can see, there are two requests to the GitLab API, one to https://git.provider.com/api/v4/projects/21/merge_requests/64/notes
and the second one to https://git.provider.com:80/api/v4/projects/21/merge_requests/64/notes?activity_filter=all_notes&id=21¬eable_id=64&order_by=created_at&page=2&per_page=20&sort=desc
.
The first request is performed successfully and the fetched data is valid. For some reason however, SonarQube appends port 80 to the second request URL which of course breaks the SSL connection.
As said, the setup works including decoration when there are only a few notes in a merge request so something breaks when a second API call must be made.
I haven’t found a workaround for this issue yet. Any help is appreciated.