docs: @VisibleForTesting
    String upload(File report) {
      LOG.debug("Upload report");
      long startTime = System.currentTimeMillis();
      PostRequest.Part filePart = new PostRequest.Part(MediaTypes.ZIP, report);
      PostRequest post = new PostRequest("api/ce/submit")
        .setMediaType(MediaTypes.PROTOBUF)
        .setParam("organization", properties.organizationKey().orElse(null))
        .setParam("projectKey", moduleHierarchy.root().key())
        .setParam("projectName", moduleHierarchy.root().getOriginalName())
        .setParam("projectBranch", moduleHierarchy.root().getBranch())
        .setPart("report", filePart);
  
      String branchName = branchConfiguration.branchName();
      if (branchName != null) {
        if (branchConfiguration.branchType() != PULL_REQUEST) {
          post.setParam(CHARACTERISTIC, "branch=" + branchName);
          post.setParam(CHARACTERISTIC, "branchType=" + branchConfiguration.branchType().name());
        } else {
          post.setParam(CHARACTERISTIC, "pullRequest=" + branchConfiguration.pullRequestKey());
        }
      }
  
      WsResponse response;
      try {
        response = wsClient.call(post).failIfNotSuccessful();
      } catch (HttpException e) {
        throw MessageException.of(String.format("Failed to upload report - %s", ScannerWsClient.createErrorMessage(e)));
      }
  
      try (InputStream protobuf = response.contentStream()) {
        return Ce.SubmitResponse.parser().parseFrom(protobuf).getTaskId();
      } catch (Exception e) {
        throw Throwables.propagate(e);
      } finally {
        long stopTime = System.currentTimeMillis();
        LOG.info("Analysis report uploaded in " + (stopTime - startTime) + "ms");
      }
    }