]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10464 Improve error message when passing a wrong organization during the analysis
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Mon, 11 Jun 2018 08:49:18 +0000 (10:49 +0200)
committerSonarTech <sonartech@sonarsource.com>
Mon, 11 Jun 2018 18:20:49 +0000 (20:20 +0200)
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/DefaultQualityProfileLoader.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java
tests/src/test/java/org/sonarqube/tests/analysis/ScannerTest.java

index 0b2be6f39e9251b4c11056f843d4cb6655f551c9..8d68be56d4f2320013828c0c2c08e89f4195dbb0 100644 (file)
@@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.function.BinaryOperator;
+import java.util.function.Supplier;
 import javax.annotation.Nullable;
 import org.sonar.api.utils.MessageException;
 import org.sonar.scanner.bootstrap.ScannerWsClient;
@@ -33,6 +34,7 @@ import org.sonar.scanner.scan.ScanProperties;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
 import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.HttpException;
 
 import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toMap;
@@ -52,16 +54,31 @@ public class DefaultQualityProfileLoader implements QualityProfileLoader {
   @Override
   public List<QualityProfile> loadDefault(@Nullable String profileName) {
     StringBuilder url = new StringBuilder(WS_URL + "?defaults=true");
-    return loadAndOverrideIfNeeded(profileName, url);
+    return handleErrors(profileName, url, () -> "Failed to load the default quality profiles");
   }
 
   @Override
   public List<QualityProfile> load(String projectKey, @Nullable String profileName) {
     StringBuilder url = new StringBuilder(WS_URL + "?projectKey=").append(encodeForUrl(projectKey));
-    return loadAndOverrideIfNeeded(profileName, url);
+    return handleErrors(profileName, url, () -> String.format("Failed to load the quality profiles of project '%s'", projectKey));
   }
 
-  private List<QualityProfile> loadAndOverrideIfNeeded(@Nullable String profileName, StringBuilder url) {
+  private List<QualityProfile> handleErrors(@Nullable String profileName, StringBuilder url, Supplier<String> errorMsg) {
+    try {
+      return loadAndOverrideIfNeeded(profileName, url);
+    } catch (HttpException e) {
+      if (e.code() == 404) {
+        throw MessageException.of(errorMsg.get() + ": " + ScannerWsClient.tryParseAsJsonError(e.content()));
+      }
+      throw new IllegalStateException(errorMsg.get(), e);
+    } catch (MessageException e) {
+      throw e;
+    } catch (Exception e) {
+      throw new IllegalStateException(errorMsg.get(), e);
+    }
+  }
+
+  private List<QualityProfile> loadAndOverrideIfNeeded(@Nullable String profileName, StringBuilder url) throws IOException {
     properties.organizationKey().ifPresent(k -> url.append("&organization=").append(encodeForUrl(k)));
     Map<String, QualityProfile> result = call(url.toString());
 
@@ -78,16 +95,13 @@ public class DefaultQualityProfileLoader implements QualityProfileLoader {
     return new ArrayList<>(result.values());
   }
 
-  private Map<String, QualityProfile> call(String url) {
+  private Map<String, QualityProfile> call(String url) throws IOException {
     GetRequest getRequest = new GetRequest(url);
     try (InputStream is = wsClient.call(getRequest).contentStream()) {
       SearchWsResponse profiles = SearchWsResponse.parseFrom(is);
       List<QualityProfile> profilesList = profiles.getProfilesList();
       return profilesList.stream().collect(toMap(QualityProfile::getLanguage, identity(), throwingMerger(), LinkedHashMap::new));
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to load quality profiles", e);
     }
-
   }
 
   private static <T> BinaryOperator<T> throwingMerger() {
index b1786ef3ad92eae649c77f4540b9eed07252fd14..2e7f4857f8b9a006c952e07c6c3018a2803509a1 100644 (file)
@@ -33,6 +33,7 @@ import org.sonar.scanner.bootstrap.ScannerWsClient;
 import org.sonar.scanner.scan.ScanProperties;
 import org.sonarqube.ws.Qualityprofiles;
 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
+import org.sonarqube.ws.client.HttpException;
 
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -116,6 +117,18 @@ public class DefaultQualityProfileLoaderTest {
     verifyNoMoreInteractions(wsClient);
   }
 
+  @Test
+  public void load_throws_MessageException_if_organization_is_not_found() throws IOException {
+    HttpException e = new HttpException("", 404, "{\"errors\":[{\"msg\":\"No organization with key 'myorg'\"}]}");
+    WsTestUtil.mockException(wsClient, e);
+
+    exception.expect(MessageException.class);
+    exception.expectMessage("Failed to load the quality profiles of project 'project': No organization with key 'myorg'");
+
+    underTest.load("project", null);
+    verifyNoMoreInteractions(wsClient);
+  }
+
   private void verifyCalledPath(String expectedPath) {
     WsTestUtil.verifyCall(wsClient, expectedPath);
   }
index 1e9c7eeab54dc2d09c490948f879fd7c7bdef889..2f8aafeaee9c966667b39cc86e624dd99e8aaec2 100644 (file)
@@ -26,10 +26,12 @@ import java.io.File;
 import java.io.IOException;
 import java.util.Map;
 import org.apache.commons.io.FileUtils;
+import org.apache.http.MessageConstraintException;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonarqube.qa.util.Tester;
 import org.sonarqube.tests.Category3Suite;
@@ -55,6 +57,9 @@ public class ScannerTest {
   @Rule
   public Tester tester = new Tester(orchestrator).disableOrganizations();
 
+  @Rule
+  public ExpectedException exception = ExpectedException.none();
+
   @Before
   public void setUp() {
     ItUtils.restoreProfile(orchestrator, getClass().getResource("/analysis/BatchTest/one-issue-per-line.xml"));
@@ -251,13 +256,13 @@ public class ScannerTest {
 
     File cache = new File(userHome, "cache");
     assertThat(cache).exists().isDirectory();
-    int cachedFiles = FileUtils.listFiles(cache, new String[]{"jar"}, true).size();
+    int cachedFiles = FileUtils.listFiles(cache, new String[] {"jar"}, true).size();
     assertThat(cachedFiles).isGreaterThan(5);
     assertThat(result.getLogs()).contains("User cache: " + cache.getAbsolutePath());
 
     result = scan("shared/xoo-sample",
       "sonar.userHome", userHome.getAbsolutePath());
-    int cachedFiles2 = FileUtils.listFiles(cache, new String[]{"jar"}, true).size();
+    int cachedFiles2 = FileUtils.listFiles(cache, new String[] {"jar"}, true).size();
     assertThat(cachedFiles).isEqualTo(cachedFiles2);
     assertThat(result.getLogs()).contains("User cache: " + cache.getAbsolutePath());
   }
@@ -380,6 +385,15 @@ public class ScannerTest {
     assertThat(getComponent(orchestrator, "com.sonarsource.it.samples:moduleB")).isNotNull();
   }
 
+  @Test
+  public void use_invalid_organization_key() {
+    BuildResult result = scanQuietly("shared/xoo-sample",
+      "sonar.organization", "non-existing-org");
+
+    assertThat(result.isSuccess()).isFalse();
+    assertThat(result.getLogs()).contains("Failed to load the default quality profiles: No organization with key 'non-existing-org'");
+  }
+
   private BuildResult scan(String projectPath, String... props) {
     SonarScanner scanner = configureScanner(projectPath, props);
     return orchestrator.executeBuild(scanner);