Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[JENKINS-38675] use refspec instead of branch name for the revision
Add support to the GerritTriggerBuildChooser enabling it to report the gerrit change refspec instead of simply reporting the branch this change is destined to. This improves readability of the resulting changelog entry on the Jenkins build page, as the user can see exactly which ref was built. To do so, we need to not only ask for the revision, but the refname. Add a context callback in order to determine in a similar way as we do the revision. Although it might be possible to replace the revision handling to use git.revParse() on the refname instead, this may not be as accurate as the change event, so we leave this in place. The result of this change is that we should see something like: Revision: <sha1id> refs/changes/x/xxxx/x Instead of Revision: <sha1id> master The resulting display is easier to understand and more accurately points out the refname that got built. Add a test to ensure that this behaves as expected. The current test can probably be improved as it relies heavily on mock objects and does not actually generate a trigger event or anything of that sort. Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
- Loading branch information
1 parent
2cb758a
commit 89eca5e
Showing
2 changed files
with
173 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
145 changes: 145 additions & 0 deletions
145
...nyericsson/hudson/plugins/gerrit/trigger/hudsontrigger/GerritTriggerBuildChooserTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
} | ||
} |