Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Jenkins 41704] Fix linking owner and obtaining graph configuration #46

Merged
merged 3 commits into from Aug 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -24,9 +24,10 @@

import hudson.model.*;
import org.kohsuke.stapler.StaplerProxy;
import jenkins.model.RunAction2;

public abstract class AbstractCppcheckBuildAction extends Actionable implements Action, HealthReportingAction, StaplerProxy {
protected Run<?, ?> owner;
public abstract class AbstractCppcheckBuildAction extends Actionable implements RunAction2, HealthReportingAction, StaplerProxy {
protected transient Run<?, ?> owner;

protected AbstractCppcheckBuildAction(Run<?, ?> owner) {
this.owner = owner;
Expand All @@ -49,4 +50,16 @@ public <T extends AbstractCppcheckBuildAction> T getPreviousResult() {
public Run<?, ?> getOwner() {
return owner;
}

public void setOwner(Run<?,?> owner) {
this.owner = owner;
}

public void onAttached(Run<?,?> r) {
setOwner(r);
}

public void onLoad(Run<?,?> r) {
setOwner(r);
}
}
Expand Up @@ -4,6 +4,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import com.thalesgroup.hudson.plugins.cppcheck.util.AbstractCppcheckBuildAction;
Expand All @@ -17,32 +18,33 @@
import org.jenkinsci.plugins.cppcheck.config.CppcheckConfigSeverityEvaluation;
import org.jenkinsci.plugins.cppcheck.util.CppcheckBuildHealthEvaluator;

import javax.annotation.Nonnull;

/**
* @author Gregory Boissinot
*/
public class CppcheckBuildAction extends AbstractCppcheckBuildAction implements SimpleBuildStep.LastBuildAction {

public static final String URL_NAME = "cppcheckResult";

private CppcheckResult result;
private final CppcheckResult result;
private final CppcheckConfig config;

private List<CppcheckProjectAction> projectActions;
/**
* The health report percentage.
*
* @since 1.15
*/
private int healthReportPercentage;

public CppcheckBuildAction(Run<?, ?> owner, CppcheckResult result, CppcheckConfig config,
public CppcheckBuildAction(@Nonnull Run<?, ?> owner, @Nonnull CppcheckResult result, @Nonnull CppcheckConfig config,
int healthReportPercentage) {
super(owner);

this.result = result;
this.config = config;
this.healthReportPercentage = healthReportPercentage;

List<CppcheckProjectAction> projectActions = new ArrayList<>();
projectActions.add(new CppcheckProjectAction(owner, config.getConfigGraph()));
this.projectActions = projectActions;

}

public String getIconFileName() {
Expand All @@ -65,6 +67,10 @@ public CppcheckResult getResult() {
return this.result;
}

public CppcheckConfig getConfig() {
return this.config;
}

Run<?, ?> getBuild() {
return this.owner;
}
Expand Down Expand Up @@ -121,6 +127,18 @@ private Object readResolve() {

@Override
public Collection<? extends Action> getProjectActions() {
return this.projectActions;

if (this.owner == null) {
return Collections.emptySet();
} else {
return Collections.singleton(new CppcheckProjectAction(owner.getParent()));
}
}

@Override
public synchronized void setOwner(Run<?,?> owner) {
super.setOwner(owner);

this.result.setOwner(owner);
}
}
Expand Up @@ -2,6 +2,7 @@

import java.io.IOException;
import java.util.Calendar;
import javax.annotation.Nonnull;
import hudson.model.AbstractProject;
import hudson.model.Job;
import hudson.model.Run;
Expand All @@ -21,77 +22,38 @@
* @author Gregory Boissinot
*/
public class CppcheckProjectAction extends AbstractCppcheckProjectAction {
/** Cppcheck graph configuration. */
private final CppcheckConfigGraph configGraph;

public String getSearchUrl() {
return getUrlName();
}
public CppcheckProjectAction(final Run<?, ?> run,
CppcheckConfigGraph configGraph) {
super(run);
this.configGraph = configGraph;
}

private boolean isRunCompleted(Run<?, ?> run) {
if (run == null) {
return false;
}

if (run.isBuilding()) {
return false;
}

if (run.getResult() == Result.SUCCESS || run.getResult() == Result.UNSTABLE) {
return true;
}

return false;
public CppcheckProjectAction(@Nonnull final Job<?, ?> job) {
super(job);
}


@Override
public Run<?, ?> getLastFinishedBuild() {
// get the very last build - no matter of its result or buildstate and search towards previous builds until the first successful or unstable result was found.
Run<?, ?> prevCompletedRun = run.getPreviousBuild();

Run<?, ?> lastRun = prevCompletedRun;
if (lastRun != null)
{
while(lastRun != null && lastRun.getNextBuild() != null) {
lastRun = lastRun.getNextBuild();
}
}
else
{
return prevCompletedRun;
}

while(lastRun != null) {
if (isRunCompleted(lastRun)) {
return lastRun;

}
lastRun = lastRun.getPreviousBuild();
}

return null;
}
Run<?, ?> lastBuild = getJob().getLastBuild();
while (lastBuild != null
&& (lastBuild.isBuilding() || lastBuild.getAction(CppcheckBuildAction.class) == null))
{
lastBuild = lastBuild.getPreviousBuild();
}

public final Run<?, ?> getProject() {
CppcheckBuildAction lastAction = getLastFinishedBuildAction();
return (lastAction != null) ? lastAction.getOwner() : null;
}

public Run<?,?> getRun() {
return super.run;
return lastBuild;
}
/**
* Get build action of the last finished build.
*
* @return the build action or null
*/
public CppcheckBuildAction getLastFinishedBuildAction() {
Run<?, ?> lastBuild = getLastFinishedBuild();
return (lastBuild != null) ? lastBuild.getAction(CppcheckBuildAction.class) : null;

@Override
public Run<?, ?> getLastResultBuild() {
for (Run<?, ?> b = getJob().getLastBuild(); b != null; b = b.getPreviousBuiltBuild())
{
CppcheckBuildAction r = b.getAction(CppcheckBuildAction.class);

if (r != null)
return b;
}
return null;
}

public final boolean isDisplayGraph() {
Expand All @@ -101,36 +63,24 @@ public final boolean isDisplayGraph() {
return false;
}

//Affect previous
b = b.getPreviousBuild();
if (b != null) {

for (; b != null; b = b.getPreviousBuild()) {
if (b.getResult().isWorseOrEqualTo(Result.FAILURE)) {
continue;
}
CppcheckBuildAction action = b.getAction(CppcheckBuildAction.class);
if (action == null || action.getResult() == null) {
continue;
}
CppcheckResult result = action.getResult();
if (result == null)
continue;

return true;
}
}
return false;
}
// Affect previous
for (b = b.getPreviousBuild(); b != null; b = b.getPreviousBuild())
{
if (b.getResult() == null || b.getResult().isWorseOrEqualTo(Result.FAILURE))
continue;

public Integer getLastResultBuild() {
Run<?, ?> b = getLastFinishedBuild();
if (b != null) {
return b.getNumber();
}
return null;
}
CppcheckBuildAction action = b.getAction(CppcheckBuildAction.class);
if (action == null ||
action.getResult() == null ||
action.getConfig() == null ||
action.getConfig().getConfigGraph() == null)
continue;

return true;
}

return false;
}

public String getDisplayName() {
return Messages.cppcheck_CppcheckResults();
Expand All @@ -153,25 +103,37 @@ public void doGraph(StaplerRequest req, StaplerResponse rsp) throws IOException
return;
}

Graph g = new CppcheckGraph(lastBuild, getDataSetBuilder().build(),
Messages.cppcheck_NumberOfErrors(),
configGraph.getXSize(),
configGraph.getYSize());
Run<?, ?> lastBuildWithResult = getLastResultBuild();
CppcheckBuildAction lastAction = lastBuildWithResult.getAction(CppcheckBuildAction.class);
CppcheckConfigGraph configGraph = (lastAction != null) ?
((lastAction.getConfig() != null) ?
lastAction.getConfig().getConfigGraph() : null) : null;

if (configGraph == null) {
rsp.sendRedirect2(req.getContextPath() + "/images/headless.png");
return;
}

Graph g = new CppcheckGraph(lastBuild, getDataSetBuilder(configGraph).build(), Messages.cppcheck_NumberOfErrors(),
configGraph.getXSize(), configGraph.getYSize());
g.doPng(req, rsp);
}

private DataSetBuilder<String, ChartUtil.NumberOnlyBuildLabel> getDataSetBuilder() {
private DataSetBuilder<String, ChartUtil.NumberOnlyBuildLabel> getDataSetBuilder(CppcheckConfigGraph configGraph) {
DataSetBuilder<String, ChartUtil.NumberOnlyBuildLabel> dsb
= new DataSetBuilder<String, ChartUtil.NumberOnlyBuildLabel>();

if (configGraph == null)
return dsb;

Run<?,?> lastBuild = getLastFinishedBuild();
CppcheckBuildAction lastAction = lastBuild.getAction(CppcheckBuildAction.class);

int numBuilds = 0;

// numBuildsInGraph <= 1 means unlimited
for (CppcheckBuildAction a = lastAction;
a != null && (configGraph.getNumBuildsInGraph() <= 1 || numBuilds < configGraph.getNumBuildsInGraph());
(a != null) && (configGraph.getNumBuildsInGraph() <= 1 || numBuilds < configGraph.getNumBuildsInGraph());
a = a.getPreviousResult(), ++numBuilds) {

ChartUtil.NumberOnlyBuildLabel label = new ChartUtil.NumberOnlyBuildLabel(a.getOwner());
Expand Down
Expand Up @@ -115,10 +115,14 @@ public CppcheckStatistics getStatistics() {
return statistics;
}

public Run<?, ?> getOwner() {
public synchronized Run<?, ?> getOwner() {
return owner;
}

public synchronized void setOwner(Run<?,?> owner) {
this.owner = owner;
}

public CppcheckSourceContainer getCppcheckSourceContainer() {
return lazyLoadSourceContainer();
}
Expand Down
@@ -1,27 +1,29 @@
package org.jenkinsci.plugins.cppcheck.util;

import hudson.model.Actionable;
import hudson.model.ProminentProjectAction;
import hudson.model.Job;
import hudson.model.Run;
import hudson.model.Action;

import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import java.io.IOException;
import javax.annotation.Nonnull;

/**
* @author Gregory Boissinot
*/
public abstract class AbstractCppcheckProjectAction extends Actionable implements Action {
public abstract class AbstractCppcheckProjectAction extends Actionable implements ProminentProjectAction {

protected final Run<?, ?> run;
protected final transient Job<?, ?> job;

public AbstractCppcheckProjectAction(Run<?, ?> run) {
this.run = run;
public AbstractCppcheckProjectAction(@Nonnull Job<?, ?> job) {
this.job = job;
}

public Run<?, ?> getRun() {
return run;
@Nonnull public Job<?, ?> getJob() {
return job;
}

public String getIconFileName() {
Expand All @@ -34,12 +36,12 @@ public String getSearchUrl() {

protected abstract Run<?, ?> getLastFinishedBuild();

protected abstract Integer getLastResultBuild();
protected abstract Run<?, ?> getLastResultBuild();

public abstract void doGraph(StaplerRequest req, StaplerResponse rsp) throws IOException;

public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException {
Integer buildNumber = getLastResultBuild();
Integer buildNumber = (getLastResultBuild() != null) ? getLastResultBuild().getNumber() : null;
if (buildNumber == null) {
rsp.sendRedirect2("nodata");
} else {
Expand Down