Skip to content

Commit

Permalink
Merge pull request #299 from jacob-keller/jk/gerrit-revision-show-ref…
Browse files Browse the repository at this point in the history
…spec

[JENKINS-38675] use refspec instead of branch name for the revision
  • Loading branch information
rsandell committed Oct 17, 2016
2 parents 2cb758a + 89eca5e commit 670fbe2
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 1 deletion.
Expand Up @@ -114,10 +114,15 @@ public Collection<Revision> getCandidateRevisions(boolean isPollCall, String sin
rev = "FETCH_HEAD";
}

String refspec = context.actOnBuild(new GetGerritEventRefspec());
if (refspec == null) {
refspec = singleBranch;
}

ObjectId sha1 = git.revParse(rev);

Revision revision = new Revision(sha1);
revision.getBranches().add(new Branch(singleBranch, sha1));
revision.getBranches().add(new Branch(refspec, sha1));

return Collections.singletonList(revision);
} catch (GitException e) {
Expand Down Expand Up @@ -276,5 +281,27 @@ public String invoke(Run<?, ?> build, VirtualChannel channel) {
}
}

/**
* Retrieve the Gerrit refspec
*/
private static class GetGerritEventRefspec
implements BuildChooserContext.ContextCallable<Run<?, ?>, String> {
static final long serialVersionUID = 0L;
@Override
public String invoke(Run<?, ?> build, VirtualChannel channel) {
GerritCause cause = build.getCause(GerritCause.class);
if (cause != null) {
GerritTriggeredEvent event = cause.getEvent();
if (event instanceof ChangeBasedEvent) {
return ((ChangeBasedEvent)event).getPatchSet().getRef();
}
if (event instanceof RefUpdated) {
return ((RefUpdated)event).getRefUpdate().getRefName();
}
}
return null;
}
}

private static final Logger LOGGER = Logger.getLogger(GerritTriggerBuildChooser.class.getName());
}
@@ -0,0 +1,145 @@
package com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger;

import hudson.plugins.git.util.BuildChooserContext;
import hudson.plugins.git.Revision;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import java.util.Collection;
import hudson.model.Job;
import hudson.model.Run;
import hudson.model.FreeStyleProject;
import hudson.model.FreeStyleBuild;
import hudson.EnvVars;
import java.io.IOException;
import java.io.Serializable;
import hudson.model.Hudson;
import org.jenkinsci.plugins.gitclient.GitClient;
import com.sonymobile.tools.gerrit.gerritevents.dto.events.PatchsetCreated;
import com.sonyericsson.hudson.plugins.gerrit.trigger.mock.Setup;
import org.eclipse.jgit.lib.ObjectId;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* Tests for {@link GerritTriggerBuildChooser}.
* @author Jacob Keller
*/
public class GerritTriggerBuildChooserTest {
/**
* Copied from the Git plugin because the real implementation is private.
*
* Ideally we can find a way to have this work somehow without needing to have this copy...
*/
static class BuildChooserContextImpl implements BuildChooserContext, Serializable {
final Job project;
final Run build;
final EnvVars environment;

/**
* Provides context for running closures while determining what to build
* @param project the Jenkins project
* @param build the Jenkins build
* @param environment the environment
*/
BuildChooserContextImpl(Job project, Run build, EnvVars environment) {
this.project = project;
this.build = build;
this.environment = environment;
}

/**
* Perform some closure, executing on the build
* @param <T> The return type from the closure
* @param callable the closure to run
* @throws IOException if IO cannot be performed
* @throws InterruptedException if the process is interrupted
* @return closure return value
*/
public <T> T actOnBuild(ContextCallable<Run<?, ?>, T> callable)
throws IOException, InterruptedException {
return callable.invoke(build, Hudson.MasterComputer.localChannel);
}

/**
* Perform some closure, executing on the project
* @param <T> The return type from the closure
* @param callable the closure to run
* @throws IOException if IO cannot be performed
* @throws InterruptedException if the process is interrupted
* @return closure return value
*/
public <T> T actOnProject(ContextCallable<Job<?, ?>, T> callable)
throws IOException, InterruptedException {
return callable.invoke(project, Hudson.MasterComputer.localChannel);
}

/**
* Get the build
* @return Jenkins build
*/
public Run<?, ?> getBuild() {
return build;
}

/**
* Get the project
* @return environment variables
*/
public EnvVars getEnvironment() {
return environment;
}
}

/**
* Tests {@link GerritTriggerBuildChooser} if it correctly determines revision.
*
* @throws Exception if so.
*/
@Test
public void testGerritTriggerBuildChooser() throws Exception {
GerritTriggerBuildChooser chooser = new GerritTriggerBuildChooser();
final ObjectId fetchHead = ObjectId.fromString("7f3547c6d55946e25e99a847b5160d69e59994ba");
final ObjectId patchsetRevision = ObjectId.fromString("38b0940738376ee1b66c332a2cb6d4d37bafa4e4");
final String singleBranch = "origin/master";
final String patchsetRefspec = "refs/changes/98/99498/2";

// Mock the necessary objects we will need to make this work
FreeStyleProject p = mock(FreeStyleProject.class);
FreeStyleBuild b = mock(FreeStyleBuild.class);
GitClient git = mock(GitClient.class);
when(git.revParse("FETCH_HEAD")).thenReturn(fetchHead);

BuildChooserContextImpl context = new BuildChooserContextImpl(p, b, null);

// get the candidate revision(s)
Collection<Revision> revs = chooser.getCandidateRevisions(true, singleBranch, git, null, null, context);

// Check that we correctly use branch when no gerrit revision is used
assertEquals(1, revs.size());
assertEquals(1, revs.iterator().next().getBranches().size());
assertEquals(singleBranch, revs.iterator().next().getBranches().iterator().next().getName());
assertEquals(fetchHead, revs.iterator().next().getBranches().iterator().next().getSHA1());

// Mock the objects to report a gerrit revision was built
// build.getCause returns some object which reports the event correctly
PatchsetCreated patchsetCreated = Setup.createPatchsetCreated();
patchsetCreated.getPatchSet().setRef(patchsetRefspec);
patchsetCreated.getPatchSet().setRevision(patchsetRevision.toString());

GerritCause gerritCause = new GerritCause();
gerritCause.setEvent(patchsetCreated);
when(b.getCause(GerritCause.class)).thenReturn(gerritCause);
when(git.revParse(patchsetRefspec)).thenReturn(patchsetRevision);
when(git.revParse(patchsetRevision.toString())).thenReturn(patchsetRevision);

// get the candidate revision(s)
revs = chooser.getCandidateRevisions(true, singleBranch, git, null, null, context);

// Check that we correctly use branch when a gerrit revision is used
assertEquals(1, revs.size());
assertEquals(1, revs.iterator().next().getBranches().size());
assertEquals(patchsetRefspec, revs.iterator().next().getBranches().iterator().next().getName());
assertEquals(patchsetRevision, revs.iterator().next().getBranches().iterator().next().getSHA1());
}
}

0 comments on commit 670fbe2

Please sign in to comment.