diff options
author | Jukka Jokiniva <jukka.jokiniva@qt.io> | 2019-01-03 12:04:39 +0200 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@qt.io> | 2019-04-09 12:30:16 +0000 |
commit | 061d5338055456655d64dd8f4ee2cc434a501bf7 (patch) | |
tree | d6a9122c19f025e17e5fa0c285b3e2a73fa9f01a | |
parent | be31ec0d9673eaf040e78b80faeef3c942fde9fa (diff) |
Add new build ssh command
Fixes: QTBI-1545
Change-Id: I2da62e83eda43fe9127cef238a3c82cf46171202
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>
6 files changed, 552 insertions, 2 deletions
diff --git a/qt-gerrit-ui-plugin/qt-gerrit-ui-plugin.html b/qt-gerrit-ui-plugin/qt-gerrit-ui-plugin.html index 9dc76e8..784011b 100644 --- a/qt-gerrit-ui-plugin/qt-gerrit-ui-plugin.html +++ b/qt-gerrit-ui-plugin/qt-gerrit-ui-plugin.html @@ -86,12 +86,17 @@ link_elem.href = '/q/status:staged'; ul_elem.insertBefore(li_elem, ul_elem.children[2]); + li_elem = htmlToElement(ul_elem.children[1].outerHTML); + link_elem = li_elem.children[0].children[1]; + link_elem.text = 'Integrating'; + link_elem.href = '/q/status:integrating'; + ul_elem.insertBefore(li_elem, ul_elem.children[3]); li_elem = htmlToElement(ul_elem.children[1].outerHTML); link_elem = li_elem.children[0].children[1]; link_elem.text = 'Deferred'; link_elem.href = '/q/status:deferred'; - ul_elem.insertBefore(li_elem, ul_elem.children[4]); + ul_elem.insertBefore(li_elem, ul_elem.children[5]); }); // Customize change view diff --git a/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuild.java b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuild.java new file mode 100644 index 0000000..d6cba28 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuild.java @@ -0,0 +1,175 @@ +// +// Copyright (C) 2019 The Qt Company +// + +package com.googlesource.gerrit.plugins.qtcodereview; + +import com.google.common.flogger.FluentLogger; +import com.google.gerrit.extensions.restapi.AuthException; +import com.google.gerrit.extensions.restapi.RestApiException; +import com.google.gerrit.reviewdb.client.Branch; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gerrit.server.InternalUser; +import com.google.gerrit.server.git.GitRepositoryManager; +import com.google.gerrit.server.permissions.PermissionBackend; +import com.google.gerrit.server.permissions.PermissionBackendException; +import com.google.gerrit.server.permissions.ProjectPermission; +import com.google.gerrit.server.permissions.RefPermission; +import com.google.gerrit.server.project.NoSuchProjectException; +import com.google.gerrit.server.project.NoSuchRefException; +import com.google.gerrit.server.query.change.ChangeData; +import com.google.gerrit.server.update.BatchUpdate; +import com.google.gerrit.server.update.UpdateException; +import com.google.gerrit.server.util.time.TimeUtil; +import com.google.gerrit.sshd.SshCommand; +import com.google.gerrit.sshd.CommandMetaData; + +import com.google.gwtorm.server.OrmException; + +import com.google.inject.Inject; +import com.google.inject.Provider; + +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.errors.RepositoryNotFoundException; +import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.kohsuke.args4j.Option; + +import java.io.IOException; +import java.util.List; +import java.util.Map.Entry; + +@CommandMetaData(name="staging-new-build", description="Create unique build branch of the current staging branch and change the gerrit status of the changes to INTEGRATING.") +class QtCommandNewBuild extends SshCommand { + + @Inject + private PermissionBackend permissionBackend; + + @Inject + private GitRepositoryManager gitManager; + + @Inject + private Provider<ReviewDb> dbProvider; + + @Inject + private BatchUpdate.Factory updateFactory; + + @Inject + private QtUtil qtUtil; + + @Inject + private QtChangeUpdateOp.Factory qtUpdateFactory; + + @Option(name = "--project", aliases = {"-p"}, + required = true, usage = "project name") + private String project; + + @Option(name = "--staging-branch", aliases = {"-s"}, + required = true, usage = "branch name, e.g. refs/staging/master or just master") + private String stagingBranch; + + @Option(name = "--build-id", aliases = {"-i"}, + required = true, usage = "build id, e.g. refs/builds/my_build or just my_build") + private String build; + + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + private Repository git; + + + @Override + protected void run() throws UnloggedFailure { + + logger.atInfo().log("qtcodereview: staging-new-build -p %s -s %s -i %s", project, stagingBranch, build); + + try { + Project.NameKey projectKey = new Project.NameKey(project); + git = gitManager.openRepository(projectKey); + + Branch.NameKey buildBranchKey = QtUtil.getNameKeyLong(project, QtUtil.R_BUILDS, build); + Branch.NameKey stagingBranchKey = QtUtil.getNameKeyLong(project, QtUtil.R_STAGING, stagingBranch); + Branch.NameKey destBranchShortKey = QtUtil.getNameKeyShort(project, QtUtil.R_STAGING, stagingBranch); + Branch.NameKey destinationKey = QtUtil.getNameKeyLong(project, QtUtil.R_HEADS, stagingBranch); + + // Check required permissions + permissionBackend.user(user).project(projectKey).ref(destinationKey.get()).check(RefPermission.UPDATE); + permissionBackend.user(user).project(projectKey).ref(buildBranchKey.get()).check(RefPermission.CREATE); + + if (QtUtil.branchExists(git, buildBranchKey) == true) { + logger.atSevere().log("qtcodereview: staging-new-build Target build %s already exists", buildBranchKey); + throw die("Target build already exists!"); + } + + if (QtUtil.branchExists(git, stagingBranchKey) == false) { + logger.atSevere().log("qtcodereview: staging-new-build staging ref %s not found", stagingBranchKey); + throw die("Staging ref not found!"); + } + + // Create build reference. + Result result = qtUtil.createBuildRef(git, user.asIdentifiedUser(), + projectKey, stagingBranchKey, buildBranchKey); + String message = String.format("Added to build %s for %s", build, destinationKey); + + if (result != Result.NEW && result != Result.FAST_FORWARD) { + logger.atSevere().log("qtcodereview: staging-new-build failed to create new build ref %s result %s", + buildBranchKey, result); + throw new UnloggedFailure(1, "fatal: failed to create new build ref: " + result); + } else { + // list the changes in staging branch but missing from the destination branch + List<Entry<ChangeData, RevCommit>> openChanges = qtUtil.listChangesNotMerged(git, buildBranchKey, destBranchShortKey); + + // Make sure that there are changes in the staging branch. + if (openChanges.isEmpty()) { + logger.atSevere().log("qtcodereview: staging-new-build No changes in staging branch %s.", stagingBranchKey); + throw die("No changes in staging branch. Not creating a build reference"); + } + + QtChangeUpdateOp op = qtUpdateFactory.create(Change.Status.INTEGRATING, message, null, null, null); + try (BatchUpdate u = updateFactory.create(dbProvider.get(), projectKey, user, TimeUtil.nowTs())) { + for (Entry<ChangeData, RevCommit> item: openChanges) { + Change change = item.getKey().change(); + logger.atInfo().log("qtcodereview: staging-new-build inserted change %s (%s) into build %s for %s", + change, item.getValue().toString(), build, destinationKey); + u.addOp(change.getId(), op); + } + u.execute(); + } + } + + logger.atInfo().log("qtcodereview: staging-new-build build %s for %s created", build, destBranchShortKey); + + } catch (AuthException e) { + logger.atSevere().log("qtcodereview: staging-new-build Authentication failed to access repository: %s", e); + throw die("Authentication failed to access repository"); + } catch (PermissionBackendException e) { + logger.atSevere().log("qtcodereview: staging-new-build Not enough permissions to access repository %s", e); + throw die("Not enough permissions to access repository"); + } catch (RepositoryNotFoundException e) { + throw die("project not found"); + } catch (IOException e) { + logger.atSevere().log("qtcodereview: staging-new-build Failed to access repository %s", e); + throw die("Failed to access repository"); + } catch (OrmException e) { + logger.atSevere().log("qtcodereview: staging-new-build Failed to access database %s", e); + throw die("Failed to access database"); + } catch (QtUtil.BranchNotFoundException e) { + logger.atSevere().log("qtcodereview: staging-new-build Failed to access build or staging ref %s", e); + throw die("Failed to access build or staging ref"); + } catch (NoSuchRefException e) { + logger.atSevere().log("qtcodereview: staging-new-build Invalid branch name %s", e); + throw die("Invalid branch name"); + } catch (UpdateException | RestApiException e) { + logger.atSevere().log("qtcodereview: staging-new-build failed to update change status %s", e); + throw die("Failed to update change status"); + } finally { + if (git != null) { + git.close(); + } + } + } + +} diff --git a/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtSshModule.java b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtSshModule.java index ca7c940..306d032 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtSshModule.java +++ b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtSshModule.java @@ -1,5 +1,5 @@ // -// Copyright (C) 2018 The Qt Company +// Copyright (C) 2019 The Qt Company // package com.googlesource.gerrit.plugins.qtcodereview; @@ -11,5 +11,6 @@ class QtSshModule extends PluginCommandModule { @Override protected void configureCommands() { command(QtCommandPing.class); + command(QtCommandNewBuild.class); } } diff --git a/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtUtil.java b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtUtil.java index bf14223..8033d80 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtUtil.java +++ b/src/main/java/com/googlesource/gerrit/plugins/qtcodereview/QtUtil.java @@ -48,10 +48,14 @@ import org.eclipse.jgit.merge.MergeStrategy; import org.eclipse.jgit.merge.ThreeWayMerger; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.transport.ReceiveCommand; import java.io.IOException; +import java.util.AbstractMap; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.Map; /** @@ -64,6 +68,7 @@ public class QtUtil { public static final String R_HEADS = "refs/heads/"; public static final String R_STAGING = "refs/staging/"; + public static final String R_BUILDS = "refs/builds/"; private final Provider<InternalChangeQuery> queryProvider; private final GitReferenceUpdated referenceUpdated; @@ -85,6 +90,13 @@ public class QtUtil { } } + public static class BranchNotFoundException extends Exception { + private static final long serialVersionUID = 1L; + public BranchNotFoundException(final String message) { + super(message); + } + } + public static Project.NameKey getProjectKey(final String project) { String projectName = project; if (project.endsWith(Constants.DOT_GIT_EXT)) { @@ -94,6 +106,24 @@ public class QtUtil { } /** + * Creates a branch key including ref prefix. + * @param project Project for the branch key. + * @param prefix Expected prefix. + * @param branch Branch name with or without prefix. + * @return Branch name key with prefix. + */ + public static Branch.NameKey getNameKeyLong(final String project, + final String prefix, + final String branch) { + final Project.NameKey projectKey = getProjectKey(project); + if (branch.startsWith(prefix)) { + return new Branch.NameKey(projectKey, branch); + } else { + return new Branch.NameKey(projectKey, prefix + branch); + } + } + + /** * Creates a branch key without any prefix. * @param project Project for the branch key. * @param prefix Prefix to remove. @@ -111,6 +141,11 @@ public class QtUtil { } } + public static boolean branchExists(Repository git, final Branch.NameKey branch) + throws IOException { + return git.getRefDatabase().getRef(branch.get()) != null; + } + /** * Gets a staging branch for a branch. * @param branch Branch under refs/heads. E.g. refs/heads/master. Can be short @@ -152,6 +187,51 @@ public class QtUtil { } } + /** + * Creates a build ref. Build refs are stored under refs/builds. + * + * @param git Git repository. + * @param stagingBranch Staging branch to create the build ref from. Can be + * short name. + * @param newBranch Build ref name, under refs/builds. Can be short name. + * @return + * @throws IOException + * @throws NoSuchRefException + */ + public Result createBuildRef(Repository git, + IdentifiedUser user, + final Project.NameKey projectKey, + final Branch.NameKey stagingBranch, + final Branch.NameKey newBranch) + throws IOException, NoSuchRefException { + final String stagingBranchName; + if (stagingBranch.get().startsWith(R_STAGING)) { + stagingBranchName = stagingBranch.get(); + } else { + stagingBranchName = R_STAGING + stagingBranch.get(); + } + + final String buildBranchName; + if (newBranch.get().startsWith(R_BUILDS)) { + buildBranchName = newBranch.get(); + } else { + buildBranchName = R_BUILDS + newBranch.get(); + } + + Ref sourceRef = git.getRefDatabase().getRef(stagingBranchName); + if (sourceRef == null) { throw new NoSuchRefException(stagingBranchName); } + + RefUpdate refUpdate = git.updateRef(buildBranchName); + refUpdate.setNewObjectId(sourceRef.getObjectId()); + refUpdate.setForceUpdate(false); + RefUpdate.Result result = refUpdate.update(); + + // send ref created event + referenceUpdated.fire(projectKey, refUpdate, ReceiveCommand.Type.CREATE, user.state()); + + return result; + } + private static Result updateRef(Repository git, final String ref, final String newValue, @@ -305,6 +385,52 @@ public class QtUtil { } } + /** + * Lists not merged changes between branches. + * @param git jGit Repository. Must be open. + * @param db ReviewDb of a Gerrit site. + * @param branch Branch to search for the changes. + * @param destination Destination branch for changes. + * @return List of not merged changes. + * @throws IOException Thrown by Repository or RevWalk if repository is not + * accessible. + * @throws OrmException Thrown if ReviewDb is not accessible. + */ + public List<Map.Entry<ChangeData,RevCommit>> listChangesNotMerged(Repository git, + final Branch.NameKey branch, + final Branch.NameKey destination) + throws IOException, OrmException, + BranchNotFoundException { + + List<Map.Entry<ChangeData, RevCommit>> result = new ArrayList<Map.Entry<ChangeData, RevCommit>>(); + RevWalk revWalk = new RevWalk(git); + + try { + Ref ref = git.getRefDatabase().getRef(branch.get()); + if (ref == null) throw new BranchNotFoundException("No such branch: " + branch); + Ref refDest = git.getRefDatabase().getRef(destination.get()); + if (refDest == null) throw new BranchNotFoundException("No such branch: " + destination); + RevCommit firstCommit = revWalk.parseCommit(ref.getObjectId()); + revWalk.markStart(firstCommit); + // Destination is the walker end point + revWalk.markUninteresting(revWalk.parseCommit(refDest.getObjectId())); + + Iterator<RevCommit> i = revWalk.iterator(); + while (i.hasNext()) { + RevCommit commit = i.next(); + List<ChangeData> changes = queryProvider.get().byBranchCommit(destination, commit.name()); + if (changes != null && !changes.isEmpty()) { + if (changes.size() > 1) logger.atWarning().log("qtcodereview: commit belongs to multiple changes: %s", commit.name()); + ChangeData cd = changes.get(0); + result.add(new AbstractMap.SimpleEntry<ChangeData,RevCommit>(cd, commit)); + } + } + } finally { + revWalk.dispose(); + } + return result; + } + public static RevCommit merge(PersonIdent committerIdent, Repository git, ObjectInserter objInserter, diff --git a/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtCodeReviewIT.java b/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtCodeReviewIT.java index 28a9d73..5fbb78d 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtCodeReviewIT.java +++ b/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtCodeReviewIT.java @@ -45,6 +45,7 @@ public class QtCodeReviewIT extends LightweightPluginDaemonTest { protected static final String R_HEADS = "refs/heads/"; protected static final String R_STAGING = "refs/staging/"; + protected static final String R_BUILDS = "refs/builds/"; protected static final String R_PUSH = "refs/for/"; protected static final String CONTENT_DATA = "hereisjustsomecontentforthecommits"; @@ -116,6 +117,17 @@ public class QtCodeReviewIT extends LightweightPluginDaemonTest { return response; } + protected void QtNewBuild(String branch, String buildId) throws Exception { + String commandStr; + commandStr ="gerrit-plugin-qt-workflow staging-new-build"; + commandStr += " --project " + project.get(); + commandStr += " --staging-branch " + branch; + commandStr += " --build-id " + buildId; + String resultStr = adminSshSession.exec(commandStr); + assertThat(adminSshSession.getError()).isNull(); + resetEvents(); + } + protected PushOneCommit.Result pushCommit(String branch, String message, String file, diff --git a/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuildIT.java b/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuildIT.java new file mode 100644 index 0000000..f029046 --- /dev/null +++ b/src/test/java/com/googlesource/gerrit/plugins/qtcodereview/QtCommandNewBuildIT.java @@ -0,0 +1,231 @@ +// Copyright (C) 2019 The Qt Company + +package com.googlesource.gerrit.plugins.qtcodereview; + +import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.gerrit.acceptance.PushOneCommit; +import com.google.gerrit.acceptance.RestResponse; +import com.google.gerrit.acceptance.TestPlugin; +import com.google.gerrit.acceptance.UseSsh; + +import com.google.gerrit.common.data.Permission; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.ChangeMessage; + +import org.eclipse.jgit.revwalk.RevCommit; + +import java.util.ArrayList; + +import org.junit.Before; +import org.junit.Test; + +@TestPlugin( + name = "gerrit-plugin-qt-workflow", + sysModule = "com.googlesource.gerrit.plugins.qtcodereview.QtModule", + sshModule = "com.googlesource.gerrit.plugins.qtcodereview.QtSshModule" +) + +@UseSsh +public class QtCommandNewBuildIT extends QtCodeReviewIT { + + private final String BUILDING_MSG = "Added to build "; + + @Before + public void SetDefaultPermissions() throws Exception { + grant(project, "refs/heads/master", Permission.QT_STAGE, false, REGISTERED_USERS); + grant(project, "refs/staging/*", Permission.PUSH, false, adminGroupUuid()); + grant(project, "refs/builds/*", Permission.CREATE, false, adminGroupUuid()); + } + + @Test + public void singleChange_New_Staged_Integrating() throws Exception { + PushOneCommit.Result c = pushCommit("master", "commitmsg1", "file1", "content1"); + approve(c.getChangeId()); + QtStage(c); + + RevCommit buildHead = qtNewBuild("master", "test-build-100", c, null); + } + + @Test + public void multiChange_New_Staged_Integrating() throws Exception { + // Push 3 independent commits + RevCommit initialHead = getRemoteHead(); + PushOneCommit.Result c1 = pushCommit("master", "commitmsg1", "file1", "content1"); + testRepo.reset(initialHead); + PushOneCommit.Result c2 = pushCommit("master", "commitmsg2", "file2", "content2"); + testRepo.reset(initialHead); + PushOneCommit.Result c3 = pushCommit("master", "commitmsg3", "file3", "content3"); + approve(c1.getChangeId()); + approve(c2.getChangeId()); + approve(c3.getChangeId()); + QtStage(c1); + QtStage(c2); + QtStage(c3); + + RevCommit buildHead = qtNewBuild("master", "test-build-101", c3, null); + Change change = c1.getChange().change(); + assertThat(change.getStatus()).isEqualTo(Change.Status.INTEGRATING); + change = c2.getChange().change(); + assertThat(change.getStatus()).isEqualTo(Change.Status.INTEGRATING); + } + + + @Test + public void errorNewBuild_NoPermission() throws Exception { + PushOneCommit.Result c = pushCommit("master", "commitmsg1", "file1", "content1"); + approve(c.getChangeId()); + QtStage(c); + + String commandStr; + commandStr ="gerrit-plugin-qt-workflow staging-new-build"; + commandStr += " --project " + project.get(); + commandStr += " --staging-branch master"; + commandStr += " --build-id test-build-500"; + String resultStr = userSshSession.exec(commandStr); + assertThat(userSshSession.getError()).contains("Authentication failed to access repository"); + } + + @Test + public void errorNewBuild_RepoNotFound() throws Exception { + PushOneCommit.Result c = pushCommit("master", "commitmsg1", "file1", "content1"); + approve(c.getChangeId()); + QtStage(c); + + String commandStr; + commandStr ="gerrit-plugin-qt-workflow staging-new-build"; + commandStr += " --project notarepo"; + commandStr += " --staging-branch master"; + commandStr += " --build-id test-build-500"; + String resultStr = adminSshSession.exec(commandStr); + assertThat(adminSshSession.getError()).contains("project not found"); + } + + @Test + public void errorNewBuild_BuildAlreadyExists() throws Exception { + PushOneCommit.Result c = pushCommit("master", "commitmsg1", "file1", "content1"); + approve(c.getChangeId()); + QtStage(c); + + RevCommit buildHead = qtNewBuild("master", "test-build-501", c, null); + String resultStr = qtNewBuildExpectFail("master", "test-build-501"); + assertThat(resultStr).contains("Target build already exists!"); + } + + @Test + public void errorNewBuild_NoChanges() throws Exception { + RevCommit initialHead = getRemoteHead(); + PushOneCommit.Result c = pushCommit("master", "commitmsg1", "file1", "content1"); + approve(c.getChangeId()); + QtStage(c); + QtUnStage(c); + + String resultStr = qtNewBuildExpectFail("master", "test-build-502"); + assertThat(resultStr).contains("No changes in staging branch. Not creating a build reference"); + } + + @Test + public void errorNewBuild_NoStagingRef() throws Exception { + PushOneCommit.Result c = pushCommit("master", "commitmsg1", "file1", "content1"); + + String resultStr = qtNewBuildExpectFail("master", "test-build-503"); + assertThat(resultStr).contains("Staging ref not found!"); + } + + @Test + public void errorNewBuild_NonExistingBranch() throws Exception { + PushOneCommit.Result c = pushCommit("master", "commitmsg1", "file1", "content1"); + approve(c.getChangeId()); + QtStage(c); + + String resultStr = qtNewBuildExpectFail("invalidbranchname", "test-build-504"); + assertThat(resultStr).contains("Staging ref not found!"); + } + + @Test + public void errorAmend_Status_Integrating() throws Exception { + RevCommit initialHead = getRemoteHead(); + PushOneCommit.Result c1 = pushCommit("master", "commitmsg1", "file1", "content1"); + approve(c1.getChangeId()); + QtStage(c1); + RevCommit buildHead = qtNewBuild("master", "test-build-150", c1, null); + + PushOneCommit.Result c2 = amendCommit(c1.getChangeId()); + c2.assertErrorStatus(" closed"); + + RevCommit updatedHead = getRemoteHead(project, "master"); + assertThat(updatedHead.getId()).isEqualTo(initialHead.getId()); // not updated + } + + private RevCommit qtNewBuild(String branch, + String buildId, + PushOneCommit.Result c, + RevCommit expectedHead) + throws Exception { + String stagingRef = R_STAGING + branch; + String branchRef = R_HEADS + branch; + String buildRef = R_BUILDS + buildId; + String commandStr; + RevCommit initialHead = getRemoteHead(project, branchRef); + + commandStr ="gerrit-plugin-qt-workflow staging-new-build"; + commandStr += " --project " + project.get(); + commandStr += " --staging-branch " + branch; + commandStr += " --build-id " + buildId; + String resultStr = adminSshSession.exec(commandStr); + assertThat(adminSshSession.getError()).isNull(); + + RevCommit updatedHead = getRemoteHead(project, branchRef); + assertThat(updatedHead.getId()).isEqualTo(initialHead.getId()); // master is not updated + + RevCommit stagingHead = getRemoteHead(project, stagingRef); + assertThat(stagingHead.getId()).isNotEqualTo(initialHead.getId()); // staging is not master + + if (expectedHead == null) { + assertCherryPick(stagingHead, c.getCommit(), getCurrentPatchSHA(c)); + expectedHead = stagingHead; + } + + RevCommit buildHead = getRemoteHead(project, buildRef); + assertThat(buildHead).isEqualTo(expectedHead); // build ref is updated + assertRefUpdatedEvents(buildRef, null, expectedHead); + + resetEvents(); + + Change change = c.getChange().change(); + assertThat(change.getStatus()).isEqualTo(Change.Status.INTEGRATING); + + ArrayList<ChangeMessage> messages = new ArrayList(c.getChange().messages()); + assertThat(messages.get(messages.size() - 1).getMessage()).contains(BUILDING_MSG + buildId); // check last message + + return buildHead; + } + + private String qtNewBuildExpectFail(String branch, + String buildId) + throws Exception { + String stagingRef = R_STAGING + branch; + String branchRef = R_HEADS + branch; + String commandStr; + RevCommit initialHead = getRemoteHead(project, branchRef); + RevCommit stagingHeadOld = getRemoteHead(project, stagingRef); + + commandStr ="gerrit-plugin-qt-workflow staging-new-build"; + commandStr += " --project " + project.get(); + commandStr += " --staging-branch " + branch; + commandStr += " --build-id " + buildId; + String resultStr = adminSshSession.exec(commandStr); + + RevCommit updatedHead = getRemoteHead(project, branchRef); + if (updatedHead != null) assertThat(updatedHead.getId()).isEqualTo(initialHead.getId()); // master is not updated + + RevCommit stagingHead = getRemoteHead(project, stagingRef); + if (stagingHeadOld != null && stagingHead != null) assertThat(stagingHead.getId()).isEqualTo(stagingHeadOld.getId()); // staging is not updated + + return adminSshSession.getError(); + } + + +} |