|
28 | 28 | import org.sonarsource.sonarlint.core.commons.log.SonarLintLogger;
|
29 | 29 | import org.sonarsource.sonarlint.core.commons.progress.SonarLintCancelMonitor;
|
30 | 30 | import org.sonarsource.sonarlint.core.repository.config.ConfigurationRepository;
|
| 31 | +import org.sonarsource.sonarlint.core.repository.connection.ConnectionConfigurationRepository; |
| 32 | +import org.sonarsource.sonarlint.core.rpc.protocol.SonarLintRpcClient; |
31 | 33 | import org.sonarsource.sonarlint.core.rpc.protocol.SonarLintRpcErrorCode;
|
32 | 34 | import org.sonarsource.sonarlint.core.rpc.protocol.backend.sca.DependencyRiskTransition;
|
33 | 35 | import org.sonarsource.sonarlint.core.rpc.protocol.backend.tracking.AffectedPackageDto;
|
34 | 36 | import org.sonarsource.sonarlint.core.rpc.protocol.backend.sca.GetDependencyRiskDetailsResponse;
|
35 | 37 | import org.sonarsource.sonarlint.core.rpc.protocol.backend.tracking.ScaIssueDto;
|
36 | 38 | import org.sonarsource.sonarlint.core.serverapi.sca.GetIssueReleaseResponse;
|
| 39 | +import org.sonarsource.sonarlint.core.rpc.protocol.client.OpenUrlInBrowserParams; |
| 40 | +import org.sonarsource.sonarlint.core.serverapi.EndpointParams; |
| 41 | +import org.sonarsource.sonarlint.core.serverapi.ServerApiHelper; |
| 42 | +import org.sonarsource.sonarlint.core.serverapi.UrlUtils; |
37 | 43 | import org.sonarsource.sonarlint.core.serverconnection.issues.ServerScaIssue;
|
38 | 44 | import org.sonarsource.sonarlint.core.storage.StorageService;
|
| 45 | +import org.sonarsource.sonarlint.core.telemetry.TelemetryService; |
39 | 46 |
|
40 | 47 | public class ScaService {
|
41 | 48 | private static final SonarLintLogger LOG = SonarLintLogger.get();
|
42 | 49 |
|
43 | 50 | private final ConfigurationRepository configurationRepository;
|
| 51 | + private final ConnectionConfigurationRepository connectionRepository; |
44 | 52 | private final StorageService storageService;
|
45 | 53 | private final SonarQubeClientManager sonarQubeClientManager;
|
46 | 54 | private final SonarProjectBranchTrackingService branchTrackingService;
|
| 55 | + private final SonarLintRpcClient client; |
| 56 | + private final TelemetryService telemetryService; |
47 | 57 |
|
48 |
| - public ScaService(ConfigurationRepository configurationRepository, StorageService storageService, SonarQubeClientManager sonarQubeClientManager, |
49 |
| - SonarProjectBranchTrackingService branchTrackingService) { |
| 58 | + public ScaService(ConfigurationRepository configurationRepository, ConnectionConfigurationRepository connectionRepository, |
| 59 | + StorageService storageService, SonarQubeClientManager sonarQubeClientManager, |
| 60 | + SonarProjectBranchTrackingService branchTrackingService, SonarLintRpcClient client, TelemetryService telemetryService) { |
50 | 61 | this.configurationRepository = configurationRepository;
|
| 62 | + this.connectionRepository = connectionRepository; |
51 | 63 | this.storageService = storageService;
|
52 | 64 | this.sonarQubeClientManager = sonarQubeClientManager;
|
53 | 65 | this.branchTrackingService = branchTrackingService;
|
| 66 | + this.client = client; |
| 67 | + this.telemetryService = telemetryService; |
54 | 68 | }
|
55 | 69 |
|
56 | 70 | public void changeStatus(String configurationScopeId, UUID issueReleaseKey, DependencyRiskTransition transition, @CheckForNull String comment,
|
@@ -139,6 +153,38 @@ private static GetDependencyRiskDetailsResponse convertToRpcResponse(GetIssueRel
|
139 | 153 | serverResponse.vulnerability().description(), affectedPackages);
|
140 | 154 | }
|
141 | 155 |
|
| 156 | + public void openDependencyRiskInBrowser(String configurationScopeId, String dependencyKey) { |
| 157 | + var effectiveBinding = configurationRepository.getEffectiveBinding(configurationScopeId); |
| 158 | + var endpointParams = effectiveBinding.flatMap(binding -> connectionRepository.getEndpointParams(binding.connectionId())); |
| 159 | + if (effectiveBinding.isEmpty() || endpointParams.isEmpty()) { |
| 160 | + LOG.warn("Configuration scope {} is not bound properly, unable to open dependency risk", configurationScopeId); |
| 161 | + return; |
| 162 | + } |
| 163 | + var branchName = branchTrackingService.awaitEffectiveSonarProjectBranch(configurationScopeId); |
| 164 | + if (branchName.isEmpty()) { |
| 165 | + LOG.warn("Configuration scope {} has no matching branch, unable to open dependency risk", configurationScopeId); |
| 166 | + return; |
| 167 | + } |
| 168 | + |
| 169 | + var url = buildScaBrowseUrl(effectiveBinding.get().sonarProjectKey(), branchName.get(), dependencyKey, endpointParams.get()); |
| 170 | + |
| 171 | + client.openUrlInBrowser(new OpenUrlInBrowserParams(url)); |
| 172 | + |
| 173 | + // TODO: Add SCA-specific telemetry method when available |
| 174 | + // telemetryService.dependencyRiskOpenedInBrowser(); |
| 175 | + } |
| 176 | + |
| 177 | + static String buildScaBrowseUrl(String projectKey, String branch, String dependencyKey, EndpointParams endpointParams) { |
| 178 | + var relativePath = "/dependency-risks/" |
| 179 | + + UrlUtils.urlEncode(dependencyKey) |
| 180 | + + "/what?id=" |
| 181 | + + UrlUtils.urlEncode(projectKey) |
| 182 | + + "&branch=" |
| 183 | + + UrlUtils.urlEncode(branch); |
| 184 | + |
| 185 | + return ServerApiHelper.concat(endpointParams.getBaseUrl(), relativePath); |
| 186 | + } |
| 187 | + |
142 | 188 | public static class ScaIssueNotFoundException extends RuntimeException {
|
143 | 189 | private final String issueKey;
|
144 | 190 |
|
|
0 commit comments