]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11950 add revision to webhooks
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 6 May 2019 14:46:53 +0000 (16:46 +0200)
committerSonarTech <sonartech@sonarsource.com>
Wed, 22 May 2019 18:21:17 +0000 (20:21 +0200)
13 files changed:
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/webhook/WebhookPostTask.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/webhook/WebhookPostTaskTest.java
server/sonar-server-common/src/main/java/org/sonar/server/webhook/Analysis.java
server/sonar-server-common/src/main/java/org/sonar/server/webhook/WebhookPayloadFactoryImpl.java
server/sonar-server-common/src/test/java/org/sonar/server/webhook/AnalysisTest.java
server/sonar-server-common/src/test/java/org/sonar/server/webhook/ProjectAnalysisTest.java
server/sonar-server-common/src/test/java/org/sonar/server/webhook/WebhookPayloadFactoryImplTest.java
server/sonar-server/src/main/java/org/sonar/server/webhook/WebhookQGChangeEventListener.java
server/sonar-server/src/test/java/org/sonar/server/webhook/WebhookQGChangeEventListenerTest.java
sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/Analysis.java
sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTask.java
sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTester.java

index a75d150d79c8d5399c6b31295ccdee2e6eba5d11..1857c6205dd0e70747755d9f8cb9e3c0ff7f318c 100644 (file)
@@ -142,7 +142,7 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor
     Long analysisDate = getAnalysisDate();
 
     if (analysisDate != null) {
-      return of(new AnalysisImpl(analysisMetadataHolder.getUuid(), analysisDate));
+      return of(new AnalysisImpl(analysisMetadataHolder.getUuid(), analysisDate, analysisMetadataHolder.getScmRevisionId()));
     }
     return empty();
   }
@@ -305,10 +305,12 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor
 
     private final String analysisUuid;
     private final long date;
+    private final Optional<String> revision;
 
