Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
-Fixed (RebuildActionFactory): JENKINS-14905 Make "Rebuild" button av…
…ailable for builds before plugin installation time

-Fixed in test: JENKINS-14387 Cause of rebuilt job should be Cause.UserIdCause
-Added new feature: Rebuild Last on project level (see attached screenshot)
-Added HtmlUnit test to validate Rebuild and Rebuild links
  • Loading branch information
rinokadijk committed Dec 6, 2012
1 parent 3f147ce commit da8dc71
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 88 deletions.
3 changes: 3 additions & 0 deletions src/main/java/com/sonyericsson/rebuild/RebuildAction.java
Expand Up @@ -72,6 +72,9 @@ public class RebuildAction implements Action {
private transient ParametersDefinitionProperty pdp;
private static final String PARAMETERIZED_URL = "parameterized";

public RebuildAction() {
}

/**
* Getter method for pdp.
*
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/com/sonyericsson/rebuild/RebuildActionFactory.java
@@ -0,0 +1,32 @@
package com.sonyericsson.rebuild;

import static java.util.Collections.emptyList;
import static java.util.Collections.singleton;

import java.util.Collection;

import hudson.Extension;
import hudson.model.*;

/**
* Enables rebuild for builds that ran before installing the rebuild plugin.
*/
@Extension
public class RebuildActionFactory extends TransientBuildActionFactory {

@Override
public Collection<? extends Action> createFor(Run target) {
AbstractBuild build = (AbstractBuild) target;
boolean hasRebuildAction = target.getAction(RebuildAction.class) != null;
if (hasRebuildAction) {
return emptyList();
}
for (RebuildValidator rebuildValidator : Hudson.getInstance().
getExtensionList(RebuildValidator.class)) {
if (rebuildValidator.isApplicable(build)) {
return emptyList();
}
}
return singleton(new RebuildAction());
}
}
@@ -0,0 +1,22 @@
package com.sonyericsson.rebuild;

/**
* Reschedules last completed build for the project if available.
* Otherwise it behaves as if the user click on the build now button.
*/
public class RebuildLastCompletedBuildAction extends RebuildAction {

@Override
public String getUrlName() {
if (getProject() != null && getProject().getLastCompletedBuild() != null && getProject().isBuildable()) {
return getProject().getLastCompletedBuild().getNumber() + "/rebuild";
} else {
return "build?delay=0sec";
}
}

@Override
public String getDisplayName() {
return "Rebuild Last";
}
}
@@ -0,0 +1,23 @@
package com.sonyericsson.rebuild;

import static java.util.Collections.singleton;

import java.util.Collection;

import hudson.Extension;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.TransientProjectActionFactory;

/**
* Makes the rebuild button available on the project level.
* Rebuilds the last completed build.
*/
@Extension
public class RebuildProjectActionFactory extends TransientProjectActionFactory {

@Override
public Collection<? extends Action> createFor(AbstractProject abstractProject) {
return singleton(new RebuildLastCompletedBuildAction());
}
}
126 changes: 62 additions & 64 deletions src/main/java/com/sonyericsson/rebuild/Rebuilder.java
@@ -1,64 +1,62 @@
/*
* The MIT License
*
* Copyright 2010 Sony Ericsson Mobile Communications. All rights reserved.
* Copyright 2012 Sony Mobile Communications AB. All rights reservered.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.sonyericsson.rebuild;

import hudson.Extension;
import hudson.model.AbstractBuild;
import hudson.model.Hudson;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.model.listeners.RunListener;

/**
* Runtime Listner class which allows
* the user to rebuild the parameterized
* build.
* @author Shemeer S.
*/
@Extension
public class Rebuilder extends RunListener<Run> {

/**
* Rebuilder class constructor.
*/
public Rebuilder() {
super(Run.class);
}

@Override
public void onCompleted(Run r, TaskListener listener) {
if (r instanceof AbstractBuild) {
AbstractBuild build = (AbstractBuild)r;
for (RebuildValidator rebuildValidator : Hudson.getInstance().
getExtensionList(RebuildValidator.class)) {
if (rebuildValidator.isApplicable(build)) {
return;
}
}
RebuildAction rebuildAction = new RebuildAction();
build.getActions().add(rebuildAction);
}
}
}
/*
* The MIT License
*
* Copyright 2010 Sony Ericsson Mobile Communications. All rights reserved.
* Copyright 2012 Sony Mobile Communications AB. All rights reservered.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.sonyericsson.rebuild;


import hudson.Extension;
import hudson.model.*;
import hudson.model.listeners.RunListener;

/**
* Runtime Listner class which allows the user to rebuild the parameterized build.
*
* @author Shemeer S.
*/
@Extension
public class Rebuilder extends RunListener<Run> {

/**
* Rebuilder class constructor.
*/
public Rebuilder() {
super(Run.class);
}

@Override
public void onCompleted(Run r, TaskListener listener) {
if (r instanceof AbstractBuild) {
AbstractBuild build = (AbstractBuild) r;
for (RebuildValidator rebuildValidator : Hudson.getInstance().
getExtensionList(RebuildValidator.class)) {
if (rebuildValidator.isApplicable(build)) {
return;
}
}
RebuildAction rebuildAction = new RebuildAction();
build.getActions().add(rebuildAction);
}
}

}
87 changes: 63 additions & 24 deletions src/test/java/com/sonyericsson/rebuild/RebuildValidatorTest.java
Expand Up @@ -23,87 +23,126 @@
*/
package com.sonyericsson.rebuild;

import hudson.model.AbstractBuild;
import hudson.model.Build;
import hudson.model.Cause;
import hudson.model.ParametersAction;
import hudson.model.Project;
import hudson.model.StringParameterValue;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

import org.jvnet.hudson.test.HudsonTestCase;
import static org.junit.Assert.*;
import org.xml.sax.SAXException;
import com.gargoylesoftware.htmlunit.WebAssert;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

import hudson.model.*;

/**
* For testing the extension point.
*
* @author Gustaf Lundh &lt;gustaf.lundh@sonyericsson.com&gt;
*/
public class RebuildValidatorTest extends HudsonTestCase {

/**
* Tests with no extensions.
*
* @throws IOException IOException
* @throws IOException IOException
* @throws InterruptedException InterruptedException
* @throws ExecutionException ExecutionException
* @throws ExecutionException ExecutionException
*/
public void testNoRebuildValidatorExtension()
throws IOException, InterruptedException, ExecutionException {
Project projectA = createFreeStyleProject("testFreeStyleA");
Build buildA = (Build)projectA.scheduleBuild2(0, new Cause.UserCause(),
new ParametersAction(new StringParameterValue("party", "megaparty"))).get();
Build buildA = (Build) projectA.scheduleBuild2(0, new Cause.UserIdCause(),
new ParametersAction(new StringParameterValue("party",
"megaparty")))
.get();
assertNotNull(buildA.getAction(RebuildAction.class));
}

/**
* Tests with an extension returning isApplicable true.
*
* @throws IOException IOException
* @throws IOException IOException
* @throws InterruptedException InterruptedException
* @throws ExecutionException ExecutionException
* @throws ExecutionException ExecutionException
*/
public void testRebuildValidatorExtensionIsApplicableTrue()
throws IOException, InterruptedException, ExecutionException {
hudson.getExtensionList(RebuildValidator.class).add(0, new ValidatorAlwaysApplicable());
Project projectA = createFreeStyleProject("testFreeStyleB");
Build buildA = (Build)projectA.scheduleBuild2(0, new Cause.UserCause(),
new ParametersAction(new StringParameterValue("party", "megaparty"))).get();
Build buildA = (Build) projectA.scheduleBuild2(0, new Cause.UserIdCause(),
new ParametersAction(new StringParameterValue("party",
"megaparty")))
.get();
assertNull(buildA.getAction(RebuildAction.class));
}

/**
* Tests with an extension returning isApplicable false.
*
* @throws IOException IOException
* @throws IOException IOException
* @throws InterruptedException InterruptedException
* @throws ExecutionException ExecutionException
* @throws ExecutionException ExecutionException
*/
public void testRebuildValidatorExtensionIsApplicableFalse()
throws IOException, InterruptedException, ExecutionException {
hudson.getExtensionList(RebuildValidator.class).add(0, new ValidatorNeverApplicable());
Project projectA = createFreeStyleProject("testFreeStyleC");
Build buildA = (Build)projectA.scheduleBuild2(0, new Cause.UserCause(),
new ParametersAction(new StringParameterValue("party", "megaparty"))).get();
Build buildA = (Build) projectA.scheduleBuild2(0, new Cause.UserIdCause(),
new ParametersAction(new StringParameterValue("party",
"megaparty")))
.get();
assertNotNull(buildA.getAction(RebuildAction.class));
}

/**
/**
* Tests with two extensions returning isApplicable true AND false.
*
* @throws IOException IOException
* @throws IOException IOException
* @throws InterruptedException InterruptedException
* @throws ExecutionException ExecutionException
* @throws ExecutionException ExecutionException
*/
public void testRebuildValidatorExtensionIsApplicableTrueFalse()
throws IOException, InterruptedException, ExecutionException {
hudson.getExtensionList(RebuildValidator.class).add(0, new ValidatorAlwaysApplicable());
hudson.getExtensionList(RebuildValidator.class).add(0, new ValidatorNeverApplicable());
Project projectA = createFreeStyleProject("testFreeStyleC");
Build buildA = (Build)projectA.scheduleBuild2(0, new Cause.UserCause(),
new ParametersAction(new StringParameterValue("party", "megaparty"))).get();
Build buildA = (Build) projectA.scheduleBuild2(0, new Cause.UserIdCause(),
new ParametersAction(new StringParameterValue("party",
"megaparty")))
.get();
assertNull(buildA.getAction(RebuildAction.class));
}

public void test_WhenProjectWithoutParams_ThenRebuildProjectAvailable()
throws IOException, InterruptedException, ExecutionException {
FreeStyleProject project = createFreeStyleProject();

FreeStyleBuild build = project.scheduleBuild2(0).get();

RebuildLastCompletedBuildAction action = build.getProject().getAction(RebuildLastCompletedBuildAction.class);
assertNotNull(action);
}

public void test_WhenProjectWithParams_ThenRebuildProjectExecutesRebuildOfLastBuild()
throws Exception, SAXException {
FreeStyleProject project = createFreeStyleProject();

// Build (#1)
project.scheduleBuild2(0, new Cause.UserIdCause(), new ParametersAction(
new StringParameterValue("name", "test"))).get();
HtmlPage rebuildConfigPage = createWebClient().getPage(project, "1/rebuild");
// Rebuild (#2)
submit(rebuildConfigPage.getFormByName("config"));

HtmlPage projectPage = createWebClient().getPage(project);
HtmlAnchor rebuildHref = projectPage.getAnchorByText("Rebuild Last");

WebAssert.assertLinkPresentWithText(projectPage, "Rebuild Last");
assertEquals("Rebuild Last should point to the second build",
rebuildHref.getHrefAttribute(),
"/" + project.getUrl() + "2/rebuild");
}

/**
* Implementing an Extension always returning isApplicable false.
*/
Expand Down

0 comments on commit da8dc71

Please sign in to comment.