Skip to content
This repository was archived by the owner on Mar 27, 2025. It is now read-only.

Commit c093ee9

Browse files
authored
Merge pull request #72 from mathworks/CI-368-add-new-builders
Separate build steps by adding two new builders
2 parents 5014017 + 06f1582 commit c093ee9

30 files changed

+2182
-27
lines changed

pom.xml

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,31 @@
5252
<url>http://github.com/jenkinsci/matlab-plugin</url>
5353
<tag>HEAD</tag>
5454
</scm>
55-
55+
5656
<build>
57+
<plugins>
58+
<!-- Plugin to download the matlab run scripts and keep it under class
59+
resource folder -->
60+
<plugin>
61+
<groupId>com.googlecode.maven-download-plugin</groupId>
62+
<artifactId>download-maven-plugin</artifactId>
63+
<version>1.5.0</version>
64+
<executions>
65+
<execution>
66+
<id>get-matlab-runner-scripts</id>
67+
<phase>validate</phase>
68+
<goals>
69+
<goal>wget</goal>
70+
</goals>
71+
<configuration>
72+
<url>https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v0/run-matlab-command.zip</url>
73+
<unpack>true</unpack>
74+
<outputDirectory>${basedir}/src/main/resources</outputDirectory>
75+
</configuration>
76+
</execution>
77+
</executions>
78+
</plugin>
79+
</plugins>
5780
<pluginManagement>
5881
<plugins>
5982
<!--This plugin's configuration is used to store Eclipse m2e settings
@@ -92,6 +115,33 @@
92115
<artifactId>maven-site-plugin</artifactId>
93116
<version>3.7.1</version>
94117
</plugin>
118+
<!-- Delete the runner files during clean operation -->
119+
<plugin>
120+
<artifactId>maven-clean-plugin</artifactId>
121+
<version>3.0.0</version>
122+
<executions>
123+
<execution>
124+
<id>default-clean</id>
125+
<phase>clean</phase>
126+
<goals>
127+
<goal>clean</goal>
128+
</goals>
129+
<configuration>
130+
<filesets>
131+
<fileset>
132+
<directory>${basedir}/src/main/resources</directory>
133+
<includes>
134+
<include>**/*.bat</include>
135+
<include>**/*.sh</include>
136+
<include>**/*.txt</include>
137+
</includes>
138+
<followSymlinks>false</followSymlinks>
139+
</fileset>
140+
</filesets>
141+
</configuration>
142+
</execution>
143+
</executions>
144+
</plugin>
95145
</plugins>
96146
</pluginManagement>
97147
</build>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.mathworks.ci;
2+
3+
/**
4+
* Copyright 2019-2020 The MathWorks, Inc.
5+
*
6+
* This is Utility class which provides commonly used methods for form validations across builders
7+
*
8+
*/
9+
import java.util.List;
10+
import java.util.function.Function;
11+
import hudson.util.FormValidation;
12+
import hudson.util.FormValidation.Kind;
13+
14+
public class FormValidationUtil {
15+
16+
public static FormValidation getFirstErrorOrWarning(
17+
List<Function<String, FormValidation>> validations, String validationArg) {
18+
if (validations == null || validations.isEmpty())
19+
return FormValidation.ok();
20+
try {
21+
for (Function<String, FormValidation> val : validations) {
22+
FormValidation validationResult = val.apply(validationArg);
23+
if (validationResult.kind.compareTo(Kind.ERROR) == 0
24+
|| validationResult.kind.compareTo(Kind.WARNING) == 0) {
25+
return validationResult;
26+
}
27+
}
28+
} catch (Exception e) {
29+
return FormValidation.warning(Message.getValue("Builder.invalid.matlab.root.warning"));
30+
}
31+
return FormValidation.ok();
32+
}
33+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.mathworks.ci;
2+
/**
3+
* Copyright 2019-2020 The MathWorks, Inc.
4+
*
5+
* Build Interface has two default methods. MATLAB builders can override the
6+
* default behavior.
7+
*
8+
*/
9+
10+
import java.io.IOException;
11+
import java.io.InputStream;
12+
import hudson.EnvVars;
13+
import hudson.FilePath;
14+
import hudson.Launcher;
15+
import hudson.Launcher.ProcStarter;
16+
import hudson.model.Computer;
17+
import hudson.model.TaskListener;
18+
19+
public interface MatlabBuild {
20+
21+
/**
22+
* This Method decorates the launcher with MATLAB command provided and returns the Process
23+
* object to launch MATLAB with appropriate startup options like -r or -batch
24+
* @param workspace Current build workspace
25+
* @param launcher Current build launcher
26+
* @param listener Current build listener
27+
* @param envVars Environment variables of the current build
28+
* @param matlabCommand MATLAB command to execute on shell
29+
* @return matlabLauncher returns the process launcher to run MATLAB commands
30+
*/
31+
default ProcStarter getProcessToRunMatlabCommand(FilePath workspace, Launcher launcher,TaskListener listener, EnvVars envVars, String matlabCommand) throws IOException, InterruptedException {
32+
//Get node specific tmp directory to copy matlab runner script
33+
String tmpDir = getNodeSpecificTmpFolderPath();
34+
FilePath targetWorkspace = new FilePath(launcher.getChannel(), tmpDir);
35+
ProcStarter matlabLauncher;
36+
if(launcher.isUnix()) {
37+
matlabLauncher = launcher.launch().pwd(workspace).envs(envVars).cmds(tmpDir+"/run_matlab_command.sh",matlabCommand).stdout(listener);
38+
39+
//Copy runner .sh for linux platform in workspace.
40+
copyFileInWorkspace(MatlabBuilderConstants.SHELL_RUNNER_SCRIPT, "Builder.matlab.runner.script.target.file.linux.name", targetWorkspace);
41+
}else {
42+
launcher = launcher.decorateByPrefix("cmd.exe","/C");
43+
matlabLauncher = launcher.launch().pwd(workspace).envs(envVars).cmds(tmpDir+"\\"+"run_matlab_command.bat","\""+matlabCommand+"\"").stdout(listener);
44+
//Copy runner.bat for Windows platform in workspace.
45+
copyFileInWorkspace(MatlabBuilderConstants.BAT_RUNNER_SCRIPT, "Builder.matlab.runner.script.target.file.windows.name", targetWorkspace);
46+
}
47+
return matlabLauncher;
48+
}
49+
50+
/**
51+
* Method to copy given file from source to target node specific workspace.
52+
*/
53+
default void copyFileInWorkspace(String sourceFile, String targetFile,
54+
FilePath targetWorkspace) throws IOException, InterruptedException {
55+
final ClassLoader classLoader = getClass().getClassLoader();
56+
FilePath targetFilePath = new FilePath(targetWorkspace, Message.getValue(targetFile));
57+
InputStream in = classLoader.getResourceAsStream(sourceFile);
58+
targetFilePath.copyFrom(in);
59+
// set executable permission
60+
targetFilePath.chmod(0755);
61+
62+
}
63+
64+
default FilePath getNodeSpecificMatlabRunnerScript(Launcher launcher) throws IOException, InterruptedException {
65+
Computer cmp = Computer.currentComputer();
66+
String tmpDir = (String) cmp.getSystemProperties().get("java.io.tmpdir");
67+
if(launcher.isUnix()) {
68+
tmpDir = tmpDir+"/run_matlab_command.sh";
69+
}else {
70+
tmpDir = tmpDir+"\\"+"run_matlab_command.bat";
71+
}
72+
return new FilePath(launcher.getChannel(), tmpDir);
73+
}
74+
75+
default String getNodeSpecificTmpFolderPath() throws IOException, InterruptedException {
76+
Computer cmp = Computer.currentComputer();
77+
String tmpDir = (String) cmp.getSystemProperties().get("java.io.tmpdir");
78+
return tmpDir;
79+
}
80+
81+
}

src/main/java/com/mathworks/ci/MatlabBuilder.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@
1111
import java.io.File;
1212
import java.io.IOException;
1313
import java.io.InputStream;
14-
import java.nio.file.Files;
15-
import java.nio.file.Path;
16-
import java.nio.file.StandardCopyOption;
1714
import java.util.ArrayList;
1815
import java.util.Arrays;
1916
import java.util.Collections;
@@ -113,7 +110,9 @@ public void setMatlabRoot(String matlabRoot) {
113110
// Overridden Method used to show the text under build dropdown
114111
@Override
115112
public String getDisplayName() {
116-
return Message.getBuilderDisplayName();
113+
// No name for this descriptor as its deprecated all the jobs will be
114+
// automatically delegated to the new TestRun or Script builders.
115+
return "";
117116
}
118117

119118
@Override

src/main/java/com/mathworks/ci/MatlabBuilderConstants.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,8 @@ public class MatlabBuilderConstants {
2222
static final String STM_RESULTS = "'SimulinkTestResults'";
2323
static final String COBERTURA_CODE_COVERAGE = "'CoberturaCodeCoverage'";
2424
static final String COBERTURA_MODEL_COVERAGE = "'CoberturaModelCoverage'";
25+
26+
// Matlab Runner files
27+
static final String BAT_RUNNER_SCRIPT = "run_matlab_command.bat";
28+
static final String SHELL_RUNNER_SCRIPT = "run_matlab_command.sh";
2529
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.mathworks.ci;
2+
/**
3+
* Copyright 2019-2020 The MathWorks, Inc.
4+
*
5+
* Script builder used to run custom MATLAB commands or scripts.
6+
*
7+
*/
8+
9+
import java.io.IOException;
10+
import javax.annotation.Nonnull;
11+
import org.jenkinsci.Symbol;
12+
import org.kohsuke.stapler.DataBoundConstructor;
13+
import org.kohsuke.stapler.DataBoundSetter;
14+
import org.kohsuke.stapler.StaplerRequest;
15+
import hudson.EnvVars;
16+
import hudson.Extension;
17+
import hudson.FilePath;
18+
import hudson.Launcher;
19+
import hudson.Launcher.ProcStarter;
20+
import hudson.model.AbstractProject;
21+
import hudson.model.Result;
22+
import hudson.model.Run;
23+
import hudson.model.TaskListener;
24+
import hudson.tasks.BuildStepDescriptor;
25+
import hudson.tasks.Builder;
26+
import jenkins.tasks.SimpleBuildStep;
27+
import net.sf.json.JSONObject;
28+
29+
public class RunMatlabCommandBuilder extends Builder implements SimpleBuildStep, MatlabBuild {
30+
private int buildResult;
31+
private EnvVars env;
32+
private String matlabCommand;
33+
34+
@DataBoundConstructor
35+
public RunMatlabCommandBuilder() {
36+
37+
}
38+
39+
40+
// Getter and Setters to access local members
41+
42+
43+
@DataBoundSetter
44+
public void setMatlabCommand(String matlabCommand) {
45+
this.matlabCommand = matlabCommand;
46+
}
47+
48+
public String getMatlabCommand() {
49+
return this.matlabCommand;
50+
}
51+
52+
private String getCommand() {
53+
return this.env == null ? getMatlabCommand() : this.env.expand(getMatlabCommand());
54+
}
55+
56+
private void setEnv(EnvVars env) {
57+
this.env = env;
58+
}
59+
60+
private EnvVars getEnv() {
61+
return this.env;
62+
}
63+
64+
@Symbol("RunMatlabCommand")
65+
@Extension
66+
public static class RunMatlabCommandDescriptor extends BuildStepDescriptor<Builder> {
67+
68+
// Overridden Method used to show the text under build dropdown
69+
@Override
70+
public String getDisplayName() {
71+
return Message.getValue("Builder.script.builder.display.name");
72+
}
73+
74+
@Override
75+
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
76+
save();
77+
return super.configure(req, formData);
78+
}
79+
80+
/*
81+
* This is to identify which project type in jenkins this should be applicable.(non-Javadoc)
82+
*
83+
* @see hudson.tasks.BuildStepDescriptor#isApplicable(java.lang.Class)
84+
*
85+
* if it returns true then this build step will be applicable for all project type.
86+
*/
87+
@Override
88+
public boolean isApplicable(
89+
@SuppressWarnings("rawtypes") Class<? extends AbstractProject> jobtype) {
90+
return true;
91+
}
92+
}
93+
94+
@Override
95+
public void perform(@Nonnull Run<?, ?> build, @Nonnull FilePath workspace,
96+
@Nonnull Launcher launcher, @Nonnull TaskListener listener)
97+
throws InterruptedException, IOException {
98+
99+
try {
100+
// Set the environment variable specific to the this build
101+
setEnv(build.getEnvironment(listener));
102+
103+
// Invoke MATLAB command and transfer output to standard
104+
// Output Console
105+
106+
buildResult = execMatlabCommand(workspace, launcher, listener, getEnv());
107+
108+
if (buildResult != 0) {
109+
build.setResult(Result.FAILURE);
110+
}
111+
} finally {
112+
// Cleanup the runner File from tmp directory
113+
FilePath matlabRunnerScript = getNodeSpecificMatlabRunnerScript(launcher);
114+
if(matlabRunnerScript.exists()) {
115+
matlabRunnerScript.delete();
116+
}
117+
}
118+
}
119+
120+
private synchronized int execMatlabCommand(FilePath workspace, Launcher launcher,
121+
TaskListener listener, EnvVars envVars) throws IOException, InterruptedException {
122+
ProcStarter matlabLauncher;
123+
try {
124+
matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, listener, envVars,getCommand());
125+
} catch (Exception e) {
126+
listener.getLogger().println(e.getMessage());
127+
return 1;
128+
}
129+
return matlabLauncher.join();
130+
}
131+
}

0 commit comments

Comments
 (0)