-    private AnalysisImpl(String analysisUuid, long date) {
+    private AnalysisImpl(String analysisUuid, long date, Optional<String> revision) {
       this.analysisUuid = analysisUuid;
       this.date = date;
+      this.revision = revision;
     }
 
     @Override
@@ -320,6 +322,11 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor
     public Date getDate() {
       return new Date(date);
     }
+
+    @Override
+    public Optional<String> getRevision() {
+      return revision;
+    }
   }
 
   private static class OrganizationImpl implements Organization {
index 5976e7a1a6d8ca8fed34e6b2d866f34caf472d5c..24dfcca429456495137c3095d0b797ea59191e20 100644 (file)
@@ -52,7 +52,7 @@ public class WebhookPostTask implements PostProjectAnalysisTask {
 
   private static org.sonar.server.webhook.ProjectAnalysis convert(ProjectAnalysis projectAnalysis) {
     CeTask ceTask = new CeTask(projectAnalysis.getCeTask().getId(), CeTask.Status.valueOf(projectAnalysis.getCeTask().getStatus().name()));
-    Analysis analysis = projectAnalysis.getAnalysis().map(a -> new Analysis(a.getAnalysisUuid(), a.getDate().getTime())).orElse(null);
+    Analysis analysis = projectAnalysis.getAnalysis().map(a -> new Analysis(a.getAnalysisUuid(), a.getDate().getTime(), a.getRevision().orElse(null))).orElse(null);
     Branch branch = projectAnalysis.getBranch().map(b -> new Branch(b.isMain(), b.getName().orElse(null), Branch.Type.valueOf(b.getType().name()))).orElse(null);
     EvaluatedQualityGate qualityGate = Optional.ofNullable(projectAnalysis.getQualityGate())
       .map(QGToEvaluatedQG.INSTANCE)
index 06ce02ea14adc9c84a544d8857d84bc70d942861..0c1f81032f650cb3aa9e741d99600e4118b5ca35 100644 (file)
@@ -157,7 +157,7 @@ public class WebhookPostTaskTest {
     verify(payloadFactory).create(new ProjectAnalysis(
       new org.sonar.server.webhook.Project(project.getUuid(), project.getKey(), project.getName()),
       new org.sonar.server.webhook.CeTask(ceTask.getId(), org.sonar.server.webhook.CeTask.Status.valueOf(ceTask.getStatus().name())),
-      analysisUUid == null ? null : new Analysis(analysisUUid, date.getTime()),
+      analysisUUid == null ? null : new Analysis(analysisUUid, date.getTime(), null),
       new org.sonar.server.webhook.Branch(branch.isMain(), branch.getName().get(), org.sonar.server.webhook.Branch.Type.valueOf(branch.getType().name())),
       webQualityGate,
       analysisUUid == null ? null : date.getTime(),
index 441085257ece05f7f565a4c6001bf2da8552c439..a3433037f75b6b4bacbbe46faeec136992054427 100644 (file)
  */
 package org.sonar.server.webhook;
 
-import com.google.common.base.Objects;
-import java.util.Date;
+import java.util.Objects;
+import java.util.Optional;
+import javax.annotation.Nullable;
 
 import static java.util.Objects.requireNonNull;
 
 public final class Analysis {
   private final String uuid;
   private final long date;
+  @Nullable
+  private final String revision;
 
-  public Analysis(String uuid, long date) {
-    requireNonNull(uuid, "uuid must not be null");
-    this.uuid = uuid;
+  public Analysis(String uuid, long date, @Nullable String revision) {
+    this.uuid = requireNonNull(uuid, "uuid must not be null");
     this.date = date;
+    this.revision = revision;
   }
 
   public String getUuid() {
     return uuid;
   }
 
-  public Date getDate() {
-    return new Date(date);
+  public long getDate() {
+    return date;
+  }
+
+  public Optional<String> getRevision() {
+    return Optional.ofNullable(revision);
   }
 
   @Override
@@ -47,17 +54,18 @@ public final class Analysis {
     if (this == o) {
       return true;
     }
-    if (!(o instanceof Analysis)) {
+    if (o == null || getClass() != o.getClass()) {
       return false;
     }
     Analysis analysis = (Analysis) o;
-    return Objects.equal(uuid, analysis.uuid) &&
-      Objects.equal(date, analysis.date);
+    return date == analysis.date &&
+      uuid.equals(analysis.uuid) &&
+      Objects.equals(revision, analysis.revision);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hashCode(uuid, date);
+    return Objects.hash(uuid, date, revision);
   }
 
   @Override
@@ -65,6 +73,7 @@ public final class Analysis {
     return "Analysis{" +
       "uuid='" + uuid + '\'' +
       ", date=" + date +
+      ", revision=" + revision +
       '}';
   }
 }
index 2a683181b5195ab611d4234ff73f78c845667d93..d8ae1ce0a00c481bb017fea9eb16fd43378afca0 100644 (file)
@@ -58,7 +58,7 @@ public class WebhookPayloadFactoryImpl implements WebhookPayloadFactory {
       writer.beginObject();
       writeServer(writer);
       writeTask(writer, analysis.getCeTask());
-      writeDates(writer, analysis, system2);
+      writeAnalysis(writer, analysis, system2);
       writeProject(analysis, writer, analysis.getProject());
       analysis.getBranch().ifPresent(b -> writeBranch(writer, analysis.getProject(), b));
       analysis.getQualityGate().ifPresent(qualityGate -> writeQualityGate(writer, qualityGate));
@@ -72,8 +72,11 @@ public class WebhookPayloadFactoryImpl implements WebhookPayloadFactory {
     writer.prop("serverUrl", server.getPublicRootUrl());
   }
 
-  private static void writeDates(JsonWriter writer, ProjectAnalysis analysis, System2 system2) {
-    analysis.getAnalysis().ifPresent(a -> writer.propDateTime("analysedAt", a.getDate()));
+  private static void writeAnalysis(JsonWriter writer, ProjectAnalysis analysis, System2 system2) {
+    analysis.getAnalysis().ifPresent(a -> {
+      writer.propDateTime("analysedAt", new Date(a.getDate()));
+      a.getRevision().ifPresent(rev -> writer.prop("revision", rev));
+    });
     writer.propDateTime("changedAt", new Date(analysis.getUpdatedAt().orElse(system2.now())));
   }
 
index 561e99f7886d2dc705799188df6fbb303802276c..538a14da2f0aee372b9de61f0db7f6f590589726 100644 (file)
  */
 package org.sonar.server.webhook;
 
-import java.util.Date;
-import java.util.Random;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
-import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class AnalysisTest {
@@ -38,32 +35,17 @@ public class AnalysisTest {
     expectedException.expect(NullPointerException.class);
     expectedException.expectMessage("uuid must not be null");
 
-    new Analysis(null, 1_990L);
+    new Analysis(null, 1_990L, "abcde");
   }
 
   @Test
-  public void test_equality() {
-    String uuid = randomAlphanumeric(35);
-    long date = new Random().nextLong();
-    Analysis underTest = new Analysis(uuid, date);
-
-    assertThat(underTest).isEqualTo(underTest);
-    assertThat(underTest.getUuid()).isEqualTo(uuid);
-    assertThat(underTest.getDate()).isEqualTo(new Date(date));
-
-    assertThat(underTest).isNotEqualTo(null);
-    assertThat(underTest).isNotEqualTo(new Analysis(uuid + "1", date));
-    assertThat(underTest).isNotEqualTo(new Analysis(uuid, date + 1_000L));
-  }
-
-  @Test
-  public void test_hashcode() {
-    String uuid = randomAlphanumeric(35);
-    long date = new Random().nextLong();
-    Analysis underTest = new Analysis(uuid, date);
-
-    assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode());
-    assertThat(underTest.hashCode()).isNotEqualTo(new Analysis(uuid + "1", date).hashCode());
-    assertThat(underTest.hashCode()).isNotEqualTo(new Analysis(uuid, date + 1_000).hashCode());
+  public void test_bean() {
+    Analysis analysis = new Analysis("u1", 1_990L, "abcde");
+    assertThat(analysis.getUuid()).isEqualTo("u1");
+    assertThat(analysis.getDate()).isEqualTo(1_990L);
+    assertThat(analysis.getRevision()).hasValue("abcde");
+
+    analysis = new Analysis("u1", 1_990L, null);
+    assertThat(analysis.getRevision()).isEmpty();
   }
 }
index 6cb28a0b0f344127c04e3ca5a586d43b7176335d..e7a0b26e2140abe8b3e936193c53fe5169cfedf4 100644 (file)
@@ -38,7 +38,7 @@ public class ProjectAnalysisTest {
 
   private final CeTask ceTask = new CeTask("id", CeTask.Status.SUCCESS);
   private final Project project = new Project("uuid", "key", "name");
-  private final Analysis analysis = new Analysis("analysis_uuid", 1_500L);
+  private final Analysis analysis = new Analysis("analysis_uuid", 1_500L, "sha1");
   private final Branch branch = new Branch(true, "name", Branch.Type.SHORT);
   private final EvaluatedQualityGate qualityGate = EvaluatedQualityGate.newBuilder()
     .setQualityGate(new QualityGate("id", "name", emptySet()))
@@ -103,7 +103,7 @@ public class ProjectAnalysisTest {
     assertThat(underTest).isNotEqualTo(new ProjectAnalysis(new Project("A", "B", "C"), ceTask, analysis, branch, qualityGate, 1L, properties));
     assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, null, null, null, qualityGate, 1L, properties));
     assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, null, null, qualityGate, 1L, properties));
-    assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, new Analysis("foo", 1_500L), null, qualityGate, 1L, properties));
+    assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, new Analysis("foo", 1_500L, "sha1"), null, qualityGate, 1L, properties));
     assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, null, qualityGate, 1L, properties));
     assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties));
     assertThat(underTest).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, branch, null, 1L, properties));
