Skip to content

Commit

Permalink
[FIXED JENKINS-16376] Never wait for previous builds to complete just…
Browse files Browse the repository at this point in the history
… to get a more precise status.

If and when we need to know the status of a previous build but it is still running,
simply print a warning to the (current build’s) log and proceed as if the previous build did not exist.
  • Loading branch information
jglick committed Nov 5, 2013
1 parent 178360e commit 6fb4181
Show file tree
Hide file tree
Showing 17 changed files with 127 additions and 53 deletions.
26 changes: 23 additions & 3 deletions src/main/java/hudson/plugins/emailext/ExtendedEmailPublisher.java
Expand Up @@ -30,7 +30,7 @@
import hudson.FilePath;
import hudson.model.Action;
import hudson.model.Item;
import hudson.security.Permission;
import hudson.model.TaskListener;

import org.apache.commons.lang.StringUtils;
import org.codehaus.groovy.control.CompilerConfiguration;
Expand Down Expand Up @@ -61,6 +61,8 @@
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

import javax.mail.Address;
import javax.mail.Message;
Expand Down Expand Up @@ -572,7 +574,7 @@ private MimeMessage createMail(EmailType type, AbstractBuild<?, ?> build, BuildL
msg.setReplyTo(replyToAddresses.toArray(new InternetAddress[replyToAddresses.size()]));
}

AbstractBuild<?, ?> pb = build.getPreviousBuild();
AbstractBuild<?, ?> pb = getPreviousBuild(build, listener);
if (pb != null) {
// Send mails as replies until next successful build
MailMessageIdAction b = pb.getAction(MailMessageIdAction.class);
Expand Down Expand Up @@ -764,7 +766,25 @@ public boolean needsToRunAfterFinalized() {
}

public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.BUILD;
return BuildStepMonitor.NONE;
}

/**
* Looks for a previous build, so long as that is in fact completed.
* Necessary since {@link #getRequiredMonitorService} does not wait for the previous build,
* so in the case of parallel-capable jobs, we need to behave sensibly when a later build actually finishes before an earlier one.
* @param build a build for which we may be sending mail
* @param listener a listener to which we may print warnings in case the actual previous build is still in progress
* @return the previous build, or null if that build is missing, or is still in progress
*/
public static @CheckForNull AbstractBuild<?,?> getPreviousBuild(@Nonnull AbstractBuild<?,?> build, TaskListener listener) {
AbstractBuild<?,?> previousBuild = build.getPreviousBuild();
if (previousBuild != null && previousBuild.isBuilding()) {
listener.getLogger().println(Messages.ExtendedEmailPublisher__is_still_in_progress_ignoring_for_purpo(previousBuild.getDisplayName()));
return null;
} else {
return previousBuild;
}
}

@Override
Expand Down
Expand Up @@ -27,6 +27,7 @@
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.Util;
import java.io.IOException;

