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

Commit f7082a9

Browse files
authored
Merge pull request #176 from mathworks/3.0.0-Qualification
3.0.0 qualification -> 2.4.0 Release
2 parents 63803dc + 22058c8 commit f7082a9

37 files changed

+1011
-201
lines changed

CONFIGDOC.md

Lines changed: 87 additions & 60 deletions
Large diffs are not rendered by default.

examples/Run-MATLAB-Tests.md

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ This example shows how to run a suite of MATLAB® unit tests with Jenkins&tra
44

55
* Configure Jenkins to run a freestyle project including MATLAB tests.
66
* Interface Jenkins with a remote repository that contains the tests.
7-
* Build the freestyle project and examine the generated test artifacts.
7+
* Build the freestyle project and examine the generated artifacts.
88

9-
The freestyle project runs the tests in the Times Table App MATLAB project (which requires R2019a or later). You can create a working copy of the project files and open the project in MATLAB by running this statement in the Command Window:
9+
The freestyle project runs the tests in the Times Table App MATLAB project (which requires R2019a or later). You can create a working copy of the project files and open the project in MATLAB by running this statement in the Command Window.
1010

1111
```
1212
matlab.project.example.timesTable
@@ -17,62 +17,58 @@ For more information about the Times Table App example project, see [Explore an
1717
## Prerequisites
1818
Running the tests in this example requires you to interface Jenkins with MATLAB as well as a remote repository.
1919

20-
* To run MATLAB tests and generate test artifacts, you must install the MATLAB plugin. For information on how to install a plugin in Jenkins, see [Managing Plugins](https://jenkins.io/doc/book/managing/plugins/).
20+
* To run MATLAB tests and generate artifacts, you must install the plugin for MATLAB. For information on how to install a plugin in Jenkins, see [Managing Plugins](https://jenkins.io/doc/book/managing/plugins/).
2121
* Jenkins runs the tests in a branch of the remote repository that is specified by a URL. To follow the build steps in this example, the Times Table App project must be under Git™ source control. For example, you can create a new repository for the project using your GitHub® account. For more information, see [Use Source Control with Projects](https://www.mathworks.com/help/matlab/matlab_prog/use-source-control-with-projects.html).
22-
* To publish the test artifacts using post-build actions, relevant plugins must be installed on Jenkins. For example, the [Cobertura plugin](https://plugins.jenkins.io/cobertura) integrates Cobertura coverage reports to Jenkins, and [JUnit plugin](https://plugins.jenkins.io/junit) publishes JUnit-format test results.
22+
* To publish the artifacts using post-build actions, relevant plugins must be installed on Jenkins. For example, the [Cobertura plugin](https://plugins.jenkins.io/cobertura) integrates Cobertura coverage reports to Jenkins, and [JUnit plugin](https://plugins.jenkins.io/junit) publishes JUnit-format test results.
2323

2424
## Configure Jenkins Project to Run MATLAB Tests
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/94477040-50aee880-019f-11eb-9484-1d4ecf60ed92.png)
28+
![create_project](https://user-images.githubusercontent.com/48831250/105080784-520e6480-5a5f-11eb-9218-4d43013e2850.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/94477376-cb780380-019f-11eb-8297-1c3a4874fe0e.png)
33-
34-
3532
3. Navigate to the main page of the GitHub repository that hosts your tests. Click **Code** and copy the web URL to your clipboard.
3633

3734
![clipboard](https://user-images.githubusercontent.com/48831250/94478137-dd0ddb00-01a0-11eb-9e55-d8004863c5e7.png)
3835

3936

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.
37+
4. In the project configuration window, 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.
4138

4239
![source_control](https://user-images.githubusercontent.com/48831250/94478391-37a73700-01a1-11eb-9f89-a5a71413baf0.png)
4340

4441

45-
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.
46-
47-
![build_environment](https://user-images.githubusercontent.com/48831250/94478737-ad130780-01a1-11eb-89d8-1ef43c34fab0.png)
42+
5. In the **Build Environment** section, select **Use MATLAB version** and specify the MATLAB version you want to use in the build. If your desired MATLAB version is not listed under **Use MATLAB version**, enter the full path to its root folder in the **MATLAB root** box.
4843

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).
44+
![build_environment](https://user-images.githubusercontent.com/48831250/105091260-943ea280-5a6d-11eb-8d11-48747df7ec32.png)
5045

51-
![run_matlab_tests](https://user-images.githubusercontent.com/48831250/94479048-2f9bc700-01a2-11eb-9ff6-4ab1df99d1b9.png)
46+
6. In the **Build** section, select **Add build step > Run MATLAB Tests**. Then, select your desired 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).
5247

53-
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.
48+
![run_matlab_tests](https://user-images.githubusercontent.com/48831250/105909903-2149a480-5ff6-11eb-81f1-c3b44e9b17d1.png)
5449

55-
![post_build](https://user-images.githubusercontent.com/48831250/94479293-96b97b80-01a2-11eb-97ff-44a321bce0e9.png)
50+
7. In the **Post-build Actions** section, 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.
5651

52+
![post_build](https://user-images.githubusercontent.com/48831250/105082096-14aad680-5a61-11eb-9868-68d018199f9d.png)
5753

5854
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.
5955

60-
## Run Tests and Inspect Test Artifacts
61-
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.
56+
## Run Tests and Inspect Artifacts
57+
To build your freestyle project, 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 in the Times Table App project pass.
6258

63-
![build_1](https://user-images.githubusercontent.com/48831250/94481160-4db6f680-01a5-11eb-83eb-75027a009321.png)
59+
![build_1](https://user-images.githubusercontent.com/48831250/105084788-dca59280-5a64-11eb-858d-664a5727a947.png)
6460

65-
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.
61+
Navigate to the project workspace by clicking the **Workspace** icon in the project interface. In this example, the generated artifacts are in the `matlabTestArtifacts` folder of the workspace.
6662

67-
![workspace](https://user-images.githubusercontent.com/48831250/94481319-88209380-01a5-11eb-8681-440ea84b59d9.png)
63+
![workspace](https://user-images.githubusercontent.com/48831250/105085419-b46a6380-5a65-11eb-8d46-747dd23291bf.png)
6864

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

71-
![cobertura_report](https://user-images.githubusercontent.com/48831250/94481556-e2b9ef80-01a5-11eb-86f2-1679ae63f407.png)
67+
![cobertura_report](https://user-images.githubusercontent.com/48831250/105085331-9ac91c00-5a65-11eb-9628-efbf70520489.png)
7268

7369
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.
7470

75-
![junit_report](https://user-images.githubusercontent.com/48831250/94481735-33c9e380-01a6-11eb-9106-d96cfd7676ae.png)
71+
![junit_report](https://user-images.githubusercontent.com/48831250/105088211-956dd080-5a69-11eb-931c-aef201eb9dbe.png)
7672

7773
## See Also
7874
[MathWorks Blogs: Developer Zone – Continuous Integration](https://blogs.mathworks.com/developer/category/continuous-integration/)<br/>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.mathworks.ci;
2+
3+
/**
4+
* Copyright 2020 The MathWorks, Inc.
5+
*
6+
* Class to parse Stapler request for Use MATLAB Version build wrapper.
7+
*
8+
*/
9+
10+
import org.kohsuke.stapler.DataBoundConstructor;
11+
12+
public class MatlabBuildWrapperContent {
13+
14+
private final String matlabInstallationName;
15+
private final String matlabRootFolder;
16+
17+
@DataBoundConstructor
18+
public MatlabBuildWrapperContent(String matlabInstallationName, String matlabRootFolder){
19+
this.matlabInstallationName = matlabInstallationName;
20+
this.matlabRootFolder = matlabRootFolder;
21+
}
22+
23+
public String getMatlabInstallationName() {
24+
return matlabInstallationName;
25+
}
26+
27+
public String getMatlabRootFolder() {
28+
return matlabRootFolder;
29+
}
30+
}

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

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
package com.mathworks.ci;
22

3+
/**
4+
* Copyright 2020 The MathWorks, Inc.
5+
*
6+
* Describable class for adding MATLAB installations in Jenkins Global Tool configuration.
7+
*
8+
*/
9+
310
import hudson.CopyOnWrite;
411
import hudson.EnvVars;
512
import hudson.Extension;
@@ -15,6 +22,9 @@
1522
import java.util.Arrays;
1623
import java.util.List;
1724
import javax.annotation.CheckForNull;
25+
import javax.annotation.Nonnull;
26+
27+
import jenkins.model.Jenkins;
1828
import net.sf.json.JSONObject;
1929
import org.jenkinsci.Symbol;
2030
import org.kohsuke.stapler.DataBoundConstructor;
@@ -28,12 +38,20 @@ public MatlabInstallation(String name, @CheckForNull String home, List<? extends
2838
super(Util.fixEmptyAndTrim(name), Util.fixEmptyAndTrim(home), properties);
2939
}
3040

41+
/*
42+
* Constructor for Custom object
43+
* */
44+
45+
public MatlabInstallation(String name){
46+
super(name, null, null);
47+
}
48+
3149
@Override public MatlabInstallation forEnvironment(EnvVars envVars) {
3250
return new MatlabInstallation(getName(), envVars.expand(getHome()), getProperties().toList());
3351
}
3452

3553
@Override
36-
public MatlabInstallation forNode(Node node, TaskListener log) throws IOException, InterruptedException {
54+
public MatlabInstallation forNode(@Nonnull Node node, TaskListener log) throws IOException, InterruptedException {
3755
return new MatlabInstallation(getName(), translateFor(node, log), getProperties().toList());
3856
}
3957

@@ -43,6 +61,23 @@ public void buildEnvVars(EnvVars env) {
4361
env.put("PATH+matlabroot", pathToExecutable);
4462
}
4563

64+
public static MatlabInstallation[] getAll () {
65+
return Jenkins.get().getDescriptorByType(DescriptorImpl.class).getInstallations();
66+
}
67+
68+
public static boolean isEmpty() {
69+
return getAll().length == 0;
70+
}
71+
72+
public static MatlabInstallation getInstallation(String name) {
73+
for (MatlabInstallation inst : getAll()) {
74+
if (name.equals(inst.getName())) {
75+
return inst;
76+
}
77+
}
78+
return null;
79+
}
80+
4681
@Extension @Symbol("matlab")
4782
public static class DescriptorImpl extends ToolDescriptor<MatlabInstallation> {
4883
@CopyOnWrite
@@ -71,7 +106,5 @@ public void setInstallations(MatlabInstallation... matlabInstallations) {
71106
this.installations = matlabInstallations;
72107
save();
73108
}
74-
75109
}
76-
77110
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.mathworks.ci;
2+
3+
/**
4+
* Copyright 2020 The MathWorks, Inc.
5+
*
6+
* Describable class for MATLAB Axis that provides a list of configured MATLAB installation for
7+
* generating matrix configurations.
8+
*
9+
*/
10+
11+
import hudson.Extension;
12+
import hudson.matrix.Axis;
13+
import hudson.matrix.AxisDescriptor;
14+
import hudson.matrix.MatrixProject;
15+
import org.kohsuke.stapler.DataBoundConstructor;
16+
17+
import java.util.ArrayList;
18+
import java.util.Arrays;
19+
import java.util.List;
20+
21+
public class MatlabInstallationAxis extends Axis {
22+
23+
@DataBoundConstructor
24+
public MatlabInstallationAxis(List<String> values) {
25+
super(Message.getValue("Axis.matlab.key"), evaluateValues(values));
26+
}
27+
28+
static private List<String> evaluateValues(List<String> values) {
29+
// Add default configuration is values are null or not selected.
30+
if (values == null || values.isEmpty()) {
31+
values = new ArrayList<>(Arrays.asList("default"));
32+
}
33+
return values;
34+
}
35+
36+
@Extension
37+
public static class DescriptorImpl extends AxisDescriptor{
38+
39+
@Override
40+
public String getDisplayName() {
41+
return Message.getValue("Axis.matlab.key");
42+
}
43+
44+
@Override
45+
public boolean isInstantiable() {
46+
return !isMatlabInstallationEmpty();
47+
}
48+
49+
public boolean checkUseMatlabVersion(Object it) {
50+
return MatlabItemListener.getMatlabBuildWrapperCheckForPrj(((MatrixProject) it).getFullName()) && !isMatlabInstallationEmpty();
51+
}
52+
53+
public MatlabInstallation[] getInstallations () {
54+
return MatlabInstallation.getAll();
55+
}
56+
57+
public String getUseMatlabWarning() {
58+
return Message.getValue("Axis.use.matlab.warning");
59+
}
60+
61+
public boolean isMatlabInstallationEmpty() {
62+
return MatlabInstallation.isEmpty();
63+
}
64+
65+
public String getNoInstallationError() {
66+
return Message.getValue("Axis.no.installed.matlab.error");
67+
}
68+
}
69+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.mathworks.ci;
2+
3+
/**
4+
* Copyright 2020 The MathWorks, Inc.
5+
*
6+
* Item listener class to provide functionality to check UI element states for a
7+
* Multi-configuration project.
8+
*
9+
*/
10+
11+
import hudson.Extension;
12+
import hudson.matrix.MatrixConfiguration;
13+
import hudson.matrix.MatrixProject;
14+
import hudson.model.Item;
15+
import hudson.model.TopLevelItem;
16+
import hudson.model.listeners.ItemListener;
17+
import jenkins.model.Jenkins;
18+
19+
import java.util.Collection;
20+
import java.util.HashMap;
21+
import java.util.List;
22+
import java.util.Map;
23+
24+
@Extension
25+
public final class MatlabItemListener extends ItemListener {
26+
private static final Map<String, Boolean> prjCheckMatlabAxis = new HashMap<>();
27+
private static final Map<String, Boolean> prjCheckMatlabBuildWrapper = new HashMap<>();
28+
29+
@Override
30+
public void onLoaded(){
31+
checkItems(Jenkins.get().getItems());
32+
}
33+
34+
@Override
35+
public void onUpdated(Item item) {
36+
if(!(item instanceof MatrixProject)){
37+
return;
38+
}
39+
checkSingleItem(item);
40+
}
41+
42+
43+
private void checkItems(List<TopLevelItem> items) {
44+
for(TopLevelItem item : items){
45+
if(item instanceof MatrixProject){
46+
check((MatrixProject) item);
47+
}
48+
}
49+
}
50+
51+
private void checkSingleItem(Item item){
52+
check((MatrixProject) item);
53+
}
54+
55+
private void check(MatrixProject prj) {
56+
checkForAxis(prj);
57+
checkForBuildWrapper(prj);
58+
}
59+
60+
private void checkForAxis(MatrixProject prj) {
61+
boolean checkForAxis = false;
62+
Collection<MatrixConfiguration> configurations = prj.getActiveConfigurations();
63+
for(MatrixConfiguration conf : configurations){
64+
String matlabAxisValue = conf.getCombination().get(Message.getValue("Axis.matlab.key"));
65+
if (matlabAxisValue != null) {
66+
checkForAxis = true;
67+
break;
68+
}
69+
}
70+
prjCheckMatlabAxis.put(prj.getFullName(), checkForAxis);
71+
}
72+
73+
private void checkForBuildWrapper(MatrixProject prj) {
74+
boolean checkForBuildWrapper = false;
75+
for(Object bWrapper : prj.getBuildWrappersList().toArray()) {
76+
if(bWrapper instanceof UseMatlabVersionBuildWrapper){
77+
checkForBuildWrapper = ((UseMatlabVersionBuildWrapper) bWrapper).getMatlabInstallationName() != null;
78+
break;
79+
}
80+
}
81+
prjCheckMatlabBuildWrapper.put(prj.getFullName(), checkForBuildWrapper);
82+
}
83+
84+
public static boolean getMatlabAxisCheckForPrj(String prjName) {
85+
return prjCheckMatlabAxis.get(prjName) != null && prjCheckMatlabAxis.get(prjName);
86+
}
87+
88+
public static boolean getMatlabBuildWrapperCheckForPrj(String prjName) {
89+
return prjCheckMatlabBuildWrapper.get(prjName) != null && prjCheckMatlabBuildWrapper.get(prjName);
90+
}
91+
}

0 commit comments

Comments
 (0)