@@ -128,7 +128,7 @@ public class ProjectAnalysisTest {
     assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(new Project("A", "B", "C"), ceTask, analysis, branch, qualityGate, 1L, properties).hashCode());
     assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, null, null, null, qualityGate, 1L, properties).hashCode());
     assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, null, null, qualityGate, 1L, properties).hashCode());
-    assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, new Analysis("foo", 1_500L), null, qualityGate, 1L, properties).hashCode());
+    assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, new Analysis("foo", 1_500L, "sha1"), null, qualityGate, 1L, properties).hashCode());
     assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, null, qualityGate, 1L, properties).hashCode());
     assertThat(underTest.hashCode())
       .isNotEqualTo(new ProjectAnalysis(project, ceTask, analysis, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties).hashCode());
@@ -148,6 +148,6 @@ public class ProjectAnalysisTest {
   @Test
   public void verify_toString() {
     assertThat(underTest.toString()).isEqualTo(
-      "ProjectAnalysis{project=Project{uuid='uuid', key='key', name='name'}, ceTask=CeTask{id='id', status=SUCCESS}, branch=Branch{main=true, name='name', type=SHORT}, qualityGate=EvaluatedQualityGate{qualityGate=QualityGate{id=id, name='name', conditions=[]}, status=ERROR, evaluatedConditions=[]}, updatedAt=1, properties={a=b}, analysis=Analysis{uuid='analysis_uuid', date=1500}}");
+      "ProjectAnalysis{project=Project{uuid='uuid', key='key', name='name'}, ceTask=CeTask{id='id', status=SUCCESS}, branch=Branch{main=true, name='name', type=SHORT}, qualityGate=EvaluatedQualityGate{qualityGate=QualityGate{id=id, name='name', conditions=[]}, status=ERROR, evaluatedConditions=[]}, updatedAt=1, properties={a=b}, analysis=Analysis{uuid='analysis_uuid', date=1500, revision=sha1}}");
   }
 }
