This is my first post to this group so apologies if I'm not following the
"usual process" for this request.
I implemented a new custom (and very simple) trigger for the "email-ext"
plugin and was wondering if it was possible to integrate this into the
official plugin. The new trigger is named "Status Changed" and will send a
message as soon as the status (not_built, successful, failure, unstable,
aborted) of a job changes. The initial intent is to only notify status
changes and avoid spamming developers when there are a lot of build
failures (I know that ideally builds should be fixed quickly but ...).
I attached the source for the new trigger and the associated unit test
class. This successfully compiled against email-ext 2.34.
Note: Despite having an account to access the Wiki, I'm unable to log onto
JIRA and couldn't find how to have my access "fixed" by an admin hence this
post. If you could point me to a solution to access JIRA, I'd be grateful
(I already reset my password 3-4 times without success).
--
You received this message because you are subscribed to the Google Groups
"Jenkins Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.
package hudson.plugins.emailext.plugins.trigger;
import hudson.Extension;
import hudson.model.AbstractBuild;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.plugins.emailext.plugins.EmailTrigger;
import hudson.plugins.emailext.plugins.EmailTriggerDescriptor;
import java.io.IOException;
import javax.servlet.ServletException;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
public class StatusChangedTrigger extends EmailTrigger {
public static final String TRIGGER_NAME = "Status Changed";
@DataBoundConstructor
public StatusChangedTrigger(boolean sendToList, boolean sendToDevs, boolean sendToRequestor, boolean sendToCulprits, String recipientList,
String replyTo, String subject, String body, String attachmentsPattern, int attachBuildLog, String contentType) {
super(sendToList, sendToDevs, sendToRequestor, sendToCulprits, recipientList, replyTo, subject, body, attachmentsPattern, attachBuildLog, contentType);
}
@Override
public boolean trigger(AbstractBuild<?, ?> build, TaskListener listener) {
final Result buildResult = build.getResult();
if (buildResult != null) {
final AbstractBuild<?, ?> prevBuild = build.getPreviousBuild();
if (prevBuild == null) {
// Notify at the first status defined
return true;
}
return (build.getResult() != prevBuild.getResult());
}
return false;
}
@Extension
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
@Override
public EmailTriggerDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static final class DescriptorImpl extends EmailTriggerDescriptor {
public DescriptorImpl() {
addTriggerNameToReplace(UnstableTrigger.TRIGGER_NAME);
}
@Override
public String getDisplayName() {
return TRIGGER_NAME;
}
@Override
public void doHelp(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
rsp.getWriter().println("An email will be sent when the build status changes");
}
@Override
public boolean getDefaultSendToDevs() {
return true;
}
@Override
public boolean getDefaultSendToList() {
return false;
}
}
}
package hudson.plugins.emailext.plugins.trigger;
import hudson.model.Result;
import hudson.plugins.emailext.plugins.EmailTrigger;
import java.io.IOException;
import org.junit.Test;
/**
* Unit tests for the Calypso-specific "Status changed" trigger.
*
* @author francois_ritaly
*/
public class StatusChangedTriggerTest extends TriggerTestBase {
@Override
EmailTrigger newInstance() {
return new StatusChangedTrigger(true, true, true, false, "", "", "", "", "", 0, "project");
}
// --- Transitions from <no-status> to <status> --- //
@Test
public void testTrigger_Success() throws IOException, InterruptedException {
// Notification expected since this is the first build status defined
assertTriggered(Result.SUCCESS);
}
@Test
public void testTrigger_Aborted() throws IOException, InterruptedException {
// Notification expected since this is the first build status defined
assertTriggered(Result.ABORTED);
}
@Test
public void testTrigger_Failure() throws IOException, InterruptedException {
// Notification expected since this is the first build status defined
assertTriggered(Result.FAILURE);
}
@Test
public void testTrigger_NotBuilt() throws IOException, InterruptedException {
// Notification expected since this is the first build status defined
assertTriggered(Result.NOT_BUILT);
}
@Test
public void testTrigger_Unstable() throws IOException, InterruptedException {
// Notification expected since this is the first build status defined
assertTriggered(Result.UNSTABLE);
}
// --- Transitions between 2 statuses --- //
// There are 5 possible statuses (success, aborted, failure, not_built and unstable)
// so we must test 5x5 = 25 transitions
// Transitions from the "success" status
@Test
public void testTrigger_SuccessSuccess() throws IOException, InterruptedException {
assertNotTriggered(Result.SUCCESS, Result.SUCCESS);
}
@Test
public void testTrigger_SuccessAborted() throws IOException, InterruptedException {
assertTriggered(Result.SUCCESS, Result.ABORTED);
}
@Test
public void testTrigger_SuccessFailure() throws IOException, InterruptedException {
assertTriggered(Result.SUCCESS, Result.FAILURE);
}
@Test
public void testTrigger_SuccessNotBuilt() throws IOException, InterruptedException {
assertTriggered(Result.SUCCESS, Result.NOT_BUILT);
}
@Test
public void testTrigger_SuccessUnstable() throws IOException, InterruptedException {
assertTriggered(Result.SUCCESS, Result.UNSTABLE);
}
// Transitions from the "aborted" status
@Test
public void testTrigger_AbortedSuccess() throws IOException, InterruptedException {
assertTriggered(Result.ABORTED, Result.SUCCESS);
}
@Test
public void testTrigger_AbortedAborted() throws IOException, InterruptedException {
assertNotTriggered(Result.ABORTED, Result.ABORTED);
}
@Test
public void testTrigger_AbortedFailure() throws IOException, InterruptedException {
assertTriggered(Result.ABORTED, Result.FAILURE);
}
@Test
public void testTrigger_AbortedNotBuilt() throws IOException, InterruptedException {
assertTriggered(Result.ABORTED, Result.NOT_BUILT);
}
@Test
public void testTrigger_AbortedUnstable() throws IOException, InterruptedException {
assertTriggered(Result.ABORTED, Result.UNSTABLE);
}
// Transitions from the "failure" status
@Test
public void testTrigger_FailureSuccess() throws IOException, InterruptedException {
assertTriggered(Result.FAILURE, Result.SUCCESS);
}
@Test
public void testTrigger_FailureAborted() throws IOException, InterruptedException {
assertTriggered(Result.FAILURE, Result.ABORTED);
}
@Test
public void testTrigger_FailureFailure() throws IOException, InterruptedException {
assertNotTriggered(Result.FAILURE, Result.FAILURE);
}
@Test
public void testTrigger_FailureNotBuilt() throws IOException, InterruptedException {
assertTriggered(Result.FAILURE, Result.NOT_BUILT);
}
@Test
public void testTrigger_FailureUnstable() throws IOException, InterruptedException {
assertTriggered(Result.FAILURE, Result.UNSTABLE);
}
// Transitions from the "not_built" status
@Test
public void testTrigger_NotBuiltSuccess() throws IOException, InterruptedException {
assertTriggered(Result.NOT_BUILT, Result.SUCCESS);
}
@Test
public void testTrigger_NotBuiltAborted() throws IOException, InterruptedException {
assertTriggered(Result.NOT_BUILT, Result.ABORTED);
}
@Test
public void testTrigger_NotBuiltFailure() throws IOException, InterruptedException {
assertTriggered(Result.NOT_BUILT, Result.FAILURE);
}
@Test
public void testTrigger_NotBuiltNotBuilt() throws IOException, InterruptedException {
assertNotTriggered(Result.NOT_BUILT, Result.NOT_BUILT);
}
@Test
public void testTrigger_NotBuiltUnstable() throws IOException, InterruptedException {
assertTriggered(Result.NOT_BUILT, Result.UNSTABLE);
}
// Transitions from the "unstable" status
@Test
public void testTrigger_UnstableSuccess() throws IOException, InterruptedException {
assertTriggered(Result.UNSTABLE, Result.SUCCESS);
}
@Test
public void testTrigger_UnstableAborted() throws IOException, InterruptedException {
assertTriggered(Result.UNSTABLE, Result.ABORTED);
}
@Test
public void testTrigger_UnstableFailure() throws IOException, InterruptedException {
assertTriggered(Result.UNSTABLE, Result.FAILURE);
}
@Test
public void testTrigger_UnstableNotBuilt() throws IOException, InterruptedException {
assertTriggered(Result.UNSTABLE, Result.NOT_BUILT);
}
@Test
public void testTrigger_UnstableUnstable() throws IOException, InterruptedException {
assertNotTriggered(Result.UNSTABLE, Result.UNSTABLE);
}
}