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

Commit a5ff192

Browse files
authored
Merge pull request #164 from mathworks/2.2.1-Qualification
2.3.0 qualification
2 parents 499bfc5 + 015b4cd commit a5ff192

File tree

22 files changed

+713
-85
lines changed

22 files changed

+713
-85
lines changed

CONFIGDOC.md

Lines changed: 157 additions & 37 deletions
Large diffs are not rendered by default.

SECURITY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Reporting Security Vulnerabilities
2+
3+
If you believe you have discovered a security vulnerability, please report it to
4+
[[email protected]](mailto:[email protected]). Please see
5+
[MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html)
6+
for additional information.

examples/Run-MATLAB-Tests.md

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,50 +25,54 @@ Running the tests in this example requires you to interface Jenkins with MATLAB
2525
Create a new project and configure it by following these steps:
2626
1. In your Jenkins interface, select **New Item** on the left. A new page opens where you can choose the type of your project. Enter a project name, then click **Freestyle project**. To confirm your choices, click **OK**.
2727

28-
![create_project](https://user-images.githubusercontent.com/48831250/71735513-a7f47800-2e1c-11ea-878b-db53c059c4c7.png)
28+
![create_project](https://user-images.githubusercontent.com/48831250/94477040-50aee880-019f-11eb-9484-1d4ecf60ed92.png)
2929

3030
2. In the configuration window of your Jenkins project, navigate to the **Source Code Management** section and click **Git**. This option enables Jenkins to interface with a remote repository.
3131

32-
![git](https://user-images.githubusercontent.com/48831250/71736215-809eaa80-2e1e-11ea-9ff5-6eea39622d3e.png)
32+
![git](https://user-images.githubusercontent.com/48831250/94477376-cb780380-019f-11eb-8297-1c3a4874fe0e.png)
3333

34-
3. Navigate to the main page of the GitHub repository that hosts your tests. Click **Clone or download** and copy the web URL to your clipboard.
3534

36-
![clipboard](https://user-images.githubusercontent.com/48831250/71736069-1980f600-2e1e-11ea-9672-1af6c958d77d.png)
35+
3. Navigate to the main page of the GitHub repository that hosts your tests. Click **Code** and copy the web URL to your clipboard.
3736

38-
4. In the Jenkins interface, paste the URL into the **Repository URL** box of the **Source Code Management** section. (You also can specify the branch to build in the **Branch Specifier** box.)
37+
![clipboard](https://user-images.githubusercontent.com/48831250/94478137-dd0ddb00-01a0-11eb-9e55-d8004863c5e7.png)
38+
39+
40+
4. In the Jenkins interface, paste the URL into the **Repository URL** box of the **Source Code Management** section. You also can specify the branch to build in the **Branch Specifier** box.
41+
42+
![source_control](https://user-images.githubusercontent.com/48831250/94478391-37a73700-01a1-11eb-9f89-a5a71413baf0.png)
3943

40-
![source_control](https://user-images.githubusercontent.com/48831250/71735877-965fa000-2e1d-11ea-95c4-8b9259308e75.png)
4144

4245
5. In the **Build Environment** section of Jenkins, select **Use MATLAB Version**. Then, enter the full path to the MATLAB root folder in the **MATLAB root** box. Jenkins uses MATLAB at the specified location to run the tests.
4346

44-
![build_environment](https://user-images.githubusercontent.com/48831250/76796506-f53c8080-67a1-11ea-860f-0cca3748c723.png)
47+
![build_environment](https://user-images.githubusercontent.com/48831250/94478737-ad130780-01a1-11eb-89d8-1ef43c34fab0.png)
4548

46-
6. In the **Build** section of Jenkins, select **Add build step > Run MATLAB Tests**. Then, select your desired test artifacts to be generated in the project workspace. The plugin in this example is configured to generate Cobertura code coverage and JUnit test result reports. For more information on how to configure the plugin, see [Plugin Configuration Guide](../CONFIGDOC.md).
49+
6. In the **Build** section of Jenkins, select **Add build step > Run MATLAB Tests**. Then, select your desired test artifacts to be generated in the project workspace. The plugin in this example is configured to generate Cobertura code coverage and JUnit test result reports. Furthermore, the coverage report is generated only for the code in the `source` folder located in the root of your repository. For more information on how to configure the plugin, see [Plugin Configuration Guide](../CONFIGDOC.md).
4750

48-
![run_matlab_tests](https://user-images.githubusercontent.com/48831250/84545885-17c13580-acce-11ea-8a29-b78386a7f0ef.png)
51+
![run_matlab_tests](https://user-images.githubusercontent.com/48831250/94479048-2f9bc700-01a2-11eb-9ff6-4ab1df99d1b9.png)
4952

5053
7. In the **Post-build Actions** section of Jenkins, add two post-build actions to publish the Cobertura code coverage and JUnit test result reports. For each report, provide the path to the report file.
5154

52-
![post_build](https://user-images.githubusercontent.com/48831250/76796543-0f765e80-67a2-11ea-98f6-8180ff85d4a0.png)
55+
![post_build](https://user-images.githubusercontent.com/48831250/94479293-96b97b80-01a2-11eb-97ff-44a321bce0e9.png)
56+
5357

5458
8. Click **Save** to save the project configuration settings. You can access and modify your settings at a later stage by selecting **Configure** in the project interface.
5559

5660
## Run Tests and Inspect Test Artifacts
5761
To build your Jenkins project and run the tests specified in the repository, click **Build Now** in the project interface, which displays the project name at the top-left of the page. Jenkins triggers a build, assigns it a number under **Build History**, and runs the build. If the build is successful, a blue circle icon appears next to the build number. If the build fails, Jenkins adds a red circle icon. In this example, the build passes because all of the tests specified in the Times Table App project pass.
5862

59-
![build_1](https://user-images.githubusercontent.com/48831250/76796848-b0fdb000-67a2-11ea-8cec-753cf1eb27b2.png)
63+
![build_1](https://user-images.githubusercontent.com/48831250/94481160-4db6f680-01a5-11eb-83eb-75027a009321.png)
6064

6165
Navigate to the project workspace by clicking the **Workspace** icon in the project interface. In this example, the generated test artifacts are in the `matlabTestArtifacts` folder of the workspace.
6266

63-
![workspace](https://user-images.githubusercontent.com/48831250/76797316-a0016e80-67a3-11ea-9166-e95b5a4ac97d.png)
67+
![workspace](https://user-images.githubusercontent.com/48831250/94481319-88209380-01a5-11eb-8681-440ea84b59d9.png)
6468

6569
Access the published Cobertura code coverage report by opening the **Coverage Report** link in the project interface.
6670

67-
![cobertura_report](https://user-images.githubusercontent.com/48831250/76797272-85c79080-67a3-11ea-8a93-c9f92c66de5c.png)
71+
![cobertura_report](https://user-images.githubusercontent.com/48831250/94481556-e2b9ef80-01a5-11eb-86f2-1679ae63f407.png)
6872

6973
To view the published JUnit test results, open the **Latest Test Result** link in the project interface. In the new page, open the link in the **All Tests** table. The table expands and lists information for each of the test classes within the Times Table App project.
7074

71-
![junit_report](https://user-images.githubusercontent.com/48831250/76797445-e1921980-67a3-11ea-8ed4-157f7fd8bf77.png)
75+
![junit_report](https://user-images.githubusercontent.com/48831250/94481735-33c9e380-01a6-11eb-9106-d96cfd7676ae.png)
7276

7377
## See Also
7478
[MathWorks Blogs: Developer Zone – Continuous Integration](https://blogs.mathworks.com/developer/category/continuous-integration/)<br/>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import java.io.IOException;
1010
import java.io.InputStream;
11+
import java.util.List;
1112
import java.util.UUID;
1213
import hudson.EnvVars;
1314
import hudson.FilePath;
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.mathworks.ci;
2+
3+
import hudson.CopyOnWrite;
4+
import hudson.EnvVars;
5+
import hudson.Extension;
6+
import hudson.Util;
7+
import hudson.model.EnvironmentSpecific;
8+
import hudson.model.Node;
9+
import hudson.model.TaskListener;
10+
import hudson.slaves.NodeSpecific;
11+
import hudson.tools.ToolDescriptor;
12+
import hudson.tools.ToolInstallation;
13+
import hudson.tools.ToolProperty;
14+
import java.io.IOException;
15+
import java.util.Arrays;
16+
import java.util.List;
17+
import javax.annotation.CheckForNull;
18+
import net.sf.json.JSONObject;
19+
import org.jenkinsci.Symbol;
20+
import org.kohsuke.stapler.DataBoundConstructor;
21+
import org.kohsuke.stapler.StaplerRequest;
22+
23+
public class MatlabInstallation extends ToolInstallation implements EnvironmentSpecific<MatlabInstallation>, NodeSpecific<MatlabInstallation> {
24+
private static final long serialVersionUID = 1L;
25+
26+
@DataBoundConstructor
27+
public MatlabInstallation(String name, @CheckForNull String home, List<? extends ToolProperty<?>> properties) {
28+
super(Util.fixEmptyAndTrim(name), Util.fixEmptyAndTrim(home), properties);
29+
}
30+
31+
@Override public MatlabInstallation forEnvironment(EnvVars envVars) {
32+
return new MatlabInstallation(getName(), envVars.expand(getHome()), getProperties().toList());
33+
}
34+
35+
@Override
36+
public MatlabInstallation forNode(Node node, TaskListener log) throws IOException, InterruptedException {
37+
return new MatlabInstallation(getName(), translateFor(node, log), getProperties().toList());
38+
}
39+
40+
@Override
41+
public void buildEnvVars(EnvVars env) {
42+
String pathToExecutable = getHome() + "/bin";
43+
env.put("PATH+matlabroot", pathToExecutable);
44+
}
45+
46+
@Extension @Symbol("matlab")
47+
public static class DescriptorImpl extends ToolDescriptor<MatlabInstallation> {
48+
@CopyOnWrite
49+
private volatile MatlabInstallation[] installations = new MatlabInstallation[0];
50+
51+
public DescriptorImpl() {
52+
load();
53+
}
54+
55+
@Override
56+
public String getDisplayName() {
57+
return "MATLAB";
58+
}
59+
60+
@Override
61+
public MatlabInstallation[] getInstallations() {
62+
return Arrays.copyOf(installations, installations.length);
63+
}
64+
65+
@Override
66+
public MatlabInstallation newInstance(StaplerRequest req, JSONObject formData) {
67+
return (MatlabInstallation) req.bindJSON(clazz, formData);
68+
}
69+
70+
public void setInstallations(MatlabInstallation... matlabInstallations) {
71+
this.installations = matlabInstallations;
72+
save();
73+
}
74+
75+
}
76+
77+
}

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

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,26 @@
99
*/
1010

1111
import java.io.IOException;
12-
import java.util.*;
12+
import java.util.Map;
13+
import java.util.HashMap;
14+
import java.util.List;
15+
import java.util.ArrayList;
16+
import java.util.Optional;
17+
import java.util.Arrays;
18+
import java.util.stream.Collectors;
1319
import javax.annotation.Nonnull;
14-
import org.kohsuke.stapler.DataBoundConstructor;
15-
import org.kohsuke.stapler.DataBoundSetter;
16-
import org.kohsuke.stapler.StaplerRequest;
1720
import hudson.EnvVars;
1821
import hudson.Extension;
1922
import hudson.FilePath;
2023
import hudson.Launcher;
21-
import hudson.Launcher.ProcStarter;
2224
import hudson.model.AbstractProject;
2325
import hudson.model.Result;
2426
import hudson.model.Run;
2527
import hudson.model.TaskListener;
28+
import org.kohsuke.stapler.DataBoundConstructor;
29+
import org.kohsuke.stapler.DataBoundSetter;
30+
import org.kohsuke.stapler.StaplerRequest;
31+
import hudson.Launcher.ProcStarter;
2632
import hudson.tasks.BuildStepDescriptor;
2733
import hudson.tasks.Builder;
2834
import jenkins.tasks.SimpleBuildStep;
@@ -32,7 +38,7 @@ public class RunMatlabTestsBuilder extends Builder implements SimpleBuildStep, M
3238

3339
private int buildResult;
3440
private EnvVars env;
35-
41+
3642
// Make all old values transient which protects them writing back on disk.
3743
private transient boolean tapChkBx;
3844
private transient boolean junitChkBx;
@@ -47,16 +53,15 @@ public class RunMatlabTestsBuilder extends Builder implements SimpleBuildStep, M
4753
private Artifact stmResultsArtifact = new NullArtifact();
4854
private Artifact modelCoverageArtifact = new NullArtifact();
4955
private Artifact pdfReportArtifact = new NullArtifact();
50-
56+
private SourceFolder sourceFolder;
57+
5158
@DataBoundConstructor
5259
public RunMatlabTestsBuilder() {
5360

5461
}
5562

56-
5763
// Getter and Setters to access local members
5864

59-
6065
@DataBoundSetter
6166
public void setTapArtifact(TapArtifact tapArtifact) {
6267
this.tapArtifact = tapArtifact;
@@ -86,7 +91,13 @@ public void setModelCoverageArtifact(ModelCovArtifact modelCoverageArtifact) {
8691
public void setPdfReportArtifact(PdfArtifact pdfReportArtifact) {
8792
this.pdfReportArtifact = pdfReportArtifact;
8893
}
89-
94+
95+
@DataBoundSetter
96+
public void setSourceFolder(SourceFolder sourceFolder) {
97+
this.sourceFolder = sourceFolder;
98+
}
99+
100+
90101
public String getTapReportFilePath() {
91102
return this.getTapArtifact().getFilePath();
92103
}
@@ -135,6 +146,10 @@ public String getPdfReportFilePath() {
135146
return this.getPdfReportArtifact().getFilePath();
136147
}
137148

149+
public SourceFolder getSourceFolder() {
150+
return this.sourceFolder;
151+
}
152+
138153
private Artifact getArtifactObject(boolean isChecked, Artifact returnVal) {
139154
// If previously checked assign valid artifact object else NullArtifact.
140155
return (isChecked) ? returnVal : new NullArtifact();
@@ -286,6 +301,17 @@ private String getInputArguments() {
286301

287302
args.forEach((key, val) -> inputArgsList.add("'" + key + "'" + "," + "'" + val.replaceAll("'", "''") + "'"));
288303

304+
/*
305+
* Add source folder options to argument.
306+
* For source folder we create a MATLAB cell array and add it to input argument list.
307+
* */
308+
SourceFolder sf = getSourceFolder();
309+
if(sf != null && !sf.getSourceFolderPaths().isEmpty()){
310+
sf.addSourceToInputArgs(inputArgsList, Utilities.getCellArrayFrmList(sf.getSourceFolderPaths().stream()
311+
.map(SourceFolderPaths::getSrcFolderPath)
312+
.collect(Collectors.toList())));
313+
}
314+
289315
return String.join(",", inputArgsList);
290316
}
291317

@@ -300,6 +326,7 @@ private String getInputArguments() {
300326
* 7Csort:date/jenkinsci-dev/AFYHSG3NUEI/UsVJIKoE4B8J
301327
*
302328
*/
329+
303330
public static class PdfArtifact extends AbstractArtifactImpl {
304331

305332
private static final String PDF_TEST_REPORT = "PDFTestReport";

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import hudson.Launcher;
2323
import hudson.model.Run;
2424
import hudson.model.TaskListener;
25+
import hudson.Util;
2526

2627
public class RunMatlabTestsStep extends Step {
2728

@@ -31,7 +32,7 @@ public class RunMatlabTestsStep extends Step {
3132
private String codeCoverageCobertura;
3233
private String testResultsSimulinkTest;
3334
private String modelCoverageCobertura;
34-
35+
private List<String> sourceFolder = new ArrayList<>();
3536

3637
@DataBoundConstructor
3738
public RunMatlabTestsStep() {
@@ -93,6 +94,14 @@ public void setModelCoverageCobertura(String modelCoverageCobertura) {
9394
this.modelCoverageCobertura = modelCoverageCobertura;
9495
}
9596

97+
public List<String> getSourceFolder() {
98+
return sourceFolder;
99+
}
100+
101+
@DataBoundSetter
102+
public void setSourceFolder(List<String> sourceFolder) {
103+
this.sourceFolder = Util.fixNull(sourceFolder);
104+
}
96105

97106
@Override
98107
public StepExecution start(StepContext context) throws Exception {
@@ -126,7 +135,9 @@ private String getInputArgs() {
126135
inputArgs.add("'Test'");
127136

128137
args.forEach((key, val) -> {
129-
if (val != null) {
138+
if(key.equals("SourceFolder") && val != null){
139+
inputArgs.add("'" + key + "'" + "," + val);
140+
}else if(val != null){
130141
inputArgs.add("'" + key + "'" + "," + "'" + val.replaceAll("'", "''") + "'");
131142
}
132143
});
@@ -142,6 +153,9 @@ private Map<String, String> getGenscriptArgs() {
142153
args.put("SimulinkTestResults", getTestResultsSimulinkTest());
143154
args.put("CoberturaCodeCoverage", getCodeCoverageCobertura());
144155
args.put("CoberturaModelCoverage", getModelCoverageCobertura());
156+
if(!getSourceFolder().isEmpty()){
157+
args.put("SourceFolder", Utilities.getCellArrayFrmList(getSourceFolder()));
158+
}
145159
return args;
146160
}
147161
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.mathworks.ci;
2+
3+
/**
4+
* Copyright 2020 The MathWorks, Inc.
5+
*
6+
* Describable class for Source Folder Option in RunMATLABTest Build step.
7+
*
8+
*/
9+
10+
import hudson.Extension;
11+
import hudson.Util;
12+
import hudson.model.AbstractDescribableImpl;
13+
import hudson.model.Descriptor;
14+
import org.kohsuke.stapler.DataBoundConstructor;
15+
import java.util.List;
16+
import java.util.Map;
17+
import java.util.stream.Collectors;
18+
19+
public class SourceFolder extends AbstractDescribableImpl<SourceFolder> {
20+
21+
private List<SourceFolderPaths> sourceFolderPaths;
22+
private static final String SOURCE_FOLDER = "SourceFolder";
23+
24+
@DataBoundConstructor
25+
public SourceFolder(List<SourceFolderPaths> sourceFolderPaths) {
26+
this.sourceFolderPaths = Util.fixNull(sourceFolderPaths);
27+
}
28+
29+
public List<SourceFolderPaths> getSourceFolderPaths() {
30+
return this.sourceFolderPaths;
31+
}
32+
33+
public void addSourceToInputArgs(List<String> inputArgsList, String cellArraySourceVal) {
34+
// Concatenate all source folders to MATLAB cell array string.
35+
inputArgsList.add("'" + SOURCE_FOLDER + "'" + "," + cellArraySourceVal);
36+
}
37+
38+
@Extension public static class DescriptorImpl extends Descriptor<SourceFolder> {
39+
@Override
40+
public String getDisplayName() {
41+
return "";
42+
}
43+
}
44+
45+
}

0 commit comments

Comments
 (0)