package hudson.plugins.gradle; import hudson.*; import hudson.model.*; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.tools.ToolInstallation; import hudson.util.ArgumentListBuilder; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerRequest; import java.io.IOException; import java.util.Map; public class Gradle extends Builder { /** * The GradleBuilder build step description */ private final String description; /** * The GradleBuilder command line switches */ private final String switches; /** * The GradleBuilder tasks */ private final String tasks; private final String rootBuildScriptDir; /** * The GradleBuilder build file path */ private final String buildFile; /** * Identifies {@link GradleInstallation} to be used. */ private final String gradleName; private static final String JAVA_OPTS_KEY = "JAVA_OPTS"; @DataBoundConstructor public Gradle(String description, String switches, String tasks, String rootBuildScriptDir, String buildFile, String gradleName) { this.description = description; this.switches = switches; this.tasks = tasks; this.gradleName = gradleName; this.rootBuildScriptDir = rootBuildScriptDir; this.buildFile = buildFile; } public String getSwitches() { return switches; } public String getBuildFile() { return buildFile; } public String getGradleName() { return gradleName; } public String getTasks() { return tasks; } public String getDescription() { return description; } public String getRootBuildScriptDir() { return rootBuildScriptDir; } /** * Gets the GradleBuilder to invoke, * or null to invoke the default one. */ public GradleInstallation getGradle() { for (GradleInstallation i : getDescriptor().getInstallations()) { if (gradleName != null && i.getName().equals(gradleName)) return i; } return null; } @Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { EnvVars env = build.getEnvironment(listener); String extraSwitches = env.get("GRADLE_EXT_SWITCHES"); String normalizedSwitches; if (extraSwitches != null) { normalizedSwitches = switches + " " + extraSwitches; } else { normalizedSwitches = switches; } normalizedSwitches = normalizedSwitches.replaceAll("[\t\r\n]+", " "); normalizedSwitches = Util.replaceMacro(normalizedSwitches, env); normalizedSwitches = Util.replaceMacro(normalizedSwitches, build.getBuildVariables()); String extraTasks = env.get("GRADLE_EXT_TASKS"); String normalizedTasks; if (extraTasks != null) { normalizedTasks = tasks + " " + extraTasks; } else { normalizedTasks = tasks; } normalizedTasks = normalizedTasks.replaceAll("[\t\r\n]+", " "); ArgumentListBuilder args = new ArgumentListBuilder(); GradleInstallation ai = getGradle(); if (ai == null) { args.add(launcher.isUnix() ? "gradle" : "gradle.bat"); } else { ai = ai.forNode(Computer.currentComputer().getNode(), listener); ai = ai.forEnvironment(env); String exe = ai.getExecutable(launcher); if (exe == null) { listener.fatalError("ERROR"); return false; } args.add(exe); } args.addKeyValuePairs("-D", build.getBuildVariables()); args.addTokenized(normalizedSwitches); args.addTokenized(normalizedTasks); if (buildFile != null && buildFile.trim().length() != 0) { String buildFileNormalized = Util.replaceMacro(buildFile.trim(), env); args.add("-b"); args.add(buildFileNormalized); } if (ai != null) env.put("GRADLE_HOME", ai.getHome()); if (!launcher.isUnix()) { // on Windows, executing batch file can't return the correct error code, // so we need to wrap it into cmd.exe. // double %% is needed because we want ERRORLEVEL to be expanded after // batch file executed, not before. This alone shows how broken Windows is... args.prepend("cmd.exe", "/C"); args.add("&&", "exit", "%%ERRORLEVEL%%"); } FilePath rootLauncher; if (rootBuildScriptDir != null && rootBuildScriptDir.trim().length() != 0) { String rootBuildScriptNormalized = Util.replaceMacro(rootBuildScriptDir.trim(), env); rootBuildScriptNormalized = Util.replaceMacro(rootBuildScriptNormalized, build.getBuildVariableResolver()); rootLauncher = new FilePath(build.getModuleRoot(), rootBuildScriptNormalized); } else { rootLauncher = build.getModuleRoot(); } String javaOpts = env.get(JAVA_OPTS_KEY); if (StringUtils.isNotBlank(javaOpts)) { env.remove(JAVA_OPTS_KEY); } try { int r = launcher.launch().cmds(args).envs(env).stdout(listener).pwd(rootLauncher).join(); boolean success = r == 0; // if the build is successful then set it as success otherwise as a failure. build.setResult(Result.SUCCESS); if (!success) { build.setResult(Result.FAILURE); } return success; } catch (IOException e) { Util.displayIOException(e, listener); e.printStackTrace(listener.fatalError("command execution failed")); build.setResult(Result.FAILURE); return false; } } @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } @Extension public static final class DescriptorImpl extends BuildStepDescriptor<Builder> { @CopyOnWrite private volatile GradleInstallation[] installations = new GradleInstallation[0]; public DescriptorImpl() { load(); } protected DescriptorImpl(Class<? extends Gradle> clazz) { super(clazz); } /** * Obtains the {@link GradleInstallation.DescriptorImpl} instance. */ public GradleInstallation.DescriptorImpl getToolDescriptor() { return ToolInstallation.all().get(GradleInstallation.DescriptorImpl.class); } @Override public boolean isApplicable(Class<? extends AbstractProject> jobType) { return true; } protected void convert(Map<String, Object> oldPropertyBag) { if (oldPropertyBag.containsKey("installations")) installations = (GradleInstallation[]) oldPropertyBag.get("installations"); } @Override public String getHelpFile() { return "/plugin/gradle/help.html"; } @Override public String getDisplayName() { return Messages.step_displayName(); } public GradleInstallation[] getInstallations() { return installations; } public void setInstallations(GradleInstallation... installations) { this.installations = installations; save(); } @Override public Gradle newInstance(StaplerRequest request, JSONObject formData) throws FormException { return (Gradle) request.bindJSON(clazz, formData); } } }