Expand Down Expand Up @@ -56,7 +57,7 @@ abstract public class AbstractChangesSinceContent
public String evaluate(AbstractBuild<?, ?> build, TaskListener listener, String macroName)
throws MacroEvaluationException, IOException, InterruptedException {
// No previous build so bail
if (build.getPreviousBuild() == null) {
if (ExtendedEmailPublisher.getPreviousBuild(build, listener) == null) {
return "";
}

Expand All @@ -69,9 +70,9 @@ public String evaluate(AbstractBuild<?, ?> build, TaskListener listener, String
final AbstractBuild endBuild;
if (reverse) {
startBuild = build;
endBuild = getFirstIncludedBuild(build);
endBuild = getFirstIncludedBuild(build, listener);
} else {
startBuild = getFirstIncludedBuild(build);
startBuild = getFirstIncludedBuild(build, listener);
endBuild = build;
}
AbstractBuild<?, ?> currentBuild = null;
Expand Down Expand Up @@ -129,6 +130,5 @@ public boolean hasNestedContent() {

public abstract String getShortHelpDescription();

public abstract <P extends AbstractProject<P, B>, B extends AbstractBuild<P, B>> AbstractBuild<P, B> getFirstIncludedBuild(
AbstractBuild<P, B> build);
public abstract AbstractBuild<?,?> getFirstIncludedBuild(AbstractBuild<?,?> build, TaskListener listener);
}
Expand Up @@ -2,8 +2,8 @@

import hudson.model.AbstractBuild;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.plugins.EmailToken;
import java.io.IOException;

Expand Down Expand Up @@ -33,14 +33,14 @@ public String evaluate(AbstractBuild<?, ?> build, TaskListener listener, String

Result buildResult = build.getResult();
if (buildResult == Result.FAILURE) {
Run<?,?> prevBuild = build.getPreviousBuild();
AbstractBuild<?,?> prevBuild = ExtendedEmailPublisher.getPreviousBuild(build, listener);
if (prevBuild != null && (prevBuild.getResult() == Result.FAILURE)) {
return "Still Failing";
} else {
return "Failure";
}
} else if (buildResult == Result.UNSTABLE) {
Run<?,?> prevBuild = build.getPreviousBuild();
AbstractBuild<?,?> prevBuild = ExtendedEmailPublisher.getPreviousBuild(build, listener);
if (prevBuild != null) {
if (prevBuild.getResult() == Result.UNSTABLE) {
return "Still Unstable";
Expand All @@ -52,23 +52,23 @@ public String evaluate(AbstractBuild<?, ?> build, TaskListener listener, String
//iterate through previous builds
//(fail_or_aborted)* and then an unstable : return still unstable
//(fail_or_aborted)* and then successful : return unstable
Run<?,?> previous = prevBuild.getPreviousBuild();
AbstractBuild<?,?> previous = ExtendedEmailPublisher.getPreviousBuild(prevBuild, listener);
while (previous != null) {
if (previous.getResult() == Result.SUCCESS) {
return "Unstable";
}
if (previous.getResult() == Result.UNSTABLE) {
return "Still unstable";
}
previous = previous.getPreviousBuild();
previous = ExtendedEmailPublisher.getPreviousBuild(previous, listener);
}
return "Unstable";
}
} else {
return "Unstable";
}
} else if (buildResult == Result.SUCCESS) {
Run<?,?> prevBuild = build.getPreviousBuild();
AbstractBuild<?,?> prevBuild = ExtendedEmailPublisher.getPreviousBuild(build, listener);
if (prevBuild != null && (prevBuild.getResult() == Result.UNSTABLE || prevBuild.getResult() == Result.FAILURE)) {
return "Fixed";
} else {
Expand Down
Expand Up @@ -4,6 +4,7 @@
import hudson.model.AbstractBuild.DependencyChange;
import hudson.model.AbstractProject;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.Util;
import hudson.plugins.emailext.plugins.EmailToken;
import hudson.scm.ChangeLogSet;
Expand All @@ -12,7 +13,6 @@
import org.jenkinsci.plugins.tokenmacro.MacroEvaluationException;

import java.io.IOException;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
Expand Down Expand Up @@ -72,18 +72,21 @@ public String evaluate(AbstractBuild<?, ?> build, TaskListener listener, String
Util.printf(buf, format, new ChangesSincePrintfSpec(entry, pathFormat, dateFormatter));
}

if (showDependencies && build.getPreviousBuild() != null)
for (Entry<AbstractProject, DependencyChange> e : build
.getDependencyChanges(build.getPreviousBuild()).entrySet()) {
buf.append("\n=======================\n");
buf.append("\nChanges in ").append(e.getKey().getName())
.append(":\n");
for (AbstractBuild<?, ?> b : e.getValue().getBuilds()) {
for (ChangeLogSet.Entry entry : b.getChangeSet()) {
Util.printf(buf, format, new ChangesSincePrintfSpec(entry, pathFormat, dateFormatter));
if (showDependencies) {
AbstractBuild previousBuild = ExtendedEmailPublisher.getPreviousBuild(build, listener);
if (previousBuild != null) {
for (Entry<AbstractProject, DependencyChange> e : build.getDependencyChanges(previousBuild).entrySet()) {
buf.append("\n=======================\n");
buf.append("\nChanges in ").append(e.getKey().getName())
.append(":\n");
for (AbstractBuild<?, ?> b : e.getValue().getBuilds()) {
for (ChangeLogSet.Entry entry : b.getChangeSet()) {
Util.printf(buf, format, new ChangesSincePrintfSpec(entry, pathFormat, dateFormatter));
}
}
}
}
}

return buf.toString();
}
Expand Down
@@ -1,8 +1,9 @@
package hudson.plugins.emailext.plugins.content;

import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.plugins.EmailToken;

@EmailToken
Expand All @@ -28,14 +29,13 @@ public String getShortHelpDescription() {
}

@Override
public <P extends AbstractProject<P, B>, B extends AbstractBuild<P, B>> AbstractBuild<P, B> getFirstIncludedBuild(
AbstractBuild<P, B> build) {
AbstractBuild<P, B> firstIncludedBuild = build;
public AbstractBuild<?,?> getFirstIncludedBuild(AbstractBuild<?,?> build, TaskListener listener) {
AbstractBuild<?,?> firstIncludedBuild = build;

B prev = firstIncludedBuild.getPreviousBuild();
AbstractBuild<?,?> prev = ExtendedEmailPublisher.getPreviousBuild(firstIncludedBuild, listener);
while (prev != null && prev.getResult() != Result.SUCCESS) {
firstIncludedBuild = prev;
prev = firstIncludedBuild.getPreviousBuild();
prev = ExtendedEmailPublisher.getPreviousBuild(firstIncludedBuild, listener);
}

return firstIncludedBuild;
Expand Down
@@ -1,8 +1,9 @@
package hudson.plugins.emailext.plugins.content;

import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.plugins.EmailToken;

@EmailToken
Expand All @@ -28,14 +29,13 @@ public String getShortHelpDescription() {
}

@Override
public <P extends AbstractProject<P, B>, B extends AbstractBuild<P, B>> AbstractBuild<P, B> getFirstIncludedBuild(
AbstractBuild<P, B> build) {
AbstractBuild<P, B> firstIncludedBuild = build;
public AbstractBuild<?,?> getFirstIncludedBuild(AbstractBuild<?,?> build, TaskListener listener) {
AbstractBuild<?,?> firstIncludedBuild = build;

B prev = firstIncludedBuild.getPreviousBuild();
AbstractBuild<?,?> prev = ExtendedEmailPublisher.getPreviousBuild(firstIncludedBuild, listener);
while (prev != null && prev.getResult().isWorseThan(Result.UNSTABLE)) {
firstIncludedBuild = prev;
prev = firstIncludedBuild.getPreviousBuild();
prev = ExtendedEmailPublisher.getPreviousBuild(firstIncludedBuild, listener);
}

return firstIncludedBuild;
Expand Down
Expand Up @@ -4,6 +4,7 @@
import hudson.model.AbstractBuild;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.plugins.EmailTrigger;
import hudson.plugins.emailext.plugins.EmailTriggerDescriptor;
import org.kohsuke.stapler.DataBoundConstructor;
Expand All @@ -24,7 +25,7 @@ public boolean trigger(AbstractBuild<?, ?> build, TaskListener listener) {
Result buildResult = build.getResult();

if (buildResult == Result.UNSTABLE) {
AbstractBuild<?, ?> prevBuild = build.getPreviousBuild();
AbstractBuild<?, ?> prevBuild = ExtendedEmailPublisher.getPreviousBuild(build, listener);
if (prevBuild != null && (prevBuild.getResult() == Result.FAILURE)) {
return true;
}
Expand Down
Expand Up @@ -4,6 +4,7 @@
import hudson.model.AbstractBuild;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.plugins.EmailTrigger;
import hudson.plugins.emailext.plugins.EmailTriggerDescriptor;

Expand All @@ -26,7 +27,7 @@ public boolean trigger(AbstractBuild<?, ?> build, TaskListener listener) {
Result buildResult = build.getResult();

if (buildResult == Result.SUCCESS) {
AbstractBuild<?, ?> prevBuild = build.getPreviousBuild();
AbstractBuild<?, ?> prevBuild = ExtendedEmailPublisher.getPreviousBuild(build, listener);
if (prevBuild != null && (prevBuild.getResult() == Result.UNSTABLE || prevBuild.getResult() == Result.FAILURE)) {
return true;
}
Expand Down
Expand Up @@ -4,6 +4,7 @@
import hudson.model.AbstractBuild;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.plugins.EmailTrigger;
import hudson.plugins.emailext.plugins.EmailTriggerDescriptor;

Expand All @@ -25,7 +26,7 @@ public boolean trigger(AbstractBuild<?, ?> build, TaskListener listener) {
Result buildResult = build.getResult();

if (buildResult == Result.SUCCESS) {
AbstractBuild<?, ?> prevBuild = getPreviousBuild(build);
AbstractBuild<?, ?> prevBuild = getPreviousBuild(build, listener);
if (prevBuild != null && (prevBuild.getResult() == Result.UNSTABLE || prevBuild.getResult() == Result.FAILURE)) {
return true;
}
Expand All @@ -37,13 +38,13 @@ public boolean trigger(AbstractBuild<?, ?> build, TaskListener listener) {
/**
* Find most recent previous build matching certain criteria.
*/
private AbstractBuild<?, ?> getPreviousBuild(AbstractBuild<?, ?> build) {
private AbstractBuild<?, ?> getPreviousBuild(AbstractBuild<?, ?> build, TaskListener listener) {

AbstractBuild<?, ?> prevBuild = build.getPreviousBuild();
AbstractBuild<?, ?> prevBuild = ExtendedEmailPublisher.getPreviousBuild(build, listener);

// Skip ABORTED builds
if (prevBuild != null && (prevBuild.getResult() == Result.ABORTED)) {
return getPreviousBuild(prevBuild);
return getPreviousBuild(prevBuild, listener);
}

return prevBuild;
Expand Down
Expand Up @@ -3,6 +3,7 @@
import hudson.Extension;
import hudson.model.AbstractBuild;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.plugins.EmailTrigger;
import hudson.plugins.emailext.plugins.EmailTriggerDescriptor;

Expand All @@ -20,11 +21,12 @@ public ImprovementTrigger(boolean sendToList, boolean sendToDevs, boolean sendTo

@Override
public boolean trigger(AbstractBuild<?, ?> build, TaskListener listener) {
AbstractBuild<?,?> previousBuild = ExtendedEmailPublisher.getPreviousBuild(build, listener);

if (build.getPreviousBuild() == null)
if (previousBuild == null)
return false;
if (build.getTestResultAction() == null) return false;
if (build.getPreviousBuild().getTestResultAction() == null)
if (previousBuild.getTestResultAction() == null)
return false;

int numCurrFailures = getNumFailures(build);
Expand All @@ -33,7 +35,7 @@ public boolean trigger(AbstractBuild<?, ?> build, TaskListener listener) {
// builds that aggregate downstream test results before those test
// results are available...
return build.getTestResultAction().getTotalCount() > 0
&& numCurrFailures < getNumFailures(build.getPreviousBuild())
&& numCurrFailures < getNumFailures(previousBuild)
&& numCurrFailures > 0;
}

Expand Down
Expand Up @@ -3,6 +3,7 @@
import hudson.model.AbstractBuild;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.plugins.EmailTrigger;
import hudson.plugins.emailext.plugins.EmailTriggerDescriptor;

Expand Down Expand Up @@ -35,7 +36,7 @@ public boolean trigger(AbstractBuild<?, ?> build, TaskListener listener) {
return false;
}

build = build.getPreviousBuild();
build = ExtendedEmailPublisher.getPreviousBuild(build, listener);
}

// Check the the preceding build was a success.
Expand Down
Expand Up @@ -4,6 +4,7 @@
import hudson.model.Result;
import hudson.model.AbstractBuild;
import hudson.model.TaskListener;
import hudson.plugins.emailext.ExtendedEmailPublisher;
import hudson.plugins.emailext.plugins.EmailTrigger;
import hudson.plugins.emailext.plugins.EmailTriggerDescriptor;

Expand All @@ -22,14 +23,15 @@ public RegressionTrigger(boolean sendToList, boolean sendToDevs, boolean sendToR

@Override
public boolean trigger(AbstractBuild<?, ?> build, TaskListener listener) {
if (build.getPreviousBuild() == null)
AbstractBuild<?,?> previousBuild = ExtendedEmailPublisher.getPreviousBuild(build, listener);
if (previousBuild == null)
return build.getResult() == Result.FAILURE;
if (build.getTestResultAction() == null) return false;
if (build.getPreviousBuild().getTestResultAction() == null)
if (previousBuild.getTestResultAction() == null)
return build.getTestResultAction().getFailCount() > 0;

return build.getTestResultAction().getFailCount() >
build.getPreviousBuild().getTestResultAction().getFailCount();
previousBuild.getTestResultAction().getFailCount();
}

@Extension
Expand Down

0 comments on commit 6fb4181

Please sign in to comment.