Skip to content

Commit

Permalink
Add support for matrix builds
Browse files Browse the repository at this point in the history
Matrix builds show as red until all broken sub-jobs are claimed.

The code was based on code lifted from pull request 1 from henriklynggaard.

[FIXED JENKINS-8458]
  • Loading branch information
david-resnick committed Oct 1, 2013
1 parent 394f78e commit bb5616c
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 37 deletions.
15 changes: 15 additions & 0 deletions src/main/java/hudson/model/IViewEntry.java
Expand Up @@ -102,10 +102,25 @@ public interface IViewEntry {
*/
public abstract String getClaim();

/**
* @return Matrix subjob combination info for unclaimed broken subjobs.
*/
public abstract String getUnclaimedMatrixBuilds();

public abstract Result getLastFinishedResult();

public abstract boolean hasChildren();

/**
* @return <code>true</code> if the build is claimed or if any matrix sub-jobs have been
* claimed.
*/
public abstract boolean isClaimed();

/**
* @return <code>true</code> if the build is claimed or if all broken matrix sub-jobs have been
* claimed.
*/
public abstract boolean isCompletelyClaimed();

}
141 changes: 106 additions & 35 deletions src/main/java/hudson/model/JobViewEntry.java
@@ -1,6 +1,8 @@
package hudson.model;

import hudson.Functions;
import hudson.matrix.MatrixRun;
import hudson.matrix.MatrixBuild;
import hudson.plugins.claim.ClaimBuildAction;
import hudson.tasks.test.AbstractTestResultAction;

