Skip to content
Permalink
Browse files

Support for ciManagement maven notifications.

In order to enable ciManagement maven notifications you have to check the
option "E-mail Notification" into the section "Build Settings" from the
job, and add a ciManagement section to the pom.xml with the following
settings:

ciManagement
|-- system=hudson (you have to put "hudson" here )
|-- ur=http://serverurl/
|-- notifiers
|----- notifier
|-------- type=mail (you have to put "mail" here)
|-------- sendOnError=true
|-------- sendOnFailure=true
|-------- sendOnSuccess>false
|-------- sendOnWarning>false
|-------- configuration
|------------ recipients=some.email@domain.org (recipients have the same
format than the same field in the Job configuration page)

You can override this configuration in any module of the maven proyect.

[FIXED JENKINS-1201]
[FIXED JENKINS-6421]
  • Loading branch information...
mrebasti committed Oct 7, 2013
1 parent 53987d1 commit 2f924d838f4ad49334531950cb3e7187ed147b69
@@ -25,6 +25,7 @@

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

import hudson.CopyOnWrite;
import hudson.Functions;
import hudson.Util;
@@ -48,21 +49,26 @@
import hudson.util.AlternativeUiTextProvider;
import hudson.util.DescribableList;
import jenkins.model.Jenkins;

import org.apache.maven.model.Notifier;
import org.apache.maven.project.MavenProject;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;

import javax.servlet.ServletException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

