Skip to content

Commit

Permalink
[JENKINS-34983] - Add pipeline support (#12)
Browse files Browse the repository at this point in the history
* Add pipeline support

* Update POM version

* Add automated tests

* Add Jenkinsfile

* Fix FindBugs warnings
  • Loading branch information
basil committed Jun 15, 2018
1 parent 5975e20 commit 5c473a4
Show file tree
Hide file tree
Showing 9 changed files with 519 additions and 73 deletions.
1 change: 1 addition & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
buildPlugin(jenkinsVersions: [null, '2.121.1'])
43 changes: 40 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.480</version>
<version>3.15</version>
<relativePath />
</parent>

<artifactId>text-finder</artifactId>
<packaging>hpi</packaging>
<version>1.11-SNAPSHOT</version>
<name>Jenkins TextFinder plugin</name>
<url>http://wiki.jenkins-ci.org/display/JENKINS/Text-finder+Plugin</url>
<properties>
<jenkins.version>1.651</jenkins.version>
<java.level>7</java.level>
</properties>

<developers>
<developer>
Expand All @@ -28,17 +33,49 @@
<url>https://github.com/jenkinsci/${project.artifactId}-plugin</url>
</scm>

<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-basic-steps</artifactId>
<version>2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>2.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-durable-task-step</artifactId>
<version>2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>2.4</version>
<scope>test</scope>
</dependency>
</dependencies>

<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
<url>https://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>

<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
<url>https://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
</project>
Expand Down
194 changes: 125 additions & 69 deletions src/main/java/hudson/plugins/textfinder/TextFinderPublisher.java
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
package hudson.plugins.textfinder;

import hudson.FilePath.FileCallable;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.Extension;
import static hudson.Util.fixEmpty;
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.remoting.RemoteOutputStream;
import hudson.remoting.VirtualChannel;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import hudson.util.FormValidation;
import jenkins.MasterToSlaveFileCallable;
import jenkins.tasks.SimpleBuildStep;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.apache.commons.io.IOUtils;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;

import javax.servlet.ServletException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.Serializable;
import java.util.regex.Matcher;
Expand All @@ -39,24 +44,20 @@
*
* @author Santiago.PericasGeertsen@sun.com
*/
public class TextFinderPublisher extends Recorder implements Serializable {
public class TextFinderPublisher extends Recorder implements Serializable, SimpleBuildStep {

public final String fileSet;
public String fileSet;
public final String regexp;
public final boolean succeedIfFound;
public final boolean unstableIfFound;
public boolean succeedIfFound;
public boolean unstableIfFound;
/**
* True to also scan the whole console output
*/
public final boolean alsoCheckConsoleOutput;
public boolean alsoCheckConsoleOutput;

@DataBoundConstructor
public TextFinderPublisher(String fileSet, String regexp, boolean succeedIfFound, boolean unstableIfFound, boolean alsoCheckConsoleOutput) {
this.fileSet = Util.fixEmpty(fileSet.trim());
public TextFinderPublisher(String regexp) {
this.regexp = regexp;
this.succeedIfFound = succeedIfFound;
this.unstableIfFound = unstableIfFound;
this.alsoCheckConsoleOutput = alsoCheckConsoleOutput;

// Attempt to compile regular expression
try {
Expand All @@ -66,13 +67,49 @@ public TextFinderPublisher(String fileSet, String regexp, boolean succeedIfFound
}
}

@Deprecated
public TextFinderPublisher(
String fileSet,
String regexp,
boolean succeedIfFound,
boolean unstableIfFound,
boolean alsoCheckConsoleOutput) {
this(regexp);
this.fileSet = Util.fixEmpty(fileSet.trim());
this.succeedIfFound = succeedIfFound;
this.unstableIfFound = unstableIfFound;
this.alsoCheckConsoleOutput = alsoCheckConsoleOutput;
}

@DataBoundSetter
public void setFileSet(String fileSet) {
this.fileSet = Util.fixEmpty(fileSet.trim());
}

@DataBoundSetter
public void setSucceedIfFound(boolean succeedIfFound) {
this.succeedIfFound = succeedIfFound;
}

@DataBoundSetter
public void setUnstableIfFound(boolean unstableIfFound) {
this.unstableIfFound = unstableIfFound;
}

@DataBoundSetter
public void setAlsoCheckConsoleOutput(boolean alsoCheckConsoleOutput) {
this.alsoCheckConsoleOutput = alsoCheckConsoleOutput;
}

@Override
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
}

public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
findText(build, listener.getLogger());
return true;
@Override
public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener)
throws InterruptedException, IOException {
findText(run, workspace, listener);
}

/**
Expand All @@ -81,13 +118,16 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
private static final class AbortException extends RuntimeException {
}

private void findText(AbstractBuild build, PrintStream logger) throws IOException, InterruptedException {
private void findText(Run<?, ?> run, FilePath workspace, TaskListener listener)
throws IOException, InterruptedException {
try {
PrintStream logger = listener.getLogger();
boolean foundText = false;

if(alsoCheckConsoleOutput) {
logger.println("Checking console output");
foundText |= checkFile(build.getLogFile(), compilePattern(logger), logger, true);
foundText |=
checkFile(run.getLogFile(), compilePattern(logger, regexp), logger, true);
} else {
// printing this when checking console output will cause the plugin
// to find this line, which would be pointless.
Expand All @@ -98,57 +138,14 @@ private void findText(AbstractBuild build, PrintStream logger) throws IOExceptio
final RemoteOutputStream ros = new RemoteOutputStream(logger);

if(fileSet!=null) {
foundText |= build.getWorkspace().act(new FileCallable<Boolean>() {
public Boolean invoke(File ws, VirtualChannel channel) throws IOException {
PrintStream logger = new PrintStream(ros);

// Collect list of files for searching
FileSet fs = new FileSet();
org.apache.tools.ant.Project p = new org.apache.tools.ant.Project();
fs.setProject(p);
fs.setDir(ws);
fs.setIncludes(fileSet);
DirectoryScanner ds = fs.getDirectoryScanner(p);

// Any files in the final set?
String[] files = ds.getIncludedFiles();
if (files.length == 0) {
logger.println("Jenkins Text Finder: File set '" +
fileSet + "' is empty");
throw new AbortException();
}

Pattern pattern = compilePattern(logger);

boolean foundText = false;

for (String file : files) {
File f = new File(ws, file);

if (!f.exists()) {
logger.println("Jenkins Text Finder: Unable to" +
" find file '" + f + "'");
continue;
}
if (!f.canRead()) {
logger.println("Jenkins Text Finder: Unable to" +
" read from file '" + f + "'");
continue;
}

foundText |= checkFile(f, pattern, logger, false);
}

return foundText;
}
});
foundText |= workspace.act(new FileChecker(ros, fileSet, regexp));
}

if (foundText != succeedIfFound)
build.setResult(unstableIfFound ? Result.UNSTABLE : Result.FAILURE);
run.setResult(unstableIfFound ? Result.UNSTABLE : Result.FAILURE);
} catch (AbortException e) {
// no test file found
build.setResult(Result.UNSTABLE);
run.setResult(Result.UNSTABLE);
}
}

Expand All @@ -159,14 +156,15 @@ public Boolean invoke(File ws, VirtualChannel channel) throws IOException {
* true to return immediately as soon as the first hit is found. this is necessary
* when we are scanning the console output, because otherwise we'll loop forever.
*/
private boolean checkFile(File f, Pattern pattern, PrintStream logger, boolean abortAfterFirstHit) {
private static boolean checkFile(
File f, Pattern pattern, PrintStream logger, boolean abortAfterFirstHit) {
boolean logFilename = true;
boolean foundText = false;
BufferedReader reader=null;
try {
// Assume default encoding and text files
String line;
reader = new BufferedReader(new FileReader(f));
reader = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF-8"));
while ((line = reader.readLine()) != null) {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
Expand All @@ -189,7 +187,7 @@ private boolean checkFile(File f, Pattern pattern, PrintStream logger, boolean a
return foundText;
}

private Pattern compilePattern(PrintStream logger) {
private static Pattern compilePattern(PrintStream logger, String regexp) {
Pattern pattern;
try {
pattern = Pattern.compile(regexp);
Expand All @@ -201,17 +199,20 @@ private Pattern compilePattern(PrintStream logger) {
return pattern;
}

@Symbol("findText")
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
@Override
public String getDisplayName() {
return Messages.DisplayName();
return Messages.TextFinderPublisher_DisplayName();
}

@Override
public String getHelpFile() {
return "/plugin/text-finder/help.html";
}

@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
Expand All @@ -233,6 +234,61 @@ public FormValidation doCheckRegexp(@QueryParameter String value) throws IOExcep
}
}

private static class FileChecker extends MasterToSlaveFileCallable<Boolean> {

private final RemoteOutputStream ros;
private final String fileSet;
private final String regexp;

public FileChecker(RemoteOutputStream ros, String fileSet, String regexp) {
this.ros = ros;
this.fileSet = fileSet;
this.regexp = regexp;
}

@Override
public Boolean invoke(File ws, VirtualChannel channel) throws IOException {
PrintStream logger = new PrintStream(ros, false, "UTF-8");

// Collect list of files for searching
FileSet fs = new FileSet();
org.apache.tools.ant.Project p = new org.apache.tools.ant.Project();
fs.setProject(p);
fs.setDir(ws);
fs.setIncludes(fileSet);
DirectoryScanner ds = fs.getDirectoryScanner(p);

// Any files in the final set?
String[] files = ds.getIncludedFiles();
if (files.length == 0) {
logger.println("Jenkins Text Finder: File set '" + fileSet + "' is empty");
throw new AbortException();
}

Pattern pattern = compilePattern(logger, regexp);

boolean foundText = false;

for (String file : files) {
File f = new File(ws, file);

if (!f.exists()) {
logger.println("Jenkins Text Finder: Unable to" + " find file '" + f + "'");
continue;
}
if (!f.canRead()) {
logger.println(
"Jenkins Text Finder: Unable to" + " read from file '" + f + "'");
continue;
}

foundText |= checkFile(f, pattern, logger, false);
}

return foundText;
}
}

private static final long serialVersionUID = 1L;
}

Original file line number Diff line number Diff line change
@@ -1 +1 @@
DisplayName=Jenkins Text Finder
TextFinderPublisher.DisplayName=Jenkins Text Finder
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<f:entry field="fileSet" title="${%Files}">
<f:textbox/>
Expand Down
Loading

0 comments on commit 5c473a4

Please sign in to comment.