Skip to content

Commit

Permalink
Merge pull request #4 from olivergondza/stop-maven-build
Browse files Browse the repository at this point in the history
[JENKINS-19801] Abort module build when maven build is aborted
  • Loading branch information
olivergondza committed Nov 4, 2013
2 parents 080b778 + e01eb60 commit 93dfb65
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 49 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.532</version>
<version>1.538</version>
</parent>

<groupId>org.jenkins-ci.main</groupId><!-- for historical reason, this plugin has a different groupId -->
Expand Down
24 changes: 17 additions & 7 deletions src/main/java/hudson/maven/MavenBuild.java
Expand Up @@ -613,22 +613,32 @@ protected void close() {
e.printStackTrace();
}

abstract class Terminate extends RunExecution {
@Override public void post(BuildListener listener) {}
@Override public void cleanUp(BuildListener listener) {}
}

if(isInProgress()) {
// Build was aborted, abort run as well.
MavenBuild.this.execute(new Terminate() {
@Override
public Result run(BuildListener listener) {
return Result.ABORTED;
}
});
}

if(hasntStartedYet()) {
// Mark the build as not_built. This method is used when the aggregated build
// failed before it didn't even get to this module
// OR if the aggregated build is an incremental one and this
// module needn't be build.
MavenBuild.this.execute(new RunExecution() {
MavenBuild.this.execute(new Terminate() {
@Override
public Result run(BuildListener listener) {
listener.getLogger().println(Messages.MavenBuild_FailedEarlier());
return Result.NOT_BUILT;
}

public void post(BuildListener listener) {
}

public void cleanUp(BuildListener listener) {
}
});
}

Expand Down
137 changes: 96 additions & 41 deletions src/test/java/hudson/maven/MavenBuildTest.java
@@ -1,11 +1,16 @@
package hudson.maven;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

import hudson.Launcher;
import hudson.model.BallColor;
import hudson.model.BuildListener;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Result;
import hudson.model.StringParameterDefinition;
import hudson.model.queue.QueueTaskFuture;
import hudson.tasks.Maven.MavenInstallation;
import hudson.tasks.test.AbstractTestResultAction;
import hudson.tasks.test.AggregatedTestResultAction;
Expand All @@ -14,116 +19,128 @@
import java.io.IOException;
import java.util.Map;

import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Bug;
import org.jvnet.hudson.test.Email;
import org.jvnet.hudson.test.ExtractResourceSCM;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.SingleFileSCM;

/**
* @author Kohsuke Kawaguchi
*/
public class MavenBuildTest extends HudsonTestCase {
public class MavenBuildTest {

@Rule public JenkinsRule j = new JenkinsRule();

/**
* NPE in {@code build.getProject().getWorkspace()} for {@link MavenBuild}.
*/
@Bug(4192)
@Test
public void testMavenWorkspaceExists() throws Exception {
configureDefaultMaven();
MavenModuleSet m = createMavenProject();
j.configureDefaultMaven();
MavenModuleSet m = j.createMavenProject();
m.getReporters().add(new TestReporter());
m.setScm(new ExtractResourceSCM(getClass().getResource("HUDSON-4192.zip")));
buildAndAssertSuccess(m);
j.buildAndAssertSuccess(m);
}

/**
* {@link Result} getting set to SUCCESS even if there's a test failure, when the test failure
* does not happen in the final task segment.
*/
@Bug(4177)
@Test
public void testTestFailureInEarlyTaskSegment() throws Exception {
configureDefaultMaven();
MavenModuleSet m = createMavenProject();
j.configureDefaultMaven();
MavenModuleSet m = j.createMavenProject();
m.setGoals("clean install findbugs:findbugs");
m.setScm(new ExtractResourceSCM(getClass().getResource("maven-test-failure-findbugs.zip")));
assertBuildStatus(Result.UNSTABLE, m.scheduleBuild2(0).get());
j.assertBuildStatus(Result.UNSTABLE, m.scheduleBuild2(0).get());
}

/**
* Verify that a compilation error properly shows up as a failure.
*/
@Test
public void testCompilationFailure() throws Exception {
configureDefaultMaven();
MavenModuleSet m = createMavenProject();
j.configureDefaultMaven();
MavenModuleSet m = j.createMavenProject();
m.setGoals("clean install");
m.setScm(new ExtractResourceSCM(getClass().getResource("maven-compilation-failure.zip")));
assertBuildStatus(Result.FAILURE, m.scheduleBuild2(0).get());
j.assertBuildStatus(Result.FAILURE, m.scheduleBuild2(0).get());
}

/**
* Workspace determination problem on non-aggregator style build.
*/
@Bug(4226)
@Test
public void testParallelModuleBuild() throws Exception {
configureDefaultMaven();
MavenModuleSet m = createMavenProject();
j.configureDefaultMaven();
MavenModuleSet m = j.createMavenProject();
m.setScm(new ExtractResourceSCM(getClass().getResource("multimodule-maven.zip")));

buildAndAssertSuccess(m);
j.buildAndAssertSuccess(m);

m.setAggregatorStyleBuild(false);

// run module builds
buildAndAssertSuccess(m.getModule("test$module1"));
buildAndAssertSuccess(m.getModule("test$module1"));
j.buildAndAssertSuccess(m.getModule("test$module1"));
j.buildAndAssertSuccess(m.getModule("test$module1"));
}

@Bug(value=8395)
@Test
public void testMaven2BuildWrongScope() throws Exception {

File pom = new File(this.getClass().getResource("test-pom-8395.xml").toURI());
MavenModuleSet m = createMavenProject();
MavenInstallation mavenInstallation = configureDefaultMaven();
MavenModuleSet m = j.createMavenProject();
MavenInstallation mavenInstallation = j.configureDefaultMaven();
m.setMaven( mavenInstallation.getName() );
m.getReporters().add(new TestReporter());
m.setRootPOM(pom.getAbsolutePath());
m.setGoals( "clean validate" );
MavenModuleSetBuild mmsb = buildAndAssertSuccess(m);
MavenModuleSetBuild mmsb = j.buildAndAssertSuccess(m);
assertFalse( mmsb.getProject().getModules().isEmpty());
}

@Bug(value=8390)
@Test
public void testMaven2BuildWrongInheritence() throws Exception {

MavenModuleSet m = createMavenProject();
MavenInstallation mavenInstallation = configureDefaultMaven();
MavenModuleSet m = j.createMavenProject();
MavenInstallation mavenInstallation = j.configureDefaultMaven();
m.setMaven( mavenInstallation.getName() );
m.getReporters().add(new TestReporter());
m.setScm(new ExtractResourceSCM(getClass().getResource("incorrect-inheritence-testcase.zip")));
m.setGoals( "clean validate" );
MavenModuleSetBuild mmsb = buildAndAssertSuccess(m);
MavenModuleSetBuild mmsb = j.buildAndAssertSuccess(m);
assertFalse( mmsb.getProject().getModules().isEmpty());
}

@Bug(value=8445)
@Test
public void testMaven2SeveralModulesInDirectory() throws Exception {

MavenModuleSet m = createMavenProject();
MavenInstallation mavenInstallation = configureDefaultMaven();
MavenModuleSet m = j.createMavenProject();
MavenInstallation mavenInstallation = j.configureDefaultMaven();
m.setMaven( mavenInstallation.getName() );
m.getReporters().add(new TestReporter());
m.setScm(new ExtractResourceSCM(getClass().getResource("several-modules-in-directory.zip")));
m.setGoals( "clean validate" );
MavenModuleSetBuild mmsb = buildAndAssertSuccess(m);
MavenModuleSetBuild mmsb = j.buildAndAssertSuccess(m);
assertFalse( mmsb.getProject().getModules().isEmpty());
}

@Email("https://groups.google.com/d/msg/hudson-users/Xhw00UopVN0/FA9YqDAIsSYJ")
@Test
public void testMavenWithDependencyVersionInEnvVar() throws Exception {

MavenModuleSet m = createMavenProject();
MavenInstallation mavenInstallation = configureDefaultMaven();
MavenModuleSet m = j.createMavenProject();
MavenInstallation mavenInstallation = j.configureDefaultMaven();
ParametersDefinitionProperty parametersDefinitionProperty =
new ParametersDefinitionProperty(new StringParameterDefinition( "JUNITVERSION", "3.8.2" ));

Expand All @@ -132,19 +149,20 @@ public void testMavenWithDependencyVersionInEnvVar() throws Exception {
m.getReporters().add(new TestReporter());
m.setScm(new ExtractResourceSCM(getClass().getResource("envars-maven-project.zip")));
m.setGoals( "clean test-compile" );
MavenModuleSetBuild mmsb = buildAndAssertSuccess(m);
MavenModuleSetBuild mmsb = j.buildAndAssertSuccess(m);
assertFalse( mmsb.getProject().getModules().isEmpty());
}

@Bug(8573)
@Test
public void testBuildTimeStampProperty() throws Exception {
MavenInstallation mavenInstallation = configureDefaultMaven();
MavenModuleSet m = createMavenProject();
MavenInstallation mavenInstallation = j.configureDefaultMaven();
MavenModuleSet m = j.createMavenProject();
m.setMaven( mavenInstallation.getName() );
m.getReporters().add(new TestReporter());
m.setScm(new ExtractResourceSCM(getClass().getResource("JENKINS-8573.zip")));
m.setGoals( "process-resources" );
buildAndAssertSuccess(m);
j.buildAndAssertSuccess(m);
String content = m.getLastBuild().getWorkspace().child( "target/classes/test.txt" ).readToString();
assertFalse( content.contains( "${maven.build.timestamp}") );
assertFalse( content.contains( "${maven.build.timestamp}") );
Expand All @@ -153,18 +171,19 @@ public void testBuildTimeStampProperty() throws Exception {
}

@Bug(value=15865)
@Test
public void testMavenFailsafePluginTestResultsAreRecorded() throws Exception {

// GIVEN: a Maven project with maven-failsafe-plugin and Maven 2.2.1
MavenModuleSet mavenProject = createMavenProject();
MavenInstallation mavenInstallation = configureDefaultMaven();
MavenModuleSet mavenProject = j.createMavenProject();
MavenInstallation mavenInstallation = j.configureDefaultMaven();
mavenProject.setMaven(mavenInstallation.getName());
mavenProject.getReporters().add(new TestReporter());
mavenProject.setScm(new ExtractResourceSCM(getClass().getResource("JENKINS-15865.zip")));
mavenProject.setGoals( "clean install" );

// WHEN project is build
MavenModuleSetBuild mmsb = buildAndAssertSuccess(mavenProject);
MavenModuleSetBuild mmsb = j.buildAndAssertSuccess(mavenProject);

// THEN we have a testresult recorded
AggregatedTestResultAction aggregatedTestResultAction = mmsb.getAggregatedTestResultAction();
Expand All @@ -180,34 +199,70 @@ public void testMavenFailsafePluginTestResultsAreRecorded() throws Exception {
}

@Bug(18178)
@Test
public void testExtensionsConflictingWithCore() throws Exception {
MavenModuleSet m = createMavenProject();
m.setMaven(configureDefaultMaven().getName());
MavenModuleSet m = j.createMavenProject();
m.setMaven(j.configureDefaultMaven().getName());
m.setScm(new SingleFileSCM("pom.xml",
"<project><modelVersion>4.0.0</modelVersion>" +
"<groupId>g</groupId><artifactId>a</artifactId><version>0</version>" +
"<build><extensions>" +
"<extension><groupId>org.springframework.build.aws</groupId><artifactId>org.springframework.build.aws.maven</artifactId><version>3.0.0.RELEASE</version></extension>" +
"</extensions></build></project>"));
buildAndAssertSuccess(m);
j.buildAndAssertSuccess(m);
}


@Bug(19801)
@Test
public void stopBuildAndAllSubmoduleBuilds() throws Exception {
j.configureDefaultMaven();
MavenModuleSet project = j.createMavenProject();
project.setGoals("clean package");
project.setScm(new ExtractResourceSCM(
getClass().getResource("/hudson/maven/maven-multimod.zip")
));

MavenModuleSetBuild build = project.scheduleBuild2(0).waitForStart();

ensureSubmoduleBuildsStarted(build);

build.doStop();

Thread.sleep(2000);

This comment has been minimized.

Copy link
@kutzi

kutzi Nov 4, 2013

Member

Why 2 seconds - why not e.g. 1 or 3? This means that this test case needs 2 seconds just for waiting the build to stop.

I know that's not easy at all in Jenkins, but isn't there a way to test this without relying on fragile timing?

j.assertBuildStatus(Result.ABORTED, build);
assertFalse(build.isBuilding());
for (MavenBuild mb: build.getModuleLastBuilds().values()) {
final String moduleName = mb.getParent().getDisplayName();
assertFalse("Module " + moduleName + " is still building", mb.isBuilding());
}
}

private void ensureSubmoduleBuildsStarted(MavenModuleSetBuild build) throws InterruptedException {
for (;;) {
for (MavenBuild mb: build.getModuleLastBuilds().values()) {
if (Result.SUCCESS.equals(mb.getResult())) return;

This comment has been minimized.

Copy link
@kutzi

kutzi Nov 4, 2013

Member

Doesn't this only assure that one submodule build has started?

This comment has been minimized.

Copy link
@olivergondza

olivergondza Nov 5, 2013

Author Member

I want to ensure that there is a submodule being built when I hit the stop button. Otherwise I might end up stopping the build before submodules even started to build.

}
Thread.sleep(1000);
}
}

/**
* This tests build a project with two modules. One that have tests failures
* and the other don't compile due to a missing dependency.
*
* @throws Exception
*/
@Bug(16522)
@Test
public void testCorrectModuleBuildStatus() throws Exception {
MavenModuleSet mavenProject = createMavenProject();
MavenInstallation mavenInstallation = configureDefaultMaven();
MavenModuleSet mavenProject = j.createMavenProject();
MavenInstallation mavenInstallation = j.configureDefaultMaven();
mavenProject.setMaven(mavenInstallation.getName());
mavenProject.setScm(new ExtractResourceSCM(getClass().getResource("JENKINS-16522.zip")));
mavenProject.setGoals( "clean install" );
MavenModuleSetBuild build = mavenProject.scheduleBuild2(0).get();

assertBuildStatus(Result.FAILURE, build);
j.assertBuildStatus(Result.FAILURE, build);

MavenModule moduleA = mavenProject.getModule("org.marcelo$moduleA");
assertNotNull(moduleA);
Expand Down

1 comment on commit 93dfb65

@olivergondza
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kutzi: Thanks for pointing out how ugly it was. e1e7d22 is better.

Please sign in to comment.