@@ -192,8 +198,9 @@ public boolean isBuildable() {
* <p>
* This method is invoked on {@link MavenModule} that has the matching
* {@link ModuleName}.
* @throws IOException
*/
/*package*/ void reconfigure(PomInfo pom) {
/*package*/ void reconfigure(PomInfo pom) throws IOException {
this.displayName = pom.displayName;
this.version = pom.version;
this.packaging = pom.packaging;
@@ -202,21 +209,61 @@ public boolean isBuildable() {
this.children = pom.children;
this.nestLevel = pom.getNestLevel();
disabled = false;

if (pom.mailNotifier != null) {
MavenReporter reporter = getReporters().get(MavenMailer.class);
if (reporter != null) {
MavenMailer mailer = (MavenMailer) reporter;
mailer.dontNotifyEveryUnstableBuild = !pom.mailNotifier.isSendOnFailure();
String recipients = pom.mailNotifier.getConfiguration().getProperty("recipients");
if (recipients != null) {
mailer.recipients = recipients;
}
}

MavenMailer projectMailer = getParent().getReporters() == null? null: getParent().getReporters().get(MavenMailer.class);
if (projectMailer != null) {
Notifier notifier = getCiManagementNotifier(pom);
if (notifier != null) {
MavenMailer mailer;

if (pom.parent == null) {//If isModuleRoot then..
mailer = projectMailer;
} else {
mailer = getOrCreateMavenMailer(pom);
}

mailer.perModuleEmail = projectMailer.perModuleEmail;
mailer.dontNotifyEveryUnstableBuild = !notifier.isSendOnFailure();

String recipients = notifier.getConfiguration().getProperty("recipients");

mailer.recipients = projectMailer.recipients;
mailer.mavenRecipients = recipients;
} else {
getReporters().remove(MavenMailer.class);
}
} else {
// When "E-mail Notification" is unchecked then I remove the
// MavenMailer from the modules.
if (getReporters() != null) {
getReporters().remove(MavenMailer.class);
}
}
}

/**
private MavenMailer getOrCreateMavenMailer(PomInfo pom) {
MavenMailer mavenMailer = getReporters().get(MavenMailer.class);
if (mavenMailer == null) {
mavenMailer = new MavenMailer();
getReporters().add(mavenMailer);
}

return mavenMailer;
}

private Notifier getCiManagementNotifier(PomInfo pom) {
Notifier notifier = null;

if (pom.mailNotifier != null) {
notifier = pom.mailNotifier;
} else if (pom.parent != null) {
notifier = getCiManagementNotifier(pom.parent);
}

return notifier;
}

/**
* Returns if the given POM likely describes the same module with the same dependencies.
* Implementation needs not be 100% accurate in the true case, but it MUST return false
* if is not the same.
@@ -662,20 +709,29 @@ protected void performDelete() throws IOException, InterruptedException {
* Creates a list of {@link MavenReporter}s to be used for a build of this project.
*/
protected List<MavenReporter> createReporters() {
List<MavenReporter> reporterList = new ArrayList<MavenReporter>();

getReporters().addAllTo(reporterList);
getParent().getReporters().addAllTo(reporterList);
Set<MavenReporter> reporterSet = new TreeSet<MavenReporter>(new Comparator<MavenReporter>() {
@Override
public int compare(MavenReporter o1, MavenReporter o2) {
if (o1.getClass() == o2.getClass()) {
return 0;
}
return 1;
}
});

getReporters().addAllTo(reporterSet);
getParent().getReporters().addAllTo(reporterSet);


for (MavenReporterDescriptor d : MavenReporterDescriptor.all()) {
if(getReporters().contains(d))
continue; // already configured
MavenReporter auto = d.newAutoInstance(this);
if(auto!=null)
reporterList.add(auto);
reporterSet.add(auto);
}

return reporterList;
return new ArrayList<MavenReporter>(reporterSet);
}

/**
@@ -1032,7 +1032,7 @@ protected void post2(BuildListener listener) throws Exception {
public void cleanUp(BuildListener listener) throws Exception {
MavenMailer mailer = project.getReporters().get(MavenMailer.class);
if (mailer != null) {
new MailSender(mailer.recipients,
new MailSender(mailer.getAllRecipients(),
mailer.dontNotifyEveryUnstableBuild,
mailer.sendToIndividuals).execute(MavenModuleSetBuild.this, listener);
}
@@ -46,16 +46,23 @@
* @see Mailer
*/
public String recipients;
public String mavenRecipients;
public boolean dontNotifyEveryUnstableBuild;
public boolean sendToIndividuals;
public boolean perModuleEmail;

public boolean end(MavenBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
if(perModuleEmail) {
new MailSender(recipients,dontNotifyEveryUnstableBuild,sendToIndividuals).execute(build,listener);
new MailSender(getAllRecipients(),dontNotifyEveryUnstableBuild,sendToIndividuals).execute(build,listener);
}
return true;
}

public String getAllRecipients() {
return this.recipients == null ?
this.mavenRecipients :
this.recipients + " " + this.mavenRecipients;

This comment has been minimized.

Copy link
@mrebasti

mrebasti Oct 23, 2013

Author Contributor

this line seems to be causing JENKINS-20209. I'll do some tests and send a fix.

}

@Extension
public static final class DescriptorImpl extends MavenReporterDescriptor {
@@ -10,6 +10,7 @@
import hudson.model.DependencyGraph;
import hudson.model.MockHelper;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -38,7 +39,7 @@
private MavenProject project;

@Before
public void before() {
public void before() throws IOException {
suppress(constructor(AbstractProject.class));
suppress(constructor(DescriptorImpl.class));

@@ -58,10 +59,11 @@ public void before() {
/**
* Tests that a {@link MavenModule} which builds a plugin is recognized as a snapshot
* dependency in another module using that plugin.
* @throws IOException
*/
@Test
@Bug(10530)
public void testMavenModuleAsPluginDependency() {
public void testMavenModuleAsPluginDependency() throws IOException {
MavenModule pluginModule = createPluginProject();

addModuleAsPluginDependency(this.module, pluginModule);
@@ -78,7 +80,7 @@ public void testMavenModuleAsPluginDependency() {
Assert.assertSame(this.module, downstream.get(0));
}

private static void addModuleAsPluginDependency(MavenModule module, MavenModule pluginModule) {
private static void addModuleAsPluginDependency(MavenModule module, MavenModule pluginModule) throws IOException {
Build build = new Build();
Plugin plugin = new Plugin();
plugin.setGroupId(pluginModule.getModuleName().groupId);
@@ -96,7 +98,7 @@ private static void addModuleAsPluginDependency(MavenModule module, MavenModule
module.reconfigure(new PomInfo(project, null, "relPath"));
}

private static MavenModule createPluginProject() {
private static MavenModule createPluginProject() throws IOException {
MavenModule pluginModule = mock(MavenModule.class);
basicMocking(pluginModule);

@@ -112,7 +114,7 @@ private static MavenModule createPluginProject() {
return pluginModule;
}

private static void basicMocking(MavenModule mock) {
private static void basicMocking(MavenModule mock) throws IOException {
when(mock.isBuildable()).thenReturn(Boolean.TRUE);
doCallRealMethod().when(mock).reconfigure(Matchers.any(PomInfo.class));
doCallRealMethod().when(mock).buildDependencyGraph(Matchers.any(DependencyGraph.class));
@@ -129,9 +131,10 @@ private static void basicMocking(MavenModule mock) {
}
/**
* This test is a standard project that has a versioned dependency.
* @throws IOException
*/
@Test
public void testSimpleVersion() {
public void testSimpleVersion() throws IOException {
TestComponents testComponents = createTestComponents("1.0.1-SNAPSHOT");

DependencyGraph graph = testComponents.graph;
@@ -154,9 +157,10 @@ public void testSimpleVersion() {
/**
* This tests that a version range declaration in the dependency of a top level project
* resolves the up and downstream correctly.
* @throws IOException
*/
@Test
public void testSimpleVersionRange() {
public void testSimpleVersionRange() throws IOException {
TestComponents testComponents = createTestComponents("[1.0.0, )");

DependencyGraph graph = testComponents.graph;
@@ -179,9 +183,10 @@ public void testSimpleVersionRange() {
/**
* Test multiple projects with dependencies on differing library versions declared with
* multiple version definitions.
* @throws IOException
*/
@Test
public void testMultipleDependencies() {
public void testMultipleDependencies() throws IOException {

MavenProject projectA = createMavenProject("ProjectA", "test", "projectA", "1.0-SNAPSHOT", "jar");
Dependency dependencyA = createDependency("test", "library", "[1.0, 2.0)");
@@ -237,9 +242,10 @@ public void testMultipleDependencies() {
/**
* This tests a project that has a dependency on a specific version of X.
* The project X has moved on and so should not have any dependencies on ProjectA.
* @throws IOException
*/
@Test
public void testProjectWithSpecifiedVersionAndNoDependencies() {
public void testProjectWithSpecifiedVersionAndNoDependencies() throws IOException {
MavenProject projectA = createMavenProject("ProjectA", "test", "projectA", "1.0-SNAPSHOT", "jar");
Dependency dependencyA = createDependency("test", "library", "1.0");
projectA.getDependencies().add(dependencyA);
@@ -280,7 +286,7 @@ public void testProjectWithSpecifiedVersionAndNoDependencies() {
Assert.assertEquals(0, upstreamX.size());
}

private TestComponents createTestComponents(String libraryVersion) {
private TestComponents createTestComponents(String libraryVersion) throws IOException {
MavenProject appProject = createMavenProject("testapp", "test", "application", "1.0-SNAPSHOT", "jar");
Dependency dependency = createDependency("test", "library", libraryVersion);
appProject.getDependencies().add(dependency);
@@ -319,7 +325,7 @@ private static void enhanceMavenModuleMock(MavenModule module,
when(module.getAllMavenModules()).thenReturn(allProjects);
}

private static MavenModule mockMavenModule(MavenProject project) {
private static MavenModule mockMavenModule(MavenProject project) throws IOException {
MavenModule mavenModule = mock(MavenModule.class);
when(mavenModule.getName()).thenReturn(project.getName());
basicMocking(mavenModule);

2 comments on commit 2f924d8

@kutzi

This comment has been minimized.

Copy link
Member

replied Oct 23, 2013

@mrebasti

This comment has been minimized.

Copy link
Contributor Author

replied Oct 23, 2013

Please sign in to comment.
You can’t perform that action at this time.