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

Remoting-Friendly #6

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
/.idea/
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@
</developer>
</developers>

<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>token-macro</artifactId>
<version>2.1</version>
</dependency>
</dependencies>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
Expand Down
109 changes: 92 additions & 17 deletions src/main/java/SlackUploader.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,35 @@
*/

import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.FreeStyleProject;
import hudson.remoting.Callable;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import hudson.util.DirScanner;
import hudson.util.FileVisitor;
import hudson.util.FormValidation;
import jenkins.security.MasterToSlaveCallable;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.tokenmacro.MacroEvaluationException;
import org.jenkinsci.plugins.tokenmacro.TokenMacro;
import org.jenkinsci.remoting.RoleChecker;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
Expand All @@ -33,7 +49,7 @@ public class SlackUploader extends Recorder {
private final String token;
private final String filePath;
private static final String CHOICE_OF_SHELL = "/bin/bash";

@DataBoundConstructor
public SlackUploader(String channel, String token, String filePath) {
super();
Expand All @@ -53,8 +69,8 @@ public String getFilePath() {
public String getToken() {
return token;
}


@Override
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
Expand All @@ -63,18 +79,15 @@ public BuildStepMonitor getRequiredMonitorService() {
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
//To change body of generated methods, choose Tools | Templates.
LogOutput log = new LogOutput();
Runtime runtime = Runtime.getRuntime();
Process process = null;

LogOutput log = new LogOutput();

try {
String script = generateScript();

process = runScript(runtime, script);

log.logOutput(listener, process);
generateScript(build, launcher, listener);
} catch (Throwable cause) {
log.logOutput(listener, process);
throw new RuntimeException(cause);
}
return true;
}
Expand All @@ -84,14 +97,12 @@ private Process runScript(Runtime runtime, String script) throws IOException {
return process;
}


private void generateScript(final AbstractBuild<?, ?> build, final Launcher launcher, final BuildListener listener) throws Throwable {
String mask = TokenMacro.expandAll(build, listener, filePath);

private String generateScript() {
String loop = "for file in $(ls " + filePath + ");";
loop+="do ";
String curlRequest = loop + "curl -F file=@$file -F channels=" + channel +" -F token=" + token + " https://slack.com/api/files.upload ;";
String loopDone = curlRequest + "done;";
return loopDone;
listener.getLogger().println(String.format("Invoking Uploader (channel=%s, filePath=%s)", channel, filePath));

launcher.getChannel().callAsync(new FileUploadRunner(listener, mask, channel, token)).get();
}

@Override
Expand Down Expand Up @@ -159,4 +170,68 @@ public SlackUploader newInstance(StaplerRequest req, JSONObject formData) throws


}

public static class FileUploadRunner extends MasterToSlaveCallable<Boolean, Throwable> implements Serializable {
private static final long serialVersionUID = 1L;

private final String filePath;

private final String channel;

private final String token;

private final BuildListener listener;

public FileUploadRunner(BuildListener listener, String filePath, String channel, String token) {
this.listener = listener;
this.filePath = filePath;
this.channel = channel;
this.token = token;
}

@Override
public Boolean call() throws Throwable {
final List<String> commandList = new ArrayList<>();

String dirName = filePath;
String includeMask = "**/*";

final int i = filePath.indexOf('*');

final File tmpFile = new File(filePath);

if (-1 != i) {
dirName = filePath.substring(0, i);
includeMask = filePath.substring(i);
} else if (tmpFile.exists() && tmpFile.isFile()) {
dirName = tmpFile.getParentFile().getPath();
includeMask = tmpFile.getName();
}

listener.getLogger().println(String.format("Using dirname=%s and includeMask=%s", dirName, includeMask));

new DirScanner.Glob(includeMask, null).scan(new File(dirName), new FileVisitor() {
@Override
public void visit(File f, String relativePath) throws IOException {
if (f.isFile()) {
final String command = String.format("curl -F file=@\"%s\" -F channels=\"%s\" -F token=\"%s\" https://slack.com/api/files.upload", f.getAbsolutePath(), channel, token);

listener.getLogger().println("Adding file " + f.getAbsolutePath());

commandList.add(command);
}
}
});

String allCommands = StringUtils.join(commandList, " ; ");

if (commandList.isEmpty()) {
listener.getLogger().println("No files found for mask=" + this.filePath);
}

Runtime.getRuntime().exec(new String[] { "/bin/sh", "-c", allCommands});

return ! commandList.isEmpty();
}
}
}