CD: Use peeled commit id for annotated tags

For annotated tags newObjectId is the ObjectId of the tag itself
and not the ObjectId of the referenced commit.
In case of annotated tags peel the reference to get the ObjectId
of the commit when looking up corresponding SCS.

Solves: Jira GER-1566
Change-Id: I4bf689e49459d580d8f4a64c4014283870fd276b
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParser.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParser.java
index b16c8b9..5b8677d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParser.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParser.java
@@ -52,6 +52,7 @@
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
@@ -212,15 +213,14 @@
     }
   }
 
-  public void createAndScheduleArtc(
-      String projectName, String tagName, String commitId, Long creationTime) {
+  public void createAndScheduleArtc(String projectName, String tagName, Long creationTime) {
     CompositionDefinedEventKey cd =
         CompositionDefinedEventKey.create(mapper.tagCompositionName(projectName), tagName);
     try {
       Optional<UUID> cdId = eventHub.getExistingId(cd);
       if (cdId.isEmpty()) {
         /* Cd event is missing, create it first */
-        createAndScheduleCd(projectName, tagName, commitId, creationTime);
+        createAndScheduleCd(projectName, tagName, creationTime);
         cdId = eventHub.getExistingId(cd);
       }
       if (!cdId.isEmpty()) {
@@ -232,12 +232,15 @@
     }
   }
 
-  private void createAndScheduleCd(
-      String projectName, String tagName, String commitId, Long creationTime) {
+  private void createAndScheduleCd(String projectName, String tagName, Long creationTime) {
     SourceChangeEventKey scs = null;
     Optional<UUID> scsId = Optional.empty();
 
     try {
+      String commitId = peelTag(projectName, tagName);
+      if (commitId == null) {
+        return;
+      }
       scs = SourceChangeEventKey.scsKey(projectName, RefNames.REFS_HEADS + "master", commitId);
       scsId = eventHub.getExistingId(scs);
 
@@ -268,6 +271,20 @@
     }
   }
 
+  private String peelTag(String projectName, String tagName) {
+    try (Repository repo = repoManager.openRepository(Project.nameKey(projectName))) {
+      Ref tagRef = repo.getRefDatabase().exactRef(Constants.R_TAGS + tagName);
+      if (tagRef != null) {
+        ObjectId peeled = repo.getRefDatabase().peel(tagRef).getPeeledObjectId();
+        return peeled != null ? peeled.getName() : tagRef.getObjectId().getName();
+      }
+      logger.atSevere().log("Cannot find tag: %s:%s", projectName, tagName);
+    } catch (IOException e) {
+      logger.atSevere().withCause(e).log("Unable to peel tag: %s:%s", projectName, tagName);
+    }
+    return null;
+  }
+
   private Optional<UUID> findSourceChangeEventKey(String projectName, String commitId)
       throws EiffelEventIdLookupException {
     List<String> branches;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParsingQueue.java b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParsingQueue.java
index 775ea1c..7d57e58 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParsingQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParsingQueue.java
@@ -146,7 +146,6 @@
     scheduleArtcCreation(
         event.getProjectName(),
         event.getRefName().substring(RefNames.REFS_TAGS.length()),
-        event.getNewObjectId(),
         TimeUtil.nowMs());
   }
 
@@ -157,22 +156,20 @@
         tagRef.startsWith(RefNames.REFS_TAGS)
             ? tagRef.substring(RefNames.REFS_TAGS.length())
             : tagRef,
-        resource.getTagInfo().revision,
         resource.getTagInfo().created.getTime());
   }
 
-  public void scheduleArtcCreation(
-      String projectName, String tagName, String commitId, Long creationTime) {
+  public void scheduleArtcCreation(String projectName, String tagName, Long creationTime) {
     schedule(
-        new EventParsingWorker(ARTC, projectName, tagName, commitId) {
+        new EventParsingWorker(ARTC, projectName, tagName) {
 
           @Override
           public void doRun() {
             try {
-              eventParser.createAndScheduleArtc(projectName, tagName, commitId, creationTime);
+              eventParser.createAndScheduleArtc(projectName, tagName, creationTime);
             } catch (Exception e) {
               logger.atSevere().withCause(e).log(
-                  "Failed to create ARTC for %s:%s:%s", projectName, tagName, commitId);
+                  "Failed to create ARTC for %s:%s", projectName, tagName);
             }
           }
         });
@@ -203,6 +200,10 @@
     private final EiffelEventType type;
     private boolean running;
 
+    public EventParsingWorker(EiffelEventType type, String repoName, String refName) {
+      this(type, repoName, refName, null);
+    }
+
     public EventParsingWorker(
         EiffelEventType type, String repoName, String refName, String commitId) {
       this.type = type;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventsTest.java b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventsTest.java
index f14c50c..b9a8208 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventsTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/EiffelEventsTest.java
@@ -162,11 +162,21 @@
         tagName);
   }
 
-  protected String createTagRef() throws Exception {
+  protected String createTagRef(boolean annotated) throws Exception {
+    return createTagRef(getHead(repo(), "HEAD").getName(), annotated);
+  }
+
+  protected String createTagRef(String revision, boolean annotated) throws Exception {
+    return createTagRef("v." + number++, revision, annotated);
+  }
+
+  protected String createTagRef(String name, String revision, boolean annotated) throws Exception {
     TagInput input = new TagInput();
-    input.ref = "v." + number;
-    number++;
-    input.revision = getHead(repo(), "HEAD").getName();
+    input.ref = name;
+    input.revision = revision;
+    if (annotated) {
+      input.message = "A message";
+    }
     return gApi.projects().name(project.get()).tag(input.ref).create(input).get().ref;
   }
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/listeners/GerritEventListenersIT.java b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/listeners/GerritEventListenersIT.java
index 97c3348..2c14fa1 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/listeners/GerritEventListenersIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/listeners/GerritEventListenersIT.java
@@ -153,9 +153,28 @@
   }
 
   @Test
-  public void tagCreatedResultsInEvent() throws Exception {
+  public void lightweightTagCreatedResultsInEvent() throws Exception {
     UUID parentEventId = markMasterAsHandled(SCS);
-    String tagName = createTagRef().substring(RefNames.REFS_TAGS.length());
+    String tagName = createTagRef(false).substring(RefNames.REFS_TAGS.length());
+
+    EventKey artcKey = ArtifactEventKey.create(tagPURL(project.get(), tagName));
+    EiffelEvent artcEvent = publisher.getPublished(artcKey);
+    assertNotNull("Publisher did not find ARTC event", artcEvent);
+    assertEquals(EventKey.fromEvent(artcEvent), artcKey);
+
+    EventKey cdKey = CompositionDefinedEventKey.create(tagCompositionName(project.get()), tagName);
+    EiffelEvent cdEvent = publisher.getPublished(cdKey);
+    assertNotNull("Publisher did not find CD event", cdEvent);
+    assertEquals(EventKey.fromEvent(cdEvent), cdKey);
+
+    assertArtcLinks(cdEvent.meta.id, artcEvent.links);
+    assertCdLinks(parentEventId, cdEvent.links);
+  }
+
+  @Test
+  public void annotatedTagCreatedResultsInEvent() throws Exception {
+    UUID parentEventId = markMasterAsHandled(SCS);
+    String tagName = createTagRef(true).substring(RefNames.REFS_TAGS.length());
 
     EventKey artcKey = ArtifactEventKey.create(tagPURL(project.get(), tagName));
     EiffelEvent artcEvent = publisher.getPublished(artcKey);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParserIT.java b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParserIT.java
index b8f6cd6..b0ed89b 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParserIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/EiffelEventParserIT.java
@@ -41,6 +41,7 @@
 import com.googlesource.gerrit.plugins.eventseiffel.mapping.EiffelEventFactory;
 import com.googlesource.gerrit.plugins.eventseiffel.mapping.EiffelEventMapper;
 import java.time.Instant;
+import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.junit.Before;
 import org.junit.Test;
@@ -201,23 +202,18 @@
 
   @Test
   public void artcQueued() throws Exception {
-    eventParser.createAndScheduleArtc(project.get(), TAG_NAME, getHeadRevision(), EPOCH_MILLIS);
+    eventParser.createAndScheduleArtc(project.get(), TAG_NAME, EPOCH_MILLIS);
     assertEquals(0, TestEventHub.EVENTS.size());
   }
 
   @Test
-  public void artcQueuedscsHandled() throws Exception {
-    SourceChangeEventKey scs =
-        SourceChangeEventKey.scsKey(project.get(), getHead(), getHeadRevision());
-    markAsHandled(scs, getHead(repo(), "HEAD"));
-    ArtifactEventKey artc = ArtifactEventKey.create(tagPURL(project.get(), TAG_NAME));
-    CompositionDefinedEventKey cd =
-        CompositionDefinedEventKey.create(tagCompositionName(project.get()), TAG_NAME);
+  public void annotatedTagArtcQueuedscsHandled() throws Exception {
+    assertArtcQueuedScsHandled(true);
+  }
 
-    eventParser.createAndScheduleArtc(project.get(), TAG_NAME, getHeadRevision(), EPOCH_MILLIS);
-    assertEquals(2, TestEventHub.EVENTS.size());
-    assertCorrectEvent(0, cd);
-    assertCorrectEvent(1, artc);
+  @Test
+  public void LightweightTagArtcQueuedscsHandled() throws Exception {
+    assertArtcQueuedScsHandled(false);
   }
 
   @Test
@@ -230,11 +226,28 @@
         CompositionDefinedEventKey.create(tagCompositionName(project.get()), TAG_NAME);
     markAsHandled(cd);
 
-    eventParser.createAndScheduleArtc(project.get(), TAG_NAME, getHeadRevision(), EPOCH_MILLIS);
+    eventParser.createAndScheduleArtc(project.get(), TAG_NAME, EPOCH_MILLIS);
     assertEquals(1, TestEventHub.EVENTS.size());
     assertCorrectEvent(0, artc);
   }
 
+  private void assertArtcQueuedScsHandled(boolean annotated) throws Exception {
+    SourceChangeEventKey scs =
+        SourceChangeEventKey.scsKey(project.get(), getHead(), getHeadRevision());
+    markAsHandled(scs, getHead(repo(), "HEAD"));
+    String ref =
+        createTagRef(getHead(repo(), "HEAD").getName(), annotated)
+            .substring(Constants.R_TAGS.length());
+    ArtifactEventKey artc = ArtifactEventKey.create(tagPURL(project.get(), ref));
+    CompositionDefinedEventKey cd =
+        CompositionDefinedEventKey.create(tagCompositionName(project.get()), ref);
+
+    eventParser.createAndScheduleArtc(project.get(), ref, EPOCH_MILLIS);
+    assertEquals(2, TestEventHub.EVENTS.size());
+    assertCorrectEvent(0, cd);
+    assertCorrectEvent(1, artc);
+  }
+
   private void assertNbrQueriesFor(SourceChangeEventKey key, int nbrQueries) {
     assertEquals(nbrQueries, TestEventStorage.INSTANCE.queriesFor(key));
   }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/rest/EventsEiffelRestIT.java b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/rest/EventsEiffelRestIT.java
index e0cef31..d483a66 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/rest/EventsEiffelRestIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/eventseiffel/rest/EventsEiffelRestIT.java
@@ -91,7 +91,7 @@
 
   @Test
   public void createSccsFromTagForbidden() throws Exception {
-    createSccs(createTagRef(), true).assertStatus(400);
+    createSccs(createTagRef(true), true).assertStatus(400);
   }
 
   @Test
@@ -118,13 +118,13 @@
 
   @Test
   public void createScssFromTagForbidden() throws Exception {
-    createScss(createTagRef(), true).assertStatus(400);
+    createScss(createTagRef(true), true).assertStatus(400);
   }
 
   @Test
   public void createArtcAsAdmin() throws Exception {
     createScss("master", true).assertStatus(202);
-    String tagName = createTagRef().substring(RefNames.REFS_TAGS.length());
+    String tagName = createTagRef(true).substring(RefNames.REFS_TAGS.length());
     createArtcs(tagName, true).assertStatus(202);
     ArtifactEventKey artc = ArtifactEventKey.create(tagPURL(project.get(), tagName));
     EiffelEvent event = publisher.getPublished(artc);
@@ -134,7 +134,7 @@
   @Test
   public void createArtcAsNonAdminForbidden() throws Exception {
     createScss("master", true).assertStatus(202);
-    String tagName = createTagRef().substring(RefNames.REFS_TAGS.length());
+    String tagName = createTagRef(true).substring(RefNames.REFS_TAGS.length());
     createArtcs(tagName, false).assertStatus(403);
     ArtifactEventKey artc = ArtifactEventKey.create(tagPURL(project.get(), tagName));
     EiffelEvent event = publisher.getPublished(artc);