Skip to content

Commit

Permalink
[FIXED JENKINS-23713] Allow BuildStep to work with non-AbstractProject
Browse files Browse the repository at this point in the history
Merged pull request #1330
  • Loading branch information
kohsuke committed Aug 12, 2014
2 parents 233f52e + 445323d commit a92245a
Show file tree
Hide file tree
Showing 21 changed files with 314 additions and 58 deletions.
3 changes: 3 additions & 0 deletions changelog.html
Expand Up @@ -58,6 +58,9 @@
<li class="major rfe">
Moved JUnit reporting functionality to a plugin.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-23263">issue 23263</a>)
<li class=rfe>
Allow BuildStep to work with non-AbstractProject
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-23713">issue 23713</a>)
</ul>
</div><!--=TRUNK-END=-->

Expand Down
10 changes: 9 additions & 1 deletion core/src/main/java/hudson/model/Fingerprint.java
Expand Up @@ -119,7 +119,7 @@ void setName(String newName) {
* Gets the {@link Job} that this pointer points to,
* or null if such a job no longer exists.
*/
public AbstractProject getJob() {
public AbstractProject getJob() { // TODO add variant returning Job
return Jenkins.getInstance().getItemByFullName(name,AbstractProject.class);
}

Expand Down Expand Up @@ -894,7 +894,15 @@ public List<RangeItem> _getUsages() {
return r;
}

@Deprecated
public synchronized void add(AbstractBuild b) throws IOException {
addFor((Run) b);
}

/**
* @since 1.577
*/
public synchronized void addFor(Run b) throws IOException {
add(b.getParent().getFullName(), b.getNumber());
}

Expand Down
31 changes: 13 additions & 18 deletions core/src/main/java/hudson/tasks/ArtifactArchiver.java
Expand Up @@ -27,10 +27,10 @@
import hudson.Launcher;
import hudson.Util;
import hudson.Extension;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.model.listeners.ItemListener;
import hudson.remoting.VirtualChannel;
import hudson.util.FormValidation;
Expand All @@ -52,14 +52,16 @@
import javax.annotation.Nonnull;
import jenkins.model.BuildDiscarder;
import jenkins.model.Jenkins;
import jenkins.tasks.SimpleBuildStep;
import jenkins.util.BuildListenerAdapter;
import org.kohsuke.stapler.DataBoundSetter;

/**
* Copies the artifacts into an archive directory.
*
* @author Kohsuke Kawaguchi
*/
public class ArtifactArchiver extends Recorder {
public class ArtifactArchiver extends Recorder implements SimpleBuildStep {

private static final Logger LOG = Logger.getLogger(ArtifactArchiver.class.getName());

Expand Down Expand Up @@ -185,7 +187,7 @@ public boolean isDefaultExcludes() {
this.defaultExcludes = defaultExcludes;
}

private void listenerWarnOrError(BuildListener listener, String message) {
private void listenerWarnOrError(TaskListener listener, String message) {
if (allowEmptyArchive) {
listener.getLogger().println(String.format("WARN: %s", message));
} else {
Expand All @@ -194,32 +196,27 @@ private void listenerWarnOrError(BuildListener listener, String message) {
}

@Override
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws InterruptedException {
public void perform(Run<?,?> build, FilePath ws, Launcher launcher, TaskListener listener) throws InterruptedException {
if(artifacts.length()==0) {
listener.error(Messages.ArtifactArchiver_NoIncludes());
build.setResult(Result.FAILURE);
return true;
return;
}

if (onlyIfSuccessful && build.getResult() != null && build.getResult().isWorseThan(Result.UNSTABLE)) {
listener.getLogger().println(Messages.ArtifactArchiver_SkipBecauseOnlyIfSuccessful());
return true;
return;
}

listener.getLogger().println(Messages.ArtifactArchiver_ARCHIVING_ARTIFACTS());
try {
FilePath ws = build.getWorkspace();
if (ws==null) { // #3330: slave down?
return true;
}

String artifacts = build.getEnvironment(listener).expand(this.artifacts);

Map<String,String> files = ws.act(new ListFiles(artifacts, excludes, defaultExcludes));
if (!files.isEmpty()) {
build.pickArtifactManager().archive(ws, launcher, listener, files);
build.pickArtifactManager().archive(ws, launcher, BuildListenerAdapter.wrap(listener), files);
if (fingerprint) {
new Fingerprinter(artifacts).perform(build, launcher, listener);
new Fingerprinter(artifacts).perform(build, ws, launcher, listener);
}
} else {
Result result = build.getResult();
Expand All @@ -239,17 +236,15 @@ public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListene
if (!allowEmptyArchive) {
build.setResult(Result.FAILURE);
}
return true;
return;
}
} catch (IOException e) {
Util.displayIOException(e,listener);
e.printStackTrace(listener.error(
Messages.ArtifactArchiver_FailedToArchive(artifacts)));
build.setResult(Result.FAILURE);
return true;
return;
}

return true;
}

private static final class ListFiles implements FilePath.FileCallable<Map<String,String>> {
Expand Down
24 changes: 22 additions & 2 deletions core/src/main/java/hudson/tasks/BuildStepCompatibilityLayer.java
Expand Up @@ -23,6 +23,8 @@
*/
package hudson.tasks;

import hudson.AbortException;
import hudson.FilePath;
import hudson.model.Build;
import hudson.model.BuildListener;
import hudson.model.Action;
Expand All @@ -35,6 +37,10 @@
import java.util.Collection;
import java.util.Collections;

import hudson.model.Run;
import hudson.model.TaskListener;
import jenkins.tasks.SimpleBuildStep;

/**
* Provides compatibility with {@link BuildStep} before 1.150
* so that old plugin binaries can continue to function with new Hudson.
Expand All @@ -54,11 +60,25 @@ public boolean prebuild(AbstractBuild<?,?> build, BuildListener listener) {
return true;
}

/**
* @inheritDoc
* @return Delegates to {@link SimpleBuildStep#perform(Run, FilePath, Launcher, TaskListener)} if possible, always returning true or throwing an error.
*/
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
if (build instanceof Build)
if (this instanceof SimpleBuildStep) {
// delegate to the overloaded version defined in SimpleBuildStep
FilePath workspace = build.getWorkspace();
if (workspace == null) {
throw new AbortException("no workspace for " + build);
}
((SimpleBuildStep) this).perform(build, workspace, launcher, listener);
return true;
} else if (build instanceof Build) {
// delegate to the legacy signature deprecated in 1.312
return perform((Build)build,launcher,listener);
else
} else {
return true;
}
}

public Action getProjectAction(AbstractProject<?, ?> project) {
Expand Down
40 changes: 21 additions & 19 deletions core/src/main/java/hudson/tasks/Fingerprinter.java
Expand Up @@ -33,7 +33,6 @@
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.BuildListener;
import jenkins.model.DependencyDeclarer;
import hudson.model.DependencyGraph;
import hudson.model.DependencyGraph.Dependency;
Expand Down Expand Up @@ -74,13 +73,14 @@
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.model.RunAction2;
import jenkins.tasks.SimpleBuildStep;

/**
* Records fingerprints of the specified files.
*
* @author Kohsuke Kawaguchi
*/
public class Fingerprinter extends Recorder implements Serializable, DependencyDeclarer {
public class Fingerprinter extends Recorder implements Serializable, DependencyDeclarer, SimpleBuildStep {
public static boolean enableFingerprintsInDependencyGraph = Boolean.getBoolean(Fingerprinter.class.getName() + ".enableFingerprintsInDependencyGraph");

/**
Expand Down Expand Up @@ -111,7 +111,7 @@ public boolean getRecordBuildArtifacts() {
}

@Override
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws InterruptedException {
public void perform(Run<?,?> build, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException {
try {
listener.getLogger().println(Messages.Fingerprinter_Recording());

Expand All @@ -120,7 +120,7 @@ public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListene
EnvVars environment = build.getEnvironment(listener);
if(targets.length()!=0) {
String expandedTargets = environment.expand(targets);
record(build, listener, record, expandedTargets);
record(build, workspace, listener, record, expandedTargets);
}

FingerprintAction fingerprintAction = build.getAction(FingerprintAction.class);
Expand All @@ -139,7 +139,6 @@ public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListene
}

// failing to record fingerprints is an error but not fatal
return true;
}

public BuildStepMonitor getRequiredMonitorService() {
Expand Down Expand Up @@ -185,7 +184,7 @@ public boolean shouldTriggerBuild(AbstractBuild build,
}
}

private void record(AbstractBuild<?,?> build, BuildListener listener, Map<String,String> record, final String targets) throws IOException, InterruptedException {
private void record(Run<?,?> build, FilePath ws, TaskListener listener, Map<String,String> record, final String targets) throws IOException, InterruptedException {
final class Record implements Serializable {
final boolean produced;
final String relativePath;
Expand All @@ -199,7 +198,7 @@ public Record(boolean produced, String relativePath, String fileName, String md5
this.md5sum = md5sum;
}

Fingerprint addRecord(AbstractBuild build) throws IOException {
Fingerprint addRecord(Run build) throws IOException {
FingerprintMap map = Jenkins.getInstance().getFingerprintMap();
return map.getOrCreate(produced?build:null, fileName, md5sum);
}
Expand All @@ -209,13 +208,6 @@ Fingerprint addRecord(AbstractBuild build) throws IOException {

final long buildTimestamp = build.getTimeInMillis();

FilePath ws = build.getWorkspace();
if(ws==null) {
listener.error(Messages.Fingerprinter_NoWorkspace());
build.setResult(Result.FAILURE);
return;
}

List<Record> records = ws.act(new FileCallable<List<Record>>() {
public List<Record> invoke(File baseDir, VirtualChannel channel) throws IOException {
List<Record> results = new ArrayList<Record>();
Expand Down Expand Up @@ -250,7 +242,7 @@ public List<Record> invoke(File baseDir, VirtualChannel channel) throws IOExcept
listener.error(Messages.Fingerprinter_FailedFor(r.relativePath));
continue;
}
fp.add(build);
fp.addFor(build);
record.put(r.relativePath,fp.getHashString());
}
}
Expand Down Expand Up @@ -285,7 +277,7 @@ public boolean isApplicable(Class<? extends AbstractProject> jobType) {
*/
public static final class FingerprintAction implements RunAction2 {

private transient AbstractBuild build;
private transient Run build;

private static final Random rand = new Random();

Expand All @@ -296,12 +288,17 @@ public static final class FingerprintAction implements RunAction2 {

private transient WeakReference<Map<String,Fingerprint>> ref;

public FingerprintAction(AbstractBuild build, Map<String, String> record) {
public FingerprintAction(Run build, Map<String, String> record) {
this.build = build;
this.record = PackedMap.of(record);
compact();
}

@Deprecated
public FingerprintAction(AbstractBuild build, Map<String, String> record) {
this((Run) build, record);
}

public void add(Map<String,String> moreRecords) {
Map<String,String> r = new HashMap<String, String>(record);
r.putAll(moreRecords);
Expand All @@ -322,10 +319,15 @@ public String getUrlName() {
return "fingerprints";
}

public AbstractBuild getBuild() {
public Run getRun() {
return build;
}

@Deprecated
public AbstractBuild getBuild() {
return build instanceof AbstractBuild ? (AbstractBuild) build : null;
}

/**
* Obtains the raw data.
*/
Expand All @@ -334,7 +336,7 @@ public Map<String,String> getRecords() {
}

@Override public void onLoad(Run<?,?> r) {
build = (AbstractBuild) r;
build = r;
compact();
}

Expand Down
30 changes: 26 additions & 4 deletions core/src/main/java/hudson/util/ChartUtil.java
Expand Up @@ -24,6 +24,7 @@
package hudson.util;

import hudson.model.AbstractBuild;
import hudson.model.Run;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.data.category.CategoryDataset;
Expand All @@ -46,31 +47,52 @@ public class ChartUtil {
* Can be used as a graph label. Only displays numbers.
*/
public static final class NumberOnlyBuildLabel implements Comparable<NumberOnlyBuildLabel> {

private final Run<?,?> run;

@Deprecated
public final AbstractBuild build;

/**
* @since 1.577
*/
public NumberOnlyBuildLabel(Run<?,?> run) {
this.run = run;
this.build = run instanceof AbstractBuild ? (AbstractBuild) run : null;
}

@Deprecated
public NumberOnlyBuildLabel(AbstractBuild build) {
this.run = build;
this.build = build;
}

/**
* @since 1.577
*/
public Run<?, ?> getRun() {
return run;
}

public int compareTo(NumberOnlyBuildLabel that) {
return this.build.number-that.build.number;
return this.run.number-that.run.number;
}

@Override
public boolean equals(Object o) {
if(!(o instanceof NumberOnlyBuildLabel)) return false;
NumberOnlyBuildLabel that = (NumberOnlyBuildLabel) o;
return build==that.build;
return run==that.run;
}

@Override
public int hashCode() {
return build.hashCode();
return run.hashCode();
}

@Override
public String toString() {
return build.getDisplayName();
return run.getDisplayName();
}
}

Expand Down

0 comments on commit a92245a

Please sign in to comment.