-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #72 from mathworks/CI-368-add-new-builders
Separate build steps by adding two new builders
- Loading branch information
Showing
30 changed files
with
2,182 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.mathworks.ci; | ||
|
||
/** | ||
* Copyright 2019-2020 The MathWorks, Inc. | ||
* | ||
* This is Utility class which provides commonly used methods for form validations across builders | ||
* | ||
*/ | ||
import java.util.List; | ||
import java.util.function.Function; | ||
import hudson.util.FormValidation; | ||
import hudson.util.FormValidation.Kind; | ||
|
||
public class FormValidationUtil { | ||
|
||
public static FormValidation getFirstErrorOrWarning( | ||
List<Function<String, FormValidation>> validations, String validationArg) { | ||
if (validations == null || validations.isEmpty()) | ||
return FormValidation.ok(); | ||
try { | ||
for (Function<String, FormValidation> val : validations) { | ||
FormValidation validationResult = val.apply(validationArg); | ||
if (validationResult.kind.compareTo(Kind.ERROR) == 0 | ||
|| validationResult.kind.compareTo(Kind.WARNING) == 0) { | ||
return validationResult; | ||
} | ||
} | ||
} catch (Exception e) { | ||
return FormValidation.warning(Message.getValue("Builder.invalid.matlab.root.warning")); | ||
} | ||
return FormValidation.ok(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package com.mathworks.ci; | ||
/** | ||
* Copyright 2019-2020 The MathWorks, Inc. | ||
* | ||
* Build Interface has two default methods. MATLAB builders can override the | ||
* default behavior. | ||
* | ||
*/ | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import hudson.EnvVars; | ||
import hudson.FilePath; | ||
import hudson.Launcher; | ||
import hudson.Launcher.ProcStarter; | ||
import hudson.model.Computer; | ||
import hudson.model.TaskListener; | ||
|
||
public interface MatlabBuild { | ||
|
||
/** | ||
* This Method decorates the launcher with MATLAB command provided and returns the Process | ||
* object to launch MATLAB with appropriate startup options like -r or -batch | ||
* @param workspace Current build workspace | ||
* @param launcher Current build launcher | ||
* @param listener Current build listener | ||
* @param envVars Environment variables of the current build | ||
* @param matlabCommand MATLAB command to execute on shell | ||
* @return matlabLauncher returns the process launcher to run MATLAB commands | ||
*/ | ||
default ProcStarter getProcessToRunMatlabCommand(FilePath workspace, Launcher launcher,TaskListener listener, EnvVars envVars, String matlabCommand) throws IOException, InterruptedException { | ||
//Get node specific tmp directory to copy matlab runner script | ||
String tmpDir = getNodeSpecificTmpFolderPath(); | ||
FilePath targetWorkspace = new FilePath(launcher.getChannel(), tmpDir); | ||
ProcStarter matlabLauncher; | ||
if(launcher.isUnix()) { | ||
matlabLauncher = launcher.launch().pwd(workspace).envs(envVars).cmds(tmpDir+"/run_matlab_command.sh",matlabCommand).stdout(listener); | ||
|
||
//Copy runner .sh for linux platform in workspace. | ||
copyFileInWorkspace(MatlabBuilderConstants.SHELL_RUNNER_SCRIPT, "Builder.matlab.runner.script.target.file.linux.name", targetWorkspace); | ||
}else { | ||
launcher = launcher.decorateByPrefix("cmd.exe","/C"); | ||
matlabLauncher = launcher.launch().pwd(workspace).envs(envVars).cmds(tmpDir+"\\"+"run_matlab_command.bat","\""+matlabCommand+"\"").stdout(listener); | ||
//Copy runner.bat for Windows platform in workspace. | ||
copyFileInWorkspace(MatlabBuilderConstants.BAT_RUNNER_SCRIPT, "Builder.matlab.runner.script.target.file.windows.name", targetWorkspace); | ||
} | ||
return matlabLauncher; | ||
} | ||
|
||
/** | ||
* Method to copy given file from source to target node specific workspace. | ||
*/ | ||
default void copyFileInWorkspace(String sourceFile, String targetFile, | ||
FilePath targetWorkspace) throws IOException, InterruptedException { | ||
final ClassLoader classLoader = getClass().getClassLoader(); | ||
FilePath targetFilePath = new FilePath(targetWorkspace, Message.getValue(targetFile)); | ||
InputStream in = classLoader.getResourceAsStream(sourceFile); | ||
targetFilePath.copyFrom(in); | ||
// set executable permission | ||
targetFilePath.chmod(0755); | ||
|
||
} | ||
|
||
default FilePath getNodeSpecificMatlabRunnerScript(Launcher launcher) throws IOException, InterruptedException { | ||
Computer cmp = Computer.currentComputer(); | ||
String tmpDir = (String) cmp.getSystemProperties().get("java.io.tmpdir"); | ||
if(launcher.isUnix()) { | ||
tmpDir = tmpDir+"/run_matlab_command.sh"; | ||
}else { | ||
tmpDir = tmpDir+"\\"+"run_matlab_command.bat"; | ||
} | ||
return new FilePath(launcher.getChannel(), tmpDir); | ||
} | ||
|
||
default String getNodeSpecificTmpFolderPath() throws IOException, InterruptedException { | ||
Computer cmp = Computer.currentComputer(); | ||
String tmpDir = (String) cmp.getSystemProperties().get("java.io.tmpdir"); | ||
return tmpDir; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
src/main/java/com/mathworks/ci/RunMatlabCommandBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package com.mathworks.ci; | ||
/** | ||
* Copyright 2019-2020 The MathWorks, Inc. | ||
* | ||
* Script builder used to run custom MATLAB commands or scripts. | ||
* | ||
*/ | ||
|
||
import java.io.IOException; | ||
import javax.annotation.Nonnull; | ||
import org.jenkinsci.Symbol; | ||
import org.kohsuke.stapler.DataBoundConstructor; | ||
import org.kohsuke.stapler.DataBoundSetter; | ||
import org.kohsuke.stapler.StaplerRequest; | ||
import hudson.EnvVars; | ||
import hudson.Extension; | ||
import hudson.FilePath; | ||
import hudson.Launcher; | ||
import hudson.Launcher.ProcStarter; | ||
import hudson.model.AbstractProject; | ||
import hudson.model.Result; | ||
import hudson.model.Run; | ||
import hudson.model.TaskListener; | ||
import hudson.tasks.BuildStepDescriptor; | ||
import hudson.tasks.Builder; | ||
import jenkins.tasks.SimpleBuildStep; | ||
import net.sf.json.JSONObject; | ||
|
||
public class RunMatlabCommandBuilder extends Builder implements SimpleBuildStep, MatlabBuild { | ||
private int buildResult; | ||
private EnvVars env; | ||
private String matlabCommand; | ||
|
||
@DataBoundConstructor | ||
public RunMatlabCommandBuilder() { | ||
|
||
} | ||
|
||
|
||
// Getter and Setters to access local members | ||
|
||
|
||
@DataBoundSetter | ||
public void setMatlabCommand(String matlabCommand) { | ||
this.matlabCommand = matlabCommand; | ||
} | ||
|
||
public String getMatlabCommand() { | ||
return this.matlabCommand; | ||
} | ||
|
||
private String getCommand() { | ||
return this.env == null ? getMatlabCommand() : this.env.expand(getMatlabCommand()); | ||
} | ||
|
||
private void setEnv(EnvVars env) { | ||
this.env = env; | ||
} | ||
|
||
private EnvVars getEnv() { | ||
return this.env; | ||
} | ||
|
||
@Symbol("RunMatlabCommand") | ||
@Extension | ||
public static class RunMatlabCommandDescriptor extends BuildStepDescriptor<Builder> { | ||
|
||
// Overridden Method used to show the text under build dropdown | ||
@Override | ||
public String getDisplayName() { | ||
return Message.getValue("Builder.script.builder.display.name"); | ||
} | ||
|
||
@Override | ||
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { | ||
save(); | ||
return super.configure(req, formData); | ||
} | ||
|
||
/* | ||
* This is to identify which project type in jenkins this should be applicable.(non-Javadoc) | ||
* | ||
* @see hudson.tasks.BuildStepDescriptor#isApplicable(java.lang.Class) | ||
* | ||
* if it returns true then this build step will be applicable for all project type. | ||
*/ | ||
@Override | ||
public boolean isApplicable( | ||
@SuppressWarnings("rawtypes") Class<? extends AbstractProject> jobtype) { | ||
return true; | ||
} | ||
} | ||
|
||
@Override | ||
public void perform(@Nonnull Run<?, ?> build, @Nonnull FilePath workspace, | ||
@Nonnull Launcher launcher, @Nonnull TaskListener listener) | ||
throws InterruptedException, IOException { | ||
|
||
try { | ||
// Set the environment variable specific to the this build | ||
setEnv(build.getEnvironment(listener)); | ||
|
||
// Invoke MATLAB command and transfer output to standard | ||
// Output Console | ||
|
||
buildResult = execMatlabCommand(workspace, launcher, listener, getEnv()); | ||
|
||
if (buildResult != 0) { | ||
build.setResult(Result.FAILURE); | ||
} | ||
} finally { | ||
// Cleanup the runner File from tmp directory | ||
FilePath matlabRunnerScript = getNodeSpecificMatlabRunnerScript(launcher); | ||
if(matlabRunnerScript.exists()) { | ||
matlabRunnerScript.delete(); | ||
} | ||
} | ||
} | ||
|
||
private synchronized int execMatlabCommand(FilePath workspace, Launcher launcher, | ||
TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { | ||
ProcStarter matlabLauncher; | ||
try { | ||
matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, listener, envVars,getCommand()); | ||
} catch (Exception e) { | ||
listener.getLogger().println(e.getMessage()); | ||
return 1; | ||
} | ||
return matlabLauncher.join(); | ||
} | ||
} |
Oops, something went wrong.