Expand All @@ -23,7 +25,7 @@
*/
public class JobViewEntry implements IViewEntry {

private static final String NOT_CLAIMED = "Not Claimed";
private static final String NOT_CLAIMED = "Not Claimed.";

private final RadiatorView radiatorView;

Expand Down Expand Up @@ -101,8 +103,7 @@ public String getStatus() {
if (getStable()) {
return "successful";
}
if (!StringUtils.isEmpty(getClaim())
&& !getClaim().equals(NOT_CLAIMED + ".")) {
if (isCompletelyClaimed()) {
return "claimed";
}
if (getBroken()) {
Expand Down Expand Up @@ -411,44 +412,114 @@ public boolean getStable() {
* @see hudson.model.IViewEntry#getClaim()
*/
public String getClaim() {
String claim = null;
if (Hudson.getInstance().getPlugin("claim") != null) {
claim = NOT_CLAIMED;
Run lastBuild = job.getLastBuild();
while (lastBuild != null && lastBuild.isBuilding()) {
// claims can only be made against builds once they've finished,
// so check the previous build if currently building.
lastBuild = lastBuild.getPreviousBuild();
}
if (lastBuild != null) {
// TODO - check previous build if currently building.
List<ClaimBuildAction> claimActionList = lastBuild
.getActions(ClaimBuildAction.class);
if (claimActionList.size() == 1) {
ClaimBuildAction claimAction = claimActionList.get(0);
if (claimAction.isClaimed()) {
String by = claimAction.getClaimedByName();
String reason = claimAction.getReason();
claim = // "Claimed by " +
by;
if (reason != null) {
claim += ": " + reason;
}
}
} else if (claimActionList.size() > 1) {
claim = "Error parsing claim details";
Log.warn("Multiple ClaimBuildActions found for job "
+ job.toString());
// check we have claim plugin
if (Hudson.getInstance().getPlugin("claim") == null) {
return null;
}
Run<?, ?> lastBuild = getLastCompletedRun();
// find the claim
String claim = "";
if (lastBuild instanceof hudson.matrix.MatrixBuild) {
MatrixBuild matrixBuild = (hudson.matrix.MatrixBuild) lastBuild;
claim = buildMatrixClaimString(matrixBuild, true);
} else {
ClaimBuildAction claimAction = getClaimForRun(lastBuild);
if (claimAction != null && claimAction.isClaimed()) {
StringBuilder sb = new StringBuilder();
if (claimAction.getReason() != null) {
sb.append(claimAction.getReason()).append(" ");
}
sb.append("(");
sb.append(claimAction.getClaimedByName());
sb.append(").");
claim = sb.toString();
} else {
claim = NOT_CLAIMED;
}
claim += ".";
}
return claim;
}

public String getUnclaimedMatrixBuilds() {
if (Hudson.getInstance().getPlugin("claim") == null) {
return "";
}
Run<?, ?> lastBuild = getLastCompletedRun();
if (!(lastBuild instanceof hudson.matrix.MatrixBuild)) {
return "";
}
MatrixBuild matrixBuild = (hudson.matrix.MatrixBuild) lastBuild;
return buildMatrixClaimString(matrixBuild, false);
}

private Run<?,?> getLastCompletedRun() {
Run<?, ?> run = job.getLastBuild();
while (run != null && run.isBuilding()) {
// claims can only be made against builds once they've finished,
// so check the previous build if currently building.
run = run.getPreviousBuild();
}
return run;
}

private String buildMatrixClaimString(MatrixBuild matrixBuild, boolean includeClaimed) {
StringBuilder claimed = new StringBuilder();
StringBuilder unclaimed = new StringBuilder();
for (MatrixRun combination : matrixBuild.getRuns()) {
Result result = combination.getResult();
if (!(Result.FAILURE.equals(result) || Result.UNSTABLE.equals(result))) {
continue;
}
ClaimBuildAction claimAction = getClaimForRun(combination);
if (claimAction != null && claimAction.isClaimed()) {
claimed.append(combination.getParent().getCombination()
.toString());
claimed.append(": ");
if (claimAction.getReason() != null) {
claimed.append(claimAction.getReason()).append(" ");
}
claimed.append("(");
claimed.append(claimAction.getClaimedByName());
claimed.append(").<br/>");
} else {
unclaimed.append(combination.getParent().getCombination().toString());
unclaimed.append(": ").append(NOT_CLAIMED).append("<br/>");
}
}

String claims = unclaimed.toString();
if (includeClaimed) {
claims += claimed.toString();
}
return claims;
}

private ClaimBuildAction getClaimForRun(Run<?, ?> run) {
ClaimBuildAction claimAction = null;
List<ClaimBuildAction> claimActionList = run
.getActions(ClaimBuildAction.class);
if (claimActionList.size() == 1) {
claimAction = claimActionList.get(0);
} else if (claimActionList.size() > 1) {
Log.warn("Multiple ClaimBuildActions found for job "
+ job.toString());
}
return claimAction;
}

public boolean isClaimed() {
return !StringUtils.isEmpty(getClaim())
&& !"Not Claimed.".equals(getClaim());
return !NOT_CLAIMED.equals(getClaim());
}

public boolean isCompletelyClaimed() {
String claim = getClaim();
if (StringUtils.isEmpty(claim)) {
return false;
}
if (NOT_CLAIMED.equals(getClaim())) {
return false;
}
return ! claim.contains(NOT_CLAIMED);
}

public Result getLastFinishedResult() {
Expand All @@ -458,4 +529,4 @@ public Result getLastFinishedResult() {
public boolean hasChildren() {
return false;
}
}
}
12 changes: 10 additions & 2 deletions src/main/java/hudson/model/ProjectViewEntry.java
Expand Up @@ -35,7 +35,7 @@ public TreeSet<IViewEntry> getClaimedBuilds() {
new EntryComparator());
for (IViewEntry job : jobs) {
if (job.getBroken() || job.getFailCount() > 0)
if (job.isClaimed())
if (job.isCompletelyClaimed())
failing.add(job);
}
return failing;
Expand Down Expand Up @@ -66,7 +66,7 @@ public TreeSet<IViewEntry> getUnclaimedJobs() {
new EntryComparator());
for (IViewEntry job : jobs) {
if ((!job.getStable()) || job.getFailCount() > 0) {
if (!job.isClaimed())
if (!job.isCompletelyClaimed())
unclaimed.add(job);
}
}
Expand Down Expand Up @@ -244,4 +244,12 @@ public String getTitle() {
}
return getName() + ": " + StringUtils.join(jobNames, ", ");
}

public boolean isCompletelyClaimed() {
throw new UnsupportedOperationException();
}

public String getUnclaimedMatrixBuilds() {
throw new UnsupportedOperationException();
}
}
1 change: 1 addition & 0 deletions src/main/resources/hudson/model/RadiatorView/project.jelly
Expand Up @@ -57,6 +57,7 @@
<a href="${subjob.lastBuildUrl}">${subjobShortName}</a>
<j:if test="${subjob.getBuilding()}">(building now)</j:if>
<j:if test="${subjob.getQueued()}">(build pending)</j:if>
${subjob.getUnclaimedMatrixBuilds()}
</li>
</j:forEach>
</ul>
Expand Down

0 comments on commit bb5616c

Please sign in to comment.