Merge branch 'stable-2.15' into stable-2.16

* stable-2.15:
  Adapt to the new related changes class on stable-2.15
  Fix submission of changes using the botUser identity
  Bazel: Include eclipse-out directory in .bazelignore

Change-Id: I470ea6b7a492be31dd3e72c91f46a93d7534fb83
diff --git a/.bazelignore b/.bazelignore
new file mode 100644
index 0000000..30f1613
--- /dev/null
+++ b/.bazelignore
@@ -0,0 +1 @@
+eclipse-out
diff --git a/src/main/java/com/criteo/gerrit/plugins/automerge/AtomicityHelper.java b/src/main/java/com/criteo/gerrit/plugins/automerge/AtomicityHelper.java
index 4ad4233..4e14a46 100644
--- a/src/main/java/com/criteo/gerrit/plugins/automerge/AtomicityHelper.java
+++ b/src/main/java/com/criteo/gerrit/plugins/automerge/AtomicityHelper.java
@@ -8,13 +8,13 @@
 import com.google.gerrit.extensions.api.changes.SubmitInput;
 import com.google.gerrit.extensions.client.ChangeStatus;
 import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.Emails;
+import com.google.gerrit.server.change.ChangeResource;
 import com.google.gerrit.server.change.RevisionResource;
 import com.google.gerrit.server.notedb.ChangeNotes;
 import com.google.gerrit.server.permissions.PermissionBackend;
@@ -24,7 +24,6 @@
 import com.google.gerrit.server.project.SubmitRuleEvaluator;
 import com.google.gerrit.server.project.SubmitRuleOptions;
 import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.restapi.change.ChangesCollection;
 import com.google.gerrit.server.restapi.change.GetRelated;
 import com.google.gerrit.server.restapi.change.Submit;
 import com.google.gwtorm.server.OrmException;
@@ -42,8 +41,6 @@
 
   @Inject ChangeData.Factory changeDataFactory;
 
-  @Inject private ChangesCollection collection;
-
   @Inject AutomergeConfig config;
 
   @Inject Provider<ReviewDb> db;
@@ -62,6 +59,8 @@
 
   @Inject SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory;
 
+  @Inject ChangeResource.Factory changeResourceFactory;
+
   /**
    * Check if the current patchset of the specified change has dependent unmerged changes.
    *
@@ -167,10 +166,13 @@
       permissionBackend.user(getBotUser()).change(notes).database(db).check(READ);
       ChangeData changeData =
           changeDataFactory.create(db.get(), new Project.NameKey(project), changeId);
+
       RevisionResource r =
-          new RevisionResource(collection.parse(changeId), changeData.currentPatchSet());
+          new RevisionResource(
+              changeResourceFactory.create(changeData.notes(), getBotUser()),
+              changeData.currentPatchSet());
       return r;
-    } catch (ResourceNotFoundException | AuthException | PermissionBackendException e) {
+    } catch (AuthException | PermissionBackendException e) {
       throw new NoSuchChangeException(changeId);
     }
   }
diff --git a/src/test/java/com/criteo/gerrit/plugins/automerge/AutomaticMergerTest.java b/src/test/java/com/criteo/gerrit/plugins/automerge/AutomaticMergerTest.java
new file mode 100644
index 0000000..b8ee99f
--- /dev/null
+++ b/src/test/java/com/criteo/gerrit/plugins/automerge/AutomaticMergerTest.java
@@ -0,0 +1,97 @@
+package com.criteo.gerrit.plugins.automerge;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
+import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.acceptance.TestPlugin;
+import com.google.gerrit.extensions.api.changes.ChangeApi;
+import com.google.gerrit.extensions.api.changes.Changes;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.client.ChangeStatus;
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.server.account.externalids.ExternalIds;
+import com.google.inject.Inject;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+
+@NoHttpd
+@TestPlugin(
+    name = "autosubmitter",
+    sysModule = "com.criteo.gerrit.plugins.automerge.AutomergeModule")
+public class AutomaticMergerTest extends LightweightPluginDaemonTest {
+  private static final String BOT_USERS = "Bot Users";
+  private static final String DEVELOPERS = "Developers";
+  private TestAccount botUser;
+  private TestAccount regularUser;
+  @Inject ExternalIds extIds;
+
+  @Before
+  public void setup() throws Exception {
+    gApi.groups().create(BOT_USERS);
+    gApi.groups().create(DEVELOPERS);
+    botUser = accountCreator.create("botuser", "botuser@mycompany.com", "Bot User", BOT_USERS);
+    regularUser =
+        accountCreator.create("developer", "developer@mycompany.com", "Developer", DEVELOPERS);
+    grant(project, "refs/*", "submit", false, groupUUID(BOT_USERS));
+    grantLabel("Code-Review", -2, 2, project, "refs/*", false, groupUUID(DEVELOPERS), false);
+  }
+
+  @Test
+  @GerritConfig(name = "automerge.botEmail", value = "botuser@mycompany.com")
+  public void changeReviewedShouldNotBeAutomaticallyMergedIfNotApproved() throws Exception {
+    int changeNum = createChangeNum(user);
+
+    assertThat(changesApi().id(changeNum).get().status).isEqualTo(ChangeStatus.NEW);
+  }
+
+  @Test
+  @GerritConfig(name = "automerge.botEmail", value = "botuser@mycompany.com")
+  public void changeReviewedShouldBeAutomaticallyMergedOnceApproved() throws Exception {
+    int changeNum = createChangeNum(user);
+    changesApi().id(changeNum).current().review(ReviewInput.approve());
+
+    assertThat(changesApi().id(changeNum).get().status).isEqualTo(ChangeStatus.MERGED);
+  }
+
+  @Test
+  @GerritConfig(name = "automerge.botEmail", value = "botuser@mycompany.com")
+  public void changeShouldBeAutomaticallyMergedByBotUser() throws Exception {
+    int changeNum = createChangeNum(user);
+    ChangeApi changeApi = changesApi().id(changeNum);
+    changeApi.current().review(ReviewInput.approve());
+
+    ChangeInfo changeInfo = changeApi.get();
+    assertThat(changeInfo.submitter).isNotNull();
+    assertThat(changeInfo.submitter._accountId).isEqualTo(new Integer(botUser.id.get()));
+    assertThat(changeInfo.submitter.email).isEqualTo(botUser.email);
+  }
+
+  private AccountGroup.UUID groupUUID(String name) {
+    return groupCache.get(new AccountGroup.NameKey(name)).get().getGroupUUID();
+  }
+
+  private Changes changesApi() {
+    setApiUser(regularUser);
+    return gApi.changes();
+  }
+
+  private int createChangeNum(TestAccount user) throws Exception {
+    List<String> msgs =
+        Arrays.asList(createChangeAsUser("refs/for/master", user).getMessage().split("\n"));
+    String changeUrl = msgs.get(msgs.size() - 1).trim().split(" ")[0];
+    return Integer.parseInt(changeUrl.substring(changeUrl.lastIndexOf('/') + 1));
+  }
+
+  protected PushOneCommit.Result createChangeAsUser(String ref, TestAccount user) throws Exception {
+    PushOneCommit.Result result = pushFactory.create(db, user.getIdent(), testRepo).to(ref);
+    result.assertOkStatus();
+    return result;
+  }
+}