]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11707 Return branch QG status conditions in WS
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Fri, 8 Feb 2019 22:10:11 +0000 (16:10 -0600)
committerSonarTech <sonartech@sonarsource.com>
Mon, 11 Mar 2019 19:21:02 +0000 (20:21 +0100)
server/sonar-server/src/main/java/org/sonar/server/component/ComponentFinder.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWsParameters.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygates/ProjectStatusRequest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygates/QualitygatesService.java

index aef692f52be435d52af808ff0429d5810f58aff8..847d9d68653c640aaabd08596ad77e85aac1c92b 100644 (file)
@@ -133,9 +133,6 @@ public class ComponentFinder {
     return checkFoundWithOptional(organizationDto, "Organization with uuid '%s' not found", organizationUuid);
   }
 
-  /**
-   * Components of the main branch won't be found
-   */
   public ComponentDto getByKeyAndBranch(DbSession dbSession, String key, String branch) {
     Optional<ComponentDto> componentDto = dbClient.componentDao().selectByKeyAndBranch(dbSession, key, branch);
     if (componentDto.isPresent() && componentDto.get().isEnabled()) {
index 0284864ba8ac25ed7a17ebb90718a476d57d9d37..904ade20796b2b1d417ad5239db8e33960df38e1 100644 (file)
@@ -38,7 +38,6 @@ import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.measure.LiveMeasureDto;
 import org.sonar.db.measure.MeasureDto;
 import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.component.ComponentFinder.ParamNames;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.ws.KeyExamples;
@@ -47,8 +46,10 @@ import org.sonarqube.ws.Qualitygates.ProjectStatusResponse;
 import static com.google.common.base.Strings.isNullOrEmpty;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.ACTION_PROJECT_STATUS;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ANALYSIS_ID;
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_BRANCH;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PROJECT_ID;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PROJECT_KEY;
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PULL_REQUEST;
 import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
 import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
 import static org.sonar.server.ws.WsUtils.checkRequest;
@@ -58,7 +59,8 @@ public class ProjectStatusAction implements QualityGatesWsAction {
   private static final String QG_STATUSES_ONE_LINE = Arrays.stream(ProjectStatusResponse.Status.values())
     .map(Enum::toString)
     .collect(Collectors.joining(", "));
-  private static final String MSG_ONE_PARAMETER_ONLY = String.format("Either '%s', '%s' or '%s' must be provided", PARAM_ANALYSIS_ID, PARAM_PROJECT_ID, PARAM_PROJECT_KEY);
+  private static final String MSG_ONE_PROJECT_PARAMETER_ONLY = String.format("Either '%s', '%s' or '%s' must be provided", PARAM_ANALYSIS_ID, PARAM_PROJECT_ID, PARAM_PROJECT_KEY);
+  private static final String MSG_ONE_BRANCH_PARAMETER_ONLY = String.format("Either '%s' or '%s' can be provided, not both", PARAM_BRANCH, PARAM_PULL_REQUEST);
 
   private final DbClient dbClient;
   private final ComponentFinder componentFinder;
@@ -74,7 +76,7 @@ public class ProjectStatusAction implements QualityGatesWsAction {
   public void define(WebService.NewController controller) {
     WebService.NewAction action = controller.createAction(ACTION_PROJECT_STATUS)
       .setDescription(String.format("Get the quality gate status of a project or a Compute Engine task.<br />" +
-        MSG_ONE_PARAMETER_ONLY + "<br />" +
+        MSG_ONE_PROJECT_PARAMETER_ONLY + "<br />" +
         "The different statuses returned are: %s. The %s status is returned when there is no quality gate associated with the analysis.<br />" +
         "Returns an HTTP code 404 if the analysis associated with the task is not found or does not exist.<br />" +
         "Requires one of the following permissions:" +
@@ -87,6 +89,7 @@ public class ProjectStatusAction implements QualityGatesWsAction {
       .setSince("5.3")
       .setHandler(this)
       .setChangelog(
+        new Change("7.7", "The parameters 'branch' and 'pullRequest' were added"),
         new Change("7.6", "The field 'warning' is deprecated from the response"),
         new Change("6.4", "The field 'ignoredConditions' is added to the response"));
 
@@ -96,13 +99,23 @@ public class ProjectStatusAction implements QualityGatesWsAction {
 
     action.createParam(PARAM_PROJECT_ID)
       .setSince("5.4")
-      .setDescription("Project id")
+      .setDescription("Project id. Doesn't work with branches or pull requests")
       .setExampleValue(Uuids.UUID_EXAMPLE_01);
 
     action.createParam(PARAM_PROJECT_KEY)
       .setSince("5.4")
       .setDescription("Project key")
       .setExampleValue(KeyExamples.KEY_PROJECT_EXAMPLE_001);
+
+    action.createParam(PARAM_BRANCH)
+      .setSince("7.7")
+      .setDescription("Branch key")
+      .setExampleValue(KeyExamples.KEY_BRANCH_EXAMPLE_001);
+
+    action.createParam(PARAM_PULL_REQUEST)
+      .setSince("7.7")
+      .setDescription("Pull request id")
+      .setExampleValue(KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001);
   }
 
   @Override
@@ -110,20 +123,24 @@ public class ProjectStatusAction implements QualityGatesWsAction {
     String analysisId = request.param(PARAM_ANALYSIS_ID);
     String projectId = request.param(PARAM_PROJECT_ID);
     String projectKey = request.param(PARAM_PROJECT_KEY);
+    String branchKey = request.param(PARAM_BRANCH);
+    String pullRequestId = request.param(PARAM_PULL_REQUEST);
     checkRequest(
       !isNullOrEmpty(analysisId)
         ^ !isNullOrEmpty(projectId)
         ^ !isNullOrEmpty(projectKey),
-      MSG_ONE_PARAMETER_ONLY);
+      MSG_ONE_PROJECT_PARAMETER_ONLY);
+    checkRequest(isNullOrEmpty(branchKey) || isNullOrEmpty(pullRequestId), MSG_ONE_BRANCH_PARAMETER_ONLY);
 
     try (DbSession dbSession = dbClient.openSession(false)) {
-      ProjectStatusResponse projectStatusResponse = doHandle(dbSession, analysisId, projectId, projectKey);
+      ProjectStatusResponse projectStatusResponse = doHandle(dbSession, analysisId, projectId, projectKey, branchKey, pullRequestId);
       writeProtobuf(projectStatusResponse, request, response);
     }
   }
 
-  private ProjectStatusResponse doHandle(DbSession dbSession, @Nullable String analysisId, @Nullable String projectId, @Nullable String projectKey) {
-    ProjectAndSnapshot projectAndSnapshot = getProjectAndSnapshot(dbSession, analysisId, projectId, projectKey);
+  private ProjectStatusResponse doHandle(DbSession dbSession, @Nullable String analysisId, @Nullable String projectId,
+    @Nullable String projectKey, @Nullable String branchKey, @Nullable String pullRequestId) {
+    ProjectAndSnapshot projectAndSnapshot = getProjectAndSnapshot(dbSession, analysisId, projectId, projectKey, branchKey, pullRequestId);
     checkPermission(projectAndSnapshot.project);
     Optional<String> measureData = loadQualityGateDetails(dbSession, projectAndSnapshot, analysisId != null);
 
@@ -132,19 +149,26 @@ public class ProjectStatusAction implements QualityGatesWsAction {
       .build();
   }
 
-  private ProjectAndSnapshot getProjectAndSnapshot(DbSession dbSession, @Nullable String analysisId, @Nullable String projectId, @Nullable String projectKey) {
+  private ProjectAndSnapshot getProjectAndSnapshot(DbSession dbSession, @Nullable String analysisId, @Nullable String projectId,
+    @Nullable String projectKey, @Nullable String branchKey, @Nullable String pullRequestId) {
     if (!isNullOrEmpty(analysisId)) {
       return getSnapshotThenProject(dbSession, analysisId);
     }
     if (!isNullOrEmpty(projectId) ^ !isNullOrEmpty(projectKey)) {
-      return getProjectThenSnapshot(dbSession, projectId, projectKey);
+      return getProjectThenSnapshot(dbSession, projectId, projectKey, branchKey, pullRequestId);
     }
 
-    throw BadRequestException.create(MSG_ONE_PARAMETER_ONLY);
+    throw BadRequestException.create(MSG_ONE_PROJECT_PARAMETER_ONLY);
   }
 
-  private ProjectAndSnapshot getProjectThenSnapshot(DbSession dbSession, String projectId, String projectKey) {
-    ComponentDto projectDto = componentFinder.getByUuidOrKey(dbSession, projectId, projectKey, ParamNames.PROJECT_ID_AND_KEY);
+  private ProjectAndSnapshot getProjectThenSnapshot(DbSession dbSession, @Nullable String projectId, @Nullable String projectKey,
+    @Nullable String branchKey, @Nullable String pullRequestId) {
+    ComponentDto projectDto;
+    if (projectId != null) {
+      projectDto = componentFinder.getRootComponentByUuidOrKey(dbSession, projectId, null);
+    } else {
+      projectDto = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, projectKey, branchKey, pullRequestId);
+    }
     Optional<SnapshotDto> snapshot = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, projectDto.projectUuid());
     return new ProjectAndSnapshot(projectDto, snapshot.orElse(null));
   }
index f5d763635fb37e80df2b00f5db8dfb334772bd7f..608e18a8b7da197ef878934406e31a8650e363bb 100644 (file)
@@ -32,6 +32,8 @@ public class QualityGatesWsParameters {
 
   static final String PARAM_ORGANIZATION = "organization";
   public static final String PARAM_ANALYSIS_ID = "analysisId";
+  public static final String PARAM_BRANCH = "branch";
+  public static final String PARAM_PULL_REQUEST = "pullRequest";
   public static final String PARAM_PROJECT_ID = "projectId";
   public static final String PARAM_PROJECT_KEY = "projectKey";
   public static final String PARAM_PAGE_SIZE = "pageSize";
index 19d7b9481ac8183489c41f5113291a3f847a7f9e..4dfcc43009a710d334c8756e3368558ce47a44b8 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchType;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.metric.MetricDto;
@@ -52,9 +53,11 @@ import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
 import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
 import static org.sonar.db.metric.MetricTesting.newMetricDto;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ANALYSIS_ID;
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_BRANCH;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ORGANIZATION;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PROJECT_ID;
 import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PROJECT_KEY;
+import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PULL_REQUEST;
 import static org.sonar.test.JsonAssert.assertJson;
 
 public class ProjectStatusActionTest {
@@ -80,7 +83,9 @@ public class ProjectStatusActionTest {
       .containsExactlyInAnyOrder(
         tuple("analysisId", false),
         tuple("projectKey", false),
-        tuple("projectId", false));
+        tuple("projectId", false),
+        tuple("branch", false),
+        tuple("pullRequest", false));
   }
 
   @Test
@@ -159,6 +164,38 @@ public class ProjectStatusActionTest {
     assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json"));
   }
 
+  @Test
+  public void return_past_status_when_branch_is_referenced_by_past_analysis_id() throws IOException {
+    OrganizationDto organization = db.organizations().insert();
+    ComponentDto project = db.components().insertPrivateProject(organization);
+    ComponentDto branch = db.components().insertProjectBranch(project);
+    SnapshotDto pastAnalysis = dbClient.snapshotDao().insert(dbSession, newAnalysis(branch)
+      .setLast(false)
+      .setPeriodMode("last_version")
+      .setPeriodParam("2015-12-07")
+      .setPeriodDate(956789123987L));
+    SnapshotDto lastAnalysis = dbClient.snapshotDao().insert(dbSession, newAnalysis(branch)
+      .setLast(true)
+      .setPeriodMode("last_version")
+      .setPeriodParam("2016-12-07")
+      .setPeriodDate(1_500L));
+    MetricDto gateDetailsMetric = insertGateDetailMetric();
+    dbClient.measureDao().insert(dbSession,
+      newMeasureDto(gateDetailsMetric, branch, pastAnalysis)
+        .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionTest/measure_data.json"))));
+    dbClient.measureDao().insert(dbSession,
+      newMeasureDto(gateDetailsMetric, branch, lastAnalysis)
+        .setData("not_used"));
+    dbSession.commit();
+    userSession.addProjectPermission(UserRole.USER, project);
+
+    String response = ws.newRequest()
+      .setParam(PARAM_ANALYSIS_ID, pastAnalysis.getUuid())
+      .execute().getInput();
+
+    assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json"));
+  }
+
   @Test
   public void return_live_status_when_project_is_referenced_by_its_key() throws IOException {
     OrganizationDto organization = db.organizations().insert();
@@ -181,6 +218,56 @@ public class ProjectStatusActionTest {
     assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json"));
   }
 
+  @Test
+  public void return_live_status_when_branch_is_referenced_by_its_key() throws IOException {
+    OrganizationDto organization = db.organizations().insert();
+    ComponentDto project = db.components().insertPrivateProject(organization);
+    ComponentDto branch = db.components().insertProjectBranch(project);
+
+    dbClient.snapshotDao().insert(dbSession, newAnalysis(branch)
+      .setPeriodMode("last_version")
+      .setPeriodParam("2015-12-07")
+      .setPeriodDate(956789123987L));
+    MetricDto gateDetailsMetric = insertGateDetailMetric();
+    dbClient.liveMeasureDao().insert(dbSession,
+      newLiveMeasure(branch, gateDetailsMetric)
+        .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionTest/measure_data.json"))));
+    dbSession.commit();
+    userSession.addProjectPermission(UserRole.USER, project);
+
+    String response = ws.newRequest()
+      .setParam(PARAM_PROJECT_KEY, project.getKey())
+      .setParam(PARAM_BRANCH, branch.getBranch())
+      .execute().getInput();
+
+    assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json"));
+  }
+
+  @Test
+  public void return_live_status_when_pull_request_is_referenced_by_its_key() throws IOException {
+    OrganizationDto organization = db.organizations().insert();
+    ComponentDto project = db.components().insertPrivateProject(organization);
+    ComponentDto pr = db.components().insertProjectBranch(project, branch -> branch.setBranchType(BranchType.PULL_REQUEST));
+
+    dbClient.snapshotDao().insert(dbSession, newAnalysis(pr)
+      .setPeriodMode("last_version")
+      .setPeriodParam("2015-12-07")
+      .setPeriodDate(956789123987L));
+    MetricDto gateDetailsMetric = insertGateDetailMetric();
+    dbClient.liveMeasureDao().insert(dbSession,
+      newLiveMeasure(pr, gateDetailsMetric)
+        .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionTest/measure_data.json"))));
+    dbSession.commit();
+    userSession.addProjectPermission(UserRole.USER, project);
+
+    String response = ws.newRequest()
+      .setParam(PARAM_PROJECT_KEY, project.getKey())
+      .setParam(PARAM_PULL_REQUEST, pr.getPullRequest())
+      .execute().getInput();
+
+    assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json"));
+  }
+
   @Test
   public void return_undefined_status_if_specified_analysis_is_not_found() {
     OrganizationDto organization = db.organizations().insert();
@@ -294,6 +381,23 @@ public class ProjectStatusActionTest {
       .execute().getInput();
   }
 
+  @Test
+  public void fail_if_branch_key_and_pull_request_id_provided() {
+    OrganizationDto organization = db.organizations().insert();
+    ComponentDto project = db.components().insertPrivateProject(organization);
+    logInAsSystemAdministrator();
+
+    expectedException.expect(BadRequestException.class);
+    expectedException.expectMessage("Either 'branch' or 'pullRequest' can be provided, not both");
+
+    ws.newRequest()
+      .setParam(PARAM_PROJECT_KEY, "key")
+      .setParam(PARAM_BRANCH, "branch")
+      .setParam(PARAM_PULL_REQUEST, "pr")
+      .setParam(PARAM_ORGANIZATION, organization.getKey())
+      .execute().getInput();
+  }
+
   @Test
   public void fail_if_no_parameter_provided() {
     logInAsSystemAdministrator();
@@ -332,7 +436,7 @@ public class ProjectStatusActionTest {
     SnapshotDto snapshot = db.components().insertSnapshot(branch);
 
     expectedException.expect(NotFoundException.class);
-    expectedException.expectMessage(format("Component id '%s' not found", branch.uuid()));
+    expectedException.expectMessage(format("Project id '%s' not found", branch.uuid()));
 
     ws.newRequest()
       .setParam("projectId", branch.uuid())
index c1d79dab65f3c2982a948585e3c9c878c725a1a6..08598155b2f98b42040301b349f665fe5e87bf49 100644 (file)
@@ -34,6 +34,8 @@ public class ProjectStatusRequest {
   private String analysisId;
   private String projectId;
   private String projectKey;
+  private String branch;
+  private String pullRequest;
 
   /**
    * Example value: "AU-TpxcA-iU5OvuD2FL1"
@@ -70,4 +72,22 @@ public class ProjectStatusRequest {
   public String getProjectKey() {
     return projectKey;
   }
+
+  public String getBranch() {
+    return branch;
+  }
+
+  public ProjectStatusRequest setBranch(String branch) {
+    this.branch = branch;
+    return this;
+  }
+
+  public String getPullRequest() {
+    return pullRequest;
+  }
+
+  public ProjectStatusRequest setPullRequest(String pullRequest) {
+    this.pullRequest = pullRequest;
+    return this;
+  }
 }
index 12c7331f0d3bea8f931825333aeea0780d11697b..b7634f9c0b7e17c3aeccd2d184df00d9a760e430 100644 (file)
  */
 package org.sonarqube.ws.client.qualitygates;
 
-import java.util.stream.Collectors;
 import javax.annotation.Generated;
 import org.sonarqube.ws.MediaTypes;
-import org.sonarqube.ws.client.BaseService;
-import org.sonarqube.ws.client.GetRequest;
-import org.sonarqube.ws.client.PostRequest;
-import org.sonarqube.ws.client.WsConnector;
-import org.sonarqube.ws.Qualitygates.CreateResponse;
 import org.sonarqube.ws.Qualitygates.CreateConditionResponse;
+import org.sonarqube.ws.Qualitygates.CreateResponse;
 import org.sonarqube.ws.Qualitygates.GetByProjectResponse;
 import org.sonarqube.ws.Qualitygates.ListWsResponse;
 import org.sonarqube.ws.Qualitygates.ProjectStatusResponse;
 import org.sonarqube.ws.Qualitygates.SearchResponse;
 import org.sonarqube.ws.Qualitygates.ShowWsResponse;
 import org.sonarqube.ws.Qualitygates.UpdateConditionResponse;
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.PostRequest;
+import org.sonarqube.ws.client.WsConnector;
 
 /**
  * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates">Further information about this web service online</a>
@@ -46,9 +45,9 @@ public class QualitygatesService extends BaseService {
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/copy">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -59,13 +58,13 @@ public class QualitygatesService extends BaseService {
         .setParam("name", request.getName())
         .setParam("organization", request.getOrganization())
         .setMediaType(MediaTypes.JSON)
-      ).content();
+    ).content();
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/create">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -78,9 +77,9 @@ public class QualitygatesService extends BaseService {
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/create_condition">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -96,9 +95,9 @@ public class QualitygatesService extends BaseService {
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/delete_condition">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -108,13 +107,13 @@ public class QualitygatesService extends BaseService {
         .setParam("id", request.getId())
         .setParam("organization", request.getOrganization())
         .setMediaType(MediaTypes.JSON)
-      ).content();
+    ).content();
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/deselect">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -125,13 +124,13 @@ public class QualitygatesService extends BaseService {
         .setParam("projectId", request.getProjectId())
         .setParam("projectKey", request.getProjectKey())
         .setMediaType(MediaTypes.JSON)
-      ).content();
+    ).content();
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/destroy">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -141,13 +140,13 @@ public class QualitygatesService extends BaseService {
         .setParam("id", request.getId())
         .setParam("organization", request.getOrganization())
         .setMediaType(MediaTypes.JSON)
-      ).content();
+    ).content();
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a GET request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/get_by_project">Further information about this action online (including a response example)</a>
    * @since 6.1
    */
@@ -160,9 +159,9 @@ public class QualitygatesService extends BaseService {
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a GET request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/list">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -174,9 +173,9 @@ public class QualitygatesService extends BaseService {
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a GET request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/project_status">Further information about this action online (including a response example)</a>
    * @since 5.3
    */
@@ -185,14 +184,16 @@ public class QualitygatesService extends BaseService {
       new GetRequest(path("project_status"))
         .setParam("analysisId", request.getAnalysisId())
         .setParam("projectId", request.getProjectId())
-        .setParam("projectKey", request.getProjectKey()),
+        .setParam("projectKey", request.getProjectKey())
+        .setParam("branch", request.getBranch())
+        .setParam("pullRequest", request.getPullRequest()),
       ProjectStatusResponse.parser());
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/rename">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -203,13 +204,13 @@ public class QualitygatesService extends BaseService {
         .setParam("name", request.getName())
         .setParam("organization", request.getOrganization())
         .setMediaType(MediaTypes.JSON)
-      ).content();
+    ).content();
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a GET request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/search">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -226,9 +227,9 @@ public class QualitygatesService extends BaseService {
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/select">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -240,13 +241,13 @@ public class QualitygatesService extends BaseService {
         .setParam("projectId", request.getProjectId())
         .setParam("projectKey", request.getProjectKey())
         .setMediaType(MediaTypes.JSON)
-      ).content();
+    ).content();
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/set_as_default">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -256,13 +257,13 @@ public class QualitygatesService extends BaseService {
         .setParam("id", request.getId())
         .setParam("organization", request.getOrganization())
         .setMediaType(MediaTypes.JSON)
-      ).content();
+    ).content();
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a GET request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/show">Further information about this action online (including a response example)</a>
    * @since 4.3
    */
@@ -276,9 +277,9 @@ public class QualitygatesService extends BaseService {
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/unset_default">Further information about this action online (including a response example)</a>
    * @since 4.3
    * @deprecated since 7.0
@@ -288,13 +289,13 @@ public class QualitygatesService extends BaseService {
     return call(
       new PostRequest(path("unset_default"))
         .setMediaType(MediaTypes.JSON)
-      ).content();
+    ).content();
   }
 
   /**
-   *
    * This is part of the internal API.
    * This is a POST request.
+   *
    * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/qualitygates/update_condition">Further information about this action online (including a response example)</a>
    * @since 4.3
    */