index 8dd178a31adece4e4789a38ed260e815e914e2f7..61d0b9115afa901cd823d51efcb782fe43c2190a 100644 (file)
@@ -73,6 +73,7 @@ public class WebhookPayloadFactoryImplTest {
         "  \"taskId\": \"#1\"," +
         "  \"status\": \"SUCCESS\"," +
         "  \"analysedAt\": \"2017-07-14T04:40:00+0200\"," +
+        "  \"revision\": \"sha1\"," +
         "  \"changedAt\": \"2017-07-14T04:40:00+0200\"," +
         "  \"project\": {" +
         "    \"key\": \"P1\"," +
@@ -117,6 +118,7 @@ public class WebhookPayloadFactoryImplTest {
         "  \"taskId\": \"#1\"," +
         "  \"status\": \"SUCCESS\"," +
         "  \"analysedAt\": \"2017-07-14T04:40:00+0200\"," +
+        "  \"revision\": \"sha1\"," +
         "  \"changedAt\": \"2017-07-14T04:40:00+0200\"," +
         "  \"project\": {" +
         "    \"key\": \"P1\"," +
@@ -146,7 +148,7 @@ public class WebhookPayloadFactoryImplTest {
       .setStatus(Metric.Level.ERROR)
       .build();
     Map<String, String> scannerProperties = ImmutableMap.of(
-      "sonar.analysis.revision", "ab45d24",
+      "sonar.analysis.foo", "bar",
       "sonar.analysis.buildNumber", "B123",
       "not.prefixed.with.sonar.analysis", "should be ignored",
       "ignored", "should be ignored too");
@@ -159,6 +161,7 @@ public class WebhookPayloadFactoryImplTest {
         "  \"taskId\": \"#1\"," +
         "  \"status\": \"SUCCESS\"," +
         "  \"analysedAt\": \"2017-07-14T04:40:00+0200\"," +
+        "  \"revision\": \"sha1\"," +
         "  \"changedAt\": \"2017-07-14T04:40:00+0200\"," +
         "  \"project\": {" +
         "    \"key\": \"P1\"," +
@@ -172,7 +175,7 @@ public class WebhookPayloadFactoryImplTest {
         "    ]" +
         "  }," +
         "  \"properties\": {" +
-        "    \"sonar.analysis.revision\": \"ab45d24\"," +
+        "    \"sonar.analysis.foo\": \"bar\"," +
         "    \"sonar.analysis.buildNumber\": \"B123\"" +
         "  }" +
         "}");
@@ -318,7 +321,7 @@ public class WebhookPayloadFactoryImplTest {
 
   private static ProjectAnalysis newAnalysis(@Nullable CeTask task, @Nullable EvaluatedQualityGate gate,
     @Nullable Branch branch, @Nullable Long analysisDate, Map<String, String> scannerProperties) {
-    return new ProjectAnalysis(new Project("P1_UUID", PROJECT_KEY, "Project One"), task, analysisDate == null ? null : new Analysis("A_UUID1", analysisDate), branch,
+    return new ProjectAnalysis(new Project("P1_UUID", PROJECT_KEY, "Project One"), task, analysisDate == null ? null : new Analysis("A_UUID1", analysisDate, "sha1"), branch,
       gate, analysisDate, scannerProperties);
   }
 }
index 49d54691998d5ec80021d687e55b6c4aaff6b925..5c611b581ae6ffb55992955caace7b7293ca16b6 100644 (file)
@@ -94,7 +94,7 @@ public class WebhookQGChangeEventListener implements QGChangeEventListener {
     ProjectAnalysis projectAnalysis = new ProjectAnalysis(
       new Project(projectUuid, project.getKey(), project.name()),
       null,
-      new Analysis(analysis.getUuid(), analysis.getCreatedAt()),
+      new Analysis(analysis.getUuid(), analysis.getCreatedAt(), analysis.getRevision()),
       new Branch(branch.isMain(), branch.getKey(), Type.valueOf(branch.getBranchType().name())),
       evaluatedQualityGate,
       null,
index fa8341e2a072ef88f1804ed4993db95f47c4d706..4f43a4fc05fa0241f0bfdf622e3c49172857e0cf 100644 (file)
@@ -166,7 +166,7 @@ public class WebhookQGChangeEventListenerTest {
       new ProjectAnalysis(
         new Project(project.uuid(), project.getKey(), project.name()),
         null,
-        new Analysis(analysis.getUuid(), analysis.getCreatedAt()),
+        new Analysis(analysis.getUuid(), analysis.getCreatedAt(), analysis.getRevision()),
         new Branch(false, "foo", Branch.Type.SHORT),
         newQualityGate,
         null,
index bcf6eed24ea5dfac1401e7e9444854dde96f58e7..7114e393713af24286486b74d105d39da53da7ff 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.api.ce.posttask;
 
 import java.util.Date;
+import java.util.Optional;
 
 public interface Analysis {
   /**
@@ -31,4 +32,10 @@ public interface Analysis {
    * Date of the analysis.
    */
   Date getDate();
+
+  /**
+   * SCM revision, if declared during analysis
+   * @since 7.8
+   */
+  Optional<String> getRevision();
 }
index ec1b4be349a9362769b93798d8572e24ce692b83..e71857cd3324c29d4749cf7255a1b39b9f58934b 100644 (file)
@@ -31,11 +31,9 @@ import org.sonar.api.ce.ComputeEngineSide;
  *
  * <p>
  * If more then one implementation of {@link PostProjectAnalysisTask} is found, they will be executed in no specific order.
- * 
  *
  * <p>
  * Class {@link PostProjectAnalysisTaskTester} is provided to write unit tests of implementations of this interface.
- * 
  *
  * @since 5.5
  * @see PostProjectAnalysisTaskTester
@@ -124,7 +122,10 @@ public interface PostProjectAnalysisTask {
     ScannerContext getScannerContext();
 
     /**
-     * Revision Id that has been analysed
+     * Revision Id that has been analysed. May return null.
+     * @since 7.6
+     * @deprecated in 7.8, replaced by {@code Analysis#getRevision()}
+     * @see #getAnalysis()
      */
     String getScmRevisionId();
   }
index 30a4e3293d4ae13e3f8414772ceb7343693f6f19..e50157cf9d0819fe5b284937a6e1e7d589d9b433 100644 (file)
@@ -31,7 +31,6 @@ import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 
 /**
@@ -815,6 +814,8 @@ public class PostProjectAnalysisTaskTester {
   public static final class AnalysisBuilder {
     private String analysisUuid;
     private Date date;
+    @Nullable
+    private String revision;
 
     private AnalysisBuilder() {
       // prevents instantiation outside PostProjectAnalysisTaskTester
@@ -830,6 +831,11 @@ public class PostProjectAnalysisTaskTester {
       return this;
     }
 
+    public AnalysisBuilder setRevision(@Nullable String s) {
+      this.revision = s;
+      return this;
+    }
+
     public Analysis build() {
       return new Analysis() {
 
@@ -842,6 +848,11 @@ public class PostProjectAnalysisTaskTester {
         public Date getDate() {
           return date;
         }
+
+        @Override
+        public Optional<String> getRevision() {
+          return Optional.ofNullable(revision);
+        }
       };
     }
   }