package org.jfrog.hudson.pipeline.steps;
import com.google.inject.Inject;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.Node;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.plugins.gradle.Gradle;
import hudson.plugins.gradle.GradleInstallation;
import hudson.util.ArgumentListBuilder;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution;
import org.jenkinsci.plugins.workflow.steps.StepContextParameter;
import org.jfrog.build.api.Build;
import org.jfrog.build.api.BuildInfoFields;
import org.jfrog.hudson.gradle.GradleInitScriptWriter;
import org.jfrog.hudson.pipeline.Utils;
import org.jfrog.hudson.pipeline.executors.MavenGradleEnvExtractor;
import org.jfrog.hudson.pipeline.types.GradleBuild;
import org.jfrog.hudson.pipeline.types.buildInfo.BuildInfo;
import org.jfrog.hudson.pipeline.types.deployers.Deployer;
import org.jfrog.hudson.pipeline.types.deployers.GradleDeployer;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.File;
import java.io.IOException;
/**
* Created by Tamirh on 04/08/2016.
*/
public class ArtifactoryGradleBuild extends AbstractStepImpl {
private GradleBuild gradleBuild;
private String tasks;
private String buildFile;
private String rootDir;
private String tool;
private String switches;
private BuildInfo buildInfo;
private boolean useWrapper;
private boolean usesPlugin;
@DataBoundConstructor
public ArtifactoryGradleBuild(GradleBuild gradleBuild, String tool, String rootDir, String buildFile, String tasks, String switches, boolean useWrapper, BuildInfo buildInfo, boolean usesPlugin) {
this.gradleBuild = gradleBuild;
this.tasks = tasks == null ? "artifactoryPublish" : tasks;
this.rootDir = rootDir == null ? "" : rootDir;
this.buildFile = StringUtils.isEmpty(buildFile) ? "build.gradle" : buildFile;
this.tool = tool == null ? "" : tool;
this.switches = switches == null ? "" : switches;
this.buildInfo = buildInfo;
this.useWrapper = useWrapper;
this.usesPlugin = usesPlugin;
}
public GradleBuild getGradleBuild() {
return gradleBuild;
}
public String getTool() {
return tool;
}
public String getSwitches() {
return switches;
}
public String getTasks() {
return tasks;
}
public String getBuildFile() {
return buildFile;
}
public BuildInfo getBuildInfo() {
return buildInfo;
}
public String getRootDir() {
return rootDir;
}
public void setGradleBuild(GradleBuild gradleBuild) {
this.gradleBuild = gradleBuild;
}
public boolean isUseWrapper() {
return useWrapper;
}
public boolean isUsesPlugin() {
return usesPlugin;
}
public static class Execution extends AbstractSynchronousNonBlockingStepExecution<BuildInfo> {
private static final long serialVersionUID = 1L;
@StepContextParameter
private transient Run build;
@StepContextParameter
private transient TaskListener listener;
@StepContextParameter
private transient Launcher launcher;
@Inject(optional = true)
private transient ArtifactoryGradleBuild step;
@StepContextParameter
private transient FilePath ws;
@StepContextParameter
private transient EnvVars env;
@Override
protected BuildInfo run() throws Exception {
BuildInfo buildInfo = Utils.prepareBuildinfo(build, step.getBuildInfo());
Deployer deployer = getDeployer();
deployer.createPublisherBuildInfoDetails(buildInfo);
MavenGradleEnvExtractor envExtractor = new MavenGradleEnvExtractor(build,
buildInfo, deployer, step.getGradleBuild().getResolver(), listener, launcher);
ArgumentListBuilder args = getGradleExecutor();
envExtractor.buildEnvVars(ws, env);
exe(args);
String generatedBuildPath = env.get(BuildInfoFields.GENERATED_BUILD_INFO);
Build regularBuildInfo = Utils.getGeneratedBuildInfo(build, listener, launcher, generatedBuildPath);
buildInfo.append(regularBuildInfo);
return buildInfo;
}
private Deployer getDeployer() {
Deployer deployer = step.getGradleBuild().getDeployer();
if (deployer == null || deployer.isEmpty()) {
deployer = GradleDeployer.EMPTY_DEPLOYER;
}
return deployer;
}
private ArgumentListBuilder getGradleExecutor() {
ArgumentListBuilder args = new ArgumentListBuilder();
if (step.isUseWrapper()) {
String execName = !launcher.isUnix() ? GradleInstallation.WINDOWS_GRADLE_WRAPPER_COMMAND : GradleInstallation.UNIX_GRADLE_WRAPPER_COMMAND;
FilePath gradleWrapperFile = new FilePath(new FilePath(ws, step.getRootDir()), execName);
args.add(gradleWrapperFile.getRemote());
} else {
try {
getGradleHome(args);
} catch (IOException e) {
listener.error("Couldn't find Gradle executable.");
build.setResult(Result.FAILURE);
throw new Run.RunnerAbortedException();
} catch (InterruptedException e) {
listener.error("Couldn't find Gradle executable.");
build.setResult(Result.FAILURE);
throw new Run.RunnerAbortedException();
}
}
args.addTokenized(getSwitches());
args.addTokenized(getTasks());
args.add("-b");
args.add(step.getBuildFile());
if (!launcher.isUnix()) {
args = args.toWindowsCommand();
}
return args;
}
private String getTasks() {
String tasks = step.getTasks();
if (!(tasks.contains("artifactoryP") || tasks.contains("artifactoryPublish"))) {
tasks += " artifactoryPublish";
}
return tasks;
}
private String getSwitches() {
String switches = step.getSwitches();
if (!step.getGradleBuild().isUsesPlugin()) {
try {
switches += " --init-script " + createInitScript();
} catch (Exception e) {
listener.getLogger().println("Error occurred while writing Gradle Init Script: " + e.getMessage());
build.setResult(Result.FAILURE);
}
}
return switches;
}
private void exe(ArgumentListBuilder args) {
StringBuilder pwd = new StringBuilder(ws.getRemote())
.append(launcher.isUnix() ? "/" : "\\")
.append(step.getRootDir());
boolean failed;
try {
int exitValue = launcher.launch().cmds(args).envs(env).stdout(listener).pwd(pwd.toString()).join();
failed = (exitValue != 0);
} catch (Exception e) {
listener.error("Couldn't execute gradle task. " + e.getMessage());
build.setResult(Result.FAILURE);
throw new Run.RunnerAbortedException();
}
if (failed) {
build.setResult(Result.FAILURE);
throw new Run.RunnerAbortedException();
}
}
private GradleInstallation getGradleInstallation() {
if (!StringUtils.isEmpty(step.getTool())) {
GradleInstallation[] installations = Jenkins.getInstance().getDescriptorByType(Gradle.DescriptorImpl.class).getInstallations();
for (GradleInstallation i : installations) {
if (step.getTool().equals(i.getName())) {
return i;
}
}
}
return null;
}
private FilePath getGradleHome(ArgumentListBuilder args) throws IOException, InterruptedException {
if (!StringUtils.isEmpty(step.getTool())) {
GradleInstallation gi = getGradleInstallation();
if (gi == null) {
listener.error("Couldn't find Gradle executable.");
build.setResult(Result.FAILURE);
throw new Run.RunnerAbortedException();
} else {
Node node = Utils.getNode(launcher);
gi = gi.forNode(node, listener);
gi = gi.forEnvironment(env);
}
env.put("GRADLE_HOME", gi.getHome());
args.add(gi.getExecutable(launcher));
return new FilePath(launcher.getChannel(), gi.getHome());
}
if (env.get("GRADLE_HOME") != null) {
return new FilePath(new File(env.get("GRADLE_HOME")));
}
build.setResult(Result.FAILURE);
throw new RuntimeException("Couldn't find gradle installation");
}
private String createInitScript() throws Exception {
GradleInitScriptWriter writer = new GradleInitScriptWriter(build, launcher);
FilePath initScript = ws.createTextTempFile("init-artifactory", "gradle",
writer.generateInitScript(), false);
String initScriptPath = initScript.getRemote();
initScriptPath = initScriptPath.replace('\\', '/');
return initScriptPath;
}
}
@Extension
public static final class DescriptorImpl extends AbstractStepDescriptorImpl {
public DescriptorImpl() {
super(ArtifactoryGradleBuild.Execution.class);
}
@Override
public String getFunctionName() {
return "ArtifactoryGradleBuild";
}
@Override
public String getDisplayName() {
return "run Artifactory gradle";
}
@Override
public boolean isAdvanced() {
return true;
}
}
}