From f40f2e26802c1336d427832b39f4872958de956b Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 20 Feb 2024 22:19:33 +0530 Subject: [PATCH 01/52] Fixed 289 as per comment --- .../com/mathworks/ci/BuildArtifactAction/summary.jelly | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly index 20599d5a..04fc4751 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly @@ -7,10 +7,8 @@ xmlns:i="jelly:fmt">

MATLAB Build Result

-

Total task ran: ${it.totalCount}

- +

Task run: ${it.totalCount}

+

Failed: ${it.failCount}

+

Skipped: ${it.skipCount}

\ No newline at end of file From 5351a75eeb3550fcdb8927b088cdf11f1e5654e3 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 20 Feb 2024 22:27:22 +0530 Subject: [PATCH 02/52] Fixed error message issue 288 --- .../com/mathworks/ci/BuildArtifactAction/summary.jelly | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly index 04fc4751..5624984d 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly @@ -7,6 +7,11 @@ xmlns:i="jelly:fmt">

MATLAB Build Result

+ + +
Unable to run a MATLAB build.
+
+

Task run: ${it.totalCount}

Failed: ${it.failCount}

Skipped: ${it.skipCount}

From 2203ba66c9a06b67936d182c6dddf6ed810b181f Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Wed, 21 Feb 2024 10:46:10 +0530 Subject: [PATCH 03/52] Fixed 289 --- .../com/mathworks/ci/BuildArtifactAction/summary.jelly | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly index 5624984d..2bd6d551 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly @@ -12,8 +12,12 @@
Unable to run a MATLAB build.
-

Task run: ${it.totalCount}

-

Failed: ${it.failCount}

-

Skipped: ${it.skipCount}

+

Tasks run: ${it.totalCount}

+
+ Failed: ${it.failCount} +
+
+ Skipped: ${it.skipCount} +
\ No newline at end of file From 26f423a3ddc4937b749a632dc8166460c4af9910 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:49:27 +0530 Subject: [PATCH 04/52] 2.11.2 snapshot qualification (#296) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 --- pom.xml | 2 +- .../com/mathworks/ci/BuildTargetNote.java | 1 + .../+ciplugins/+jenkins/BuildReportPlugin.m | 2 +- .../ci/BuildArtifactAction/index.jelly | 4 ++-- .../ci/BuildArtifactAction/summary.jelly | 19 +++++++++++++------ 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index dfd69040..83868f62 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ matlab - 2.11.2-SNAPSHOT + 2.12.1-SNAPSHOT hpi diff --git a/src/main/java/com/mathworks/ci/BuildTargetNote.java b/src/main/java/com/mathworks/ci/BuildTargetNote.java index 0367df4a..51ec6137 100644 --- a/src/main/java/com/mathworks/ci/BuildTargetNote.java +++ b/src/main/java/com/mathworks/ci/BuildTargetNote.java @@ -22,6 +22,7 @@ public BuildTargetNote() { public ConsoleAnnotator annotate(Object context, MarkupText text, int charPos) { MarkupText.SubText t = text.findToken(Pattern.compile("MATLAB-Build-")); String taskName = text.subText(13, text.length()-2).getText(); + taskName = taskName.replace("]","").trim(); if (t != null) t.addMarkup(0, t.length()-1, "", ""); return null; diff --git a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m index 5825b614..ccdfbd94 100644 --- a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m +++ b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m @@ -6,7 +6,7 @@ function runTaskGraph(plugin, pluginData) runTaskGraph@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData); - fID = fopen('.matlab/buildArtifact.json', 'w'); + fID = fopen(fullfile(getenv("WORKSPACE"),'.matlab/buildArtifact.json'), 'w'); taskDetails = struct(); for idx = 1:numel(pluginData.TaskResults) taskDetails(idx).name = pluginData.TaskResults(idx).Name; diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly index 9942cdfc..c8cf845c 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly @@ -59,12 +59,12 @@ - ${p.taskName} + ${p.taskName} - FAILED + FAILED diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly index d98e839f..2bd6d551 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly @@ -6,11 +6,18 @@ xmlns:f="/lib/form" xmlns:i="jelly:fmt"> -

MATLAB Build Results

-

This build report includes ${it.totalCount} tasks.

-
    -
  1. Number of failed tasks: ${it.failCount}

  2. -
  3. Number of skipped tasks: ${it.skipCount}

  4. -
+

MATLAB Build Result

+ + +
Unable to run a MATLAB build.
+
+
+

Tasks run: ${it.totalCount}

+
+ Failed: ${it.failCount} +
+
+ Skipped: ${it.skipCount} +
\ No newline at end of file From 1341a92adfdbde2fa16c1dc4af735db91c70247c Mon Sep 17 00:00:00 2001 From: Tushar Sharma <150027500+tsharmaMW@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:38:57 +0530 Subject: [PATCH 05/52] Add build options (#294) * add build options * update gitignore * add tests for build options * add fixes and more tests * fix tests * modify help text * fix help text * minor text fix * fix null error and formatting * remove buildOptions check from EnvVarSupport test * add env variables support for build options and formatting fixes * minor fixes --- .gitignore | 2 +- .../java/com/mathworks/ci/BuildOptions.java | 31 +++++++++++++++++++ .../ci/MatlabBuildStepExecution.java | 16 ++++++---- .../mathworks/ci/RunMatlabBuildBuilder.java | 15 +++++++++ .../com/mathworks/ci/RunMatlabBuildStep.java | 12 ++++++- .../mathworks/ci/BuildOptions/config.jelly | 6 ++++ .../ci/RunMatlabBuildBuilder/config.jelly | 2 ++ .../help-buildOptions.html | 6 ++++ .../help-startupOptions.html | 9 ++++-- .../ci/RunMatlabBuildStep/config.jelly | 8 +++-- .../RunMatlabBuildStep/help-buildOptions.html | 6 ++++ .../help-startupOptions.html | 6 +++- .../ci/RunMatlabBuildBuilderTest.java | 18 +++++++++++ .../mathworks/ci/RunMatlabBuildStepTest.java | 12 +++++++ 14 files changed, 136 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/mathworks/ci/BuildOptions.java create mode 100644 src/main/resources/com/mathworks/ci/BuildOptions/config.jelly create mode 100644 src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html create mode 100644 src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html diff --git a/.gitignore b/.gitignore index d6f71020..22535b44 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ work # Binaries and downloaded resources src/main/resources/matlab-script-generator.zip -src/main/resources/run_matlab_command.* +src/main/resources/**/run-matlab-command* src/main/resources/license.txt **/.DS_Store \ No newline at end of file diff --git a/src/main/java/com/mathworks/ci/BuildOptions.java b/src/main/java/com/mathworks/ci/BuildOptions.java new file mode 100644 index 00000000..39f1c290 --- /dev/null +++ b/src/main/java/com/mathworks/ci/BuildOptions.java @@ -0,0 +1,31 @@ + +package com.mathworks.ci; + +/** + * Copyright 2024 The MathWorks, Inc. + * + * Describable class for Build Options. + * + */ + +import hudson.Extension; +import hudson.Util; +import hudson.model.AbstractDescribableImpl; +import hudson.model.Descriptor; +import org.kohsuke.stapler.DataBoundConstructor; + +public class BuildOptions extends AbstractDescribableImpl { + + private String options; + + @DataBoundConstructor + public BuildOptions(String options) { + this.options = Util.fixNull(options); + } + + public String getOptions() { + return this.options; + } + + @Extension public static class DescriptorImpl extends Descriptor {} +} diff --git a/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java b/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java index 7f587321..c98deb64 100644 --- a/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java +++ b/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java @@ -25,18 +25,16 @@ public class MatlabBuildStepExecution extends SynchronousNonBlockingStepExecutio private String tasks; private String startupOptions; + private String buildOptions; private static String DEFAULT_PLUGIN = "+ciplugins/+jenkins/getDefaultPlugins.m"; private static String BUILD_REPORT_PLUGIN = "+ciplugins/+jenkins/BuildReportPlugin.m"; private static String TASK_RUN_PROGRESS_PLUGIN = "+ciplugins/+jenkins/TaskRunProgressPlugin.m"; - public MatlabBuildStepExecution(StepContext context, String tasks, String startupOptions) { + public MatlabBuildStepExecution(StepContext context, String tasks, String startupOptions, String buildOptions) { super(context); this.tasks = tasks; this.startupOptions = startupOptions; - } - - private String getTasks() { - return this.tasks; + this.buildOptions = buildOptions; } @Override @@ -113,7 +111,8 @@ private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqu // Create a new command runner script in the temp folder. final FilePath matlabBuildFile = new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); - final String tasks = getContext().get(EnvVars.class).expand(getTasks()); + final String tasks = getContext().get(EnvVars.class).expand(this.tasks); + final String buildOptions = getContext().get(EnvVars.class).expand(this.buildOptions); // Set ENV variable to override the default plugin list envVars.put("MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE", "ciplugins.jenkins.getDefaultPlugins"); @@ -122,6 +121,11 @@ private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqu if (!tasks.trim().isEmpty()) { cmd += " " + tasks; } + + if (!buildOptions.trim().isEmpty()) { + cmd += " " + buildOptions; + } + final String matlabBuildFileContent = "addpath(pwd);cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; diff --git a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java b/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java index 58bb773d..b09ebf4b 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java +++ b/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java @@ -32,6 +32,7 @@ public class RunMatlabBuildBuilder extends Builder implements SimpleBuildStep, M private int buildResult; private String tasks; private StartupOptions startupOptions; + private BuildOptions buildOptions; private static String DEFAULT_PLUGIN = "+ciplugins/+jenkins/getDefaultPlugins.m"; private static String BUILD_REPORT_PLUGIN = "+ciplugins/+jenkins/BuildReportPlugin.m"; private static String TASK_RUN_PROGRESS_PLUGIN = "+ciplugins/+jenkins/TaskRunProgressPlugin.m"; @@ -50,6 +51,11 @@ public void setStartupOptions(StartupOptions startupOptions) { this.startupOptions = startupOptions; } + @DataBoundSetter + public void setBuildOptions (BuildOptions buildOptions) { + this.buildOptions = buildOptions; + } + public String getTasks() { return this.tasks; } @@ -57,6 +63,10 @@ public String getTasks() { public StartupOptions getStartupOptions() { return this.startupOptions; } + + public BuildOptions getBuildOptions() { + return this.buildOptions; + } @Extension public static class RunMatlabBuildDescriptor extends BuildStepDescriptor { @@ -165,6 +175,7 @@ private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqu final FilePath matlabCommandFile = new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); final String tasks = envVars.expand(getTasks()); + final String buildOptions = envVars.expand(getBuildOptions() == null ? "": getBuildOptions().getOptions()); // Set ENV variable to override the default plugin list envVars.put("MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE", "ciplugins.jenkins.getDefaultPlugins"); @@ -175,6 +186,10 @@ private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqu cmd += " " + tasks; } + if (!buildOptions.trim().isEmpty()) { + cmd += " " + buildOptions; + } + final String matlabCommandFileContent = "addpath(pwd);cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; diff --git a/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java b/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java index 2992ae58..091c993f 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java +++ b/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java @@ -25,6 +25,7 @@ public class RunMatlabBuildStep extends Step { private String tasks; private String startupOptions; + private String buildOptions; @DataBoundConstructor public RunMatlabBuildStep() { @@ -39,6 +40,10 @@ public String getStartupOptions() { return Util.fixNull(startupOptions); } + public String getBuildOptions() { + return Util.fixNull(buildOptions); + } + @DataBoundSetter public void setTasks(String tasks) { this.tasks = tasks; @@ -49,9 +54,14 @@ public void setStartupOptions(String startupOptions) { this.startupOptions = startupOptions; } + @DataBoundSetter + public void setBuildOptions (String buildOptions) { + this.buildOptions = buildOptions; + } + @Override public StepExecution start(StepContext context) throws Exception { - return new MatlabBuildStepExecution(context, getTasks(), getStartupOptions()); + return new MatlabBuildStepExecution(context, getTasks(), getStartupOptions(), getBuildOptions()); } @Extension diff --git a/src/main/resources/com/mathworks/ci/BuildOptions/config.jelly b/src/main/resources/com/mathworks/ci/BuildOptions/config.jelly new file mode 100644 index 00000000..c2716089 --- /dev/null +++ b/src/main/resources/com/mathworks/ci/BuildOptions/config.jelly @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly index b5e12dd2..3693ca23 100644 --- a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly @@ -6,5 +6,7 @@ + + diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html new file mode 100644 index 00000000..751d20ba --- /dev/null +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html @@ -0,0 +1,6 @@ +
+ Specify a space-separated list of MATLAB build options. The plugin supports + the build options that you can pass to the buildtool command.
+ Example: -continueOnFailure
+ Example: -continueOnFailure -skip test +
diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html index 033e04a2..98cde2a1 100644 --- a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html @@ -1,3 +1,8 @@
- A space-separated list of MATLAB startup options. -
+ Specify a space-separated list of MATLAB startup options.
+ Example: -nojvm
+ Example: -nojvm -logfile output.log +
 
+ Note: Specifying the -batch or -r option is not supported. + + \ No newline at end of file diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly index df600b40..4687525c 100644 --- a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly @@ -1,11 +1,15 @@ - + - + + + + + diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html new file mode 100644 index 00000000..751d20ba --- /dev/null +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html @@ -0,0 +1,6 @@ +
+ Specify a space-separated list of MATLAB build options. The plugin supports + the build options that you can pass to the buildtool command.
+ Example: -continueOnFailure
+ Example: -continueOnFailure -skip test +
diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html index 033e04a2..d450f39a 100644 --- a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html @@ -1,3 +1,7 @@
- A space-separated list of MATLAB startup options. + Specify a space-separated list of MATLAB startup options.
+ Example: -nojvm
+ Example: -nojvm -logfile output.log +
 
+ Note: Specifying the -batch or -r option is not supported.
diff --git a/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java b/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java index ee9b0491..72f57c36 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java +++ b/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java @@ -222,6 +222,21 @@ public void verifyBuildPicksTheCorrectStartupOptions() throws Exception { jenkins.assertLogContains("-nojvm -uniqueoption", build); } + /* + * Test to verify builder correctly sets build options that user entered. + */ + @Test + public void verifyBuildPicksTheCorrectBuildOptions() throws Exception { + this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); + project.getBuildWrappersList().add(this.buildWrapper); + scriptBuilder.setTasks(""); + scriptBuilder.setBuildOptions(new BuildOptions("-continueOnFailure -skip compile")); + project.getBuildersList().add(this.scriptBuilder); + FreeStyleBuild build = project.scheduleBuild2(0).get(); + jenkins.assertLogContains("Generating MATLAB script with content", build); + jenkins.assertLogContains("-continueOnFailure -skip compile", build); + } + /* * Test to verify if MATLAB scratch file is not generated in workspace for this builder. */ @@ -244,13 +259,16 @@ public void verifyBuildSupportsEnvVar() throws Exception { EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); EnvVars var = prop.getEnvVars(); var.put("TASKS", "compile"); + var.put("BUILD_OPTIONS", "-continueOnFailure -skip test"); jenkins.jenkins.getGlobalNodeProperties().add(prop); this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); project.getBuildWrappersList().add(this.buildWrapper); scriptBuilder.setTasks("$TASKS"); + scriptBuilder.setBuildOptions(new BuildOptions("$BUILD_OPTIONS")); project.getBuildersList().add(scriptBuilder); FreeStyleBuild build = project.scheduleBuild2(0).get(); jenkins.assertLogContains("compile", build); + jenkins.assertLogContains("-continueOnFailure -skip test", build); } /* diff --git a/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java b/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java index bd4ea2b3..bab80f74 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java +++ b/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java @@ -123,6 +123,18 @@ public void verifyStartupOptionsSameAsScript() throws Exception { j.assertLogContains("-nojvm -uniqueoption", build); } + /* + * Verify appropriate build options are invoked as in pipeline script + */ + @Test + public void verifyBuildOptionsSameAsScript() throws Exception { + project.setDefinition( + new CpsFlowDefinition("node { runMATLABBuild(buildOptions: '-continueOnFailure -skip compile') }", true)); + + WorkflowRun build = project.scheduleBuild2(0).get(); + j.assertLogContains("-continueOnFailure -skip compile", build); + } + /* * Verify script can run Matrix build */ From 748d709861c0bb4f35b880bb639dd39d2f47c77d Mon Sep 17 00:00:00 2001 From: mw-hrastega <48831250+mw-hrastega@users.noreply.github.com> Date: Wed, 13 Mar 2024 09:02:49 -0400 Subject: [PATCH 06/52] documenting MATLAB build options and MATLAB build result --- CONFIGDOC.md | 101 +++++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 48 deletions(-) diff --git a/CONFIGDOC.md b/CONFIGDOC.md index 7feb261f..129b653d 100644 --- a/CONFIGDOC.md +++ b/CONFIGDOC.md @@ -33,7 +33,7 @@ In this example, the list includes two registered tools as well as the option fo ![use_matlab_version_tool](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/1ef811c5-c69a-41c3-8649-55c5f2239776) -When you specify a MATLAB version in the **Build Environment** section, the plugin prepends its `bin` folder to the system PATH environment variable of the build agent and invokes it to perform the build. If the build agent already has your preferred MATLAB version on the path, then you are not required to select **Use MATLAB version**. In this case, the plugin uses the topmost MATLAB version on the system path. The build fails if the operating system cannot find MATLAB on the path. +When you specify a MATLAB version in the **Build Environment** section, the plugin prepends its `bin` folder to the `PATH` system environment variable of the build agent and invokes it to perform the build. If the build agent already has your preferred MATLAB version on the path, then you are not required to select **Use MATLAB version**. In this case, the plugin uses the topmost MATLAB version on the system path. The build fails if the operating system cannot find MATLAB on the path. You can use the [`matlabroot`](https://www.mathworks.com/help/matlab/ref/matlabroot.html) function to return the full path to your preferred MATLAB root folder. The path depends on the platform, MATLAB version, and installation location. This table shows examples of the root folder path on different platforms. @@ -46,31 +46,35 @@ You can use the [`matlabroot`](https://www.mathworks.com/help/matlab/ref/matlabr ### Specify Build Steps When you set up the **Build Steps** section of the project configuration window, the plugin provides you with three build steps: -* To run a MATLAB build, use the [Run MATLAB Build](#run-matlab-build) step. +* To run a MATLAB build using the MATLAB build tool, use the [Run MATLAB Build](#run-matlab-build) step. * To run MATLAB and Simulink tests and generate artifacts, use the [Run MATLAB Tests](#run-matlab-tests) step. -* To run a MATLAB script, function, or statement, use the [Run MATLAB Command](#run-matlab-command) step. +* To run MATLAB scripts, functions, and statements, use the [Run MATLAB Command](#run-matlab-command) step. -You can specify optional MATLAB startup options for a step by first selecting **Startup options** and then populating the box that appears in the step configuration interface. For example, specify `-nojvm` to start MATLAB without the JVM™ software. If you specify more than one startup option, use a space to separate them (for example, `-nojvm -logfile "output.log"`). For more information about MATLAB startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html). +You can specify MATLAB startup options for a step by first selecting **Startup options** and then populating the box that appears in the step configuration interface. For example, specify `-nojvm` to start MATLAB without the JVM™ software. If you specify more than one startup option, use a space to separate them (for example, `-nojvm -logfile output.log`). For more information about MATLAB startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html). > :information_source: **Note:** Selecting **Startup options** to specify the `-batch` or `-r` option is not supported. If you use a source code management (SCM) system such as Git™, then your project should include the appropriate SCM configuration to check out the code before it can invoke the plugin. If you do not use any SCM systems to manage your code, then an additional build step might be required to ensure that the code is available in the project workspace before the build starts. +> :information_source: **Note:** By default, when you use the **Run MATLAB Build**, **Run MATLAB Tests**, or **Run MATLAB Command** step, the root of your repository serves as the MATLAB startup folder. To run your MATLAB code using a different folder, specify the `-sd` startup option or include the `cd` command when using the **Run MATLAB Command** step. + #### Run MATLAB Build The **Run MATLAB Build** step lets you run a build using the [MATLAB build tool](https://www.mathworks.com/help/matlab/matlab_prog/overview-of-matlab-build-tool.html). You can use this step to run the tasks specified in a file named `buildfile.m` in the root of your repository. To use the **Run MATLAB Build** step, you need MATLAB R2022b or a later release. Specify the tasks you want to execute in the **Tasks** box. If you specify more than one task, use a space to separate them. If you do not specify any tasks, the plugin runs the default tasks in `buildfile.m` as well as all the tasks on which they depend. For example, enter `mytask` in the **Tasks** box to run a task named `mytask` as well as all the tasks on which it depends. -![run_matlab_build](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/b0df3645-e8df-48fe-8dd3-e429706dd61c) +run_matlab_build + +You can specify build options for your MATLAB build by first selecting **Build options** and then populating the box that appears in the step configuration interface. For example, specify `-continueOnFailure` to continue running the MATLAB build upon a build environment setup or task failure. If you specify more than one build option, use a space to separate them (for example, `-continueOnFailure -skip test`). The plugin supports the same [options](https://www.mathworks.com/help/matlab/ref/buildtool.html#mw_50c0f35e-93df-4579-963d-f59f2fba1dba) that you can pass to the `buildtool` command. -MATLAB exits with exit code 0 if the specified tasks run without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the Jenkins build to fail. +MATLAB exits with exit code 0 if the specified tasks run without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail. -When you use this step, a file named `buildfile.m` must be in the root of your repository. For more information about the build tool, see [Create and Run Tasks Using Build Tool](https://www.mathworks.com/help/matlab/matlab_prog/create-and-run-tasks-using-build-tool.html). +You can access the result of running a MATLAB build interactively in your Jenkins interface. After your build runs, the Jenkins build summary page displays the number of tasks that ran, failed, and were skipped. If your build ran successfully, you can click the **MATLAB Build Result** link on the page to access the table of task results. This table provides information about each task that was part of the MATLAB build. Clicking a task name in the table displays relevant build log information on the **Console Output** page. #### Run MATLAB Tests The **Run MATLAB Tests** build step lets you run MATLAB and Simulink tests and generate artifacts, such as test results in JUnit-style XML format and code coverage results in Cobertura XML format. By default, the plugin includes any test files in your [MATLAB project](https://www.mathworks.com/help/matlab/projects.html) that have a `Test` label. If your build does not use a MATLAB project, or if it uses a MATLAB release before R2019a, then the plugin includes all tests in the root of your repository and in any of its subfolders. -You can customize the **Run MATLAB Tests** build step in the step configuration interface. For example, you can add source folders to the MATLAB search path, control which tests to run, and generate various test and coverage artifacts. If you do not select any of the existing options, all the tests in your project run, and any test failure causes the build to fail. +You can customize the **Run MATLAB Tests** build step in the step configuration interface. For example, you can add source folders to the MATLAB search path, control which tests to run, and generate test and coverage artifacts. If you do not select any of the existing options, all the tests in your project run, and any test failure causes the step to fail. Select **Source folder** if you want to specify the location of a folder containing source code, relative to the project root folder. The plugin adds the specified folder and its subfolders to the top of the MATLAB search path. If you specify a source folder and then generate coverage results, the plugin uses only the source code in the specified folder and its subfolders to generate the results. You can specify more than one folder by clicking **Add folder**. @@ -96,7 +100,7 @@ To generate test and coverage artifacts, select options in the **Generate Test A ![run_matlab_tests_artifacts](https://user-images.githubusercontent.com/48831250/217651806-1c8a6e9a-13a8-4d05-819b-e97533cc7bae.png) -The **Run MATLAB Tests** build step produces a MATLAB script file and uses it to run the tests and generate the artifacts. The plugin writes the contents of this file to the build log. You can review the build log in **Console Output** to understand the testing workflow. +The **Run MATLAB Tests** build step produces a MATLAB script file and uses it to run the tests and generate the artifacts. The plugin writes the contents of this file to the build log. You can review the build log on the **Console Output** page to understand the testing workflow. Artifacts that the plugin generates are subject to these restrictions: * Producing a PDF test report on macOS platforms is supported in MATLAB R2020b and later. @@ -110,9 +114,9 @@ Specify the MATLAB script, function, or statement you want to execute in the **C For example, enter `myscript` in the **Command** box to run a script named `myscript.m` in the root of your repository. -![run_matlab_command](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/45a99722-d872-403b-8c1a-90e23199ba47) +run_matlab_command -MATLAB exits with exit code 0 if the specified script, function, or statement executes without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the Jenkins build to fail. To fail the build in certain conditions, use the [`assert`](https://www.mathworks.com/help/matlab/ref/assert.html) or [`error`](https://www.mathworks.com/help/matlab/ref/error.html) function. +MATLAB exits with exit code 0 if the specified script, function, or statement executes without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail. To fail the step in certain conditions, use the [`assert`](https://www.mathworks.com/help/matlab/ref/assert.html) or [`error`](https://www.mathworks.com/help/matlab/ref/error.html) function. When you use this step, all the required files must be on the MATLAB search path. If your script or function is not in the root of your repository, you can use the [`addpath`](https://www.mathworks.com/help/matlab/ref/addpath.html), [`cd`](https://www.mathworks.com/help/matlab/ref/cd.html), or [`run`](https://www.mathworks.com/help/matlab/ref/run.html) function to ensure that it is on the path when invoked. For example, to run `myscript.m` in a folder named `myfolder` located in the root of the repository, you can specify the contents of the **Command** box like this: @@ -126,9 +130,9 @@ To specify the MATLAB version, select **Use MATLAB version** in the **Build Envi ![build_environment](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/6fa3187a-5674-4435-9c69-4210a21b8d88) To run MATLAB code and Simulink models, specify the appropriate build steps in the **Build Steps** section: -* If you add the [**Run MATLAB Build**](#run-matlab-build) step, specify your MATLAB build tasks in the **Tasks** box. -* If you add the [**Run MATLAB Tests**](#run-matlab-tests) step, specify your source code, test suite filters, run customization options, and test and coverage artifacts to be generated in the project workspace. -* If you add the [**Run MATLAB Command**](#run-matlab-command) step, specify your MATLAB script, function, or statement in the **Command** box. +* If you add the [**Run MATLAB Build**](#run-matlab-build) step, specify your MATLAB build tasks and options. +* If you add the [**Run MATLAB Tests**](#run-matlab-tests) step, specify your source code, test suite filters, run customization options, and test and coverage artifacts to generate. +* If you add the [**Run MATLAB Command**](#run-matlab-command) step, specify your MATLAB script, function, or statement. ## Set Up Multi-Configuration Project @@ -143,7 +147,7 @@ There are two ways to specify multiple MATLAB versions in a multi-configuration ![add_axis](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/8d134ca1-892e-4014-98e3-14fd8fbb3024) ### Add MATLAB Axis -If your Jenkins instance includes MATLAB versions registered as tools, then **MATLAB** appears as an option when you click **Add axis** in the **Configuration Matrix** section. By adding the **MATLAB** axis, you can select MATLAB versions and add them as axis values to your matrix configuration. The list includes all MATLAB versions that have been registered as Jenkins tools. In this example, there are two MATLAB versions registered as tools. In each build iteration, the plugin prepends one of the selected versions to the PATH environment variable and invokes it to run the build. +If your Jenkins instance includes MATLAB versions registered as tools, then **MATLAB** appears as an option when you click **Add axis** in the **Configuration Matrix** section. By adding the **MATLAB** axis, you can select MATLAB versions and add them as axis values to your matrix configuration. The list includes all MATLAB versions that have been registered as Jenkins tools. In this example, there are two MATLAB versions registered as tools. In each build iteration, the plugin prepends one of the selected versions to the `PATH` environment variable and invokes it to run the build. ![matlab_axis](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/047283bb-782c-4437-af3b-ce296e73cf1a) @@ -170,9 +174,9 @@ You can add several axes in the **Configuration Matrix** section. For example, a Once you have specified the axes, add the required build steps in the **Build Steps** section: -* If you add the [**Run MATLAB Build**](#run-matlab-build) step, specify your MATLAB build tasks in the **Tasks** box. -* If you add the [**Run MATLAB Tests**](#run-matlab-tests) step, specify your source code, test suite filters, run customization options, and test and coverage artifacts to be generated in the project workspace. -* If you add the [**Run MATLAB Command**](#run-matlab-command) step, specify your MATLAB script, function, or statement in the **Command** box. You can use the user-defined axes to specify the contents of the **Command** box. For example: +* If you add the [**Run MATLAB Build**](#run-matlab-build) step, specify your MATLAB build tasks and options. +* If you add the [**Run MATLAB Tests**](#run-matlab-tests) step, specify your source code, test suite filters, run customization options, and test and coverage artifacts to generate. +* If you add the [**Run MATLAB Command**](#run-matlab-command) step, specify your MATLAB script, function, or statement. You can use the user-defined axes to specify the contents of the **Command** box. For example: ``` results = runtests(pwd,"Tag","$TEST_TAG"); assertSuccess(results); ``` @@ -180,9 +184,9 @@ Once you have specified the axes, add the required build steps in the **Build St ## Set Up Pipeline Project When you define your pipeline with a `Jenkinsfile`, the plugin provides you with three build steps: -* To run a MATLAB build, use the [`runMATLABBuild`](#use-the-runmatlabbuild-step) step. +* To run a MATLAB build using the MATLAB build tool, use the [`runMATLABBuild`](#use-the-runmatlabbuild-step) step. * To run MATLAB and Simulink tests and generate artifacts, use the [`runMATLABTests`](#use-the-runmatlabtests-step) step. -* To run a MATLAB script, function, or statement, use the [`runMATLABCommand`](#use-the-runmatlabcommand-step) step. +* To run MATLAB scripts, functions, and statements, use the [`runMATLABCommand`](#use-the-runmatlabcommand-step) step. To configure the plugin for a pipeline project: 1) Define your pipeline in a `Jenkinsfile` in the root of your repository. @@ -192,10 +196,12 @@ To configure the plugin for a pipeline project: You can also define your pipeline directly in the project configuration window. If you select `Pipeline script` from the **Definition** list, you can author your pipeline code in the **Script** box. When you define your pipeline this way, it must include an additional stage to check out your code from source control. +> :information_source: **Note:** By default, when you use the `runMATLABBuild`, `runMATLABTests`, or `runMATLABCommand` step, the root of your repository serves as the MATLAB startup folder. To run your MATLAB code using a different folder, specify the `-sd` startup option or include the `cd` command when using the `runMATLABCommand` step. + ### Add MATLAB to System Path -When the plugin executes steps that use MATLAB in your pipeline, the plugin uses the topmost MATLAB version on the system path. If the PATH environment variable of the build agent does not include any MATLAB versions, you must update the variable with the MATLAB root folder that should be used for the build. +When the plugin executes steps that use MATLAB in your pipeline, the plugin uses the topmost MATLAB version on the system path. If the `PATH` environment variable of the build agent does not include any MATLAB versions, you must update the variable with the MATLAB root folder that should be used for the build. -To update the system PATH environment variable using declarative pipeline syntax, use an `environment` block in your `Jenkinsfile`. For example, prepend MATLAB R2023b to the system PATH environment variable and use it to run your command. +To update the `PATH` environment variable using declarative pipeline syntax, use an `environment` block in your `Jenkinsfile`. For example, prepend MATLAB R2023b to the `PATH` environment variable and use it to run your command. ```groovy // Declarative Pipeline @@ -216,7 +222,7 @@ pipeline { } ``` -If you define your pipeline using scripted pipeline syntax, set the PATH environment variable in the `node` block. For example: +If you define your pipeline using scripted pipeline syntax, set the `PATH` environment variable in the `node` block. For example: ```groovy // Scripted Pipeline @@ -233,9 +239,9 @@ Use the `runMATLABBuild` step in your pipeline to run a build using the [MATLAB Input | Description ------------------------- | --------------- -`tasks` | (Optional) Tasks to execute. If you specify more than one task, use a space to separate them. If you specify the step without this input (for example, `runMATLABBuild()`), the plugin runs the default tasks in `buildfile.m` as well as all the tasks on which they depend.
MATLAB exits with exit code 0 if the tasks run without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the stage to fail.
**Example:** `tasks: 'test'`
**Example:** `tasks: 'compile test'` -`startupOptions` | (Optional) MATLAB startup options. If you specify more than one option, use a space to separate them. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).
Using this input to specify the `-batch` or `-r` option is not supported.
**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile "output.log"'` - +`tasks` |

(Optional) Tasks to run, specified as a list of task names separated by spaces. If you specify the step without this input (for example, `runMATLABBuild()`), the plugin runs the default tasks in `buildfile.m` as well as all the tasks on which they depend.

MATLAB exits with exit code 0 if the tasks run without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail.

**Example:** `tasks: 'test'`
**Example:** `tasks: 'compile test'`

+`buildOptions` |

(Optional) MATLAB build options, specified as a list of options separated by spaces. The plugin supports the same [options](https://www.mathworks.com/help/matlab/ref/buildtool.html#mw_50c0f35e-93df-4579-963d-f59f2fba1dba) that you can pass to the `buildtool` command.

**Example:** `buildOptions: '-continueOnFailure'`
**Example:** `buildOptions: '-continueOnFailure -skip test'`

+`startupOptions` |

(Optional) MATLAB startup options, specified as a list of options separated by spaces. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).

Using this input to specify the `-batch` or `-r` option is not supported.

**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile output.log'`

For example, in your `Jenkinsfile`, define a declarative pipeline to run a task named `mytask` as well as all the tasks on which it depends. @@ -262,11 +268,10 @@ node { } ``` -When you use this step, a file named `buildfile.m` must be in the root of your repository. For more information about the build tool, see [Create and Run Tasks Using Build Tool](https://www.mathworks.com/help/matlab/matlab_prog/create-and-run-tasks-using-build-tool.html). - +You can access the result of running a MATLAB build interactively in your Jenkins interface. After your build runs, the Jenkins build summary page displays the number of tasks that ran, failed, and were skipped. If your build ran successfully, you can click the **MATLAB Build Result** link on the page to access the table of task results. This table provides information about each task that was part of the MATLAB build. Clicking a task name in the table displays relevant build log information on the **Console Output** page. ### Use the `runMATLABTests` Step -Use the `runMATLABTests` step in your pipeline to run MATLAB and Simulink tests and generate various test and coverage artifacts. By default, the plugin includes any test files in your [MATLAB project](https://www.mathworks.com/help/matlab/projects.html) that have a `Test` label. If your pipeline does not use a MATLAB project, or if it uses a MATLAB release before R2019a, then the plugin includes all tests in the root of your repository and in any of its subfolders. +Use the `runMATLABTests` step in your pipeline to run MATLAB and Simulink tests and generate test and coverage artifacts. By default, the plugin includes any test files in your [MATLAB project](https://www.mathworks.com/help/matlab/projects.html) that have a `Test` label. If your pipeline does not use a MATLAB project, or if it uses a MATLAB release before R2019a, then the plugin includes all tests in the root of your repository and in any of its subfolders. For example, in your `Jenkinsfile`, define a declarative pipeline to run the tests in your project. @@ -294,26 +299,26 @@ node { } ``` -MATLAB exits with exit code 0 if the test suite runs without any failures. Otherwise, MATLAB terminates with a nonzero exit code, which causes the stage to fail. +MATLAB exits with exit code 0 if the test suite runs without any failures. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail. -You can customize the `runMATLABTests` step using optional inputs. For example, you can add source folders to the MATLAB search path, control which tests to run, and generate various artifacts. +You can customize the `runMATLABTests` step using optional inputs. For example, you can add source folders to the MATLAB search path, control which tests to run, and generate test and coverage artifacts. Input | Description ------------------------- | --------------- -`sourceFolder` | (Optional) Location of the folder containing source code, relative to the project root folder. The specified folder and its subfolders are added to the top of the MATLAB search path. If you specify `sourceFolder` and then generate coverage results, the plugin uses only the source code in the specified folder and its subfolders to generate the results. You can specify multiple folders using a comma-separated list.
**Example:** `sourceFolder: ['source']`
**Example:** `sourceFolder: ['source/folderA', 'source/folderB']` -`selectByFolder` | (Optional) Location of the folder used to select test suite elements, relative to the project root folder. To create a test suite, the plugin uses only the tests in the specified folder and its subfolders. You can specify multiple folders using a comma-separated list.
**Example:** `selectByFolder: ['test']`
**Example:** `selectByFolder: ['test/folderA', 'test/folderB']` -`selectByTag` | (Optional) Test tag used to select test suite elements. To create a test suite, the plugin uses only the test elements with the specified tag.
**Example:** `selectByTag: 'FeatureA'` -`strict` | (Optional) Option to apply strict checks when running tests, specified as `false` or `true`. By default, the value is `false`. If you specify a value of `true`, the plugin generates a qualification failure whenever a test issues a warning.
**Example:** `strict: true` -`useParallel` | (Optional) Option to run tests in parallel, specified as `false` or `true`. By default, the value is `false` and tests run in serial. If the test runner configuration is suited for parallelization, you can specify a value of `true` to run tests in parallel. This input requires a Parallel Computing Toolbox license.
**Example:** `useParallel: true` -`outputDetail` | (Optional) Amount of output detail displayed for the test run, specified as `'None'`, `'Terse'`, `'Concise'`, `'Detailed'`, or `'Verbose'`. By default, the plugin displays failing and logged events at the `Detailed` level and test run progress at the `Concise` level.
**Example:** `outputDetail: 'Verbose'` -`loggingLevel` | (Optional) Maximum verbosity level for logged diagnostics included for the test run, specified as `'None'`, `'Terse'`, `'Concise'`, `'Detailed'`, or `'Verbose'`. By default, the plugin includes diagnostics logged at the `Terse` level.
**Example:** `loggingLevel: 'Detailed'` -`testResultsPDF` | (Optional) Path to write the test results in PDF format. On macOS platforms, this input is supported in MATLAB R2020b and later.
**Example:** `testResultsPDF: 'test-results/results.pdf'` -`testResultsTAP` | (Optional) Path to write the test results in TAP format.
**Example:** `testResultsTAP: 'test-results/results.tap'` -`testResultsJUnit` | (Optional) Path to write the test results in JUnit-style XML format.
**Example:** `testResultsJUnit: 'test-results/results.xml'` -`testResultsSimulinkTest` | (Optional) Path to export Simulink Test Manager results in MLDATX format. This input requires a Simulink Test license and is supported in MATLAB R2019a and later.
**Example:** `testResultsSimulinkTest: 'test-results/results.mldatx'` -`codeCoverageCobertura` | (Optional) Path to write the code coverage results in Cobertura XML format.
**Example:** `codeCoverageCobertura: 'code-coverage/coverage.xml'` -`modelCoverageCobertura` | (Optional) Path to write the model coverage results in Cobertura XML format. This input requires a Simulink Coverage license and is supported in MATLAB R2018b and later.
**Example:** `modelCoverageCobertura: 'model-coverage/coverage.xml'` -`startupOptions` | (Optional) MATLAB startup options. If you specify more than one option, use a space to separate them. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).
Using this input to specify the `-batch` or `-r` option is not supported.
**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile "output.log"'` +`sourceFolder` |

(Optional) Location of the folder containing source code, relative to the project root folder. The specified folder and its subfolders are added to the top of the MATLAB search path. If you specify `sourceFolder` and then generate coverage results, the plugin uses only the source code in the specified folder and its subfolders to generate the results. You can specify multiple folders using a comma-separated list.

**Example:** `sourceFolder: ['source']`
**Example:** `sourceFolder: ['source/folderA', 'source/folderB']`

+`selectByFolder` |

(Optional) Location of the folder used to select test suite elements, relative to the project root folder. To create a test suite, the plugin uses only the tests in the specified folder and its subfolders. You can specify multiple folders using a comma-separated list.

**Example:** `selectByFolder: ['test']`
**Example:** `selectByFolder: ['test/folderA', 'test/folderB']`

+`selectByTag` |

(Optional) Test tag used to select test suite elements. To create a test suite, the plugin uses only the test elements with the specified tag.

**Example:** `selectByTag: 'FeatureA'`

+`strict` |

(Optional) Option to apply strict checks when running tests, specified as `false` or `true`. By default, the value is `false`. If you specify a value of `true`, the plugin generates a qualification failure whenever a test issues a warning.

**Example:** `strict: true`

+`useParallel` |

(Optional) Option to run tests in parallel, specified as `false` or `true`. By default, the value is `false` and tests run in serial. If the test runner configuration is suited for parallelization, you can specify a value of `true` to run tests in parallel. This input requires a Parallel Computing Toolbox license.

**Example:** `useParallel: true`

+`outputDetail` |

(Optional) Amount of output detail displayed for the test run, specified as `'None'`, `'Terse'`, `'Concise'`, `'Detailed'`, or `'Verbose'`. By default, the plugin displays failing and logged events at the `Detailed` level and test run progress at the `Concise` level.

**Example:** `outputDetail: 'Verbose'`

+`loggingLevel` |

(Optional) Maximum verbosity level for logged diagnostics included for the test run, specified as `'None'`, `'Terse'`, `'Concise'`, `'Detailed'`, or `'Verbose'`. By default, the plugin includes diagnostics logged at the `Terse` level.

**Example:** `loggingLevel: 'Detailed'`

+`testResultsPDF` |

(Optional) Path to write the test results in PDF format. On macOS platforms, this input is supported in MATLAB R2020b and later.

**Example:** `testResultsPDF: 'test-results/results.pdf'`

+`testResultsTAP` |

(Optional) Path to write the test results in TAP format.

**Example:** `testResultsTAP: 'test-results/results.tap'`

+`testResultsJUnit` |

(Optional) Path to write the test results in JUnit-style XML format.

**Example:** `testResultsJUnit: 'test-results/results.xml'`

+`testResultsSimulinkTest` |

(Optional) Path to export Simulink Test Manager results in MLDATX format. This input requires a Simulink Test license and is supported in MATLAB R2019a and later.

**Example:** `testResultsSimulinkTest: 'test-results/results.mldatx'`

+`codeCoverageCobertura` |

(Optional) Path to write the code coverage results in Cobertura XML format.

**Example:** `codeCoverageCobertura: 'code-coverage/coverage.xml'`

+`modelCoverageCobertura` |

(Optional) Path to write the model coverage results in Cobertura XML format. This input requires a Simulink Coverage license and is supported in MATLAB R2018b and later.

**Example:** `modelCoverageCobertura: 'model-coverage/coverage.xml'`

+`startupOptions` |

(Optional) MATLAB startup options, specified as a list of options separated by spaces. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).

Using this input to specify the `-batch` or `-r` option is not supported.

**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile output.log'`

For instance, define a declarative pipeline to run the tests in your MATLAB project, and then generate test results in JUnit-style XML format and code coverage results in Cobertura XML format at specified locations on the build agent. Generate the coverage results for only the code in the `source` folder in the root of your repository. @@ -350,8 +355,8 @@ Use the `runMATLABCommand` step in your pipeline to run MATLAB scripts, function Input | Description ------------------------- | --------------- -`command` | (Required) Script, function, or statement to execute. If the value of `command` is the name of a MATLAB script or function, do not specify the file extension. If you specify more than one script, function, or statement, use a comma or semicolon to separate them.
MATLAB exits with exit code 0 if the specified script, function, or statement executes without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the stage to fail. To fail the stage in certain conditions, use the [`assert`](https://www.mathworks.com/help/matlab/ref/assert.html) or [`error`](https://www.mathworks.com/help/matlab/ref/error.html) function.
**Example:** `command: 'myscript'`
**Example:** `command: 'results = runtests, assertSuccess(results);'` -`startupOptions` | (Optional) MATLAB startup options. If you specify more than one option, use a space to separate them. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).
Using this input to specify the `-batch` or `-r` option is not supported.
**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile "output.log"'` +`command` |

(Required) Script, function, or statement to execute. If the value of `command` is the name of a MATLAB script or function, do not specify the file extension. If you specify more than one script, function, or statement, use a comma or semicolon to separate them.

MATLAB exits with exit code 0 if the specified script, function, or statement executes without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail. To fail the step in certain conditions, use the [`assert`](https://www.mathworks.com/help/matlab/ref/assert.html) or [`error`](https://www.mathworks.com/help/matlab/ref/error.html) function.

**Example:** `command: 'myscript'`
**Example:** `command: 'results = runtests, assertSuccess(results);'`

+`startupOptions` |

(Optional) MATLAB startup options, specified as a list of options separated by spaces. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).

Using this input to specify the `-batch` or `-r` option is not supported.

**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile output.log'`

For example, in your `Jenkinsfile`, define a declarative pipeline to run a script named `myscript.m`. @@ -466,7 +471,7 @@ pipeline { } ``` -If you define your pipeline using scripted pipeline syntax, use the `tool` keyword followed by the name of the tool to retrieve the path to the MATLAB root folder. Then, prepend the MATLAB `bin` folder to the PATH environment variable. +If you define your pipeline using scripted pipeline syntax, use the `tool` keyword followed by the name of the tool to retrieve the path to the MATLAB root folder. Then, prepend the MATLAB `bin` folder to the `PATH` environment variable. ```groovy // Scripted Pipeline From a492d0ce65966c0e6e5f3cf18e5318eb2f13fb51 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 19 Mar 2024 19:31:35 +0530 Subject: [PATCH 07/52] Fixed issue 298 (#300) --- .../com/mathworks/ci/BuildArtifactAction/summary.jelly | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly index 2bd6d551..ee5beef9 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly @@ -6,7 +6,7 @@ xmlns:f="/lib/form" xmlns:i="jelly:fmt"> -

MATLAB Build Result

+

MATLAB Build Results

Unable to run a MATLAB build.
From 42ec3e54438b58bcaf145a45662106be09378ba4 Mon Sep 17 00:00:00 2001 From: mw-hrastega <48831250+mw-hrastega@users.noreply.github.com> Date: Fri, 22 Mar 2024 09:44:31 -0400 Subject: [PATCH 08/52] adding a new screenshot for build results and minor updates (#304) --- CONFIGDOC.md | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/CONFIGDOC.md b/CONFIGDOC.md index 129b653d..562ddb91 100644 --- a/CONFIGDOC.md +++ b/CONFIGDOC.md @@ -39,9 +39,9 @@ You can use the [`matlabroot`](https://www.mathworks.com/help/matlab/ref/matlabr | Platform | Path to MATLAB Root Folder | |--------------|---------------------------------| -| Windows | C:\Program Files\MATLAB\R2023b | -| Linux® | /usr/local/MATLAB/R2023b | -| macOS | /Applications/MATLAB_R2023b.app | +| Windows | C:\Program Files\MATLAB\R2024a | +| Linux® | /usr/local/MATLAB/R2024a | +| macOS | /Applications/MATLAB_R2024a.app | ### Specify Build Steps When you set up the **Build Steps** section of the project configuration window, the plugin provides you with three build steps: @@ -69,7 +69,9 @@ You can specify build options for your MATLAB build by first selecting **Build o MATLAB exits with exit code 0 if the specified tasks run without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail. -You can access the result of running a MATLAB build interactively in your Jenkins interface. After your build runs, the Jenkins build summary page displays the number of tasks that ran, failed, and were skipped. If your build ran successfully, you can click the **MATLAB Build Result** link on the page to access the table of task results. This table provides information about each task that was part of the MATLAB build. Clicking a task name in the table displays relevant build log information on the **Console Output** page. +Starting in R2024a, you can access the result of running a MATLAB build interactively in your Jenkins interface. After your build runs, the Jenkins build summary page displays the number of tasks that ran, failed, and were skipped. You can click the **MATLAB Build Results** link on the page to access the table of task results. The table provides information about each task that was part of the MATLAB build. Clicking a task name in the table displays relevant build log information on the **Console Output** page. + +![matlab_build_results](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/bf3a8f01-12d6-436e-8a9e-10f465a98f6a) #### Run MATLAB Tests The **Run MATLAB Tests** build step lets you run MATLAB and Simulink tests and generate artifacts, such as test results in JUnit-style XML format and code coverage results in Cobertura XML format. By default, the plugin includes any test files in your [MATLAB project](https://www.mathworks.com/help/matlab/projects.html) that have a `Test` label. If your build does not use a MATLAB project, or if it uses a MATLAB release before R2019a, then the plugin includes all tests in the root of your repository and in any of its subfolders. @@ -201,16 +203,16 @@ You can also define your pipeline directly in the project configuration window. ### Add MATLAB to System Path When the plugin executes steps that use MATLAB in your pipeline, the plugin uses the topmost MATLAB version on the system path. If the `PATH` environment variable of the build agent does not include any MATLAB versions, you must update the variable with the MATLAB root folder that should be used for the build. -To update the `PATH` environment variable using declarative pipeline syntax, use an `environment` block in your `Jenkinsfile`. For example, prepend MATLAB R2023b to the `PATH` environment variable and use it to run your command. +To update the `PATH` environment variable using declarative pipeline syntax, use an `environment` block in your `Jenkinsfile`. For example, prepend MATLAB R2024a to the `PATH` environment variable and use it to run your command. ```groovy // Declarative Pipeline pipeline { agent any environment { - PATH = "C:\\Program Files\\MATLAB\\R2023b\\bin;${PATH}" // Windows agent - // PATH = "/usr/local/MATLAB/R2023b/bin:${PATH}" // Linux agent - // PATH = "/Applications/MATLAB_R2023b.app/bin:${PATH}" // macOS agent + PATH = "C:\\Program Files\\MATLAB\\R2024a\\bin;${PATH}" // Windows agent + // PATH = "/usr/local/MATLAB/R2024a/bin:${PATH}" // Linux agent + // PATH = "/Applications/MATLAB_R2024a.app/bin:${PATH}" // macOS agent } stages { stage('Run MATLAB Command') { @@ -227,9 +229,9 @@ If you define your pipeline using scripted pipeline syntax, set the `PATH` envir ```groovy // Scripted Pipeline node { - env.PATH = "C:\\Program Files\\MATLAB\\R2023b\\bin;${env.PATH}" // Windows agent - // env.PATH = "/usr/local/MATLAB/R2023b/bin:${env.PATH}" // Linux agent - // env.PATH = "/Applications/MATLAB_R2023b.app/bin:${env.PATH}" // macOS agent + env.PATH = "C:\\Program Files\\MATLAB\\R2024a\\bin;${env.PATH}" // Windows agent + // env.PATH = "/usr/local/MATLAB/R2024a/bin:${env.PATH}" // Linux agent + // env.PATH = "/Applications/MATLAB_R2024a.app/bin:${env.PATH}" // macOS agent runMATLABCommand(command: 'disp("Hello World!")') } ``` @@ -268,7 +270,7 @@ node { } ``` -You can access the result of running a MATLAB build interactively in your Jenkins interface. After your build runs, the Jenkins build summary page displays the number of tasks that ran, failed, and were skipped. If your build ran successfully, you can click the **MATLAB Build Result** link on the page to access the table of task results. This table provides information about each task that was part of the MATLAB build. Clicking a task name in the table displays relevant build log information on the **Console Output** page. +Starting in R2024a, you can access the result of running a MATLAB build interactively in your Jenkins interface. After your build runs, the Jenkins build summary page displays the number of tasks that ran, failed, and were skipped. You can click the **MATLAB Build Results** link on the page to access the table of task results. The table provides information about each task that was part of the MATLAB build. Clicking a task name in the table displays relevant build log information on the **Console Output** page. ### Use the `runMATLABTests` Step Use the `runMATLABTests` step in your pipeline to run MATLAB and Simulink tests and generate test and coverage artifacts. By default, the plugin includes any test files in your [MATLAB project](https://www.mathworks.com/help/matlab/projects.html) that have a `Test` label. If your pipeline does not use a MATLAB project, or if it uses a MATLAB release before R2019a, then the plugin includes all tests in the root of your repository and in any of its subfolders. @@ -390,7 +392,7 @@ When you use the `runMATLABCommand` step, all the required files must be on the ### Use MATLAB in Matrix Build Like multi-configuration projects, you can use MATLAB as part of a [matrix](https://www.jenkins.io/doc/book/pipeline/syntax/#declarative-matrix) build in pipeline projects. For example, you can define a pipeline to run your test suite on different platforms or against different versions of MATLAB. -This example defines a declarative pipeline to run your MATLAB code and generate artifacts using MATLAB R2022b, R2023a, and R2023b. The pipeline has a `matrix` block to define the possible name-value combinations that should run in parallel. +This example defines a declarative pipeline to run your MATLAB code and generate artifacts using MATLAB R2022b, R2023b, and R2024a. The pipeline has a `matrix` block to define the possible name-value combinations that should run in parallel. ```groovy // Declarative Pipeline @@ -406,7 +408,7 @@ pipeline { axes { axis { name 'MATLAB_VERSION' - values 'R2022b', 'R2023a', 'R2023b' + values 'R2022b', 'R2023b', 'R2024a' } } stages { @@ -440,11 +442,11 @@ To register a MATLAB version as a Jenkins tool: 3) Specify the name you want to assign to the MATLAB version in the **Name** box, and enter the full path to its root folder in the **MATLAB root** box. To register the MATLAB version as a tool, do not select **Install automatically**. 4) To confirm your choices, click **Save** at the bottom of the page. -For example, register MATLAB R2023b as a Jenkins tool on your Windows local agent. +For example, register MATLAB R2024a as a Jenkins tool on your Windows local agent. -![matlab_tool](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/50cb92d2-7b46-4bb7-822d-073e746e1d92) +![matlab_tool](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/8e3625a8-96a9-424a-b675-c5a13643e85b) -If your Jenkins instance includes remote agents, you can register MATLAB as a tool on the remote agents using the tool name that you specified on the local agent. For example, if you registered MATLAB R2023b as a tool on your local agent, you can register the same MATLAB version installed on a remote agent as a tool on that agent. To register a MATLAB version as a Jenkins tool on a remote agent: +If your Jenkins instance includes remote agents, you can register MATLAB as a tool on the remote agents using the tool name that you specified on the local agent. For example, if you registered MATLAB R2024a as a tool on your local agent, you can register the same MATLAB version installed on a remote agent as a tool on that agent. To register a MATLAB version as a Jenkins tool on a remote agent: 1) Navigate to the **Node Properties** interface of the agent. You can access this interface by selecting **Manage Jenkins > Nodes**, following the link corresponding to the agent, and then selecting **Configure** on the left. 2) Select **Tool Locations**. Then, select the tool name from the **Name** list. The list contains the names assigned to the registered MATLAB versions on the local agent. @@ -452,14 +454,14 @@ If your Jenkins instance includes remote agents, you can register MATLAB as a to 4) Click **Save** to confirm your choices. ### Use MATLAB as a Tool in Pipeline Project -To invoke MATLAB as a Jenkins tool using declarative pipeline syntax, use a `tools` block in your `Jenkinsfile`. To specify the tool in the block, use the `matlab` keyword followed by the name assigned to the tool on the **Tools** page. For example, run `myscript.m` using the MATLAB version that has been registered as a tool named R2023b. +To invoke MATLAB as a Jenkins tool using declarative pipeline syntax, use a `tools` block in your `Jenkinsfile`. To specify the tool in the block, use the `matlab` keyword followed by the name assigned to the tool on the **Tools** page. For example, run `myscript.m` using the MATLAB version that has been registered as a tool named R2024a. ```groovy // Declarative Pipeline pipeline { agent any tools { - matlab 'R2023b' + matlab 'R2024a' } stages { stage('Run MATLAB Command') { @@ -478,7 +480,7 @@ If you define your pipeline using scripted pipeline syntax, use the `tool` keywo node { def matlabver stage('Run MATLAB Command') { - matlabver = tool 'R2023b' + matlabver = tool 'R2024a' if (isUnix()) { env.PATH = "${matlabver}/bin:${env.PATH}" // Linux or macOS agent } else { @@ -501,7 +503,7 @@ pipeline { axes { axis { name 'MATLAB_VERSION' - values 'R2022b', 'R2023a', 'R2023b' + values 'R2022b', 'R2023b', 'R2024a' } } tools { From 5f246295f3db5976533b20c204cf6dc25a5e5a75 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Mon, 25 Mar 2024 18:29:43 +0530 Subject: [PATCH 09/52] Release 2.13.0 (#306) * Initial fix * Added support for build visualization (Latest) (#268) * Added support for build visualization * Fixed findbug issues * Fixed findbug issues * Fixed findbug issues * Deleted failuresummary.jelly * Refactored tests * Refactored jelly file * Updated as per review comments * updated jelly as per review comment * Using overide plugin method to generate json file * Updated as per review comment * Updated as per review comment * Added log updater plugin * Added log link support * Fixed spotbug issue * Renamed plugin packages * Changed data types for artifact data * empty * Fixed test failure * Fixed Merge conflicts * Fixed spotbug issue * Updated as per review comments * Updated as per review comments * Updated as per review comments * Updated as per review comments * Build visulization support for pipeline (#278) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 * 2.11.2 snapshot qualification (#296) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 * Add build options (#294) * add build options * update gitignore * add tests for build options * add fixes and more tests * fix tests * modify help text * fix help text * minor text fix * fix null error and formatting * remove buildOptions check from EnvVarSupport test * add env variables support for build options and formatting fixes * minor fixes * documenting MATLAB build options and MATLAB build result * Fixed issue 298 (#300) * adding a new screenshot for build results and minor updates (#304) --------- Co-authored-by: sameagen Co-authored-by: sameagen-MW <122639681+sameagen-MW@users.noreply.github.com> Co-authored-by: Tushar Sharma <150027500+tsharmaMW@users.noreply.github.com> Co-authored-by: mw-hrastega <48831250+mw-hrastega@users.noreply.github.com> --- .gitignore | 2 +- CONFIGDOC.md | 139 ++++++----- pom.xml | 8 +- .../com/mathworks/ci/BuildArtifactAction.java | 220 +++++++++++++++++ .../com/mathworks/ci/BuildArtifactData.java | 55 +++++ .../mathworks/ci/BuildConsoleAnnotator.java | 83 +++++++ .../java/com/mathworks/ci/BuildOptions.java | 31 +++ .../com/mathworks/ci/BuildTargetNote.java | 38 +++ .../ci/MatlabBuildStepExecution.java | 110 +++++++-- .../ci/MatlabCommandStepExecution.java | 8 +- .../mathworks/ci/RunMatlabBuildBuilder.java | 109 +++++++- .../com/mathworks/ci/RunMatlabBuildStep.java | 12 +- .../mathworks/ci/RunMatlabCommandBuilder.java | 8 +- .../+ciplugins/+jenkins/BuildReportPlugin.m | 25 ++ .../+jenkins/TaskRunProgressPlugin.m | 13 + .../+ciplugins/+jenkins/getDefaultPlugins.m | 14 ++ .../ci/BuildArtifactAction/index.jelly | 91 +++++++ .../ci/BuildArtifactAction/summary.jelly | 23 ++ .../mathworks/ci/BuildOptions/config.jelly | 6 + .../ci/RunMatlabBuildBuilder/config.jelly | 2 + .../help-buildOptions.html | 6 + .../help-startupOptions.html | 9 +- .../ci/RunMatlabBuildStep/config.jelly | 8 +- .../RunMatlabBuildStep/help-buildOptions.html | 6 + .../help-startupOptions.html | 6 +- .../mathworks/ci/BuildArtifactActionTest.java | 233 ++++++++++++++++++ .../ci/RunMatlabBuildBuilderTest.java | 23 +- .../mathworks/ci/RunMatlabBuildStepTest.java | 12 + .../buildArtifacts.t2/buildArtifact.json | 9 + .../buildArtifacts/t1/buildArtifact.json | 25 ++ 30 files changed, 1228 insertions(+), 106 deletions(-) create mode 100644 src/main/java/com/mathworks/ci/BuildArtifactAction.java create mode 100644 src/main/java/com/mathworks/ci/BuildArtifactData.java create mode 100644 src/main/java/com/mathworks/ci/BuildConsoleAnnotator.java create mode 100644 src/main/java/com/mathworks/ci/BuildOptions.java create mode 100644 src/main/java/com/mathworks/ci/BuildTargetNote.java create mode 100644 src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m create mode 100644 src/main/resources/+ciplugins/+jenkins/TaskRunProgressPlugin.m create mode 100644 src/main/resources/+ciplugins/+jenkins/getDefaultPlugins.m create mode 100644 src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly create mode 100644 src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly create mode 100644 src/main/resources/com/mathworks/ci/BuildOptions/config.jelly create mode 100644 src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html create mode 100644 src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html create mode 100644 src/test/java/com/mathworks/ci/BuildArtifactActionTest.java create mode 100644 src/test/resources/buildArtifacts.t2/buildArtifact.json create mode 100644 src/test/resources/buildArtifacts/t1/buildArtifact.json diff --git a/.gitignore b/.gitignore index d6f71020..22535b44 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ work # Binaries and downloaded resources src/main/resources/matlab-script-generator.zip -src/main/resources/run_matlab_command.* +src/main/resources/**/run-matlab-command* src/main/resources/license.txt **/.DS_Store \ No newline at end of file diff --git a/CONFIGDOC.md b/CONFIGDOC.md index 7feb261f..562ddb91 100644 --- a/CONFIGDOC.md +++ b/CONFIGDOC.md @@ -33,44 +33,50 @@ In this example, the list includes two registered tools as well as the option fo ![use_matlab_version_tool](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/1ef811c5-c69a-41c3-8649-55c5f2239776) -When you specify a MATLAB version in the **Build Environment** section, the plugin prepends its `bin` folder to the system PATH environment variable of the build agent and invokes it to perform the build. If the build agent already has your preferred MATLAB version on the path, then you are not required to select **Use MATLAB version**. In this case, the plugin uses the topmost MATLAB version on the system path. The build fails if the operating system cannot find MATLAB on the path. +When you specify a MATLAB version in the **Build Environment** section, the plugin prepends its `bin` folder to the `PATH` system environment variable of the build agent and invokes it to perform the build. If the build agent already has your preferred MATLAB version on the path, then you are not required to select **Use MATLAB version**. In this case, the plugin uses the topmost MATLAB version on the system path. The build fails if the operating system cannot find MATLAB on the path. You can use the [`matlabroot`](https://www.mathworks.com/help/matlab/ref/matlabroot.html) function to return the full path to your preferred MATLAB root folder. The path depends on the platform, MATLAB version, and installation location. This table shows examples of the root folder path on different platforms. | Platform | Path to MATLAB Root Folder | |--------------|---------------------------------| -| Windows | C:\Program Files\MATLAB\R2023b | -| Linux® | /usr/local/MATLAB/R2023b | -| macOS | /Applications/MATLAB_R2023b.app | +| Windows | C:\Program Files\MATLAB\R2024a | +| Linux® | /usr/local/MATLAB/R2024a | +| macOS | /Applications/MATLAB_R2024a.app | ### Specify Build Steps When you set up the **Build Steps** section of the project configuration window, the plugin provides you with three build steps: -* To run a MATLAB build, use the [Run MATLAB Build](#run-matlab-build) step. +* To run a MATLAB build using the MATLAB build tool, use the [Run MATLAB Build](#run-matlab-build) step. * To run MATLAB and Simulink tests and generate artifacts, use the [Run MATLAB Tests](#run-matlab-tests) step. -* To run a MATLAB script, function, or statement, use the [Run MATLAB Command](#run-matlab-command) step. +* To run MATLAB scripts, functions, and statements, use the [Run MATLAB Command](#run-matlab-command) step. -You can specify optional MATLAB startup options for a step by first selecting **Startup options** and then populating the box that appears in the step configuration interface. For example, specify `-nojvm` to start MATLAB without the JVM™ software. If you specify more than one startup option, use a space to separate them (for example, `-nojvm -logfile "output.log"`). For more information about MATLAB startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html). +You can specify MATLAB startup options for a step by first selecting **Startup options** and then populating the box that appears in the step configuration interface. For example, specify `-nojvm` to start MATLAB without the JVM™ software. If you specify more than one startup option, use a space to separate them (for example, `-nojvm -logfile output.log`). For more information about MATLAB startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html). > :information_source: **Note:** Selecting **Startup options** to specify the `-batch` or `-r` option is not supported. If you use a source code management (SCM) system such as Git™, then your project should include the appropriate SCM configuration to check out the code before it can invoke the plugin. If you do not use any SCM systems to manage your code, then an additional build step might be required to ensure that the code is available in the project workspace before the build starts. +> :information_source: **Note:** By default, when you use the **Run MATLAB Build**, **Run MATLAB Tests**, or **Run MATLAB Command** step, the root of your repository serves as the MATLAB startup folder. To run your MATLAB code using a different folder, specify the `-sd` startup option or include the `cd` command when using the **Run MATLAB Command** step. + #### Run MATLAB Build The **Run MATLAB Build** step lets you run a build using the [MATLAB build tool](https://www.mathworks.com/help/matlab/matlab_prog/overview-of-matlab-build-tool.html). You can use this step to run the tasks specified in a file named `buildfile.m` in the root of your repository. To use the **Run MATLAB Build** step, you need MATLAB R2022b or a later release. Specify the tasks you want to execute in the **Tasks** box. If you specify more than one task, use a space to separate them. If you do not specify any tasks, the plugin runs the default tasks in `buildfile.m` as well as all the tasks on which they depend. For example, enter `mytask` in the **Tasks** box to run a task named `mytask` as well as all the tasks on which it depends. -![run_matlab_build](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/b0df3645-e8df-48fe-8dd3-e429706dd61c) +run_matlab_build + +You can specify build options for your MATLAB build by first selecting **Build options** and then populating the box that appears in the step configuration interface. For example, specify `-continueOnFailure` to continue running the MATLAB build upon a build environment setup or task failure. If you specify more than one build option, use a space to separate them (for example, `-continueOnFailure -skip test`). The plugin supports the same [options](https://www.mathworks.com/help/matlab/ref/buildtool.html#mw_50c0f35e-93df-4579-963d-f59f2fba1dba) that you can pass to the `buildtool` command. + +MATLAB exits with exit code 0 if the specified tasks run without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail. -MATLAB exits with exit code 0 if the specified tasks run without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the Jenkins build to fail. +Starting in R2024a, you can access the result of running a MATLAB build interactively in your Jenkins interface. After your build runs, the Jenkins build summary page displays the number of tasks that ran, failed, and were skipped. You can click the **MATLAB Build Results** link on the page to access the table of task results. The table provides information about each task that was part of the MATLAB build. Clicking a task name in the table displays relevant build log information on the **Console Output** page. -When you use this step, a file named `buildfile.m` must be in the root of your repository. For more information about the build tool, see [Create and Run Tasks Using Build Tool](https://www.mathworks.com/help/matlab/matlab_prog/create-and-run-tasks-using-build-tool.html). +![matlab_build_results](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/bf3a8f01-12d6-436e-8a9e-10f465a98f6a) #### Run MATLAB Tests The **Run MATLAB Tests** build step lets you run MATLAB and Simulink tests and generate artifacts, such as test results in JUnit-style XML format and code coverage results in Cobertura XML format. By default, the plugin includes any test files in your [MATLAB project](https://www.mathworks.com/help/matlab/projects.html) that have a `Test` label. If your build does not use a MATLAB project, or if it uses a MATLAB release before R2019a, then the plugin includes all tests in the root of your repository and in any of its subfolders. -You can customize the **Run MATLAB Tests** build step in the step configuration interface. For example, you can add source folders to the MATLAB search path, control which tests to run, and generate various test and coverage artifacts. If you do not select any of the existing options, all the tests in your project run, and any test failure causes the build to fail. +You can customize the **Run MATLAB Tests** build step in the step configuration interface. For example, you can add source folders to the MATLAB search path, control which tests to run, and generate test and coverage artifacts. If you do not select any of the existing options, all the tests in your project run, and any test failure causes the step to fail. Select **Source folder** if you want to specify the location of a folder containing source code, relative to the project root folder. The plugin adds the specified folder and its subfolders to the top of the MATLAB search path. If you specify a source folder and then generate coverage results, the plugin uses only the source code in the specified folder and its subfolders to generate the results. You can specify more than one folder by clicking **Add folder**. @@ -96,7 +102,7 @@ To generate test and coverage artifacts, select options in the **Generate Test A ![run_matlab_tests_artifacts](https://user-images.githubusercontent.com/48831250/217651806-1c8a6e9a-13a8-4d05-819b-e97533cc7bae.png) -The **Run MATLAB Tests** build step produces a MATLAB script file and uses it to run the tests and generate the artifacts. The plugin writes the contents of this file to the build log. You can review the build log in **Console Output** to understand the testing workflow. +The **Run MATLAB Tests** build step produces a MATLAB script file and uses it to run the tests and generate the artifacts. The plugin writes the contents of this file to the build log. You can review the build log on the **Console Output** page to understand the testing workflow. Artifacts that the plugin generates are subject to these restrictions: * Producing a PDF test report on macOS platforms is supported in MATLAB R2020b and later. @@ -110,9 +116,9 @@ Specify the MATLAB script, function, or statement you want to execute in the **C For example, enter `myscript` in the **Command** box to run a script named `myscript.m` in the root of your repository. -![run_matlab_command](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/45a99722-d872-403b-8c1a-90e23199ba47) +run_matlab_command -MATLAB exits with exit code 0 if the specified script, function, or statement executes without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the Jenkins build to fail. To fail the build in certain conditions, use the [`assert`](https://www.mathworks.com/help/matlab/ref/assert.html) or [`error`](https://www.mathworks.com/help/matlab/ref/error.html) function. +MATLAB exits with exit code 0 if the specified script, function, or statement executes without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail. To fail the step in certain conditions, use the [`assert`](https://www.mathworks.com/help/matlab/ref/assert.html) or [`error`](https://www.mathworks.com/help/matlab/ref/error.html) function. When you use this step, all the required files must be on the MATLAB search path. If your script or function is not in the root of your repository, you can use the [`addpath`](https://www.mathworks.com/help/matlab/ref/addpath.html), [`cd`](https://www.mathworks.com/help/matlab/ref/cd.html), or [`run`](https://www.mathworks.com/help/matlab/ref/run.html) function to ensure that it is on the path when invoked. For example, to run `myscript.m` in a folder named `myfolder` located in the root of the repository, you can specify the contents of the **Command** box like this: @@ -126,9 +132,9 @@ To specify the MATLAB version, select **Use MATLAB version** in the **Build Envi ![build_environment](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/6fa3187a-5674-4435-9c69-4210a21b8d88) To run MATLAB code and Simulink models, specify the appropriate build steps in the **Build Steps** section: -* If you add the [**Run MATLAB Build**](#run-matlab-build) step, specify your MATLAB build tasks in the **Tasks** box. -* If you add the [**Run MATLAB Tests**](#run-matlab-tests) step, specify your source code, test suite filters, run customization options, and test and coverage artifacts to be generated in the project workspace. -* If you add the [**Run MATLAB Command**](#run-matlab-command) step, specify your MATLAB script, function, or statement in the **Command** box. +* If you add the [**Run MATLAB Build**](#run-matlab-build) step, specify your MATLAB build tasks and options. +* If you add the [**Run MATLAB Tests**](#run-matlab-tests) step, specify your source code, test suite filters, run customization options, and test and coverage artifacts to generate. +* If you add the [**Run MATLAB Command**](#run-matlab-command) step, specify your MATLAB script, function, or statement. ## Set Up Multi-Configuration Project @@ -143,7 +149,7 @@ There are two ways to specify multiple MATLAB versions in a multi-configuration ![add_axis](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/8d134ca1-892e-4014-98e3-14fd8fbb3024) ### Add MATLAB Axis -If your Jenkins instance includes MATLAB versions registered as tools, then **MATLAB** appears as an option when you click **Add axis** in the **Configuration Matrix** section. By adding the **MATLAB** axis, you can select MATLAB versions and add them as axis values to your matrix configuration. The list includes all MATLAB versions that have been registered as Jenkins tools. In this example, there are two MATLAB versions registered as tools. In each build iteration, the plugin prepends one of the selected versions to the PATH environment variable and invokes it to run the build. +If your Jenkins instance includes MATLAB versions registered as tools, then **MATLAB** appears as an option when you click **Add axis** in the **Configuration Matrix** section. By adding the **MATLAB** axis, you can select MATLAB versions and add them as axis values to your matrix configuration. The list includes all MATLAB versions that have been registered as Jenkins tools. In this example, there are two MATLAB versions registered as tools. In each build iteration, the plugin prepends one of the selected versions to the `PATH` environment variable and invokes it to run the build. ![matlab_axis](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/047283bb-782c-4437-af3b-ce296e73cf1a) @@ -170,9 +176,9 @@ You can add several axes in the **Configuration Matrix** section. For example, a Once you have specified the axes, add the required build steps in the **Build Steps** section: -* If you add the [**Run MATLAB Build**](#run-matlab-build) step, specify your MATLAB build tasks in the **Tasks** box. -* If you add the [**Run MATLAB Tests**](#run-matlab-tests) step, specify your source code, test suite filters, run customization options, and test and coverage artifacts to be generated in the project workspace. -* If you add the [**Run MATLAB Command**](#run-matlab-command) step, specify your MATLAB script, function, or statement in the **Command** box. You can use the user-defined axes to specify the contents of the **Command** box. For example: +* If you add the [**Run MATLAB Build**](#run-matlab-build) step, specify your MATLAB build tasks and options. +* If you add the [**Run MATLAB Tests**](#run-matlab-tests) step, specify your source code, test suite filters, run customization options, and test and coverage artifacts to generate. +* If you add the [**Run MATLAB Command**](#run-matlab-command) step, specify your MATLAB script, function, or statement. You can use the user-defined axes to specify the contents of the **Command** box. For example: ``` results = runtests(pwd,"Tag","$TEST_TAG"); assertSuccess(results); ``` @@ -180,9 +186,9 @@ Once you have specified the axes, add the required build steps in the **Build St ## Set Up Pipeline Project When you define your pipeline with a `Jenkinsfile`, the plugin provides you with three build steps: -* To run a MATLAB build, use the [`runMATLABBuild`](#use-the-runmatlabbuild-step) step. +* To run a MATLAB build using the MATLAB build tool, use the [`runMATLABBuild`](#use-the-runmatlabbuild-step) step. * To run MATLAB and Simulink tests and generate artifacts, use the [`runMATLABTests`](#use-the-runmatlabtests-step) step. -* To run a MATLAB script, function, or statement, use the [`runMATLABCommand`](#use-the-runmatlabcommand-step) step. +* To run MATLAB scripts, functions, and statements, use the [`runMATLABCommand`](#use-the-runmatlabcommand-step) step. To configure the plugin for a pipeline project: 1) Define your pipeline in a `Jenkinsfile` in the root of your repository. @@ -192,19 +198,21 @@ To configure the plugin for a pipeline project: You can also define your pipeline directly in the project configuration window. If you select `Pipeline script` from the **Definition** list, you can author your pipeline code in the **Script** box. When you define your pipeline this way, it must include an additional stage to check out your code from source control. +> :information_source: **Note:** By default, when you use the `runMATLABBuild`, `runMATLABTests`, or `runMATLABCommand` step, the root of your repository serves as the MATLAB startup folder. To run your MATLAB code using a different folder, specify the `-sd` startup option or include the `cd` command when using the `runMATLABCommand` step. + ### Add MATLAB to System Path -When the plugin executes steps that use MATLAB in your pipeline, the plugin uses the topmost MATLAB version on the system path. If the PATH environment variable of the build agent does not include any MATLAB versions, you must update the variable with the MATLAB root folder that should be used for the build. +When the plugin executes steps that use MATLAB in your pipeline, the plugin uses the topmost MATLAB version on the system path. If the `PATH` environment variable of the build agent does not include any MATLAB versions, you must update the variable with the MATLAB root folder that should be used for the build. -To update the system PATH environment variable using declarative pipeline syntax, use an `environment` block in your `Jenkinsfile`. For example, prepend MATLAB R2023b to the system PATH environment variable and use it to run your command. +To update the `PATH` environment variable using declarative pipeline syntax, use an `environment` block in your `Jenkinsfile`. For example, prepend MATLAB R2024a to the `PATH` environment variable and use it to run your command. ```groovy // Declarative Pipeline pipeline { agent any environment { - PATH = "C:\\Program Files\\MATLAB\\R2023b\\bin;${PATH}" // Windows agent - // PATH = "/usr/local/MATLAB/R2023b/bin:${PATH}" // Linux agent - // PATH = "/Applications/MATLAB_R2023b.app/bin:${PATH}" // macOS agent + PATH = "C:\\Program Files\\MATLAB\\R2024a\\bin;${PATH}" // Windows agent + // PATH = "/usr/local/MATLAB/R2024a/bin:${PATH}" // Linux agent + // PATH = "/Applications/MATLAB_R2024a.app/bin:${PATH}" // macOS agent } stages { stage('Run MATLAB Command') { @@ -216,14 +224,14 @@ pipeline { } ``` -If you define your pipeline using scripted pipeline syntax, set the PATH environment variable in the `node` block. For example: +If you define your pipeline using scripted pipeline syntax, set the `PATH` environment variable in the `node` block. For example: ```groovy // Scripted Pipeline node { - env.PATH = "C:\\Program Files\\MATLAB\\R2023b\\bin;${env.PATH}" // Windows agent - // env.PATH = "/usr/local/MATLAB/R2023b/bin:${env.PATH}" // Linux agent - // env.PATH = "/Applications/MATLAB_R2023b.app/bin:${env.PATH}" // macOS agent + env.PATH = "C:\\Program Files\\MATLAB\\R2024a\\bin;${env.PATH}" // Windows agent + // env.PATH = "/usr/local/MATLAB/R2024a/bin:${env.PATH}" // Linux agent + // env.PATH = "/Applications/MATLAB_R2024a.app/bin:${env.PATH}" // macOS agent runMATLABCommand(command: 'disp("Hello World!")') } ``` @@ -233,9 +241,9 @@ Use the `runMATLABBuild` step in your pipeline to run a build using the [MATLAB Input | Description ------------------------- | --------------- -`tasks` | (Optional) Tasks to execute. If you specify more than one task, use a space to separate them. If you specify the step without this input (for example, `runMATLABBuild()`), the plugin runs the default tasks in `buildfile.m` as well as all the tasks on which they depend.
MATLAB exits with exit code 0 if the tasks run without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the stage to fail.
**Example:** `tasks: 'test'`
**Example:** `tasks: 'compile test'` -`startupOptions` | (Optional) MATLAB startup options. If you specify more than one option, use a space to separate them. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).
Using this input to specify the `-batch` or `-r` option is not supported.
**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile "output.log"'` - +`tasks` |

(Optional) Tasks to run, specified as a list of task names separated by spaces. If you specify the step without this input (for example, `runMATLABBuild()`), the plugin runs the default tasks in `buildfile.m` as well as all the tasks on which they depend.

MATLAB exits with exit code 0 if the tasks run without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail.

**Example:** `tasks: 'test'`
**Example:** `tasks: 'compile test'`

+`buildOptions` |

(Optional) MATLAB build options, specified as a list of options separated by spaces. The plugin supports the same [options](https://www.mathworks.com/help/matlab/ref/buildtool.html#mw_50c0f35e-93df-4579-963d-f59f2fba1dba) that you can pass to the `buildtool` command.

**Example:** `buildOptions: '-continueOnFailure'`
**Example:** `buildOptions: '-continueOnFailure -skip test'`

+`startupOptions` |

(Optional) MATLAB startup options, specified as a list of options separated by spaces. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).

Using this input to specify the `-batch` or `-r` option is not supported.

**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile output.log'`

For example, in your `Jenkinsfile`, define a declarative pipeline to run a task named `mytask` as well as all the tasks on which it depends. @@ -262,11 +270,10 @@ node { } ``` -When you use this step, a file named `buildfile.m` must be in the root of your repository. For more information about the build tool, see [Create and Run Tasks Using Build Tool](https://www.mathworks.com/help/matlab/matlab_prog/create-and-run-tasks-using-build-tool.html). - +Starting in R2024a, you can access the result of running a MATLAB build interactively in your Jenkins interface. After your build runs, the Jenkins build summary page displays the number of tasks that ran, failed, and were skipped. You can click the **MATLAB Build Results** link on the page to access the table of task results. The table provides information about each task that was part of the MATLAB build. Clicking a task name in the table displays relevant build log information on the **Console Output** page. ### Use the `runMATLABTests` Step -Use the `runMATLABTests` step in your pipeline to run MATLAB and Simulink tests and generate various test and coverage artifacts. By default, the plugin includes any test files in your [MATLAB project](https://www.mathworks.com/help/matlab/projects.html) that have a `Test` label. If your pipeline does not use a MATLAB project, or if it uses a MATLAB release before R2019a, then the plugin includes all tests in the root of your repository and in any of its subfolders. +Use the `runMATLABTests` step in your pipeline to run MATLAB and Simulink tests and generate test and coverage artifacts. By default, the plugin includes any test files in your [MATLAB project](https://www.mathworks.com/help/matlab/projects.html) that have a `Test` label. If your pipeline does not use a MATLAB project, or if it uses a MATLAB release before R2019a, then the plugin includes all tests in the root of your repository and in any of its subfolders. For example, in your `Jenkinsfile`, define a declarative pipeline to run the tests in your project. @@ -294,26 +301,26 @@ node { } ``` -MATLAB exits with exit code 0 if the test suite runs without any failures. Otherwise, MATLAB terminates with a nonzero exit code, which causes the stage to fail. +MATLAB exits with exit code 0 if the test suite runs without any failures. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail. -You can customize the `runMATLABTests` step using optional inputs. For example, you can add source folders to the MATLAB search path, control which tests to run, and generate various artifacts. +You can customize the `runMATLABTests` step using optional inputs. For example, you can add source folders to the MATLAB search path, control which tests to run, and generate test and coverage artifacts. Input | Description ------------------------- | --------------- -`sourceFolder` | (Optional) Location of the folder containing source code, relative to the project root folder. The specified folder and its subfolders are added to the top of the MATLAB search path. If you specify `sourceFolder` and then generate coverage results, the plugin uses only the source code in the specified folder and its subfolders to generate the results. You can specify multiple folders using a comma-separated list.
**Example:** `sourceFolder: ['source']`
**Example:** `sourceFolder: ['source/folderA', 'source/folderB']` -`selectByFolder` | (Optional) Location of the folder used to select test suite elements, relative to the project root folder. To create a test suite, the plugin uses only the tests in the specified folder and its subfolders. You can specify multiple folders using a comma-separated list.
**Example:** `selectByFolder: ['test']`
**Example:** `selectByFolder: ['test/folderA', 'test/folderB']` -`selectByTag` | (Optional) Test tag used to select test suite elements. To create a test suite, the plugin uses only the test elements with the specified tag.
**Example:** `selectByTag: 'FeatureA'` -`strict` | (Optional) Option to apply strict checks when running tests, specified as `false` or `true`. By default, the value is `false`. If you specify a value of `true`, the plugin generates a qualification failure whenever a test issues a warning.
**Example:** `strict: true` -`useParallel` | (Optional) Option to run tests in parallel, specified as `false` or `true`. By default, the value is `false` and tests run in serial. If the test runner configuration is suited for parallelization, you can specify a value of `true` to run tests in parallel. This input requires a Parallel Computing Toolbox license.
**Example:** `useParallel: true` -`outputDetail` | (Optional) Amount of output detail displayed for the test run, specified as `'None'`, `'Terse'`, `'Concise'`, `'Detailed'`, or `'Verbose'`. By default, the plugin displays failing and logged events at the `Detailed` level and test run progress at the `Concise` level.
**Example:** `outputDetail: 'Verbose'` -`loggingLevel` | (Optional) Maximum verbosity level for logged diagnostics included for the test run, specified as `'None'`, `'Terse'`, `'Concise'`, `'Detailed'`, or `'Verbose'`. By default, the plugin includes diagnostics logged at the `Terse` level.
**Example:** `loggingLevel: 'Detailed'` -`testResultsPDF` | (Optional) Path to write the test results in PDF format. On macOS platforms, this input is supported in MATLAB R2020b and later.
**Example:** `testResultsPDF: 'test-results/results.pdf'` -`testResultsTAP` | (Optional) Path to write the test results in TAP format.
**Example:** `testResultsTAP: 'test-results/results.tap'` -`testResultsJUnit` | (Optional) Path to write the test results in JUnit-style XML format.
**Example:** `testResultsJUnit: 'test-results/results.xml'` -`testResultsSimulinkTest` | (Optional) Path to export Simulink Test Manager results in MLDATX format. This input requires a Simulink Test license and is supported in MATLAB R2019a and later.
**Example:** `testResultsSimulinkTest: 'test-results/results.mldatx'` -`codeCoverageCobertura` | (Optional) Path to write the code coverage results in Cobertura XML format.
**Example:** `codeCoverageCobertura: 'code-coverage/coverage.xml'` -`modelCoverageCobertura` | (Optional) Path to write the model coverage results in Cobertura XML format. This input requires a Simulink Coverage license and is supported in MATLAB R2018b and later.
**Example:** `modelCoverageCobertura: 'model-coverage/coverage.xml'` -`startupOptions` | (Optional) MATLAB startup options. If you specify more than one option, use a space to separate them. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).
Using this input to specify the `-batch` or `-r` option is not supported.
**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile "output.log"'` +`sourceFolder` |

(Optional) Location of the folder containing source code, relative to the project root folder. The specified folder and its subfolders are added to the top of the MATLAB search path. If you specify `sourceFolder` and then generate coverage results, the plugin uses only the source code in the specified folder and its subfolders to generate the results. You can specify multiple folders using a comma-separated list.

**Example:** `sourceFolder: ['source']`
**Example:** `sourceFolder: ['source/folderA', 'source/folderB']`

+`selectByFolder` |

(Optional) Location of the folder used to select test suite elements, relative to the project root folder. To create a test suite, the plugin uses only the tests in the specified folder and its subfolders. You can specify multiple folders using a comma-separated list.

**Example:** `selectByFolder: ['test']`
**Example:** `selectByFolder: ['test/folderA', 'test/folderB']`

+`selectByTag` |

(Optional) Test tag used to select test suite elements. To create a test suite, the plugin uses only the test elements with the specified tag.

**Example:** `selectByTag: 'FeatureA'`

+`strict` |

(Optional) Option to apply strict checks when running tests, specified as `false` or `true`. By default, the value is `false`. If you specify a value of `true`, the plugin generates a qualification failure whenever a test issues a warning.

**Example:** `strict: true`

+`useParallel` |

(Optional) Option to run tests in parallel, specified as `false` or `true`. By default, the value is `false` and tests run in serial. If the test runner configuration is suited for parallelization, you can specify a value of `true` to run tests in parallel. This input requires a Parallel Computing Toolbox license.

**Example:** `useParallel: true`

+`outputDetail` |

(Optional) Amount of output detail displayed for the test run, specified as `'None'`, `'Terse'`, `'Concise'`, `'Detailed'`, or `'Verbose'`. By default, the plugin displays failing and logged events at the `Detailed` level and test run progress at the `Concise` level.

**Example:** `outputDetail: 'Verbose'`

+`loggingLevel` |

(Optional) Maximum verbosity level for logged diagnostics included for the test run, specified as `'None'`, `'Terse'`, `'Concise'`, `'Detailed'`, or `'Verbose'`. By default, the plugin includes diagnostics logged at the `Terse` level.

**Example:** `loggingLevel: 'Detailed'`

+`testResultsPDF` |

(Optional) Path to write the test results in PDF format. On macOS platforms, this input is supported in MATLAB R2020b and later.

**Example:** `testResultsPDF: 'test-results/results.pdf'`

+`testResultsTAP` |

(Optional) Path to write the test results in TAP format.

**Example:** `testResultsTAP: 'test-results/results.tap'`

+`testResultsJUnit` |

(Optional) Path to write the test results in JUnit-style XML format.

**Example:** `testResultsJUnit: 'test-results/results.xml'`

+`testResultsSimulinkTest` |

(Optional) Path to export Simulink Test Manager results in MLDATX format. This input requires a Simulink Test license and is supported in MATLAB R2019a and later.

**Example:** `testResultsSimulinkTest: 'test-results/results.mldatx'`

+`codeCoverageCobertura` |

(Optional) Path to write the code coverage results in Cobertura XML format.

**Example:** `codeCoverageCobertura: 'code-coverage/coverage.xml'`

+`modelCoverageCobertura` |

(Optional) Path to write the model coverage results in Cobertura XML format. This input requires a Simulink Coverage license and is supported in MATLAB R2018b and later.

**Example:** `modelCoverageCobertura: 'model-coverage/coverage.xml'`

+`startupOptions` |

(Optional) MATLAB startup options, specified as a list of options separated by spaces. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).

Using this input to specify the `-batch` or `-r` option is not supported.

**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile output.log'`

For instance, define a declarative pipeline to run the tests in your MATLAB project, and then generate test results in JUnit-style XML format and code coverage results in Cobertura XML format at specified locations on the build agent. Generate the coverage results for only the code in the `source` folder in the root of your repository. @@ -350,8 +357,8 @@ Use the `runMATLABCommand` step in your pipeline to run MATLAB scripts, function Input | Description ------------------------- | --------------- -`command` | (Required) Script, function, or statement to execute. If the value of `command` is the name of a MATLAB script or function, do not specify the file extension. If you specify more than one script, function, or statement, use a comma or semicolon to separate them.
MATLAB exits with exit code 0 if the specified script, function, or statement executes without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the stage to fail. To fail the stage in certain conditions, use the [`assert`](https://www.mathworks.com/help/matlab/ref/assert.html) or [`error`](https://www.mathworks.com/help/matlab/ref/error.html) function.
**Example:** `command: 'myscript'`
**Example:** `command: 'results = runtests, assertSuccess(results);'` -`startupOptions` | (Optional) MATLAB startup options. If you specify more than one option, use a space to separate them. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).
Using this input to specify the `-batch` or `-r` option is not supported.
**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile "output.log"'` +`command` |

(Required) Script, function, or statement to execute. If the value of `command` is the name of a MATLAB script or function, do not specify the file extension. If you specify more than one script, function, or statement, use a comma or semicolon to separate them.

MATLAB exits with exit code 0 if the specified script, function, or statement executes without error. Otherwise, MATLAB terminates with a nonzero exit code, which causes the step to fail. To fail the step in certain conditions, use the [`assert`](https://www.mathworks.com/help/matlab/ref/assert.html) or [`error`](https://www.mathworks.com/help/matlab/ref/error.html) function.

**Example:** `command: 'myscript'`
**Example:** `command: 'results = runtests, assertSuccess(results);'`

+`startupOptions` |

(Optional) MATLAB startup options, specified as a list of options separated by spaces. For more information about startup options, see [Commonly Used Startup Options](https://www.mathworks.com/help/matlab/matlab_env/commonly-used-startup-options.html).

Using this input to specify the `-batch` or `-r` option is not supported.

**Example:** `startupOptions: '-nojvm'`
**Example:** `startupOptions: '-nojvm -logfile output.log'`

For example, in your `Jenkinsfile`, define a declarative pipeline to run a script named `myscript.m`. @@ -385,7 +392,7 @@ When you use the `runMATLABCommand` step, all the required files must be on the ### Use MATLAB in Matrix Build Like multi-configuration projects, you can use MATLAB as part of a [matrix](https://www.jenkins.io/doc/book/pipeline/syntax/#declarative-matrix) build in pipeline projects. For example, you can define a pipeline to run your test suite on different platforms or against different versions of MATLAB. -This example defines a declarative pipeline to run your MATLAB code and generate artifacts using MATLAB R2022b, R2023a, and R2023b. The pipeline has a `matrix` block to define the possible name-value combinations that should run in parallel. +This example defines a declarative pipeline to run your MATLAB code and generate artifacts using MATLAB R2022b, R2023b, and R2024a. The pipeline has a `matrix` block to define the possible name-value combinations that should run in parallel. ```groovy // Declarative Pipeline @@ -401,7 +408,7 @@ pipeline { axes { axis { name 'MATLAB_VERSION' - values 'R2022b', 'R2023a', 'R2023b' + values 'R2022b', 'R2023b', 'R2024a' } } stages { @@ -435,11 +442,11 @@ To register a MATLAB version as a Jenkins tool: 3) Specify the name you want to assign to the MATLAB version in the **Name** box, and enter the full path to its root folder in the **MATLAB root** box. To register the MATLAB version as a tool, do not select **Install automatically**. 4) To confirm your choices, click **Save** at the bottom of the page. -For example, register MATLAB R2023b as a Jenkins tool on your Windows local agent. +For example, register MATLAB R2024a as a Jenkins tool on your Windows local agent. -![matlab_tool](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/50cb92d2-7b46-4bb7-822d-073e746e1d92) +![matlab_tool](https://github.com/mathworks/jenkins-matlab-plugin/assets/48831250/8e3625a8-96a9-424a-b675-c5a13643e85b) -If your Jenkins instance includes remote agents, you can register MATLAB as a tool on the remote agents using the tool name that you specified on the local agent. For example, if you registered MATLAB R2023b as a tool on your local agent, you can register the same MATLAB version installed on a remote agent as a tool on that agent. To register a MATLAB version as a Jenkins tool on a remote agent: +If your Jenkins instance includes remote agents, you can register MATLAB as a tool on the remote agents using the tool name that you specified on the local agent. For example, if you registered MATLAB R2024a as a tool on your local agent, you can register the same MATLAB version installed on a remote agent as a tool on that agent. To register a MATLAB version as a Jenkins tool on a remote agent: 1) Navigate to the **Node Properties** interface of the agent. You can access this interface by selecting **Manage Jenkins > Nodes**, following the link corresponding to the agent, and then selecting **Configure** on the left. 2) Select **Tool Locations**. Then, select the tool name from the **Name** list. The list contains the names assigned to the registered MATLAB versions on the local agent. @@ -447,14 +454,14 @@ If your Jenkins instance includes remote agents, you can register MATLAB as a to 4) Click **Save** to confirm your choices. ### Use MATLAB as a Tool in Pipeline Project -To invoke MATLAB as a Jenkins tool using declarative pipeline syntax, use a `tools` block in your `Jenkinsfile`. To specify the tool in the block, use the `matlab` keyword followed by the name assigned to the tool on the **Tools** page. For example, run `myscript.m` using the MATLAB version that has been registered as a tool named R2023b. +To invoke MATLAB as a Jenkins tool using declarative pipeline syntax, use a `tools` block in your `Jenkinsfile`. To specify the tool in the block, use the `matlab` keyword followed by the name assigned to the tool on the **Tools** page. For example, run `myscript.m` using the MATLAB version that has been registered as a tool named R2024a. ```groovy // Declarative Pipeline pipeline { agent any tools { - matlab 'R2023b' + matlab 'R2024a' } stages { stage('Run MATLAB Command') { @@ -466,14 +473,14 @@ pipeline { } ``` -If you define your pipeline using scripted pipeline syntax, use the `tool` keyword followed by the name of the tool to retrieve the path to the MATLAB root folder. Then, prepend the MATLAB `bin` folder to the PATH environment variable. +If you define your pipeline using scripted pipeline syntax, use the `tool` keyword followed by the name of the tool to retrieve the path to the MATLAB root folder. Then, prepend the MATLAB `bin` folder to the `PATH` environment variable. ```groovy // Scripted Pipeline node { def matlabver stage('Run MATLAB Command') { - matlabver = tool 'R2023b' + matlabver = tool 'R2024a' if (isUnix()) { env.PATH = "${matlabver}/bin:${env.PATH}" // Linux or macOS agent } else { @@ -496,7 +503,7 @@ pipeline { axes { axis { name 'MATLAB_VERSION' - values 'R2022b', 'R2023a', 'R2023b' + values 'R2022b', 'R2023b', 'R2024a' } } tools { diff --git a/pom.xml b/pom.xml index fcb38ad5..83868f62 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ matlab - 2.11.2-SNAPSHOT + 2.12.1-SNAPSHOT hpi @@ -60,6 +60,12 @@ + + + com.googlecode.json-simple + json-simple + 1.1.1 + org.jenkins-ci.plugins diff --git a/src/main/java/com/mathworks/ci/BuildArtifactAction.java b/src/main/java/com/mathworks/ci/BuildArtifactAction.java new file mode 100644 index 00000000..11a751f0 --- /dev/null +++ b/src/main/java/com/mathworks/ci/BuildArtifactAction.java @@ -0,0 +1,220 @@ +package com.mathworks.ci; + +import hudson.FilePath; +import hudson.model.Action; +import hudson.model.Run; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.CheckForNull; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + + +public class BuildArtifactAction implements Action { + private Run build; + private FilePath workspace; + private int totalCount; + private int skipCount; + private int failCount; + private static final String ROOT_ELEMENT = "taskDetails"; + private static final String BUILD_ARTIFACT_FILE = "buildArtifact.json"; + + public BuildArtifactAction(Run build, FilePath workspace) { + this.build = build; + this.workspace = workspace; + + // Setting the counts of task when Action is created. + try{ + setCounts(); + } catch (ParseException e) { + throw new RuntimeException(e); + } catch (InterruptedException e){ + throw new RuntimeException(e); + } + } + + @CheckForNull + @Override + public String getIconFileName() { + return "document.png"; + } + + @CheckForNull + @Override + public String getDisplayName() { + return "MATLAB Build Results"; + } + + @CheckForNull + @Override + public String getUrlName() { + return "buildresults"; + } + + public List getBuildArtifact() throws ParseException, InterruptedException, IOException { + List artifactData = new ArrayList(); + FilePath fl = new FilePath(new File(build.getRootDir().getAbsolutePath() + "/" + BUILD_ARTIFACT_FILE)); + try (InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fl.toURI())), "UTF-8")) { + Object obj = new JSONParser().parse(reader); + JSONObject jo = (JSONObject) obj; + if (jo.get(ROOT_ELEMENT) instanceof JSONArray) { + JSONArray ja = (JSONArray) jo.get(ROOT_ELEMENT); + Iterator itr2 = ja.iterator(); + Iterator itr1; + while (itr2.hasNext()) { + BuildArtifactData data = new BuildArtifactData(); + itr1 = ((Map) itr2.next()).entrySet().iterator(); + while (itr1.hasNext()) { + Entry pair = itr1.next(); + iterateAllTaskAttributes(pair, data); + } + artifactData.add(data); + } + } else { + Map ja = ((Map) jo.get(ROOT_ELEMENT)); + Iterator itr1 = ja.entrySet().iterator(); + BuildArtifactData data = new BuildArtifactData(); + while (itr1.hasNext()) { + Entry pair = itr1.next(); + iterateAllTaskAttributes(pair, data); + } + artifactData.add(data); + } + } catch (IOException e) { + throw new IOException(e.getLocalizedMessage()); + } + return artifactData; + } + + public void setTotalcount(int totalCount) { + this.totalCount = totalCount; + } + + public void setSkipCount(int skipCount) { + this.skipCount = skipCount; + } + + public int getTotalCount() { + return this.totalCount; + } + + public int getFailCount() { + return this.failCount; + } + + public void setFailCount(int failCount) { + this.failCount = failCount; + } + + public int getSkipCount() { + return this.skipCount; + } + + public Run getOwner() { + return this.build; + } + + /** + * @param owner the owner to set + */ + public void setOwner(Run owner) { + this.build = owner; + } + + public FilePath getWorkspace() { + return this.workspace; + } + + private void setCounts() throws InterruptedException, ParseException { + List artifactData = new ArrayList(); + FilePath fl = new FilePath(new File(build.getRootDir().getAbsolutePath() + "/" + BUILD_ARTIFACT_FILE)); + try (InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fl.toURI())), "UTF-8")) { + Object obj = new JSONParser().parse(reader); + JSONObject jo = (JSONObject) obj; + + // getting taskDetails + if (jo.get(ROOT_ELEMENT) instanceof JSONArray) { + JSONArray ja = (JSONArray) jo.get(ROOT_ELEMENT); + Iterator itr2 = ja.iterator(); + Iterator itr1; + while (itr2.hasNext()) { + BuildArtifactData data = new BuildArtifactData(); + itr1 = ((Map) itr2.next()).entrySet().iterator(); + while (itr1.hasNext()) { + Entry pair = itr1.next(); + iterateFailedSkipped(pair, data); + } + artifactData.add(data); + setTotalcount(artifactData.size()); + } + } else { + Map ja = ((Map) jo.get(ROOT_ELEMENT)); + Iterator itr1 = ja.entrySet().iterator(); + BuildArtifactData data = new BuildArtifactData(); + while (itr1.hasNext()) { + Entry pair = itr1.next(); + iterateFailedSkipped(pair, data); + } + artifactData.add(data); + setTotalcount(artifactData.size()); + } + } catch (IOException e) { + e.printStackTrace(); + } + + // Update the FAILED and SKIPPED task count + int failCount = 0; + int skipCount = 0; + for (BuildArtifactData data : artifactData) { + if (data.getTaskFailed()) { + failCount = failCount + 1; + } else if (data.getTaskSkipped()) { + skipCount = skipCount + 1; + } + } + // Set count for each failed and skipped tasks + setFailCount(failCount); + setSkipCount(skipCount); + } + + private void iterateAllTaskAttributes(Entry pair, BuildArtifactData data) { + // Iterates across all task attributes and updates + String key = pair.getKey().toString(); + switch(key.toLowerCase()){ + case "duration": + data.setTaskDuration(pair.getValue().toString()); + break; + case "name" : + data.setTaskName(pair.getValue().toString()); + break; + case "description": + data.setTaskDescription(pair.getValue().toString()); + break; + case "failed": + data.setTaskFailed((Boolean) pair.getValue()); + break; + case "skipped": + data.setTaskSkipped((Boolean) pair.getValue()); + break; + default : + break; + } + } + + private void iterateFailedSkipped(Entry pair, BuildArtifactData data) { + if (pair.getKey().toString().equalsIgnoreCase("failed")) { + data.setTaskFailed((Boolean) pair.getValue()); + } else if (pair.getKey().toString().equalsIgnoreCase("skipped")) { + data.setTaskSkipped((Boolean) pair.getValue()); + } + } +} diff --git a/src/main/java/com/mathworks/ci/BuildArtifactData.java b/src/main/java/com/mathworks/ci/BuildArtifactData.java new file mode 100644 index 00000000..d89a5ef9 --- /dev/null +++ b/src/main/java/com/mathworks/ci/BuildArtifactData.java @@ -0,0 +1,55 @@ +package com.mathworks.ci; + +public class BuildArtifactData { + + private String taskName; + private String taskDuration; + private boolean taskFailed; + + private String taskDescription; + private boolean taskSkipped; + + public BuildArtifactData() { + } + + + public String getTaskDuration() { + return this.taskDuration; + } + + public void setTaskDuration(String taskDuration) { + this.taskDuration = taskDuration; + } + + public String getTaskName() { + return this.taskName; + } + + public void setTaskName(String taskName) { + this.taskName = taskName; + } + + public boolean getTaskSkipped() { + return this.taskSkipped; + } + + public void setTaskSkipped(boolean taskSkipped) { + this.taskSkipped = taskSkipped; + } + + public boolean getTaskFailed() { + return this.taskFailed; + } + + public void setTaskFailed(boolean taskFailed) { + this.taskFailed = taskFailed; + } + + public String getTaskDescription() { + return this.taskDescription; + } + + public void setTaskDescription(String taskDescription) { + this.taskDescription = taskDescription; + } +} diff --git a/src/main/java/com/mathworks/ci/BuildConsoleAnnotator.java b/src/main/java/com/mathworks/ci/BuildConsoleAnnotator.java new file mode 100644 index 00000000..34fb6b70 --- /dev/null +++ b/src/main/java/com/mathworks/ci/BuildConsoleAnnotator.java @@ -0,0 +1,83 @@ +package com.mathworks.ci; + +import com.google.common.base.Charsets; +import hudson.console.ConsoleLogFilter; +import hudson.console.LineTransformationOutputStream; +import hudson.model.Run; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import jenkins.util.JenkinsJVM; + +public class BuildConsoleAnnotator extends LineTransformationOutputStream { + private final OutputStream out; + private final Charset charset; + + private final byte[][] antNotes; + + public BuildConsoleAnnotator(OutputStream out, Charset charset) { + this(out, charset, createBuildNotes()); + } + + private BuildConsoleAnnotator(OutputStream out, Charset charset, byte[][] antNotes) { + this.out = out; + this.charset = charset; + this.antNotes = antNotes; + } + + private static byte[][] createBuildNotes() { + JenkinsJVM.checkJenkinsJVM(); + try { + ByteArrayOutputStream targetNote = new ByteArrayOutputStream(); + new BuildTargetNote().encodeTo(targetNote); + ByteArrayOutputStream outcomeNote = new ByteArrayOutputStream(); + return new byte[][]{targetNote.toByteArray(), outcomeNote.toByteArray()}; + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + @Override + protected void eol(byte[] b, int len) throws IOException { + String line = charset.decode(ByteBuffer.wrap(b, 0, len)).toString(); + // trim off CR/LF from the end + line = trimEOL(line); + if (line.contains("[MATLAB-Build-")) + out.write(antNotes[0]); + + out.write(b, 0, len); + } + + @Override + public void flush() throws IOException { + out.flush(); + } + + @Override + public void close() throws IOException { + super.close(); + out.close(); + } + + private static class ConsoleLogFilterImpl extends ConsoleLogFilter implements Serializable { + private static final long serialVersionUID = 1; + private byte[][] buildNotes = createBuildNotes(); + + //Taking care of old MATLAB build actions. + private Object readResolve() { + if (buildNotes == null) { + buildNotes = createBuildNotes(); + } + return this; + } + + @Override + public OutputStream decorateLogger(Run build, OutputStream logger) throws IOException, InterruptedException { + return new BuildConsoleAnnotator(logger, Charsets.UTF_8, buildNotes); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/mathworks/ci/BuildOptions.java b/src/main/java/com/mathworks/ci/BuildOptions.java new file mode 100644 index 00000000..39f1c290 --- /dev/null +++ b/src/main/java/com/mathworks/ci/BuildOptions.java @@ -0,0 +1,31 @@ + +package com.mathworks.ci; + +/** + * Copyright 2024 The MathWorks, Inc. + * + * Describable class for Build Options. + * + */ + +import hudson.Extension; +import hudson.Util; +import hudson.model.AbstractDescribableImpl; +import hudson.model.Descriptor; +import org.kohsuke.stapler.DataBoundConstructor; + +public class BuildOptions extends AbstractDescribableImpl { + + private String options; + + @DataBoundConstructor + public BuildOptions(String options) { + this.options = Util.fixNull(options); + } + + public String getOptions() { + return this.options; + } + + @Extension public static class DescriptorImpl extends Descriptor {} +} diff --git a/src/main/java/com/mathworks/ci/BuildTargetNote.java b/src/main/java/com/mathworks/ci/BuildTargetNote.java new file mode 100644 index 00000000..51ec6137 --- /dev/null +++ b/src/main/java/com/mathworks/ci/BuildTargetNote.java @@ -0,0 +1,38 @@ +package com.mathworks.ci; + +import com.google.common.annotations.VisibleForTesting; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import hudson.Extension; +import hudson.MarkupText; +import hudson.console.ConsoleAnnotationDescriptor; +import hudson.console.ConsoleAnnotator; +import hudson.console.ConsoleNote; +import java.util.regex.Pattern; + + +public class BuildTargetNote extends ConsoleNote { + @VisibleForTesting + @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Visible for testing") + public static boolean ENABLED = !Boolean.getBoolean(BuildTargetNote.class.getName() + ".disabled"); + + public BuildTargetNote() { + } + + @Override + public ConsoleAnnotator annotate(Object context, MarkupText text, int charPos) { + MarkupText.SubText t = text.findToken(Pattern.compile("MATLAB-Build-")); + String taskName = text.subText(13, text.length()-2).getText(); + taskName = taskName.replace("]","").trim(); + if (t != null) + t.addMarkup(0, t.length()-1, "", ""); + return null; + } + + @Extension + public static final class DescriptorImpl extends ConsoleAnnotationDescriptor { + public String getDisplayName() { + return "Build targets"; + } + } + +} diff --git a/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java b/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java index aeca1fe8..c98deb64 100644 --- a/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java +++ b/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java @@ -5,6 +5,10 @@ * */ +import hudson.model.Run; +import hudson.util.ArgumentListBuilder; +import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; import org.jenkinsci.plugins.workflow.steps.StepContext; import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; @@ -21,15 +25,16 @@ public class MatlabBuildStepExecution extends SynchronousNonBlockingStepExecutio private String tasks; private String startupOptions; + private String buildOptions; + private static String DEFAULT_PLUGIN = "+ciplugins/+jenkins/getDefaultPlugins.m"; + private static String BUILD_REPORT_PLUGIN = "+ciplugins/+jenkins/BuildReportPlugin.m"; + private static String TASK_RUN_PROGRESS_PLUGIN = "+ciplugins/+jenkins/TaskRunProgressPlugin.m"; - public MatlabBuildStepExecution(StepContext context, String tasks, String startupOptions) { + public MatlabBuildStepExecution(StepContext context, String tasks, String startupOptions, String buildOptions) { super(context); this.tasks = tasks; this.startupOptions = startupOptions; - } - - private String getTasks() { - return this.tasks; + this.buildOptions = buildOptions; } @Override @@ -38,12 +43,21 @@ public Void run() throws Exception { final FilePath workspace = getContext().get(FilePath.class); final TaskListener listener = getContext().get(TaskListener.class); final EnvVars env = getContext().get(EnvVars.class); + final Run build = getContext().get(Run.class); //Make sure the Workspace exists before run workspace.mkdirs(); + System.out.println("THE ROOT DIR IS"+ build.getRootDir().toString()); - int exitCode = execMatlabCommand(workspace, launcher, listener, env); + int exitCode = execMatlabCommand(workspace, launcher, listener, env, build); + //Add build result action + FilePath jsonFile = new FilePath(workspace, ".matlab/buildArtifact.json"); + if(jsonFile.exists()){ + jsonFile.copyTo(new FilePath(new File(build.getRootDir().getAbsolutePath()+"/buildArtifact.json"))); + jsonFile.delete(); + } + build.addAction(new BuildArtifactAction(build, workspace)); if(exitCode != 0){ // throw an exception if return code is non-zero @@ -60,7 +74,7 @@ public void stop(Throwable cause) throws Exception { } private int execMatlabCommand(FilePath workspace, Launcher launcher, - TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { + TaskListener listener, EnvVars envVars, Run build) throws IOException, InterruptedException { final String uniqueTmpFldrName = getUniqueNameForRunnerFile(); final String uniqueBuildFile = "build_" + getUniqueNameForRunnerFile().replaceAll("-", "_"); @@ -68,12 +82,18 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); // Create MATLAB script - createMatlabScriptByName(uniqueTmpFolderPath, uniqueBuildFile, workspace, listener); + createMatlabScriptByName(uniqueTmpFolderPath, uniqueBuildFile, listener, envVars); + + // Copy JenkinsLogging plugin in temp folder + copyFileInWorkspace(DEFAULT_PLUGIN,DEFAULT_PLUGIN,uniqueTmpFolderPath); + copyFileInWorkspace(BUILD_REPORT_PLUGIN,BUILD_REPORT_PLUGIN,uniqueTmpFolderPath); + copyFileInWorkspace(TASK_RUN_PROGRESS_PLUGIN,TASK_RUN_PROGRESS_PLUGIN,uniqueTmpFolderPath); + ProcStarter matlabLauncher; - try { - matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, listener, envVars, - "cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'); "+ uniqueBuildFile, startupOptions, uniqueTmpFldrName); + try (BuildConsoleAnnotator bca = new BuildConsoleAnnotator(listener.getLogger(), build.getCharset())) { + matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, bca, envVars, + "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'));"+ uniqueBuildFile, startupOptions, uniqueTmpFldrName); listener.getLogger() .println("#################### Starting command output ####################"); return matlabLauncher.pwd(workspace).join(); @@ -86,19 +106,28 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, } } - private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, FilePath workspace, TaskListener listener) throws IOException, InterruptedException { + private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { // Create a new command runner script in the temp folder. final FilePath matlabBuildFile = new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); - final String tasks = getContext().get(EnvVars.class).expand(getTasks()); + final String tasks = getContext().get(EnvVars.class).expand(this.tasks); + final String buildOptions = getContext().get(EnvVars.class).expand(this.buildOptions); + + // Set ENV variable to override the default plugin list + envVars.put("MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE", "ciplugins.jenkins.getDefaultPlugins"); String cmd = "buildtool"; if (!tasks.trim().isEmpty()) { cmd += " " + tasks; } + + if (!buildOptions.trim().isEmpty()) { + cmd += " " + buildOptions; + } + final String matlabBuildFileContent = - "cd '" + workspace.getRemote().replaceAll("'", "''") + "';\n" + cmd; + "addpath(pwd);cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; // Display the commands on console output for users reference listener.getLogger() @@ -106,4 +135,57 @@ private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqu matlabBuildFile.write(matlabBuildFileContent, "UTF-8"); } + + public ProcStarter getProcessToRunMatlabCommand(FilePath workspace, + Launcher launcher, BuildConsoleAnnotator bca, EnvVars envVars, String matlabCommand, String startupOpts, String uniqueName) + throws IOException, InterruptedException { + // Get node specific temp .matlab directory to copy matlab runner script + FilePath targetWorkspace; + ProcStarter matlabLauncher; + ArgumentListBuilder args = new ArgumentListBuilder(); + if (launcher.isUnix()) { + targetWorkspace = new FilePath(launcher.getChannel(), + workspace.getRemote() + "/" + MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME); + + // Determine whether we're on Mac on Linux + ByteArrayOutputStream kernelStream = new ByteArrayOutputStream(); + launcher.launch() + .cmds("uname") + .masks(true) + .stdout(kernelStream) + .join(); + + String binaryName; + String runnerName = uniqueName + "/run-matlab-command"; + if (kernelStream.toString("UTF-8").contains("Linux")) { + binaryName = "glnxa64/run-matlab-command"; + } else { + binaryName = "maci64/run-matlab-command"; + } + + args.add(MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME + "/" + runnerName); + args.add(matlabCommand); + args.add(startupOpts.split(" ")); + + matlabLauncher = launcher.launch().envs(envVars).cmds(args).stdout(bca); + + // Copy runner for linux platform in workspace. + copyFileInWorkspace(binaryName, runnerName, targetWorkspace); + } else { + targetWorkspace = new FilePath(launcher.getChannel(), + workspace.getRemote() + "\\" + MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME); + + final String runnerName = uniqueName + "\\run-matlab-command.exe"; + + args.add(targetWorkspace.toString() + "\\" + runnerName, "\"" + matlabCommand + "\""); + args.add(startupOpts.split(" ")); + + matlabLauncher = launcher.launch().envs(envVars).cmds(args).stdout(bca); + + // Copy runner for Windows platform in workspace. + copyFileInWorkspace("win64/run-matlab-command.exe", runnerName, + targetWorkspace); + } + return matlabLauncher; + } } diff --git a/src/main/java/com/mathworks/ci/MatlabCommandStepExecution.java b/src/main/java/com/mathworks/ci/MatlabCommandStepExecution.java index 49fece2c..f6a99f68 100644 --- a/src/main/java/com/mathworks/ci/MatlabCommandStepExecution.java +++ b/src/main/java/com/mathworks/ci/MatlabCommandStepExecution.java @@ -69,12 +69,12 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); // Create MATLAB script - createMatlabScriptByName(uniqueTmpFolderPath, uniqueCommandFile, workspace, listener); + createMatlabScriptByName(uniqueTmpFolderPath, uniqueCommandFile, listener); ProcStarter matlabLauncher; try { matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, listener, envVars, - "cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'); "+ uniqueCommandFile, startupOptions, uniqueTmpFldrName); + "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"')); "+ uniqueCommandFile, startupOptions, uniqueTmpFldrName); listener.getLogger() .println("#################### Starting command output ####################"); return matlabLauncher.pwd(workspace).join(); @@ -87,14 +87,14 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, } } - private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, FilePath workspace, TaskListener listener) throws IOException, InterruptedException { + private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, TaskListener listener) throws IOException, InterruptedException { // Create a new command runner script in the temp folder. final FilePath matlabCommandFile = new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); final String cmd = getContext().get(EnvVars.class).expand(getCommand()); final String matlabCommandFileContent = - "cd '" + workspace.getRemote().replaceAll("'", "''") + "';\n" + cmd; + "cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; // Display the commands on console output for users reference listener.getLogger() diff --git a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java b/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java index 3e7b4e34..b09ebf4b 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java +++ b/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java @@ -5,6 +5,9 @@ * */ +import hudson.util.ArgumentListBuilder; +import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; import javax.annotation.Nonnull; import org.kohsuke.stapler.DataBoundConstructor; @@ -22,7 +25,6 @@ import hudson.model.Computer; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; -import hudson.Util; import jenkins.tasks.SimpleBuildStep; import net.sf.json.JSONObject; @@ -30,6 +32,10 @@ public class RunMatlabBuildBuilder extends Builder implements SimpleBuildStep, M private int buildResult; private String tasks; private StartupOptions startupOptions; + private BuildOptions buildOptions; + private static String DEFAULT_PLUGIN = "+ciplugins/+jenkins/getDefaultPlugins.m"; + private static String BUILD_REPORT_PLUGIN = "+ciplugins/+jenkins/BuildReportPlugin.m"; + private static String TASK_RUN_PROGRESS_PLUGIN = "+ciplugins/+jenkins/TaskRunProgressPlugin.m"; @DataBoundConstructor public RunMatlabBuildBuilder() {} @@ -45,6 +51,11 @@ public void setStartupOptions(StartupOptions startupOptions) { this.startupOptions = startupOptions; } + @DataBoundSetter + public void setBuildOptions (BuildOptions buildOptions) { + this.buildOptions = buildOptions; + } + public String getTasks() { return this.tasks; } @@ -52,6 +63,10 @@ public String getTasks() { public StartupOptions getStartupOptions() { return this.startupOptions; } + + public BuildOptions getBuildOptions() { + return this.buildOptions; + } @Extension public static class RunMatlabBuildDescriptor extends BuildStepDescriptor { @@ -93,8 +108,15 @@ public void perform(@Nonnull Run build, @Nonnull FilePath workspace, // Invoke MATLAB build and transfer output to standard // Output Console + buildResult = execMatlabCommand(workspace, launcher, listener, env, build); - buildResult = execMatlabCommand(workspace, launcher, listener, env); + //Add build result action + FilePath jsonFile = new FilePath(workspace, ".matlab/buildArtifact.json"); + if(jsonFile.exists()){ + jsonFile.copyTo(new FilePath(new File(build.getRootDir().getAbsolutePath()+"/buildArtifact.json"))); + jsonFile.delete(); + } + build.addAction(new BuildArtifactAction(build, workspace)); if (buildResult != 0) { build.setResult(Result.FAILURE); @@ -102,7 +124,7 @@ public void perform(@Nonnull Run build, @Nonnull FilePath workspace, } private int execMatlabCommand(FilePath workspace, Launcher launcher, - TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { + TaskListener listener, EnvVars envVars, @Nonnull Run build) throws IOException, InterruptedException { /* * Handle the case for using MATLAB Axis for multi conf projects by adding appropriate @@ -117,12 +139,19 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); // Create MATLAB script - createMatlabScriptByName(uniqueTmpFolderPath, uniqueBuildFile, workspace, listener, envVars); + createMatlabScriptByName(uniqueTmpFolderPath, uniqueBuildFile, listener, envVars); + // Copy JenkinsLogging plugin in temp folder + copyFileInWorkspace(DEFAULT_PLUGIN,DEFAULT_PLUGIN,uniqueTmpFolderPath); + copyFileInWorkspace(BUILD_REPORT_PLUGIN,BUILD_REPORT_PLUGIN,uniqueTmpFolderPath); + copyFileInWorkspace(TASK_RUN_PROGRESS_PLUGIN,TASK_RUN_PROGRESS_PLUGIN,uniqueTmpFolderPath); + ProcStarter matlabLauncher; + BuildConsoleAnnotator bca = new BuildConsoleAnnotator(listener.getLogger(), build.getCharset()); String options = getStartupOptions() == null ? "" : getStartupOptions().getOptions(); try { - matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, listener, envVars, - "cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"');"+ uniqueBuildFile, options, uniqueTmpFldrName); + matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, bca, envVars, + "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'));"+ uniqueBuildFile, options, uniqueTmpFldrName); + listener.getLogger() .println("#################### Starting command output ####################"); @@ -132,6 +161,7 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, listener.getLogger().println(e.getMessage()); return 1; } finally { + bca.forceEol(); // Cleanup the tmp directory if (uniqueTmpFolderPath.exists()) { uniqueTmpFolderPath.deleteRecursive(); @@ -139,20 +169,29 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, } } - private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, FilePath workspace, TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { + private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { // Create a new command runner script in the temp folder. final FilePath matlabCommandFile = new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); final String tasks = envVars.expand(getTasks()); + final String buildOptions = envVars.expand(getBuildOptions() == null ? "": getBuildOptions().getOptions()); + + // Set ENV variable to override the default plugin list + envVars.put("MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE", "ciplugins.jenkins.getDefaultPlugins"); + String cmd = "buildtool"; if (!tasks.trim().isEmpty()) { cmd += " " + tasks; } + if (!buildOptions.trim().isEmpty()) { + cmd += " " + buildOptions; + } + final String matlabCommandFileContent = - "cd '" + workspace.getRemote().replaceAll("'", "''") + "';\n" + cmd; + "addpath(pwd);cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; // Display the commands on console output for users reference listener.getLogger() @@ -160,4 +199,58 @@ private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqu matlabCommandFile.write(matlabCommandFileContent, "UTF-8"); } + + + private ProcStarter getProcessToRunMatlabCommand(FilePath workspace, + Launcher launcher, BuildConsoleAnnotator bca, EnvVars envVars, String matlabCommand, String startupOpts, String uniqueName) + throws IOException, InterruptedException { + // Get node specific temp .matlab directory to copy matlab runner script + FilePath targetWorkspace; + ProcStarter matlabLauncher; + ArgumentListBuilder args = new ArgumentListBuilder(); + if (launcher.isUnix()) { + targetWorkspace = new FilePath(launcher.getChannel(), + workspace.getRemote() + "/" + MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME); + + // Determine whether we're on Mac on Linux + ByteArrayOutputStream kernelStream = new ByteArrayOutputStream(); + launcher.launch() + .cmds("uname") + .masks(true) + .stdout(kernelStream) + .join(); + + String binaryName; + String runnerName = uniqueName + "/run-matlab-command"; + if (kernelStream.toString("UTF-8").contains("Linux")) { + binaryName = "glnxa64/run-matlab-command"; + } else { + binaryName = "maci64/run-matlab-command"; + } + + args.add(MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME + "/" + runnerName); + args.add(matlabCommand); + args.add(startupOpts.split(" ")); + + matlabLauncher = launcher.launch().envs(envVars).cmds(args).stdout(bca); + + // Copy runner for linux platform in workspace. + copyFileInWorkspace(binaryName, runnerName, targetWorkspace); + } else { + targetWorkspace = new FilePath(launcher.getChannel(), + workspace.getRemote() + "\\" + MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME); + + final String runnerName = uniqueName + "\\run-matlab-command.exe"; + + args.add(targetWorkspace.toString() + "\\" + runnerName, "\"" + matlabCommand + "\""); + args.add(startupOpts.split(" ")); + + matlabLauncher = launcher.launch().envs(envVars).cmds(args).stdout(bca); + + // Copy runner for Windows platform in workspace. + copyFileInWorkspace("win64/run-matlab-command.exe", runnerName, + targetWorkspace); + } + return matlabLauncher; + } } diff --git a/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java b/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java index 2992ae58..091c993f 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java +++ b/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java @@ -25,6 +25,7 @@ public class RunMatlabBuildStep extends Step { private String tasks; private String startupOptions; + private String buildOptions; @DataBoundConstructor public RunMatlabBuildStep() { @@ -39,6 +40,10 @@ public String getStartupOptions() { return Util.fixNull(startupOptions); } + public String getBuildOptions() { + return Util.fixNull(buildOptions); + } + @DataBoundSetter public void setTasks(String tasks) { this.tasks = tasks; @@ -49,9 +54,14 @@ public void setStartupOptions(String startupOptions) { this.startupOptions = startupOptions; } + @DataBoundSetter + public void setBuildOptions (String buildOptions) { + this.buildOptions = buildOptions; + } + @Override public StepExecution start(StepContext context) throws Exception { - return new MatlabBuildStepExecution(context, getTasks(), getStartupOptions()); + return new MatlabBuildStepExecution(context, getTasks(), getStartupOptions(), getBuildOptions()); } @Extension diff --git a/src/main/java/com/mathworks/ci/RunMatlabCommandBuilder.java b/src/main/java/com/mathworks/ci/RunMatlabCommandBuilder.java index 33685293..6bbfb138 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabCommandBuilder.java +++ b/src/main/java/com/mathworks/ci/RunMatlabCommandBuilder.java @@ -122,13 +122,13 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); // Create MATLAB script - createMatlabScriptByName(uniqueTmpFolderPath, uniqueCommandFile, workspace, listener, envVars); + createMatlabScriptByName(uniqueTmpFolderPath, uniqueCommandFile, listener, envVars); ProcStarter matlabLauncher; String options = getStartupOptions() == null ? "" : getStartupOptions().getOptions(); try { matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, listener, envVars, - "cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"');"+ uniqueCommandFile, options, uniqueTmpFldrName); + "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'));"+ uniqueCommandFile, options, uniqueTmpFldrName); listener.getLogger() .println("#################### Starting command output ####################"); @@ -145,14 +145,14 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, } } - private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, FilePath workspace, TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { + private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { // Create a new command runner script in the temp folder. final FilePath matlabCommandFile = new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); final String cmd = envVars.expand(getMatlabCommand()); final String matlabCommandFileContent = - "cd '" + workspace.getRemote().replaceAll("'", "''") + "';\n" + cmd; + "cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; // Display the commands on console output for users reference listener.getLogger() diff --git a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m new file mode 100644 index 00000000..ccdfbd94 --- /dev/null +++ b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m @@ -0,0 +1,25 @@ +classdef BuildReportPlugin < matlab.buildtool.plugins.BuildRunnerPlugin + +% Copyright 2024 The MathWorks, Inc. + + methods (Access=protected) + + function runTaskGraph(plugin, pluginData) + runTaskGraph@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData); + fID = fopen(fullfile(getenv("WORKSPACE"),'.matlab/buildArtifact.json'), 'w'); + taskDetails = struct(); + for idx = 1:numel(pluginData.TaskResults) + taskDetails(idx).name = pluginData.TaskResults(idx).Name; + taskDetails(idx).description = pluginData.TaskGraph.Tasks(idx).Description; + taskDetails(idx).failed = pluginData.TaskResults(idx).Failed; + taskDetails(idx).skipped = pluginData.TaskResults(idx).Skipped; + taskDetails(idx).duration = string(pluginData.TaskResults(idx).Duration); + end + a = struct("taskDetails",taskDetails); + s = jsonencode(a,"PrettyPrint",true); + fprintf(fID, '%s',s); + fclose(fID); + end + + end +end \ No newline at end of file diff --git a/src/main/resources/+ciplugins/+jenkins/TaskRunProgressPlugin.m b/src/main/resources/+ciplugins/+jenkins/TaskRunProgressPlugin.m new file mode 100644 index 00000000..077837ed --- /dev/null +++ b/src/main/resources/+ciplugins/+jenkins/TaskRunProgressPlugin.m @@ -0,0 +1,13 @@ +classdef TaskRunProgressPlugin < matlab.buildtool.plugins.BuildRunnerPlugin +% + +% Copyright 2023 The MathWorks, Inc. + + methods (Access=protected) + + function runTask(plugin, pluginData) + disp("[MATLAB-Build-" + pluginData.TaskResults.Name + "]"); + runTask@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData); + end + end + end \ No newline at end of file diff --git a/src/main/resources/+ciplugins/+jenkins/getDefaultPlugins.m b/src/main/resources/+ciplugins/+jenkins/getDefaultPlugins.m new file mode 100644 index 00000000..b7a1f839 --- /dev/null +++ b/src/main/resources/+ciplugins/+jenkins/getDefaultPlugins.m @@ -0,0 +1,14 @@ +function plugins = getDefaultPlugins(pluginProviderData) +% + +% Copyright 2024 The MathWorks, Inc. +arguments + pluginProviderData (1,1) struct = struct(); +end + +plugins = [ ... + matlab.buildtool.internal.getFactoryDefaultPlugins(pluginProviderData) ... + ciplugins.jenkins.BuildReportPlugin() ... + ciplugins.jenkins.TaskRunProgressPlugin() ... +]; +end \ No newline at end of file diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly new file mode 100644 index 00000000..c8cf845c --- /dev/null +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly @@ -0,0 +1,91 @@ + + + + + + + + + +

+ +

+
+ + + No tasks + + +
+ ${(it.totalCount)} Tasks + + (${h.getDiffString(it.failCount-prev.failCount)}) + + + , Skipped ${(it.skipCount)} + + (${h.getDiffString(it.skipCount-prev.skipCount)}) + + +
+
+ +
+ +
+
+
+ ${(it.failCount)} Failures + + (${h.getDiffString(it.totalCount-prev.totalCount)}) + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + +
Task NameStatus DescriptionDuration (HH:MM:SS)
+ ${p.taskName} + + + + FAILED + + + + PASSED + + + + SKIPPED + + + + + ${p.taskDescription} + + ${p.taskDuration}
+
+
+
\ No newline at end of file diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly new file mode 100644 index 00000000..ee5beef9 --- /dev/null +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly @@ -0,0 +1,23 @@ + + + +

MATLAB Build Results

+ + +
Unable to run a MATLAB build.
+
+
+

Tasks run: ${it.totalCount}

+
+ Failed: ${it.failCount} +
+
+ Skipped: ${it.skipCount} +
+
+
\ No newline at end of file diff --git a/src/main/resources/com/mathworks/ci/BuildOptions/config.jelly b/src/main/resources/com/mathworks/ci/BuildOptions/config.jelly new file mode 100644 index 00000000..c2716089 --- /dev/null +++ b/src/main/resources/com/mathworks/ci/BuildOptions/config.jelly @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly index b5e12dd2..3693ca23 100644 --- a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly @@ -6,5 +6,7 @@
+ +
diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html new file mode 100644 index 00000000..751d20ba --- /dev/null +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html @@ -0,0 +1,6 @@ +
+ Specify a space-separated list of MATLAB build options. The plugin supports + the build options that you can pass to the buildtool command.
+ Example: -continueOnFailure
+ Example: -continueOnFailure -skip test +
diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html index 033e04a2..98cde2a1 100644 --- a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html @@ -1,3 +1,8 @@
- A space-separated list of MATLAB startup options. -
+ Specify a space-separated list of MATLAB startup options.
+ Example: -nojvm
+ Example: -nojvm -logfile output.log +
 
+ Note: Specifying the -batch or -r option is not supported. + + \ No newline at end of file diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly index df600b40..4687525c 100644 --- a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly @@ -1,11 +1,15 @@ - + - + + + + + diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html new file mode 100644 index 00000000..751d20ba --- /dev/null +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html @@ -0,0 +1,6 @@ +
+ Specify a space-separated list of MATLAB build options. The plugin supports + the build options that you can pass to the buildtool command.
+ Example: -continueOnFailure
+ Example: -continueOnFailure -skip test +
diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html index 033e04a2..d450f39a 100644 --- a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html +++ b/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html @@ -1,3 +1,7 @@
- A space-separated list of MATLAB startup options. + Specify a space-separated list of MATLAB startup options.
+ Example: -nojvm
+ Example: -nojvm -logfile output.log +
 
+ Note: Specifying the -batch or -r option is not supported.
diff --git a/src/test/java/com/mathworks/ci/BuildArtifactActionTest.java b/src/test/java/com/mathworks/ci/BuildArtifactActionTest.java new file mode 100644 index 00000000..1bfadb4b --- /dev/null +++ b/src/test/java/com/mathworks/ci/BuildArtifactActionTest.java @@ -0,0 +1,233 @@ +package com.mathworks.ci; + + +import hudson.FilePath; +import hudson.model.FreeStyleBuild; +import hudson.model.FreeStyleProject; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import org.json.simple.parser.ParseException; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; + +public class BuildArtifactActionTest { + private FreeStyleProject project; + private UseMatlabVersionBuildWrapper buildWrapper; + private RunMatlabBuildBuilder scriptBuilder; + + private static String VERSION_INFO_XML_FILE = "VersionInfo.xml"; + + public BuildArtifactActionTest(){ + } + + @Rule + public JenkinsRule jenkins = new JenkinsRule(); + + + @Before + public void testSetup() throws IOException { + this.project = jenkins.createFreeStyleProject(); + this.scriptBuilder = new RunMatlabBuildBuilder(); + this.buildWrapper = new UseMatlabVersionBuildWrapper(); + } + + @After + public void testTearDown() { + this.project = null; + this.scriptBuilder = null; + } + + private String getMatlabroot(String version) throws URISyntaxException { + String defaultVersionInfo = "versioninfo/R2017a/" + VERSION_INFO_XML_FILE; + String userVersionInfo = "versioninfo/" + version + "/" + VERSION_INFO_XML_FILE; + URL matlabRootURL = Optional.ofNullable(getResource(userVersionInfo)) + .orElseGet(() -> getResource(defaultVersionInfo)); + File matlabRoot = new File(matlabRootURL.toURI()); + return matlabRoot.getAbsolutePath().replace(File.separator + VERSION_INFO_XML_FILE, "") + .replace("R2017a", version); + } + + private URL getResource(String resource) { + return BuildArtifactAction.class.getClassLoader().getResource(resource); + } + + /** + * Verify if total BuildArtifacts returned from artifact file. + *5 + */ + + @Test + public void verifyBuildArtifactsReturned() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); + List ba = ac.getBuildArtifact(); + int expectedSize = ba.size(); + Assert.assertEquals("The build names are not matching",3,expectedSize); + } + + /** + * Verify if total Failed count returned from artifact file. + * + */ + + @Test + public void verifyFailedCount() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); + List ba = ac.getBuildArtifact(); + boolean expectedStatus = ba.get(0).getTaskFailed(); + Assert.assertEquals("The task is passed",false,expectedStatus); + } + + /** + * Verify if total skipped count returned from artifact file. + * + */ + + @Test + public void verifySkipCount() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); + List ba = ac.getBuildArtifact(); + Assert.assertEquals("The task is not skipped",true,ba.get(0).getTaskSkipped()); + } + + /** + * Verify if duration returned from artifact file. + * + */ + + @Test + public void verifyDurationIsAccurate() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); + List ba = ac.getBuildArtifact(); + Assert.assertEquals("The task duration is not matching","00:02:53",ba.get(0).getTaskDuration()); + } + + /** + * Verify if Task description returned from artifact file. + * + */ + + @Test + public void verifyTaskDescriptionIsAccurate() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); + List ba = ac.getBuildArtifact(); + Assert.assertEquals("The task description is not matching","Test show",ba.get(0).getTaskDescription()); + } + + /** + * Verify if Task name returned from artifact file. + * + */ + + @Test + public void verifyTaskNameIsAccurate() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); + List ba = ac.getBuildArtifact(); + Assert.assertEquals("The task name is not matching","show",ba.get(0).getTaskName()); + } + + /** + * Verify if total count returned from artifact file. + * + */ + + @Test + public void verifyTotalTaskCountIsAccurate() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + Assert.assertEquals("Total task count is not correct",1,ac.getTotalCount()); + } + + /** + * Verify if total count returned from artifact file. + * + */ + + @Test + public void verifyTotalTaskCountIsAccurate2() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + Assert.assertEquals("Total task count is not correct",3,ac.getTotalCount()); + } + + /** + * Verify if total failed count returned from artifact file. + * + */ + + @Test + public void verifyTotalFailedTaskCountIsAccurate() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + Assert.assertEquals("Total task count is not correct",3,ac.getTotalCount()); + Assert.assertEquals("Total task failed count is not correct",1,ac.getFailCount()); + } + /** + * Verify if total skipped count returned from artifact file. + * + */ + + @Test + public void verifyTotalSkipTaskCountIsAccurate() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { + FreeStyleBuild build = getFreestyleBuild(); + FilePath artifactRoot = new FilePath(build.getRootDir()); + copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); + BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + Assert.assertEquals("Total task count is not correct",3,ac.getTotalCount()); + Assert.assertEquals("Total task skip count is not correct",1,ac.getSkipCount()); + } + + + + private void copyFileInWorkspace(String sourceFile, String targetFile, FilePath targetWorkspace) + throws IOException, InterruptedException { + final ClassLoader classLoader = getClass().getClassLoader(); + FilePath targetFilePath = new FilePath(targetWorkspace, targetFile); + InputStream in = classLoader.getResourceAsStream(sourceFile); + targetFilePath.copyFrom(in); + // set executable permission + targetFilePath.chmod(0777); + } + + private FreeStyleBuild getFreestyleBuild() throws ExecutionException, InterruptedException, URISyntaxException { + this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2017a"))); + project.getBuildWrappersList().add(this.buildWrapper); + scriptBuilder.setTasks(""); + project.getBuildersList().add(this.scriptBuilder); + FreeStyleBuild build = project.scheduleBuild2(0).get(); + return build; + } +} diff --git a/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java b/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java index 8d80edf7..72f57c36 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java +++ b/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java @@ -203,7 +203,8 @@ public void verifyBuildPicksTheCorrectBuildBatch() throws Exception { project.getBuildersList().add(this.scriptBuilder); FreeStyleBuild build = project.scheduleBuild2(0).get(); jenkins.assertLogContains("Generating MATLAB script with content", build); - jenkins.assertLogContains("buildtool compile", build); + jenkins.assertLogContains("buildtool", build); + jenkins.assertLogContains("compile", build); } /* @@ -221,6 +222,21 @@ public void verifyBuildPicksTheCorrectStartupOptions() throws Exception { jenkins.assertLogContains("-nojvm -uniqueoption", build); } + /* + * Test to verify builder correctly sets build options that user entered. + */ + @Test + public void verifyBuildPicksTheCorrectBuildOptions() throws Exception { + this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); + project.getBuildWrappersList().add(this.buildWrapper); + scriptBuilder.setTasks(""); + scriptBuilder.setBuildOptions(new BuildOptions("-continueOnFailure -skip compile")); + project.getBuildersList().add(this.scriptBuilder); + FreeStyleBuild build = project.scheduleBuild2(0).get(); + jenkins.assertLogContains("Generating MATLAB script with content", build); + jenkins.assertLogContains("-continueOnFailure -skip compile", build); + } + /* * Test to verify if MATLAB scratch file is not generated in workspace for this builder. */ @@ -243,13 +259,16 @@ public void verifyBuildSupportsEnvVar() throws Exception { EnvironmentVariablesNodeProperty prop = new EnvironmentVariablesNodeProperty(); EnvVars var = prop.getEnvVars(); var.put("TASKS", "compile"); + var.put("BUILD_OPTIONS", "-continueOnFailure -skip test"); jenkins.jenkins.getGlobalNodeProperties().add(prop); this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); project.getBuildWrappersList().add(this.buildWrapper); scriptBuilder.setTasks("$TASKS"); + scriptBuilder.setBuildOptions(new BuildOptions("$BUILD_OPTIONS")); project.getBuildersList().add(scriptBuilder); FreeStyleBuild build = project.scheduleBuild2(0).get(); - jenkins.assertLogContains("buildtool compile", build); + jenkins.assertLogContains("compile", build); + jenkins.assertLogContains("-continueOnFailure -skip test", build); } /* diff --git a/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java b/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java index bd4ea2b3..bab80f74 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java +++ b/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java @@ -123,6 +123,18 @@ public void verifyStartupOptionsSameAsScript() throws Exception { j.assertLogContains("-nojvm -uniqueoption", build); } + /* + * Verify appropriate build options are invoked as in pipeline script + */ + @Test + public void verifyBuildOptionsSameAsScript() throws Exception { + project.setDefinition( + new CpsFlowDefinition("node { runMATLABBuild(buildOptions: '-continueOnFailure -skip compile') }", true)); + + WorkflowRun build = project.scheduleBuild2(0).get(); + j.assertLogContains("-continueOnFailure -skip compile", build); + } + /* * Verify script can run Matrix build */ diff --git a/src/test/resources/buildArtifacts.t2/buildArtifact.json b/src/test/resources/buildArtifacts.t2/buildArtifact.json new file mode 100644 index 00000000..5c9d061d --- /dev/null +++ b/src/test/resources/buildArtifacts.t2/buildArtifact.json @@ -0,0 +1,9 @@ +{ + "taskDetails": { + "name": "show", + "description": "Test show", + "failed": false, + "skipped": true, + "duration": "00:02:53" + } +} \ No newline at end of file diff --git a/src/test/resources/buildArtifacts/t1/buildArtifact.json b/src/test/resources/buildArtifacts/t1/buildArtifact.json new file mode 100644 index 00000000..f2f5d392 --- /dev/null +++ b/src/test/resources/buildArtifacts/t1/buildArtifact.json @@ -0,0 +1,25 @@ +{ + "taskDetails": [ + { + "name": "check", + "description": "Checks Description", + "failed": false, + "skipped": false, + "duration": "00:00:00" + }, + { + "name": "show", + "description": "", + "failed": true, + "skipped": false, + "duration": "00:00:00" + }, + { + "name": "test", + "description": "tests Dscription", + "failed": false, + "skipped": true, + "duration": "00:00:00" + } + ] +} \ No newline at end of file From 914fcfbcdea0f940970ebb215548e54f039071b2 Mon Sep 17 00:00:00 2001 From: sameagen Date: Mon, 25 Mar 2024 11:46:22 -0400 Subject: [PATCH 10/52] First draft of refactor --- pom.xml | 7 + .../com/mathworks/ci/BuildArtifactAction.java | 2 +- .../mathworks/ci/BuildConsoleAnnotator.java | 3 +- .../ci/MatlabBuildStepExecution.java | 191 ------------ .../mathworks/ci/MatlabBuilderConstants.java | 52 ++-- .../ci/MatlabCommandStepExecution.java | 105 ------- .../ci/MatlabExecutionException.java | 2 +- .../ci/MatlabRunTestsStepExecution.java | 94 ------ .../mathworks/ci/RunMatlabBuildBuilder.java | 256 ---------------- .../mathworks/ci/RunMatlabCommandBuilder.java | 163 ---------- .../ci/actions/MatlabActionFactory.java | 24 ++ .../ci/actions/RunMatlabBuildAction.java | 100 ++++++ .../ci/actions/RunMatlabCommandAction.java | 36 +++ .../ci/actions/RunMatlabTestsAction.java | 127 ++++++++ .../ci/freestyle/RunMatlabBuildBuilder.java | 160 ++++++++++ .../ci/freestyle/RunMatlabCommandBuilder.java | 146 +++++++++ .../RunMatlabTestsBuilder.java | 201 +++++------- .../{ => freestyle/options}/BuildOptions.java | 2 +- .../options}/SelectByFolder.java | 9 +- .../{ => freestyle/options}/SourceFolder.java | 9 +- .../options}/SourceFolderPaths.java | 2 +- .../options}/StartupOptions.java | 3 +- .../{ => freestyle/options}/TestFolders.java | 2 +- .../ci/parameters/BuildActionParameters.java | 39 +++ .../ci/parameters/MatlabActionParameters.java | 67 ++++ .../ci/parameters/RunActionParameters.java | 32 ++ .../ci/parameters/TestActionParameters.java | 137 +++++++++ .../ci/pipeline/MatlabBuildStepExecution.java | 57 ++++ .../pipeline/MatlabCommandStepExecution.java | 61 ++++ .../pipeline/MatlabRunTestsStepExecution.java | 58 ++++ .../ci/{ => pipeline}/RunMatlabBuildStep.java | 6 +- .../{ => pipeline}/RunMatlabCommandStep.java | 4 +- .../ci/{ => pipeline}/RunMatlabTestsStep.java | 76 ++--- .../ci/utilities/MatlabCommandRunner.java | 209 +++++++++++++ .../RunMatlabBuildBuilder/config.jelly | 0 .../help-buildOptions.html | 0 .../help-startupOptions.html | 0 .../RunMatlabBuildBuilder/help-tasks.html | 0 .../RunMatlabCommandBuilder/config.jelly | 0 .../help-matlabCommand.html | 0 .../help-startupOptions.html | 0 .../SelectByTag/config.jelly | 0 .../RunMatlabTestsBuilder/config.jelly | 0 .../help-coberturaArtifact.html | 0 .../help-junitArtifact.html | 0 .../help-loggingLevel.html | 0 .../help-modelCoverageArtifact.html | 0 .../help-outputDetail.html | 0 .../help-pdfReportArtifact.html | 0 .../help-selectByFolder.html | 0 .../help-selectByTag.html | 0 .../help-sourceFolder.html | 0 .../help-startupOptions.html | 0 .../help-stmResultsArtifact.html | 0 .../RunMatlabTestsBuilder/help-strict.html | 0 .../help-tapArtifact.html | 0 .../help-useParallel.html | 0 .../options}/BuildOptions/config.jelly | 0 .../options}/SelectByFolder/config.jelly | 0 .../options}/SourceFolder/config.jelly | 0 .../options}/StartupOptions/config.jelly | 0 .../RunMatlabBuildStep/config.jelly | 0 .../RunMatlabBuildStep/help-buildOptions.html | 0 .../help-startupOptions.html | 0 .../RunMatlabBuildStep/help-tasks.html | 0 .../RunMatlabCommandStep/config.jelly | 0 .../RunMatlabCommandStep/help-command.html | 0 .../help-startupOptions.html | 0 .../RunMatlabTestsStep/config.jelly | 0 .../help-codeCoverageCobertura.html | 0 .../RunMatlabTestsStep/help-loggingLevel.html | 0 .../help-modelCoverageCobertura.html | 0 .../RunMatlabTestsStep/help-outputDetail.html | 0 .../help-selectByFolder.html | 0 .../RunMatlabTestsStep/help-selectByTag.html | 0 .../RunMatlabTestsStep/help-sourceFolder.html | 0 .../help-startupOptions.html | 0 .../RunMatlabTestsStep/help-strict.html | 0 .../help-testResultsJUnit.html | 0 .../help-testResultsPDF.html | 0 .../help-testResultsSimulinkTest.html | 0 .../help-testResultsTAP.html | 0 .../RunMatlabTestsStep/help-useParallel.html | 0 .../ci/RunMatlabBuildStepTester.java | 47 --- .../ci/RunMatlabCommandStepTester.java | 48 --- .../ci/RunMatlabTestsStepTester.java | 55 ---- .../com/mathworks/ci/TestStepExecution.java | 49 --- .../mathworks/ci/BuildArtifactActionTest.java | 2 + .../mathworks/ci/MatlabInstallationTest.java | 6 +- .../ci/RunMatlabBuildBuilderTest.java | 8 +- .../ci/RunMatlabBuildBuilderTester.java | 2 + .../mathworks/ci/RunMatlabBuildStepTest.java | 31 +- .../ci/RunMatlabCommandBuilderTest.java | 7 +- .../ci/RunMatlabCommandBuilderTester.java | 2 + .../ci/RunMatlabCommandStepTest.java | 46 +-- .../RunMatlabTestBuilderPersistenceTest.java | 5 +- .../ci/RunMatlabTestsBuilderTest.java | 97 ++---- .../ci/RunMatlabTestsBuilderTester.java | 4 +- .../mathworks/ci/RunMatlabTestsStepTest.java | 52 +--- .../com/mathworks/ci/TestMessage.java | 0 .../ci/UseMatlabVersionBuildWrapperTest.java | 0 .../ci/actions/RunMatlabBuildActionTest.java | 170 +++++++++++ .../actions/RunMatlabCommandActionTest.java | 68 +++++ .../ci/actions/RunMatlabTestsActionTest.java | 172 +++++++++++ .../RunMatlabBuildBuilderUnitTest.java | 106 +++++++ .../RunMatlabCommandBuilderUnitTest.java | 102 +++++++ .../RunMatlabTestsBuilderUnitTest.java | 159 ++++++++++ ....MatlabBuildStepExecutionUnitTest.java.swp | Bin 0 -> 12288 bytes ...atlabCommandStepExecutionUnitTest.java.swp | Bin 0 -> 12288 bytes ...tlabRunTestsStepExecutionUnitTest.java.swp | Bin 0 -> 12288 bytes .../.RunMatlabBuildStepUnitTest.java.swp | Bin 0 -> 12288 bytes .../.RunMatlabCommandStepUnitTest.java.swp | Bin 0 -> 12288 bytes .../.RunMatlabTestsStepUnitTest.java.swp | Bin 0 -> 12288 bytes .../MatlabBuildStepExecutionUnitTest.java | 84 +++++ .../MatlabCommandStepExecutionUnitTest.java | 82 +++++ .../MatlabRunTestsStepExecutionUnitTest.java | 65 ++++ .../pipeline/RunMatlabBuildStepUnitTest.java | 46 +++ .../RunMatlabCommandStepUnitTest.java | 43 +++ .../pipeline/RunMatlabTestsStepUnitTest.java | 91 ++++++ .../ci/utilities/MatlabCommandRunnerTest.java | 288 ++++++++++++++++++ .../utilities/MatlabCommandRunnerTester.java | 26 ++ .../org.mockito.plugins.MockMaker | 1 + src/test/resources/testcontent.txt | 1 + 123 files changed, 3012 insertions(+), 1395 deletions(-) delete mode 100644 src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java delete mode 100644 src/main/java/com/mathworks/ci/MatlabCommandStepExecution.java delete mode 100644 src/main/java/com/mathworks/ci/MatlabRunTestsStepExecution.java delete mode 100644 src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java delete mode 100644 src/main/java/com/mathworks/ci/RunMatlabCommandBuilder.java create mode 100644 src/main/java/com/mathworks/ci/actions/MatlabActionFactory.java create mode 100644 src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java create mode 100644 src/main/java/com/mathworks/ci/actions/RunMatlabCommandAction.java create mode 100644 src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java create mode 100644 src/main/java/com/mathworks/ci/freestyle/RunMatlabBuildBuilder.java create mode 100644 src/main/java/com/mathworks/ci/freestyle/RunMatlabCommandBuilder.java rename src/main/java/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder.java (72%) rename src/main/java/com/mathworks/ci/{ => freestyle/options}/BuildOptions.java (93%) rename src/main/java/com/mathworks/ci/{ => freestyle/options}/SelectByFolder.java (79%) rename src/main/java/com/mathworks/ci/{ => freestyle/options}/SourceFolder.java (81%) rename src/main/java/com/mathworks/ci/{ => freestyle/options}/SourceFolderPaths.java (94%) rename src/main/java/com/mathworks/ci/{ => freestyle/options}/StartupOptions.java (93%) rename src/main/java/com/mathworks/ci/{ => freestyle/options}/TestFolders.java (92%) create mode 100644 src/main/java/com/mathworks/ci/parameters/BuildActionParameters.java create mode 100644 src/main/java/com/mathworks/ci/parameters/MatlabActionParameters.java create mode 100644 src/main/java/com/mathworks/ci/parameters/RunActionParameters.java create mode 100644 src/main/java/com/mathworks/ci/parameters/TestActionParameters.java create mode 100644 src/main/java/com/mathworks/ci/pipeline/MatlabBuildStepExecution.java create mode 100644 src/main/java/com/mathworks/ci/pipeline/MatlabCommandStepExecution.java create mode 100644 src/main/java/com/mathworks/ci/pipeline/MatlabRunTestsStepExecution.java rename src/main/java/com/mathworks/ci/{ => pipeline}/RunMatlabBuildStep.java (95%) rename src/main/java/com/mathworks/ci/{ => pipeline}/RunMatlabCommandStep.java (96%) rename src/main/java/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep.java (68%) create mode 100644 src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabBuildBuilder/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabBuildBuilder/help-buildOptions.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabBuildBuilder/help-startupOptions.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabBuildBuilder/help-tasks.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabCommandBuilder/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabCommandBuilder/help-matlabCommand.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabCommandBuilder/help-startupOptions.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/SelectByTag/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-coberturaArtifact.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-junitArtifact.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-loggingLevel.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-modelCoverageArtifact.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-outputDetail.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-pdfReportArtifact.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-selectByFolder.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-selectByTag.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-sourceFolder.html (100%) rename src/main/resources/com/mathworks/ci/{RunMatlabCommandStep => freestyle/RunMatlabTestsBuilder}/help-startupOptions.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-stmResultsArtifact.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-strict.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-tapArtifact.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle}/RunMatlabTestsBuilder/help-useParallel.html (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle/options}/BuildOptions/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle/options}/SelectByFolder/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle/options}/SourceFolder/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => freestyle/options}/StartupOptions/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabBuildStep/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabBuildStep/help-buildOptions.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabBuildStep/help-startupOptions.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabBuildStep/help-tasks.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabCommandStep/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabCommandStep/help-command.html (100%) rename src/main/resources/com/mathworks/ci/{RunMatlabTestsBuilder => pipeline/RunMatlabCommandStep}/help-startupOptions.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/config.jelly (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-codeCoverageCobertura.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-loggingLevel.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-modelCoverageCobertura.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-outputDetail.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-selectByFolder.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-selectByTag.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-sourceFolder.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-startupOptions.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-strict.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-testResultsJUnit.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-testResultsPDF.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-testResultsSimulinkTest.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-testResultsTAP.html (100%) rename src/main/resources/com/mathworks/ci/{ => pipeline}/RunMatlabTestsStep/help-useParallel.html (100%) delete mode 100644 src/test/java/com/mathworks/ci/RunMatlabBuildStepTester.java delete mode 100644 src/test/java/com/mathworks/ci/RunMatlabCommandStepTester.java delete mode 100644 src/test/java/com/mathworks/ci/RunMatlabTestsStepTester.java delete mode 100644 src/test/java/com/mathworks/ci/TestStepExecution.java rename src/test/java/{ => integ}/com/mathworks/ci/BuildArtifactActionTest.java (99%) rename src/test/java/{ => integ}/com/mathworks/ci/MatlabInstallationTest.java (97%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabBuildBuilderTest.java (98%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabBuildBuilderTester.java (98%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabBuildStepTest.java (89%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabCommandBuilderTest.java (96%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabCommandBuilderTester.java (95%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabCommandStepTest.java (77%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabTestBuilderPersistenceTest.java (97%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabTestsBuilderTest.java (86%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabTestsBuilderTester.java (95%) rename src/test/java/{ => integ}/com/mathworks/ci/RunMatlabTestsStepTest.java (86%) rename src/test/java/{ => integ}/com/mathworks/ci/TestMessage.java (100%) rename src/test/java/{ => integ}/com/mathworks/ci/UseMatlabVersionBuildWrapperTest.java (100%) create mode 100644 src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabBuildBuilderUnitTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabCommandBuilderUnitTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabTestsBuilderUnitTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.MatlabBuildStepExecutionUnitTest.java.swp create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.MatlabCommandStepExecutionUnitTest.java.swp create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.MatlabRunTestsStepExecutionUnitTest.java.swp create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabBuildStepUnitTest.java.swp create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabCommandStepUnitTest.java.swp create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabTestsStepUnitTest.java.swp create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/MatlabBuildStepExecutionUnitTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/MatlabCommandStepExecutionUnitTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/MatlabRunTestsStepExecutionUnitTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabBuildStepUnitTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabCommandStepUnitTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabTestsStepUnitTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java create mode 100644 src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTester.java create mode 100644 src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker create mode 100644 src/test/resources/testcontent.txt diff --git a/pom.xml b/pom.xml index 83868f62..30ce2ad2 100644 --- a/pom.xml +++ b/pom.xml @@ -100,6 +100,13 @@ workflow-job test + + + org.mockito + mockito-core + 3.1.0 + test + diff --git a/src/main/java/com/mathworks/ci/BuildArtifactAction.java b/src/main/java/com/mathworks/ci/BuildArtifactAction.java index 11a751f0..ad359725 100644 --- a/src/main/java/com/mathworks/ci/BuildArtifactAction.java +++ b/src/main/java/com/mathworks/ci/BuildArtifactAction.java @@ -136,7 +136,7 @@ public FilePath getWorkspace() { private void setCounts() throws InterruptedException, ParseException { List artifactData = new ArrayList(); - FilePath fl = new FilePath(new File(build.getRootDir().getAbsolutePath() + "/" + BUILD_ARTIFACT_FILE)); + FilePath fl = new FilePath(new File(build.getRootDir(), BUILD_ARTIFACT_FILE)); try (InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fl.toURI())), "UTF-8")) { Object obj = new JSONParser().parse(reader); JSONObject jo = (JSONObject) obj; diff --git a/src/main/java/com/mathworks/ci/BuildConsoleAnnotator.java b/src/main/java/com/mathworks/ci/BuildConsoleAnnotator.java index 34fb6b70..21f4abd7 100644 --- a/src/main/java/com/mathworks/ci/BuildConsoleAnnotator.java +++ b/src/main/java/com/mathworks/ci/BuildConsoleAnnotator.java @@ -38,7 +38,6 @@ private static byte[][] createBuildNotes() { } catch (IOException e) { throw new RuntimeException(e); } - } @Override @@ -80,4 +79,4 @@ public OutputStream decorateLogger(Run build, OutputStream logger) throws IOExce return new BuildConsoleAnnotator(logger, Charsets.UTF_8, buildNotes); } } -} \ No newline at end of file +} diff --git a/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java b/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java deleted file mode 100644 index c98deb64..00000000 --- a/src/main/java/com/mathworks/ci/MatlabBuildStepExecution.java +++ /dev/null @@ -1,191 +0,0 @@ -package com.mathworks.ci; - -/** - * Copyright 2022-2023 The MathWorks, Inc. - * - */ - -import hudson.model.Run; -import hudson.util.ArgumentListBuilder; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import org.jenkinsci.plugins.workflow.steps.StepContext; -import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; -import hudson.EnvVars; -import hudson.FilePath; -import hudson.Launcher; -import hudson.Launcher.ProcStarter; -import hudson.model.Result; -import hudson.model.TaskListener; - -public class MatlabBuildStepExecution extends SynchronousNonBlockingStepExecution implements MatlabBuild { - - private static final long serialVersionUID = 4771831219402275744L; - - private String tasks; - private String startupOptions; - private String buildOptions; - private static String DEFAULT_PLUGIN = "+ciplugins/+jenkins/getDefaultPlugins.m"; - private static String BUILD_REPORT_PLUGIN = "+ciplugins/+jenkins/BuildReportPlugin.m"; - private static String TASK_RUN_PROGRESS_PLUGIN = "+ciplugins/+jenkins/TaskRunProgressPlugin.m"; - - public MatlabBuildStepExecution(StepContext context, String tasks, String startupOptions, String buildOptions) { - super(context); - this.tasks = tasks; - this.startupOptions = startupOptions; - this.buildOptions = buildOptions; - } - - @Override - public Void run() throws Exception { - final Launcher launcher = getContext().get(Launcher.class); - final FilePath workspace = getContext().get(FilePath.class); - final TaskListener listener = getContext().get(TaskListener.class); - final EnvVars env = getContext().get(EnvVars.class); - final Run build = getContext().get(Run.class); - - //Make sure the Workspace exists before run - - workspace.mkdirs(); - System.out.println("THE ROOT DIR IS"+ build.getRootDir().toString()); - - int exitCode = execMatlabCommand(workspace, launcher, listener, env, build); - //Add build result action - FilePath jsonFile = new FilePath(workspace, ".matlab/buildArtifact.json"); - if(jsonFile.exists()){ - jsonFile.copyTo(new FilePath(new File(build.getRootDir().getAbsolutePath()+"/buildArtifact.json"))); - jsonFile.delete(); - } - build.addAction(new BuildArtifactAction(build, workspace)); - - if(exitCode != 0){ - // throw an exception if return code is non-zero - stop(new MatlabExecutionException(exitCode)); - } - - getContext().setResult(Result.SUCCESS); - return null; - } - - @Override - public void stop(Throwable cause) throws Exception { - getContext().onFailure(cause); - } - - private int execMatlabCommand(FilePath workspace, Launcher launcher, - TaskListener listener, EnvVars envVars, Run build) throws IOException, InterruptedException { - final String uniqueTmpFldrName = getUniqueNameForRunnerFile(); - final String uniqueBuildFile = - "build_" + getUniqueNameForRunnerFile().replaceAll("-", "_"); - final FilePath uniqueTmpFolderPath = - getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); - - // Create MATLAB script - createMatlabScriptByName(uniqueTmpFolderPath, uniqueBuildFile, listener, envVars); - - // Copy JenkinsLogging plugin in temp folder - copyFileInWorkspace(DEFAULT_PLUGIN,DEFAULT_PLUGIN,uniqueTmpFolderPath); - copyFileInWorkspace(BUILD_REPORT_PLUGIN,BUILD_REPORT_PLUGIN,uniqueTmpFolderPath); - copyFileInWorkspace(TASK_RUN_PROGRESS_PLUGIN,TASK_RUN_PROGRESS_PLUGIN,uniqueTmpFolderPath); - - ProcStarter matlabLauncher; - - try (BuildConsoleAnnotator bca = new BuildConsoleAnnotator(listener.getLogger(), build.getCharset())) { - matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, bca, envVars, - "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'));"+ uniqueBuildFile, startupOptions, uniqueTmpFldrName); - listener.getLogger() - .println("#################### Starting command output ####################"); - return matlabLauncher.pwd(workspace).join(); - - } finally { - // Cleanup the tmp directory - if (uniqueTmpFolderPath.exists()) { - uniqueTmpFolderPath.deleteRecursive(); - } - } - } - - private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { - - // Create a new command runner script in the temp folder. - final FilePath matlabBuildFile = - new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); - final String tasks = getContext().get(EnvVars.class).expand(this.tasks); - final String buildOptions = getContext().get(EnvVars.class).expand(this.buildOptions); - - // Set ENV variable to override the default plugin list - envVars.put("MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE", "ciplugins.jenkins.getDefaultPlugins"); - String cmd = "buildtool"; - - if (!tasks.trim().isEmpty()) { - cmd += " " + tasks; - } - - if (!buildOptions.trim().isEmpty()) { - cmd += " " + buildOptions; - } - - final String matlabBuildFileContent = - "addpath(pwd);cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; - - // Display the commands on console output for users reference - listener.getLogger() - .println("Generating MATLAB script with content:\n" + cmd + "\n"); - - matlabBuildFile.write(matlabBuildFileContent, "UTF-8"); - } - - public ProcStarter getProcessToRunMatlabCommand(FilePath workspace, - Launcher launcher, BuildConsoleAnnotator bca, EnvVars envVars, String matlabCommand, String startupOpts, String uniqueName) - throws IOException, InterruptedException { - // Get node specific temp .matlab directory to copy matlab runner script - FilePath targetWorkspace; - ProcStarter matlabLauncher; - ArgumentListBuilder args = new ArgumentListBuilder(); - if (launcher.isUnix()) { - targetWorkspace = new FilePath(launcher.getChannel(), - workspace.getRemote() + "/" + MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME); - - // Determine whether we're on Mac on Linux - ByteArrayOutputStream kernelStream = new ByteArrayOutputStream(); - launcher.launch() - .cmds("uname") - .masks(true) - .stdout(kernelStream) - .join(); - - String binaryName; - String runnerName = uniqueName + "/run-matlab-command"; - if (kernelStream.toString("UTF-8").contains("Linux")) { - binaryName = "glnxa64/run-matlab-command"; - } else { - binaryName = "maci64/run-matlab-command"; - } - - args.add(MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME + "/" + runnerName); - args.add(matlabCommand); - args.add(startupOpts.split(" ")); - - matlabLauncher = launcher.launch().envs(envVars).cmds(args).stdout(bca); - - // Copy runner for linux platform in workspace. - copyFileInWorkspace(binaryName, runnerName, targetWorkspace); - } else { - targetWorkspace = new FilePath(launcher.getChannel(), - workspace.getRemote() + "\\" + MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME); - - final String runnerName = uniqueName + "\\run-matlab-command.exe"; - - args.add(targetWorkspace.toString() + "\\" + runnerName, "\"" + matlabCommand + "\""); - args.add(startupOpts.split(" ")); - - matlabLauncher = launcher.launch().envs(envVars).cmds(args).stdout(bca); - - // Copy runner for Windows platform in workspace. - copyFileInWorkspace("win64/run-matlab-command.exe", runnerName, - targetWorkspace); - } - return matlabLauncher; - } -} diff --git a/src/main/java/com/mathworks/ci/MatlabBuilderConstants.java b/src/main/java/com/mathworks/ci/MatlabBuilderConstants.java index aadb6565..6a84b96f 100644 --- a/src/main/java/com/mathworks/ci/MatlabBuilderConstants.java +++ b/src/main/java/com/mathworks/ci/MatlabBuilderConstants.java @@ -4,47 +4,43 @@ */ public class MatlabBuilderConstants { - static final double BASE_MATLAB_VERSION_RUNTESTS_SUPPORT = 8.1; - static final double BASE_MATLAB_VERSION_NO_APP_ICON_SUPPORT = 8.6; - static final double BASE_MATLAB_VERSION_BATCH_SUPPORT = 9.5; - static final double BASE_MATLAB_VERSION_COBERTURA_SUPPORT = 9.3; - static final double BASE_MATLAB_VERSION_MODELCOVERAGE_SUPPORT = 9.5; - static final double BASE_MATLAB_VERSION_EXPORTSTMRESULTS_SUPPORT = 9.6; + public static final double BASE_MATLAB_VERSION_RUNTESTS_SUPPORT = 8.1; + public static final double BASE_MATLAB_VERSION_NO_APP_ICON_SUPPORT = 8.6; + public static final double BASE_MATLAB_VERSION_BATCH_SUPPORT = 9.5; + public static final double BASE_MATLAB_VERSION_COBERTURA_SUPPORT = 9.3; + public static final double BASE_MATLAB_VERSION_MODELCOVERAGE_SUPPORT = 9.5; + public static final double BASE_MATLAB_VERSION_EXPORTSTMRESULTS_SUPPORT = 9.6; - static final String MATLAB_RUNNER_TARGET_FILE = "Builder.matlab.runner.target.file.name"; - static final String MATLAB_TESTS_RUNNER_TARGET_FILE = "runMatlabTests.m"; - static final String MATLAB_RUNNER_RESOURCE = "com/mathworks/ci/MatlabBuilder/runMatlabTests.m"; - static final String AUTOMATIC_OPTION = "RunTestsAutomaticallyOption"; + public static final String MATLAB_RUNNER_TARGET_FILE = "Builder.matlab.runner.target.file.name"; + public static final String MATLAB_TESTS_RUNNER_TARGET_FILE = "runMatlabTests.m"; + public static final String MATLAB_RUNNER_RESOURCE = "com/mathworks/ci/MatlabBuilder/runMatlabTests.m"; + public static final String AUTOMATIC_OPTION = "RunTestsAutomaticallyOption"; // Input parameter names (Passed to runMatlabTests.m as name-value pair arguments) - static final String PDF_REPORT = "'PDFReport'"; - static final String TAP_RESULTS = "'TAPResults'"; - static final String JUNIT_RESULTS = "'JUnitResults'"; - static final String STM_RESULTS = "'SimulinkTestResults'"; - static final String COBERTURA_CODE_COVERAGE = "'CoberturaCodeCoverage'"; - static final String COBERTURA_MODEL_COVERAGE = "'CoberturaModelCoverage'"; + public static final String PDF_REPORT = "'PDFReport'"; + public static final String TAP_RESULTS = "'TAPResults'"; + public static final String JUNIT_RESULTS = "'JUnitResults'"; + public static final String STM_RESULTS = "'SimulinkTestResults'"; + public static final String COBERTURA_CODE_COVERAGE = "'CoberturaCodeCoverage'"; + public static final String COBERTURA_MODEL_COVERAGE = "'CoberturaModelCoverage'"; //Matlab Script generator package - static final String MATLAB_SCRIPT_GENERATOR = "matlab-script-generator.zip"; + public static final String MATLAB_SCRIPT_GENERATOR = "matlab-script-generator.zip"; //Test runner file prefix - static final String MATLAB_TEST_RUNNER_FILE_PREFIX = "runner_"; + public static final String MATLAB_TEST_RUNNER_FILE_PREFIX = "runner_"; //Temporary MATLAB folder name in workspace - static final String TEMP_MATLAB_FOLDER_NAME = ".matlab"; + public static final String TEMP_MATLAB_FOLDER_NAME = ".matlab"; - static final String NEW_LINE = System.getProperty("line.separator"); + public static final String NEW_LINE = System.getProperty("line.separator"); //MATLAB Runner Script - static final String TEST_RUNNER_SCRIPT = String.join(NEW_LINE, - "tmpDir=tempname;", - "mkdir(tmpDir);", - "addpath(tmpDir);", - "zipURL='${ZIP_FILE}';", - "unzip(zipURL,tmpDir);", + public static final String TEST_RUNNER_SCRIPT = String.join(NEW_LINE, + "addpath('${TEMP_FOLDER}');", "testScript = genscript(${PARAMS});", "disp('Running MATLAB script with content:');", "disp(testScript.Contents);", - "testScript.writeToFile(fullfile(tmpDir,'runnerScript.m'));", - "fprintf('___________________________________\\n\\n');"); + "fprintf('___________________________________\\n\\n');", + "run(testScript);"); } diff --git a/src/main/java/com/mathworks/ci/MatlabCommandStepExecution.java b/src/main/java/com/mathworks/ci/MatlabCommandStepExecution.java deleted file mode 100644 index f6a99f68..00000000 --- a/src/main/java/com/mathworks/ci/MatlabCommandStepExecution.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.mathworks.ci; - -/** - * Copyright 2023 The MathWorks, Inc. - * - */ - -import java.io.IOException; -import org.jenkinsci.plugins.workflow.steps.StepContext; -import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; -import hudson.EnvVars; -import hudson.FilePath; -import hudson.Launcher; -import hudson.Launcher.ProcStarter; -import hudson.model.Result; -import hudson.model.TaskListener; - -public class MatlabCommandStepExecution extends SynchronousNonBlockingStepExecution implements MatlabBuild { - - private static final long serialVersionUID = 1957239693658914450L; - - private String command; - private String startupOptions; - - public MatlabCommandStepExecution(StepContext context, String command, String startupOptions) { - super(context); - this.command = command; - this.startupOptions = startupOptions; - } - - private String getCommand() { - return this.command; - } - - @Override - public Void run() throws Exception { - final Launcher launcher = getContext().get(Launcher.class); - final FilePath workspace = getContext().get(FilePath.class); - final TaskListener listener = getContext().get(TaskListener.class); - final EnvVars env = getContext().get(EnvVars.class); - - //Make sure the Workspace exists before run - - workspace.mkdirs(); - - int exitCode = execMatlabCommand(workspace, launcher, listener, env); - - if(exitCode != 0){ - // throw an exception if return code is non-zero - stop(new MatlabExecutionException(exitCode)); - } - - getContext().setResult(Result.SUCCESS); - return null; - } - - @Override - public void stop(Throwable cause) throws Exception { - getContext().onFailure(cause); - } - - private int execMatlabCommand(FilePath workspace, Launcher launcher, - TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { - - final String uniqueTmpFldrName = getUniqueNameForRunnerFile(); - final String uniqueCommandFile = - "command_" + getUniqueNameForRunnerFile().replaceAll("-", "_"); - final FilePath uniqueTmpFolderPath = - getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); - - // Create MATLAB script - createMatlabScriptByName(uniqueTmpFolderPath, uniqueCommandFile, listener); - ProcStarter matlabLauncher; - - try { - matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, listener, envVars, - "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"')); "+ uniqueCommandFile, startupOptions, uniqueTmpFldrName); - listener.getLogger() - .println("#################### Starting command output ####################"); - return matlabLauncher.pwd(workspace).join(); - - } finally { - // Cleanup the tmp directory - if (uniqueTmpFolderPath.exists()) { - uniqueTmpFolderPath.deleteRecursive(); - } - } - } - - private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, TaskListener listener) throws IOException, InterruptedException { - - // Create a new command runner script in the temp folder. - final FilePath matlabCommandFile = - new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); - final String cmd = getContext().get(EnvVars.class).expand(getCommand()); - final String matlabCommandFileContent = - "cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; - - // Display the commands on console output for users reference - listener.getLogger() - .println("Generating MATLAB script with content:\n" + cmd + "\n"); - - matlabCommandFile.write(matlabCommandFileContent, "UTF-8"); - } -} diff --git a/src/main/java/com/mathworks/ci/MatlabExecutionException.java b/src/main/java/com/mathworks/ci/MatlabExecutionException.java index 5fef424f..d606602d 100644 --- a/src/main/java/com/mathworks/ci/MatlabExecutionException.java +++ b/src/main/java/com/mathworks/ci/MatlabExecutionException.java @@ -6,7 +6,7 @@ public class MatlabExecutionException extends Exception { private final int exitCode; - MatlabExecutionException(int exitCode) { + public MatlabExecutionException(int exitCode) { super(String.format(Message.getValue("matlab.execution.exception.prefix"), exitCode)); this.exitCode = exitCode; } diff --git a/src/main/java/com/mathworks/ci/MatlabRunTestsStepExecution.java b/src/main/java/com/mathworks/ci/MatlabRunTestsStepExecution.java deleted file mode 100644 index c4c0a39c..00000000 --- a/src/main/java/com/mathworks/ci/MatlabRunTestsStepExecution.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.mathworks.ci; - -/** - * Copyright 2020-2023 The MathWorks, Inc. - * - */ - -import java.io.IOException; -import org.jenkinsci.plugins.workflow.steps.StepContext; -import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; -import hudson.EnvVars; -import hudson.FilePath; -import hudson.Launcher; -import hudson.Launcher.ProcStarter; -import hudson.model.Result; -import hudson.model.TaskListener; - -public class MatlabRunTestsStepExecution extends SynchronousNonBlockingStepExecution implements MatlabBuild { - - private static final long serialVersionUID = 6704588180717665100L; - - private String commandArgs; - private String startupOptions; - - public MatlabRunTestsStepExecution(StepContext context, String commandArgs, String startupOptions) { - super(context); - this.commandArgs = commandArgs; - this.startupOptions = startupOptions; - } - - private String getCommandArgs() { - return this.commandArgs; - } - - @Override - public Void run() throws Exception { - final Launcher launcher = getContext().get(Launcher.class); - final FilePath workspace = getContext().get(FilePath.class); - final TaskListener listener = getContext().get(TaskListener.class); - final EnvVars env = getContext().get(EnvVars.class); - - //Make sure the Workspace exists before run - - workspace.mkdirs(); - - int exitCode = execMatlabCommand(workspace, launcher, listener, env); - - if(exitCode != 0){ - // throw an exception if return code is non-zero - stop(new MatlabExecutionException(exitCode)); - } - - getContext().setResult(Result.SUCCESS); - return null; - } - - @Override - public void stop(Throwable cause) throws Exception { - getContext().onFailure(cause); - } - - private int execMatlabCommand(FilePath workspace, Launcher launcher, - TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { - final String uniqueMatlabResourceFldr = getUniqueNameForRunnerFile(); - try { - FilePath genScriptLocation = - getFilePathForUniqueFolder(launcher, uniqueMatlabResourceFldr, workspace); - final String cmdPrefix = - "addpath('" + genScriptLocation.getRemote().replaceAll("'", "''") + "'); "; - final String matlabScriptName = getValidMatlabFileName(genScriptLocation.getBaseName()); - - ProcStarter matlabLauncher = - getProcessToRunMatlabCommand(workspace, launcher, listener, envVars, - cmdPrefix + matlabScriptName + ",delete('.matlab/" - + genScriptLocation.getBaseName() + "/" + matlabScriptName - + ".m'),runnerScript,rmdir(tmpDir,'s')", - startupOptions, uniqueMatlabResourceFldr); - - // prepare temp folder by coping genscript package and writing runner script. - prepareTmpFldr(genScriptLocation, - getRunnerScript(MatlabBuilderConstants.TEST_RUNNER_SCRIPT, envVars.expand(getCommandArgs()),uniqueMatlabResourceFldr)); - - return matlabLauncher.pwd(workspace).join(); - } finally { - // Cleanup the runner File from tmp directory - final FilePath matlabRunnerScript = - getFilePathForUniqueFolder(launcher, uniqueMatlabResourceFldr, workspace); - if (matlabRunnerScript.exists()) { - matlabRunnerScript.deleteRecursive(); - } - } - - } -} diff --git a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java b/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java deleted file mode 100644 index b09ebf4b..00000000 --- a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java +++ /dev/null @@ -1,256 +0,0 @@ -package com.mathworks.ci; - -/** - * Copyright 2022-2023 The MathWorks, Inc. - * - */ - -import hudson.util.ArgumentListBuilder; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import javax.annotation.Nonnull; -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.model.Computer; -import hudson.tasks.BuildStepDescriptor; -import hudson.tasks.Builder; -import jenkins.tasks.SimpleBuildStep; -import net.sf.json.JSONObject; - -public class RunMatlabBuildBuilder extends Builder implements SimpleBuildStep, MatlabBuild { - private int buildResult; - private String tasks; - private StartupOptions startupOptions; - private BuildOptions buildOptions; - private static String DEFAULT_PLUGIN = "+ciplugins/+jenkins/getDefaultPlugins.m"; - private static String BUILD_REPORT_PLUGIN = "+ciplugins/+jenkins/BuildReportPlugin.m"; - private static String TASK_RUN_PROGRESS_PLUGIN = "+ciplugins/+jenkins/TaskRunProgressPlugin.m"; - - @DataBoundConstructor - public RunMatlabBuildBuilder() {} - - // Getter and Setters to access local members - @DataBoundSetter - public void setTasks(String tasks) { - this.tasks = tasks; - } - - @DataBoundSetter - public void setStartupOptions(StartupOptions startupOptions) { - this.startupOptions = startupOptions; - } - - @DataBoundSetter - public void setBuildOptions (BuildOptions buildOptions) { - this.buildOptions = buildOptions; - } - - public String getTasks() { - return this.tasks; - } - - public StartupOptions getStartupOptions() { - return this.startupOptions; - } - - public BuildOptions getBuildOptions() { - return this.buildOptions; - } - - @Extension - public static class RunMatlabBuildDescriptor extends BuildStepDescriptor { - - // Overridden Method used to show the text under build dropdown - @Override - public String getDisplayName() { - return Message.getValue("Builder.build.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 jobtype) { - return true; - } - } - - @Override - public void perform(@Nonnull Run build, @Nonnull FilePath workspace, - @Nonnull Launcher launcher, @Nonnull TaskListener listener) - throws InterruptedException, IOException { - - // Get the environment variable specific to the this build - final EnvVars env = build.getEnvironment(listener); - - // Invoke MATLAB build and transfer output to standard - // Output Console - - buildResult = execMatlabCommand(workspace, launcher, listener, env, build); - - //Add build result action - FilePath jsonFile = new FilePath(workspace, ".matlab/buildArtifact.json"); - if(jsonFile.exists()){ - jsonFile.copyTo(new FilePath(new File(build.getRootDir().getAbsolutePath()+"/buildArtifact.json"))); - jsonFile.delete(); - } - build.addAction(new BuildArtifactAction(build, workspace)); - - if (buildResult != 0) { - build.setResult(Result.FAILURE); - } - } - - private int execMatlabCommand(FilePath workspace, Launcher launcher, - TaskListener listener, EnvVars envVars, @Nonnull Run build) throws IOException, InterruptedException { - - /* - * Handle the case for using MATLAB Axis for multi conf projects by adding appropriate - * matlabroot to env PATH - * */ - Utilities.addMatlabToEnvPathFrmAxis(Computer.currentComputer(), listener, envVars); - - final String uniqueTmpFldrName = getUniqueNameForRunnerFile(); - final String uniqueBuildFile = - "build_" + getUniqueNameForRunnerFile().replaceAll("-", "_"); - final FilePath uniqueTmpFolderPath = - getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); - - // Create MATLAB script - createMatlabScriptByName(uniqueTmpFolderPath, uniqueBuildFile, listener, envVars); - // Copy JenkinsLogging plugin in temp folder - copyFileInWorkspace(DEFAULT_PLUGIN,DEFAULT_PLUGIN,uniqueTmpFolderPath); - copyFileInWorkspace(BUILD_REPORT_PLUGIN,BUILD_REPORT_PLUGIN,uniqueTmpFolderPath); - copyFileInWorkspace(TASK_RUN_PROGRESS_PLUGIN,TASK_RUN_PROGRESS_PLUGIN,uniqueTmpFolderPath); - - ProcStarter matlabLauncher; - BuildConsoleAnnotator bca = new BuildConsoleAnnotator(listener.getLogger(), build.getCharset()); - String options = getStartupOptions() == null ? "" : getStartupOptions().getOptions(); - try { - matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, bca, envVars, - "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'));"+ uniqueBuildFile, options, uniqueTmpFldrName); - - - listener.getLogger() - .println("#################### Starting command output ####################"); - return matlabLauncher.pwd(workspace).join(); - - } catch (Exception e) { - listener.getLogger().println(e.getMessage()); - return 1; - } finally { - bca.forceEol(); - // Cleanup the tmp directory - if (uniqueTmpFolderPath.exists()) { - uniqueTmpFolderPath.deleteRecursive(); - } - } - } - - private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { - - // Create a new command runner script in the temp folder. - final FilePath matlabCommandFile = - new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); - final String tasks = envVars.expand(getTasks()); - final String buildOptions = envVars.expand(getBuildOptions() == null ? "": getBuildOptions().getOptions()); - - // Set ENV variable to override the default plugin list - envVars.put("MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE", "ciplugins.jenkins.getDefaultPlugins"); - - String cmd = "buildtool"; - - if (!tasks.trim().isEmpty()) { - cmd += " " + tasks; - } - - if (!buildOptions.trim().isEmpty()) { - cmd += " " + buildOptions; - } - - final String matlabCommandFileContent = - "addpath(pwd);cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; - - // Display the commands on console output for users reference - listener.getLogger() - .println("Generating MATLAB script with content:\n" + cmd + "\n"); - - matlabCommandFile.write(matlabCommandFileContent, "UTF-8"); - } - - - private ProcStarter getProcessToRunMatlabCommand(FilePath workspace, - Launcher launcher, BuildConsoleAnnotator bca, EnvVars envVars, String matlabCommand, String startupOpts, String uniqueName) - throws IOException, InterruptedException { - // Get node specific temp .matlab directory to copy matlab runner script - FilePath targetWorkspace; - ProcStarter matlabLauncher; - ArgumentListBuilder args = new ArgumentListBuilder(); - if (launcher.isUnix()) { - targetWorkspace = new FilePath(launcher.getChannel(), - workspace.getRemote() + "/" + MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME); - - // Determine whether we're on Mac on Linux - ByteArrayOutputStream kernelStream = new ByteArrayOutputStream(); - launcher.launch() - .cmds("uname") - .masks(true) - .stdout(kernelStream) - .join(); - - String binaryName; - String runnerName = uniqueName + "/run-matlab-command"; - if (kernelStream.toString("UTF-8").contains("Linux")) { - binaryName = "glnxa64/run-matlab-command"; - } else { - binaryName = "maci64/run-matlab-command"; - } - - args.add(MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME + "/" + runnerName); - args.add(matlabCommand); - args.add(startupOpts.split(" ")); - - matlabLauncher = launcher.launch().envs(envVars).cmds(args).stdout(bca); - - // Copy runner for linux platform in workspace. - copyFileInWorkspace(binaryName, runnerName, targetWorkspace); - } else { - targetWorkspace = new FilePath(launcher.getChannel(), - workspace.getRemote() + "\\" + MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME); - - final String runnerName = uniqueName + "\\run-matlab-command.exe"; - - args.add(targetWorkspace.toString() + "\\" + runnerName, "\"" + matlabCommand + "\""); - args.add(startupOpts.split(" ")); - - matlabLauncher = launcher.launch().envs(envVars).cmds(args).stdout(bca); - - // Copy runner for Windows platform in workspace. - copyFileInWorkspace("win64/run-matlab-command.exe", runnerName, - targetWorkspace); - } - return matlabLauncher; - } -} diff --git a/src/main/java/com/mathworks/ci/RunMatlabCommandBuilder.java b/src/main/java/com/mathworks/ci/RunMatlabCommandBuilder.java deleted file mode 100644 index 6bbfb138..00000000 --- a/src/main/java/com/mathworks/ci/RunMatlabCommandBuilder.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.mathworks.ci; -/** - * Copyright 2019-2023 The MathWorks, Inc. - * - * Script builder used to run custom MATLAB commands or scripts. - * - */ - -import java.io.IOException; -import javax.annotation.Nonnull; -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.model.Computer; -import hudson.tasks.BuildStepDescriptor; -import hudson.tasks.Builder; -import hudson.Util; -import jenkins.tasks.SimpleBuildStep; -import net.sf.json.JSONObject; - -public class RunMatlabCommandBuilder extends Builder implements SimpleBuildStep, MatlabBuild { - private int buildResult; - private String matlabCommand; - private StartupOptions startupOptions; - - @DataBoundConstructor - public RunMatlabCommandBuilder() { - - } - - - // Getter and Setters to access local members - - - @DataBoundSetter - public void setMatlabCommand(String matlabCommand) { - this.matlabCommand = matlabCommand; - } - - @DataBoundSetter - public void setStartupOptions(StartupOptions startupOptions) { - this.startupOptions = startupOptions; - } - - public String getMatlabCommand() { - return this.matlabCommand; - } - - public StartupOptions getStartupOptions() { - return this.startupOptions; - } - - @Extension - public static class RunMatlabCommandDescriptor extends BuildStepDescriptor { - - // 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 jobtype) { - return true; - } - } - - @Override - public void perform(@Nonnull Run build, @Nonnull FilePath workspace, - @Nonnull Launcher launcher, @Nonnull TaskListener listener) - throws InterruptedException, IOException { - - // Get the environment variable specific to the this build - final EnvVars env = build.getEnvironment(listener); - - // Invoke MATLAB command and transfer output to standard - // Output Console - - buildResult = execMatlabCommand(workspace, launcher, listener, env); - - if (buildResult != 0) { - build.setResult(Result.FAILURE); - } - } - - private int execMatlabCommand(FilePath workspace, Launcher launcher, - TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { - - /* - * Handle the case for using MATLAB Axis for multi conf projects by adding appropriate - * matlabroot to env PATH - * */ - Utilities.addMatlabToEnvPathFrmAxis(Computer.currentComputer(), listener, envVars); - - final String uniqueTmpFldrName = getUniqueNameForRunnerFile(); - final String uniqueCommandFile = - "command_" + getUniqueNameForRunnerFile().replaceAll("-", "_"); - final FilePath uniqueTmpFolderPath = - getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); - - // Create MATLAB script - createMatlabScriptByName(uniqueTmpFolderPath, uniqueCommandFile, listener, envVars); - ProcStarter matlabLauncher; - String options = getStartupOptions() == null ? "" : getStartupOptions().getOptions(); - - try { - matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, listener, envVars, - "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'));"+ uniqueCommandFile, options, uniqueTmpFldrName); - - listener.getLogger() - .println("#################### Starting command output ####################"); - return matlabLauncher.pwd(workspace).join(); - - } catch (Exception e) { - listener.getLogger().println(e.getMessage()); - return 1; - } finally { - // Cleanup the tmp directory - if (uniqueTmpFolderPath.exists()) { - uniqueTmpFolderPath.deleteRecursive(); - } - } - } - - private void createMatlabScriptByName(FilePath uniqueTmpFolderPath, String uniqueScriptName, TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { - - // Create a new command runner script in the temp folder. - final FilePath matlabCommandFile = - new FilePath(uniqueTmpFolderPath, uniqueScriptName + ".m"); - final String cmd = envVars.expand(getMatlabCommand()); - final String matlabCommandFileContent = - "cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + cmd; - - // Display the commands on console output for users reference - listener.getLogger() - .println("Generating MATLAB script with content:\n" + cmd + "\n"); - - matlabCommandFile.write(matlabCommandFileContent, "UTF-8"); - } -} diff --git a/src/main/java/com/mathworks/ci/actions/MatlabActionFactory.java b/src/main/java/com/mathworks/ci/actions/MatlabActionFactory.java new file mode 100644 index 00000000..15bd6898 --- /dev/null +++ b/src/main/java/com/mathworks/ci/actions/MatlabActionFactory.java @@ -0,0 +1,24 @@ +package com.mathworks.ci.actions; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.Serializable; +import java.io.IOException; +import com.mathworks.ci.parameters.*; + +public class MatlabActionFactory implements Serializable { + public RunMatlabCommandAction createAction(RunActionParameters params) throws IOException, InterruptedException { + return new RunMatlabCommandAction(params); + } + + public RunMatlabBuildAction createAction(BuildActionParameters params) throws IOException, InterruptedException { + return new RunMatlabBuildAction(params); + } + + public RunMatlabTestsAction createAction(TestActionParameters params) throws IOException, InterruptedException { + return new RunMatlabTestsAction(params); + } +} diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java new file mode 100644 index 00000000..d60f3d91 --- /dev/null +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java @@ -0,0 +1,100 @@ +package com.mathworks.ci.actions; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.File; +import java.io.IOException; + +import hudson.FilePath; +import hudson.model.Run; +import hudson.console.LineTransformationOutputStream; + +import com.mathworks.ci.BuildArtifactAction; +import com.mathworks.ci.BuildConsoleAnnotator; +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.parameters.BuildActionParameters; +import com.mathworks.ci.utilities.MatlabCommandRunner; + +public class RunMatlabBuildAction { + private BuildActionParameters params; + private MatlabCommandRunner runner; + private BuildConsoleAnnotator annotator; + + private static String DEFAULT_PLUGIN = + "+ciplugins/+jenkins/getDefaultPlugins.m"; + private static String BUILD_REPORT_PLUGIN = + "+ciplugins/+jenkins/BuildReportPlugin.m"; + private static String TASK_RUN_PROGRESS_PLUGIN = + "+ciplugins/+jenkins/TaskRunProgressPlugin.m"; + + public RunMatlabBuildAction(MatlabCommandRunner runner, BuildConsoleAnnotator annotator, BuildActionParameters params) { + this.runner = runner; + this.annotator = annotator; + this.params = params; + } + + public RunMatlabBuildAction(BuildActionParameters params) throws IOException, InterruptedException { + this(new MatlabCommandRunner(params), + new BuildConsoleAnnotator( + params.getTaskListener().getLogger(), + params.getBuild().getCharset()), + params); + } + + public void run() throws IOException, InterruptedException, MatlabExecutionException { + // Copy plugins and override default plugins function + runner.copyFileToTempFolder(DEFAULT_PLUGIN, DEFAULT_PLUGIN); + runner.copyFileToTempFolder(BUILD_REPORT_PLUGIN, BUILD_REPORT_PLUGIN); + runner.copyFileToTempFolder(TASK_RUN_PROGRESS_PLUGIN, TASK_RUN_PROGRESS_PLUGIN); + + // Set environment variable + runner.addEnvironmentVariable( + "MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE", + "ciplugins.jenkins.getDefaultPlugins"); + + // Redirect output to the build annotator + runner.redirectStdOut(annotator); + + // Prepare the build tool command + // TODO: Devise better solution then prepending the command + // here. + String command = "addpath('" + + runner.getTempFolder().getRemote() + + "'); buildtool"; + + if (params.getTasks() != null) { + command += " " + params.getTasks(); + } + + if (params.getBuildOptions() != null) { + command += " " + params.getBuildOptions(); + } + + try { + runner.runMatlabCommand(command); + } catch (Exception e) { + this.params.getTaskListener().getLogger() + .println(e.getMessage()); + throw(e); + } finally { + annotator.forceEol(); + } + + // Handle build result + Run build = this.params.getBuild(); + FilePath jsonFile = new FilePath(params.getWorkspace(), ".matlab/buildArtifact.json"); + if (jsonFile.exists()) { + FilePath rootLocation = new FilePath( + new File( + build.getRootDir() + .getAbsolutePath() + + "/buildArtifact.json")); + jsonFile.copyTo(rootLocation); + jsonFile.delete(); + build.addAction(new BuildArtifactAction(build, this.params.getWorkspace())); + } + } +} diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabCommandAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabCommandAction.java new file mode 100644 index 00000000..82ec5bf2 --- /dev/null +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabCommandAction.java @@ -0,0 +1,36 @@ +package com.mathworks.ci.actions; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; + +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.parameters.RunActionParameters; +import com.mathworks.ci.utilities.MatlabCommandRunner; + +public class RunMatlabCommandAction { + private RunActionParameters params; + private MatlabCommandRunner runner; + + public RunMatlabCommandAction(MatlabCommandRunner runner, RunActionParameters params) { + this.runner = runner; + this.params = params; + } + + public RunMatlabCommandAction(RunActionParameters params) throws IOException, InterruptedException { + this(new MatlabCommandRunner(params), params); + } + + public void run() throws IOException, InterruptedException, MatlabExecutionException { + try { + runner.runMatlabCommand(this.params.getCommand()); + } catch (Exception e) { + this.params.getTaskListener().getLogger() + .println(e.getMessage()); + throw(e); + } + } +} diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java new file mode 100644 index 00000000..833902b6 --- /dev/null +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java @@ -0,0 +1,127 @@ +package com.mathworks.ci.actions; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; + +import hudson.FilePath; + +import com.mathworks.ci.Utilities; +import com.mathworks.ci.MatlabBuilderConstants; +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.parameters.TestActionParameters; +import com.mathworks.ci.utilities.MatlabCommandRunner; + +public class RunMatlabTestsAction { + private MatlabCommandRunner runner; + private TestActionParameters params; + + public RunMatlabTestsAction(MatlabCommandRunner runner, TestActionParameters params) { + this.runner = runner; + this.params = params; + } + + public RunMatlabTestsAction(TestActionParameters params) throws IOException, InterruptedException { + this(new MatlabCommandRunner(params), params); + } + + public void run() throws IOException, InterruptedException, MatlabExecutionException { + // Copy in genscript + FilePath genScriptZip = runner.copyFileToTempFolder( + MatlabBuilderConstants.MATLAB_SCRIPT_GENERATOR, + "genscript.zip"); + genScriptZip.unzip(runner.getTempFolder()); + + // Prepare the command + String command = MatlabBuilderConstants.TEST_RUNNER_SCRIPT; + command = command.replace("${TEMP_FOLDER}", runner.getTempFolder().getRemote()); + command = command.replace("${PARAMS}", getParameterString()); + + // Run the command + try { + runner.runMatlabCommand(command); + } catch (Exception e) { + this.params.getTaskListener() + .getLogger() + .println(e.getMessage()); + throw(e); + } + } + + private String singleQuotify(String in) { + return "'" + in + "'"; + } + + // Concatenate the input arguments, try to keep this function as + // readable as possible because it can get hairy. + private String getParameterString() { + // The final list to be concatted and returned + final List inputArgsList = new ArrayList(); + + inputArgsList.add("'Test'"); + + // Prepare source and test folder lists + String sourceFolders = null; + if (this.params.getSourceFolder() != null) { + sourceFolders = this.params.getSourceFolder().size() == 0 + ? null + : Utilities.getCellArrayFrmList(this.params.getSourceFolder()); + } + + String selectFolders = null; + if (this.params.getSelectByFolder() != null) { + selectFolders = this.params.getSelectByFolder().size() == 0 + ? null + : Utilities.getCellArrayFrmList(this.params.getSelectByFolder()); + } + + // All string-based fields + final String[] names = { + "'PDFTestReport'", + "'TAPTestResults'", + "'JUnitTestResults'", + "'CoberturaCodeCoverage'", + MatlabBuilderConstants.STM_RESULTS, + "'CoberturaModelCoverage'", + "'SelectByTag'", + "'UseParallel'", + "'Strict'", + "'LoggingLevel'", + "'OutputDetail'", + "'SourceFolder'", + "'SelectByFolder'" + }; + final String[] values = { + this.params.getTestResultsPDF(), + this.params.getTestResultsTAP(), + this.params.getTestResultsJUnit(), + this.params.getCodeCoverageCobertura(), + this.params.getTestResultsSimulinkTest(), + this.params.getModelCoverageCobertura(), + this.params.getSelectByTag(), + this.params.getUseParallel(), + this.params.getStrict(), + this.params.getLoggingLevel(), + this.params.getOutputDetail(), + sourceFolders, + selectFolders + }; + + for (int i = 0; i < names.length; i++) { + if (values[i] != null && !values[i].equals("false")) { + inputArgsList.add(names[i]); + String arg = values[i].equals("true") || values[i].startsWith("{") + ? values[i] + : singleQuotify(values[i]); + inputArgsList.add(arg); + } + } + + return String.join(",", inputArgsList); + } +} diff --git a/src/main/java/com/mathworks/ci/freestyle/RunMatlabBuildBuilder.java b/src/main/java/com/mathworks/ci/freestyle/RunMatlabBuildBuilder.java new file mode 100644 index 00000000..89465b89 --- /dev/null +++ b/src/main/java/com/mathworks/ci/freestyle/RunMatlabBuildBuilder.java @@ -0,0 +1,160 @@ +package com.mathworks.ci.freestyle; + +/** + * Copyright 2022-2024 The MathWorks, Inc. + * + */ + +import java.io.IOException; +import javax.annotation.Nonnull; +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.init.Initializer; +import hudson.init.InitMilestone; +import hudson.model.Items; +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; + +import com.mathworks.ci.Message; +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabBuildAction; +import com.mathworks.ci.parameters.BuildActionParameters; +import com.mathworks.ci.freestyle.options.*; + +public class RunMatlabBuildBuilder extends Builder implements SimpleBuildStep { + // Deprecated + private transient int buildResult; + + // In use + private String tasks; + private StartupOptions startupOptions; + private BuildOptions buildOptions; + + private MatlabActionFactory factory; + + public RunMatlabBuildBuilder(MatlabActionFactory factory) { + this.factory = factory; + } + + @DataBoundConstructor + public RunMatlabBuildBuilder() { + this(new MatlabActionFactory()); + } + + // Getter and Setters to access local members + @DataBoundSetter + public void setTasks(String tasks) { + this.tasks = tasks; + } + + @DataBoundSetter + public void setStartupOptions(StartupOptions startupOptions) { + this.startupOptions = startupOptions; + } + + @DataBoundSetter + public void setBuildOptions(BuildOptions buildOptions) { + this.buildOptions = buildOptions; + } + + public String getTasks() { + return this.tasks; + } + + public StartupOptions getStartupOptions() { + return this.startupOptions; + } + + public String getStartupOptionsAsString() { + return this.startupOptions == null + ? "" + : this.startupOptions.getOptions(); + } + + public BuildOptions getBuildOptions() { + return this.buildOptions; + } + + public String getBuildOptionsAsString() { + return this.buildOptions == null + ? null + : this.buildOptions.getOptions(); + } + + @Extension + public static class RunMatlabBuildDescriptor extends BuildStepDescriptor { + + @Initializer(before = InitMilestone.PLUGINS_STARTED) + public static void addAliases() { + Items.XSTREAM2.addCompatibilityAlias("com.mathworks.ci.RunMatlabBuildBuilder", RunMatlabBuildBuilder.class); + } + + // Overridden Method used to show the text under build dropdown + @Override + public String getDisplayName() { + return Message.getValue("Builder.build.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 jobtype) { + return true; + } + } + + @Override + public void perform(@Nonnull Run build, @Nonnull FilePath workspace, + @Nonnull Launcher launcher, @Nonnull TaskListener listener) + throws InterruptedException, IOException { + + // Get the environment variable specific to the this build + final EnvVars env = build.getEnvironment(listener); + + BuildActionParameters params = new BuildActionParameters( + build, workspace, env, launcher, listener, + this.getStartupOptionsAsString(), + this.getTasks(), + this.getBuildOptionsAsString()); + RunMatlabBuildAction action = factory.createAction(params); + + try { + action.run(); + } catch (Exception e) { + build.setResult(Result.FAILURE); + } + } + + // Added for backwards compatibility: + // Called when object is loaded from persistent data. + protected Object readResolve() { + if (factory == null) { + factory = new MatlabActionFactory(); + } + + return this; + } +} diff --git a/src/main/java/com/mathworks/ci/freestyle/RunMatlabCommandBuilder.java b/src/main/java/com/mathworks/ci/freestyle/RunMatlabCommandBuilder.java new file mode 100644 index 00000000..758bdf22 --- /dev/null +++ b/src/main/java/com/mathworks/ci/freestyle/RunMatlabCommandBuilder.java @@ -0,0 +1,146 @@ +package com.mathworks.ci.freestyle; + +/** + * Copyright 2019-2024 The MathWorks, Inc. + * + * Script builder used to run custom MATLAB commands or scripts. + * + */ + +import java.io.IOException; +import javax.annotation.Nonnull; +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.init.Initializer; +import hudson.init.InitMilestone; +import hudson.model.Items; +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; + +import com.mathworks.ci.Message; +import com.mathworks.ci.parameters.RunActionParameters; +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabCommandAction; +import com.mathworks.ci.freestyle.options.StartupOptions; + +public class RunMatlabCommandBuilder extends Builder implements SimpleBuildStep { + // Deprecated + private transient int buildResult; + + // In use + private String matlabCommand; + private StartupOptions startupOptions; + + private MatlabActionFactory factory; + + public RunMatlabCommandBuilder(MatlabActionFactory factory) { + this.factory = factory; + } + + @DataBoundConstructor + public RunMatlabCommandBuilder() { + this(new MatlabActionFactory()); + } + + // Getter and Setters to access local members + @DataBoundSetter + public void setMatlabCommand(String matlabCommand) { + this.matlabCommand = matlabCommand; + } + + @DataBoundSetter + public void setStartupOptions(StartupOptions startupOptions) { + this.startupOptions = startupOptions; + } + + public String getMatlabCommand() { + return this.matlabCommand; + } + + public StartupOptions getStartupOptions() { + return this.startupOptions; + } + + public String getStartupOptionsAsString() { + return this.startupOptions == null + ? "" + : this.startupOptions.getOptions(); + } + + @Extension + public static class RunMatlabCommandDescriptor extends BuildStepDescriptor { + + @Initializer(before = InitMilestone.PLUGINS_STARTED) + public static void addAliases() { + Items.XSTREAM2.addCompatibilityAlias("com.mathworks.ci.RunMatlabCommandBuilder", RunMatlabCommandBuilder.class); + } + + // 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 jobtype) { + return true; + } + } + + @Override + public void perform(@Nonnull Run build, @Nonnull FilePath workspace, + @Nonnull Launcher launcher, @Nonnull TaskListener listener) + throws InterruptedException, IOException { + + // Get the environment variables specific to the this build + final EnvVars env = build.getEnvironment(listener); + + RunActionParameters params = new RunActionParameters( + build, workspace, env, + launcher, listener, + getStartupOptionsAsString(), + getMatlabCommand()); + RunMatlabCommandAction action = factory.createAction(params); + + try { + action.run(); + } catch (Exception e) { + build.setResult(Result.FAILURE); + } + } + + // Added for backwards compatibility: + // Called when object is loaded from persistent data. + protected Object readResolve() { + if (factory == null) { + factory = new MatlabActionFactory(); + } + + return this; + } +} diff --git a/src/main/java/com/mathworks/ci/RunMatlabTestsBuilder.java b/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java similarity index 72% rename from src/main/java/com/mathworks/ci/RunMatlabTestsBuilder.java rename to src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java index 42911af7..e49e4c06 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabTestsBuilder.java +++ b/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java @@ -1,7 +1,7 @@ -package com.mathworks.ci; +package com.mathworks.ci.freestyle; /** - * Copyright 2019-2023 The MathWorks, Inc. + * Copyright 2019-2024 The MathWorks, Inc. * * MATLAB test run builder used to run all MATLAB & Simulink tests automatically and generate * selected test artifacts. @@ -10,40 +10,43 @@ import java.io.IOException; import java.util.Map; -import java.util.HashMap; import java.util.List; -import java.util.ArrayList; import java.util.Optional; -import java.util.Arrays; -import java.util.stream.Collectors; import javax.annotation.Nonnull; import hudson.EnvVars; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.Util; +import hudson.init.Initializer; +import hudson.init.InitMilestone; import hudson.model.AbstractDescribableImpl; import hudson.model.AbstractProject; import hudson.model.Descriptor; import hudson.model.Result; import hudson.model.Run; +import hudson.model.Items; import hudson.model.TaskListener; -import hudson.model.Computer; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.StaplerRequest; -import hudson.Launcher.ProcStarter; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.util.ListBoxModel; import jenkins.tasks.SimpleBuildStep; import net.sf.json.JSONObject; -public class RunMatlabTestsBuilder extends Builder implements SimpleBuildStep, MatlabBuild { +import com.mathworks.ci.Message; +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabTestsAction; +import com.mathworks.ci.parameters.TestActionParameters; +import com.mathworks.ci.freestyle.options.*; + +public class RunMatlabTestsBuilder extends Builder implements SimpleBuildStep { - private int buildResult; // Make all old values transient which protects them writing back on disk. + private transient int buildResult; private transient boolean tapChkBx; private transient boolean junitChkBx; private transient boolean coberturaChkBx; @@ -67,9 +70,15 @@ public class RunMatlabTestsBuilder extends Builder implements SimpleBuildStep, M private boolean useParallel = false; private boolean strict = false; + private MatlabActionFactory factory; + + public RunMatlabTestsBuilder(MatlabActionFactory factory) { + this.factory = factory; + } + @DataBoundConstructor public RunMatlabTestsBuilder() { - + this(new MatlabActionFactory()); } // Getter and Setters to access local members @@ -194,14 +203,33 @@ public String getPdfReportFilePath() { public SelectByTag getSelectByTag() { return this.selectByTag; } + + public String getSelectByTagPath() { + return this.selectByTag == null + ? null + : selectByTag.getTestTag(); + }; + public SourceFolder getSourceFolder() { return this.sourceFolder; } + + public List getSourceFolderPaths() { + return this.sourceFolder == null + ? null + : this.sourceFolder.getSourceFolderStringPaths(); + } - public SelectByFolder getSelectByFolder(){ + public SelectByFolder getSelectByFolder() { return this.selectByFolder; } + public List getSelectByFolderPaths() { + return this.selectByFolder == null + ? null + : this.selectByFolder.getTestFolderStringPaths(); + } + private Artifact getArtifactObject(boolean isChecked, Artifact returnVal) { // If previously checked assign valid artifact object else NullArtifact. return (isChecked) ? returnVal : new NullArtifact(); @@ -228,6 +256,12 @@ public boolean getUseParallel() { public StartupOptions getStartupOptions() { return this.startupOptions; } + + public String getStartupOptionsAsString() { + return this.startupOptions == null + ? "" + : this.startupOptions.getOptions(); + } // To retain Backward compatibility protected Object readResolve() { @@ -260,6 +294,10 @@ protected Object readResolve() { this.getArtifactObject(modelCoverageChkBx, new ModelCovArtifact("matlabTestArtifacts/coberturamodelcoverage.xml")) ); + if (factory == null) { + factory = new MatlabActionFactory(); + } + return this; } @@ -268,6 +306,13 @@ protected Object readResolve() { @Extension public static class RunMatlabTestsDescriptor extends BuildStepDescriptor { + @Initializer(before = InitMilestone.PLUGINS_STARTED) + public static void addAliases() { + Items.XSTREAM2.addCompatibilityAlias("com.mathworks.ci.RunMatlabTestsBuilder", RunMatlabTestsBuilder.class); + Items.XSTREAM2.addCompatibilityAlias("com.mathworks.ci.SourceFolderPaths", SourceFolderPaths.class); + Items.XSTREAM2.addCompatibilityAlias("com.mathworks.ci.TestFolders", TestFolders.class); + } + // Overridden Method used to show the text under build dropdown @Override public String getDisplayName() { @@ -327,124 +372,30 @@ public void perform(@Nonnull Run build, @Nonnull FilePath workspace, // Get the environment variable specific to the this build final EnvVars env = build.getEnvironment(listener); - // Invoke MATLAB command and transfer output to standard - // Output Console - - buildResult = execMatlabCommand(workspace, launcher, listener, env); + TestActionParameters params = new TestActionParameters( + build, workspace, env, launcher, listener, + this.getStartupOptionsAsString(), + this.getPdfReportFilePath(), + this.getTapReportFilePath(), + this.getJunitReportFilePath(), + this.getCoberturaReportFilePath(), + this.getStmResultsFilePath(), + this.getModelCoverageFilePath(), + this.getSelectByTagPath(), + this.getLoggingLevel(), + this.getOutputDetail(), + this.getUseParallel(), + this.getStrict(), + this.getSourceFolderPaths(), + this.getSelectByFolderPaths()); + RunMatlabTestsAction action = factory.createAction(params); - if (buildResult != 0) { - build.setResult(Result.FAILURE); - } - } - - private int execMatlabCommand(FilePath workspace, Launcher launcher, - TaskListener listener, EnvVars envVars) throws IOException, InterruptedException { - - /* - * Handle the case for using MATLAB Axis for multi conf projects by adding appropriate - * matlabroot to env PATH - * */ - Utilities.addMatlabToEnvPathFrmAxis(Computer.currentComputer(), listener, envVars); - - final String uniqueTmpFldrName = getUniqueNameForRunnerFile(); - ProcStarter matlabLauncher; - String options = getStartupOptions() == null ? "" : getStartupOptions().getOptions(); try { - FilePath genScriptLocation = - getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); - - matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, listener, envVars, - constructCommandForTest(genScriptLocation), options, uniqueTmpFldrName); - - // copy genscript package in temp folder and write a runner script. - prepareTmpFldr(genScriptLocation, getRunnerScript( - MatlabBuilderConstants.TEST_RUNNER_SCRIPT, envVars.expand(getInputArguments()),uniqueTmpFldrName)); - - return matlabLauncher.pwd(workspace).join(); + action.run(); } catch (Exception e) { - listener.getLogger().println(e.getMessage()); - return 1; - } finally { - // Cleanup the runner File from tmp directory - FilePath matlabRunnerScript = - getFilePathForUniqueFolder(launcher, uniqueTmpFldrName, workspace); - if (matlabRunnerScript.exists()) { - matlabRunnerScript.deleteRecursive(); - } - } - } - - public String constructCommandForTest(FilePath scriptPath) { - final String matlabScriptName = getValidMatlabFileName(scriptPath.getBaseName()); - final String runCommand = "addpath('" + scriptPath.getRemote().replaceAll("'", "''") - + "'); " + matlabScriptName + ",delete('.matlab/" + scriptPath.getBaseName() + "/" - + matlabScriptName + ".m'),runnerScript,rmdir(tmpDir,'s')"; - return runCommand; - } - - // Concatenate the input arguments - private String getInputArguments() { - - final List inputArgsList = new ArrayList(); - final Map args = new HashMap(); - - final List artifactList = - new ArrayList(Arrays.asList(getPdfReportArtifact(), getTapArtifact(), - getJunitArtifact(), getStmResultsArtifact(), getCoberturaArtifact(), - getModelCoverageArtifact())); - - inputArgsList.add("'Test'"); - - for (Artifact artifact : artifactList) { - artifact.addFilePathArgTo(args); - } - - args.forEach((key, val) -> inputArgsList.add("'" + key + "'" + "," + "'" + val.replaceAll("'", "''") + "'")); - - /* - * Add source folder options to argument. - * For source folder we create a MATLAB cell array and add it to input argument list. - * */ - SourceFolder sf = getSourceFolder(); - if(sf != null && !sf.getSourceFolderPaths().isEmpty()){ - sf.addSourceToInputArgs(inputArgsList, Utilities.getCellArrayFrmList(sf.getSourceFolderPaths().stream() - .map(SourceFolderPaths::getSrcFolderPath) - .collect(Collectors.toList()))); - } - - // Add Test folders - if (getSelectByFolder() != null && !getSelectByFolder().getTestFolderPaths().isEmpty()) { - getSelectByFolder().addSourceToInputArgs(inputArgsList, - Utilities.getCellArrayFrmList(getSelectByFolder().getTestFolderPaths().stream() - .map(TestFolders::getTestFolders).collect(Collectors.toList()))); - } - - // Add Tag to arguments - if (getSelectByTag() != null && !getSelectByTag().getTestTag().isEmpty()) { - getSelectByTag().addTagToInputArgs(inputArgsList); - } - - // Add Logging level - if (!getLoggingLevel().equalsIgnoreCase("default")) { - inputArgsList.add("'LoggingLevel'" + "," + "'" - + getLoggingLevel() + "'"); - } - - // Add Output Detail - if (!getOutputDetail().equalsIgnoreCase("default")) { - inputArgsList.add("'OutputDetail'" + "," + "'" - + getOutputDetail() + "'"); + build.setResult(Result.FAILURE); } - - // Add UseParallel - inputArgsList.add("'UseParallel'" + "," + getUseParallel()); - - // Add Strict - inputArgsList.add("'Strict'" + "," + getStrict()); - - return String.join(",", inputArgsList); } - /* * Classes for each optional block in jelly file.This is restriction from Stapler architecture diff --git a/src/main/java/com/mathworks/ci/BuildOptions.java b/src/main/java/com/mathworks/ci/freestyle/options/BuildOptions.java similarity index 93% rename from src/main/java/com/mathworks/ci/BuildOptions.java rename to src/main/java/com/mathworks/ci/freestyle/options/BuildOptions.java index 39f1c290..e68eb968 100644 --- a/src/main/java/com/mathworks/ci/BuildOptions.java +++ b/src/main/java/com/mathworks/ci/freestyle/options/BuildOptions.java @@ -1,5 +1,5 @@ -package com.mathworks.ci; +package com.mathworks.ci.freestyle.options; /** * Copyright 2024 The MathWorks, Inc. diff --git a/src/main/java/com/mathworks/ci/SelectByFolder.java b/src/main/java/com/mathworks/ci/freestyle/options/SelectByFolder.java similarity index 79% rename from src/main/java/com/mathworks/ci/SelectByFolder.java rename to src/main/java/com/mathworks/ci/freestyle/options/SelectByFolder.java index 514f1df4..71898991 100644 --- a/src/main/java/com/mathworks/ci/SelectByFolder.java +++ b/src/main/java/com/mathworks/ci/freestyle/options/SelectByFolder.java @@ -1,6 +1,7 @@ -package com.mathworks.ci; +package com.mathworks.ci.freestyle.options; import java.util.List; +import java.util.stream.Collectors; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; @@ -23,6 +24,12 @@ public List getTestFolderPaths() { return this.testFolderPaths; } + public List getTestFolderStringPaths() { + return this.testFolderPaths.stream().map( + p -> p.getTestFolders() + ).collect(Collectors.toList()); + } + public void addSourceToInputArgs(List inputArgsList, String cellArraySourceVal) { // Concatenate all source folders to MATLAB cell array string. inputArgsList.add("'" + SELECT_BY_FOLDER + "'" + "," + cellArraySourceVal); diff --git a/src/main/java/com/mathworks/ci/SourceFolder.java b/src/main/java/com/mathworks/ci/freestyle/options/SourceFolder.java similarity index 81% rename from src/main/java/com/mathworks/ci/SourceFolder.java rename to src/main/java/com/mathworks/ci/freestyle/options/SourceFolder.java index e3cdca81..108e0d09 100644 --- a/src/main/java/com/mathworks/ci/SourceFolder.java +++ b/src/main/java/com/mathworks/ci/freestyle/options/SourceFolder.java @@ -1,4 +1,4 @@ -package com.mathworks.ci; +package com.mathworks.ci.freestyle.options; /** * Copyright 2020 The MathWorks, Inc. @@ -30,6 +30,13 @@ public List getSourceFolderPaths() { return this.sourceFolderPaths; } + public List getSourceFolderStringPaths() { + return this.sourceFolderPaths.stream().map( + (SourceFolderPaths p) -> p.getSrcFolderPath() + ) + .collect(Collectors.toList()); + } + public void addSourceToInputArgs(List inputArgsList, String cellArraySourceVal) { // Concatenate all source folders to MATLAB cell array string. inputArgsList.add("'" + SOURCE_FOLDER + "'" + "," + cellArraySourceVal); diff --git a/src/main/java/com/mathworks/ci/SourceFolderPaths.java b/src/main/java/com/mathworks/ci/freestyle/options/SourceFolderPaths.java similarity index 94% rename from src/main/java/com/mathworks/ci/SourceFolderPaths.java rename to src/main/java/com/mathworks/ci/freestyle/options/SourceFolderPaths.java index 85df7ec6..e8728cb9 100644 --- a/src/main/java/com/mathworks/ci/SourceFolderPaths.java +++ b/src/main/java/com/mathworks/ci/freestyle/options/SourceFolderPaths.java @@ -1,4 +1,4 @@ -package com.mathworks.ci; +package com.mathworks.ci.freestyle.options; /** * Copyright 2020 The MathWorks, Inc. diff --git a/src/main/java/com/mathworks/ci/StartupOptions.java b/src/main/java/com/mathworks/ci/freestyle/options/StartupOptions.java similarity index 93% rename from src/main/java/com/mathworks/ci/StartupOptions.java rename to src/main/java/com/mathworks/ci/freestyle/options/StartupOptions.java index 2388696b..631e151b 100644 --- a/src/main/java/com/mathworks/ci/StartupOptions.java +++ b/src/main/java/com/mathworks/ci/freestyle/options/StartupOptions.java @@ -1,5 +1,4 @@ - -package com.mathworks.ci; +package com.mathworks.ci.freestyle.options; /** * Copyright 2023 The MathWorks, Inc. diff --git a/src/main/java/com/mathworks/ci/TestFolders.java b/src/main/java/com/mathworks/ci/freestyle/options/TestFolders.java similarity index 92% rename from src/main/java/com/mathworks/ci/TestFolders.java rename to src/main/java/com/mathworks/ci/freestyle/options/TestFolders.java index a5dde659..3162ff9d 100644 --- a/src/main/java/com/mathworks/ci/TestFolders.java +++ b/src/main/java/com/mathworks/ci/freestyle/options/TestFolders.java @@ -1,4 +1,4 @@ -package com.mathworks.ci; +package com.mathworks.ci.freestyle.options; import org.kohsuke.stapler.DataBoundConstructor; diff --git a/src/main/java/com/mathworks/ci/parameters/BuildActionParameters.java b/src/main/java/com/mathworks/ci/parameters/BuildActionParameters.java new file mode 100644 index 00000000..55e3a1fd --- /dev/null +++ b/src/main/java/com/mathworks/ci/parameters/BuildActionParameters.java @@ -0,0 +1,39 @@ +package com.mathworks.ci.parameters; + +import java.io.IOException; +import hudson.FilePath; +import hudson.EnvVars; +import hudson.Launcher; +import hudson.model.Run; +import hudson.model.TaskListener; +import org.jenkinsci.plugins.workflow.steps.StepContext; + +/** + * Copyright 2024 The MathWorks, Inc. + * + */ + +public class BuildActionParameters extends MatlabActionParameters { + private String tasks; + private String buildOptions; + + public BuildActionParameters(StepContext context, String startupOpts, String tasks, String buildOpts) throws IOException, InterruptedException { + super(context, startupOpts); + this.tasks = tasks; + this.buildOptions = buildOpts; + } + + public BuildActionParameters(Run build, FilePath workspace, EnvVars env, Launcher launcher, TaskListener listener, String startupOpts, String tasks, String buildOptions) { + super(build, workspace, env, launcher, listener, startupOpts); + this.tasks = tasks; + this.buildOptions = buildOptions; + } + + public String getTasks() { + return tasks; + } + + public String getBuildOptions() { + return buildOptions; + } +} diff --git a/src/main/java/com/mathworks/ci/parameters/MatlabActionParameters.java b/src/main/java/com/mathworks/ci/parameters/MatlabActionParameters.java new file mode 100644 index 00000000..09856214 --- /dev/null +++ b/src/main/java/com/mathworks/ci/parameters/MatlabActionParameters.java @@ -0,0 +1,67 @@ +package com.mathworks.ci.parameters; + +import java.io.IOException; +import java.io.Serializable; +import hudson.FilePath; +import hudson.EnvVars; +import hudson.Launcher; +import hudson.model.Run; +import hudson.model.TaskListener; +import org.jenkinsci.plugins.workflow.steps.StepContext; + +/** + * Copyright 2024 The MathWorks, Inc. + * + */ + +public class MatlabActionParameters implements Serializable { + private transient Run build; + private FilePath workspace; + private EnvVars env; + private transient Launcher launcher; + private transient TaskListener listener; + + private String startupOptions; + + public MatlabActionParameters(StepContext context, String startupOpts) throws IOException, InterruptedException { + this.build = context.get(Run.class); + this.workspace = context.get(FilePath.class); + this.env = context.get(EnvVars.class); + this.launcher = context.get(Launcher.class); + this.listener = context.get(TaskListener.class); + this.startupOptions = startupOpts; + } + + public MatlabActionParameters(Run build, FilePath workspace, EnvVars env, Launcher launcher, TaskListener listener, String startupOpts) { + this.build = build; + this.workspace = workspace; + this.env = env; + this.launcher = launcher; + this.listener = listener; + this.startupOptions = startupOpts; + } + + public Run getBuild() { + return build; + } + + public FilePath getWorkspace() { + return workspace; + } + + public EnvVars getEnvVars() { + return env; + } + + public Launcher getLauncher() { + return launcher; + } + + public TaskListener getTaskListener() { + return listener; + } + + public String getStartupOptions() { + return startupOptions; + } +} diff --git a/src/main/java/com/mathworks/ci/parameters/RunActionParameters.java b/src/main/java/com/mathworks/ci/parameters/RunActionParameters.java new file mode 100644 index 00000000..769f2dfa --- /dev/null +++ b/src/main/java/com/mathworks/ci/parameters/RunActionParameters.java @@ -0,0 +1,32 @@ +package com.mathworks.ci.parameters; + +import java.io.IOException; +import hudson.FilePath; +import hudson.EnvVars; +import hudson.Launcher; +import hudson.model.Run; +import hudson.model.TaskListener; +import org.jenkinsci.plugins.workflow.steps.StepContext; + +/** + * Copyright 2024 The MathWorks, Inc. + * + */ + +public class RunActionParameters extends MatlabActionParameters { + private String command; + + public RunActionParameters(StepContext context, String startupOpts, String command) throws IOException, InterruptedException { + super(context, startupOpts); + this.command = command; + } + + public RunActionParameters(Run build, FilePath workspace, EnvVars env, Launcher launcher, TaskListener listener, String startupOpts, String command) { + super(build, workspace, env, launcher, listener, startupOpts); + this.command = command; + } + + public String getCommand() { + return command; + } +} diff --git a/src/main/java/com/mathworks/ci/parameters/TestActionParameters.java b/src/main/java/com/mathworks/ci/parameters/TestActionParameters.java new file mode 100644 index 00000000..5b3cdd56 --- /dev/null +++ b/src/main/java/com/mathworks/ci/parameters/TestActionParameters.java @@ -0,0 +1,137 @@ +package com.mathworks.ci.parameters; + +import java.util.List; +import java.util.ArrayList; +import java.io.IOException; +import hudson.FilePath; +import hudson.EnvVars; +import hudson.Launcher; +import hudson.model.Run; +import hudson.model.TaskListener; +import org.jenkinsci.plugins.workflow.steps.StepContext; + +/** + * Copyright 2024 The MathWorks, Inc. + * + */ + +public class TestActionParameters extends MatlabActionParameters { + private String testResultsPDF; + private String testResultsTAP; + private String testResultsJUnit; + private String codeCoverageCobertura; + private String testResultsSimulinkTest; + private String modelCoverageCobertura; + private String selectByTag; + private String loggingLevel; + private String outputDetail; + private boolean useParallel; + private boolean strict; + private List sourceFolder = new ArrayList<>(); + private List selectByFolder = new ArrayList<>(); + + public TestActionParameters(StepContext context, String startupOpts, + String testResultsPDF, String testResultsTAP, String testResultsJUnit, + String codeCoverageCobertura, String testResultsSimulinkTest, String modelCoverageCobertura, + String selectByTag, String loggingLevel, String outputDetail, + boolean useParallel, boolean strict, List sourceFolder, + List selectByFolder) + throws IOException, InterruptedException { + super(context, startupOpts); + this.testResultsPDF = testResultsPDF; + this.testResultsTAP = testResultsTAP; + this.testResultsJUnit = testResultsJUnit; + this.codeCoverageCobertura = codeCoverageCobertura; + this.testResultsSimulinkTest = testResultsSimulinkTest; + this.modelCoverageCobertura = modelCoverageCobertura; + this.selectByTag = selectByTag; + this.loggingLevel = loggingLevel; + this.outputDetail = outputDetail; + this.useParallel = useParallel; + this.strict = strict; + this.sourceFolder = sourceFolder; + this.selectByFolder = selectByFolder; + } + + public TestActionParameters(Run build, FilePath workspace, EnvVars env, Launcher launcher, TaskListener listener, String startupOpts, + String testResultsPDF, String testResultsTAP, String testResultsJUnit, + String codeCoverageCobertura, String testResultsSimulinkTest, String modelCoverageCobertura, + String selectByTag, String loggingLevel, String outputDetail, + boolean useParallel, boolean strict, List sourceFolder, + List selectByFolder) { + super(build, workspace, env, launcher, listener, startupOpts); + this.testResultsPDF = testResultsPDF; + this.testResultsTAP = testResultsTAP; + this.testResultsJUnit = testResultsJUnit; + this.codeCoverageCobertura = codeCoverageCobertura; + this.testResultsSimulinkTest = testResultsSimulinkTest; + this.modelCoverageCobertura = modelCoverageCobertura; + this.selectByTag = selectByTag; + this.loggingLevel = loggingLevel; + this.outputDetail = outputDetail; + this.useParallel = useParallel; + this.strict = strict; + this.sourceFolder = sourceFolder; + this.selectByFolder = selectByFolder; + } + + public String getTestResultsPDF() { + return testResultsPDF; + } + + public String getTestResultsTAP() { + return testResultsTAP; + } + + public String getTestResultsJUnit() { + return testResultsJUnit; + } + + public String getCodeCoverageCobertura() { + return codeCoverageCobertura; + } + + public String getTestResultsSimulinkTest() { + return testResultsSimulinkTest; + } + + public String getModelCoverageCobertura() { + return modelCoverageCobertura; + } + + public String getSelectByTag() { + return selectByTag; + } + + public String getLoggingLevel() { + if (loggingLevel == null) { + return null; + } + + return loggingLevel.equalsIgnoreCase("default") ? null : loggingLevel; + } + + public String getOutputDetail() { + if (outputDetail == null) { + return null; + } + + return outputDetail.equalsIgnoreCase("default") ? null : outputDetail; + } + + public String getUseParallel() { + return String.valueOf(useParallel); + } + + public String getStrict() { + return String.valueOf(strict); + } + + public List getSourceFolder() { + return sourceFolder; + } + + public List getSelectByFolder() { + return selectByFolder; + } +} diff --git a/src/main/java/com/mathworks/ci/pipeline/MatlabBuildStepExecution.java b/src/main/java/com/mathworks/ci/pipeline/MatlabBuildStepExecution.java new file mode 100644 index 00000000..a9d8e7ea --- /dev/null +++ b/src/main/java/com/mathworks/ci/pipeline/MatlabBuildStepExecution.java @@ -0,0 +1,57 @@ +package com.mathworks.ci.pipeline; + +/** + * Copyright 2022-2024 The MathWorks, Inc. + * + */ + +import java.io.IOException; + +import org.jenkinsci.plugins.workflow.steps.StepContext; +import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; +import hudson.model.Result; + +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabBuildAction; +import com.mathworks.ci.parameters.BuildActionParameters; + +public class MatlabBuildStepExecution extends SynchronousNonBlockingStepExecution { + + private static final long serialVersionUID = 4771831219402275744L; + + private BuildActionParameters params; + private MatlabActionFactory factory; + public MatlabBuildStepExecution(MatlabActionFactory factory, StepContext context, String tasks, String startupOptions, String buildOptions) throws IOException, InterruptedException { + super(context); + + this.params = new BuildActionParameters(context, startupOptions, tasks, buildOptions); + this.factory = factory; + } + + public MatlabBuildStepExecution(StepContext context, String tasks, String startupOptions, String buildOptions) throws IOException, InterruptedException { + this(new MatlabActionFactory(), context, tasks, startupOptions, buildOptions); + } + + public BuildActionParameters getParameters() { + return this.params; + } + + @Override + public Void run() throws Exception { + RunMatlabBuildAction action = factory.createAction(params); + try { + action.run(); + } catch (Exception e) { + // throw an exception if return code is non-zero + stop(e); + } + + getContext().setResult(Result.SUCCESS); + return null; + } + + @Override + public void stop(Throwable cause) throws Exception { + getContext().onFailure(cause); + } +} diff --git a/src/main/java/com/mathworks/ci/pipeline/MatlabCommandStepExecution.java b/src/main/java/com/mathworks/ci/pipeline/MatlabCommandStepExecution.java new file mode 100644 index 00000000..88f702d3 --- /dev/null +++ b/src/main/java/com/mathworks/ci/pipeline/MatlabCommandStepExecution.java @@ -0,0 +1,61 @@ +package com.mathworks.ci.pipeline; + +/** + * Copyright 2023-2024 The MathWorks, Inc. + * + */ + +import java.io.IOException; +import org.jenkinsci.plugins.workflow.steps.StepContext; +import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; +import hudson.model.Result; + +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.parameters.RunActionParameters; +import com.mathworks.ci.actions.RunMatlabCommandAction; + +public class MatlabCommandStepExecution extends SynchronousNonBlockingStepExecution { + + private static final long serialVersionUID = 1957239693658914450L; + + private String command; + private String startupOptions; + + private RunActionParameters params; + + private MatlabActionFactory factory; + + public MatlabCommandStepExecution(MatlabActionFactory factory, StepContext context, String command, String startupOptions) throws IOException, InterruptedException { + super(context); + + this.params = new RunActionParameters(context, startupOptions, command); + this.factory = factory; + } + + public MatlabCommandStepExecution(StepContext context, String command, String startupOptions) throws IOException, InterruptedException { + this(new MatlabActionFactory(), context, command, startupOptions); + } + + public RunActionParameters getParameters() { + return this.params; + } + + @Override + public Void run() throws Exception { + RunMatlabCommandAction action = factory.createAction(params); + + try { + action.run(); + } catch (Exception e) { + stop(e); + } + + getContext().setResult(Result.SUCCESS); + return null; + } + + @Override + public void stop(Throwable cause) throws Exception { + getContext().onFailure(cause); + } +} diff --git a/src/main/java/com/mathworks/ci/pipeline/MatlabRunTestsStepExecution.java b/src/main/java/com/mathworks/ci/pipeline/MatlabRunTestsStepExecution.java new file mode 100644 index 00000000..2476554f --- /dev/null +++ b/src/main/java/com/mathworks/ci/pipeline/MatlabRunTestsStepExecution.java @@ -0,0 +1,58 @@ +package com.mathworks.ci.pipeline; + +/** + * Copyright 2020-2024 The MathWorks, Inc. + * + */ + +import java.io.IOException; + +import org.jenkinsci.plugins.workflow.steps.StepContext; +import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution; + +import hudson.model.Result; + +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabTestsAction; +import com.mathworks.ci.parameters.TestActionParameters; + +public class MatlabRunTestsStepExecution extends SynchronousNonBlockingStepExecution { + + private static final long serialVersionUID = 6704588180717665100L; + + private TestActionParameters params; + private MatlabActionFactory factory; + + public MatlabRunTestsStepExecution(MatlabActionFactory factory, StepContext context, TestActionParameters params) throws IOException, InterruptedException { + super(context); + + this.params = params; + this.factory = factory; + } + + public MatlabRunTestsStepExecution(StepContext context, TestActionParameters params) throws IOException, InterruptedException { + this(new MatlabActionFactory(), context, params); + } + + public TestActionParameters getParameters() { + return this.params; + } + + @Override + public Void run() throws Exception { + RunMatlabTestsAction action = factory.createAction(params); + try { + action.run(); + } catch (Exception e) { + stop(e); + } + + getContext().setResult(Result.SUCCESS); + return null; + } + + @Override + public void stop(Throwable cause) throws Exception { + getContext().onFailure(cause); + } +} diff --git a/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java b/src/main/java/com/mathworks/ci/pipeline/RunMatlabBuildStep.java similarity index 95% rename from src/main/java/com/mathworks/ci/RunMatlabBuildStep.java rename to src/main/java/com/mathworks/ci/pipeline/RunMatlabBuildStep.java index 091c993f..ab65936b 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabBuildStep.java +++ b/src/main/java/com/mathworks/ci/pipeline/RunMatlabBuildStep.java @@ -1,7 +1,7 @@ -package com.mathworks.ci; +package com.mathworks.ci.pipeline; /** - * Copyright 2022-2023 The MathWorks, Inc. + * Copyright 2022-2024 The MathWorks, Inc. * */ @@ -21,6 +21,8 @@ import hudson.model.TaskListener; import hudson.Util; +import com.mathworks.ci.Message; + public class RunMatlabBuildStep extends Step { private String tasks; diff --git a/src/main/java/com/mathworks/ci/RunMatlabCommandStep.java b/src/main/java/com/mathworks/ci/pipeline/RunMatlabCommandStep.java similarity index 96% rename from src/main/java/com/mathworks/ci/RunMatlabCommandStep.java rename to src/main/java/com/mathworks/ci/pipeline/RunMatlabCommandStep.java index 2e1434ca..95b08c65 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabCommandStep.java +++ b/src/main/java/com/mathworks/ci/pipeline/RunMatlabCommandStep.java @@ -1,4 +1,4 @@ -package com.mathworks.ci; +package com.mathworks.ci.pipeline; /** * Copyright 2020-2023 The MathWorks, Inc. @@ -21,6 +21,8 @@ import hudson.model.TaskListener; import hudson.Util; +import com.mathworks.ci.Message; + public class RunMatlabCommandStep extends Step { private String command; diff --git a/src/main/java/com/mathworks/ci/RunMatlabTestsStep.java b/src/main/java/com/mathworks/ci/pipeline/RunMatlabTestsStep.java similarity index 68% rename from src/main/java/com/mathworks/ci/RunMatlabTestsStep.java rename to src/main/java/com/mathworks/ci/pipeline/RunMatlabTestsStep.java index ba8ee496..af5b3b8e 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabTestsStep.java +++ b/src/main/java/com/mathworks/ci/pipeline/RunMatlabTestsStep.java @@ -1,6 +1,6 @@ -package com.mathworks.ci; +package com.mathworks.ci.pipeline; /** - * Copyright 2020-2023 The MathWorks, Inc. + * Copyright 2020-2024 The MathWorks, Inc. * */ @@ -24,6 +24,9 @@ import hudson.model.TaskListener; import hudson.Util; +import com.mathworks.ci.Message; +import com.mathworks.ci.parameters.TestActionParameters; + public class RunMatlabTestsStep extends Step { private String testResultsPDF; @@ -37,8 +40,8 @@ public class RunMatlabTestsStep extends Step { private String outputDetail; private boolean useParallel; private boolean strict; - private List sourceFolder = new ArrayList<>(); - private List selectByFolder = new ArrayList<>(); + private List sourceFolder; + private List selectByFolder; private String startupOptions; @@ -108,7 +111,7 @@ public List getSourceFolder() { @DataBoundSetter public void setSourceFolder(List sourceFolder) { - this.sourceFolder = Util.fixNull(sourceFolder); + this.sourceFolder = sourceFolder; } public String getSelectByTag() { @@ -176,7 +179,23 @@ public void setStartupOptions(String startupOptions) { @Override public StepExecution start(StepContext context) throws Exception { - return new MatlabRunTestsStepExecution(context, getInputArgs(), getStartupOptions()); + TestActionParameters params = new TestActionParameters( + context, + this.getStartupOptions(), + this.getTestResultsPDF(), + this.getTestResultsTAP(), + this.getTestResultsJUnit(), + this.getCodeCoverageCobertura(), + this.getTestResultsSimulinkTest(), + this.getModelCoverageCobertura(), + this.getSelectByTag(), + this.getLoggingLevel(), + this.getOutputDetail(), + this.getUseParallel(), + this.getStrict(), + this.getSourceFolder(), + this.getSelectByFolder()); + return new MatlabRunTestsStepExecution(context, params); } @Extension @@ -198,49 +217,4 @@ public String getDisplayName() { return Message.getValue("matlab.tests.step.display.name"); } } - - private String getInputArgs() { - final List inputArgs = new ArrayList<>(); - final Map args = getGenscriptArgs(); - - inputArgs.add("'Test'"); - - args.forEach((key, val) -> { - if (val != null) { - if (key.equals("SourceFolder") || key.equals("SelectByFolder") - || key.equals("UseParallel") - || key.equals("Strict")) { - inputArgs.add("'" + key + "'" + "," + val); - } else { - inputArgs.add("'" + key + "'" + "," + "'" + val.replaceAll("'", "''") + "'"); - } - } - }); - - return String.join(",", inputArgs); - } - - private Map getGenscriptArgs() { - final Map args = new HashMap(); - args.put("PDFTestReport", getTestResultsPDF()); - args.put("TAPTestResults", getTestResultsTAP()); - args.put("JUnitTestResults", getTestResultsJUnit()); - args.put("SimulinkTestResults", getTestResultsSimulinkTest()); - args.put("CoberturaCodeCoverage", getCodeCoverageCobertura()); - args.put("CoberturaModelCoverage", getModelCoverageCobertura()); - args.put("SelectByTag", getSelectByTag()); - args.put("UseParallel", String.valueOf(getUseParallel())); - args.put("Strict", String.valueOf(getStrict())); - args.put("LoggingLevel", getLoggingLevel()); - args.put("OutputDetail", getOutputDetail()); - addFolderArgs("SourceFolder",getSourceFolder(),args); - addFolderArgs("SelectByFolder",getSelectByFolder(),args); - return args; - } - - private void addFolderArgs(String argName,List value,Map args) { - if(!value.isEmpty()){ - args.put(argName, Utilities.getCellArrayFrmList(value)); - } - } } diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java new file mode 100644 index 00000000..85921e38 --- /dev/null +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -0,0 +1,209 @@ +package com.mathworks.ci.utilities; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.ByteArrayOutputStream; +import java.util.Map; +import java.util.HashMap; +import org.apache.commons.lang.RandomStringUtils; + +import hudson.FilePath; +import hudson.EnvVars; +import hudson.Launcher; +import hudson.Launcher.ProcStarter; +import hudson.model.Computer; +import hudson.util.ArgumentListBuilder; + +import com.mathworks.ci.Utilities; +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.MatlabBuilderConstants; +import com.mathworks.ci.parameters.MatlabActionParameters; + +public class MatlabCommandRunner { + private MatlabActionParameters params; + private FilePath tempFolder; + private OutputStream stdOut; + private Map additionalEnvVars; + + public MatlabCommandRunner(MatlabActionParameters params) throws IOException, InterruptedException { + this.params = params; + this.additionalEnvVars = new HashMap(); + + // Create MATLAB folder + FilePath matlabFolder = new FilePath(params.getLauncher().getChannel(), params.getWorkspace().getRemote() + "/.matlab"); + matlabFolder.mkdirs(); + + // Create temp folder + this.tempFolder = matlabFolder.createTempDir("tempDir", null); + + // If we hit an error during shutdown while cleaning up + // there's not too much that we can do. + Runtime.getRuntime().addShutdownHook( + new Thread(() -> { + try { + tempFolder.deleteRecursive(); + } catch(Exception e) {} + })); + } + + /** + * Spawns a process to run the specified command. + * + * @param command The command to run + */ + public void runMatlabCommand(String command) throws IOException, InterruptedException, MatlabExecutionException { + + this.params.getTaskListener().getLogger() + .println("\n#################### Starting command output ####################"); + + // Prepare the executable + FilePath exePath = prepareRunnerExecutable(); + + // Create the script file + FilePath scriptFile = createFileWithContent(command); + String cmd = "setenv('MW_ORIG_WORKING_FOLDER', cd('" + + this.tempFolder.getRemote() + + "'));" + + scriptFile.getBaseName(); + + // Create command + ArgumentListBuilder args = new ArgumentListBuilder(); + args.add(exePath.getRemote()); + args.add(cmd); + args.add(this.params.getStartupOptions().split(" ")); + + // Add custom environment vars + EnvVars env = getEnvVars(); + Utilities.addMatlabToEnvPathFrmAxis( + Computer.currentComputer(), + this.params.getTaskListener(), + env); + + ProcStarter proc = this.params.getLauncher().launch() + .envs(env) + .cmds(args); + if (this.stdOut == null) { + proc.stdout(this.params.getTaskListener()); + } else { + proc.stdout(this.stdOut); + } + proc.pwd(this.params.getWorkspace()); + + int code = proc.join(); + + if (code != 0) { + throw new MatlabExecutionException(code); + } + } + + /** + * Redirects stdout. + * + * @param out the OutputStream to write to + */ + public void redirectStdOut(OutputStream out) { + this.stdOut = out; + } + + /** + * Adds an environment variable. + * + * @param key the environment variable name + * @param value the environment variable value + */ + public void addEnvironmentVariable(String key, String value) { + additionalEnvVars.put(key, value); + } + + public EnvVars getEnvVars() { + EnvVars env = new EnvVars(this.params.getEnvVars()); + env.putAll(additionalEnvVars); + return env; + } + + /** + * Copies a resource into the temporary folder. + * + * @param sourceFile the name of a resource the class loader can find. + * @param targetFile the name of the file to create in the temp folder. + * @return the FilePath to the new location in the temp folder. + */ + public FilePath copyFileToTempFolder(String sourceFile, String targetFile) throws IOException, InterruptedException { + final ClassLoader classLoader = getClass().getClassLoader(); + FilePath targetFilePath = new FilePath(this.tempFolder, targetFile); + InputStream in = classLoader.getResourceAsStream(sourceFile); + targetFilePath.copyFrom(in); + targetFilePath.chmod(0755); + + return targetFilePath; + } + + public FilePath getTempFolder() { + return tempFolder; + } + + /** + * Creates a file with the specified content in the temporary folder. + * + * Additionally, the file content will be prefixed with a statement returning to the MATLAB starting folder. + * + * @param content string that represents the content of the file. + * @return the FilePath to the script file that is created. + */ + protected FilePath createFileWithContent(String content) throws IOException, InterruptedException { + String fileName = "script_" + RandomStringUtils.randomAlphanumeric(8) + ".m"; + FilePath scriptFile = new FilePath(this.tempFolder, fileName); + + String expandedContent = getEnvVars().expand(content); + String finalContent = "cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + + expandedContent; + + this.params.getTaskListener().getLogger() + .println("Generating MATLAB script with content:\n" + expandedContent + "\n\n"); + + scriptFile.write(finalContent, "UTF-8"); + + return scriptFile; + } + + /** + * Copies platform specific runner file into the temporary folder. + * + * @return the FilePath to the runner executable + */ + protected FilePath prepareRunnerExecutable() throws IOException, InterruptedException { + Launcher launcher = this.params.getLauncher(); + if (launcher.isUnix()) { + // Run uname to check if we're on Linux + ByteArrayOutputStream kernelStream = new ByteArrayOutputStream(); + launcher.launch() + .cmds("uname") + .masks(true) + .stdout(kernelStream) + .join(); + + String runnerSource; + if (kernelStream.toString("UTF-8").contains("Linux")) { + runnerSource = "glnxa64/run-matlab-command"; + } else { + runnerSource = "maci64/run-matlab-command"; + } + + String dest = "run-matlab-command"; + copyFileToTempFolder(runnerSource, dest); + + return new FilePath(this.tempFolder, dest); + } + + // Windows + String dest = "run-matlab-command.exe"; + copyFileToTempFolder("win64/run-matlab-command.exe", dest); + return new FilePath(this.tempFolder, dest); + } +} diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabBuildBuilder/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/config.jelly rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabBuildBuilder/config.jelly diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabBuildBuilder/help-buildOptions.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-buildOptions.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabBuildBuilder/help-buildOptions.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabBuildBuilder/help-startupOptions.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-startupOptions.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabBuildBuilder/help-startupOptions.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-tasks.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabBuildBuilder/help-tasks.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabBuildBuilder/help-tasks.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabBuildBuilder/help-tasks.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabCommandBuilder/config.jelly b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabCommandBuilder/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabCommandBuilder/config.jelly rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabCommandBuilder/config.jelly diff --git a/src/main/resources/com/mathworks/ci/RunMatlabCommandBuilder/help-matlabCommand.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabCommandBuilder/help-matlabCommand.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabCommandBuilder/help-matlabCommand.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabCommandBuilder/help-matlabCommand.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabCommandBuilder/help-startupOptions.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabCommandBuilder/help-startupOptions.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabCommandBuilder/help-startupOptions.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabCommandBuilder/help-startupOptions.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/SelectByTag/config.jelly b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/SelectByTag/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/SelectByTag/config.jelly rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/SelectByTag/config.jelly diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/config.jelly b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/config.jelly rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/config.jelly diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-coberturaArtifact.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-coberturaArtifact.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-coberturaArtifact.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-coberturaArtifact.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-junitArtifact.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-junitArtifact.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-junitArtifact.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-junitArtifact.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-loggingLevel.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-loggingLevel.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-loggingLevel.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-loggingLevel.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-modelCoverageArtifact.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-modelCoverageArtifact.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-modelCoverageArtifact.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-modelCoverageArtifact.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-outputDetail.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-outputDetail.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-outputDetail.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-outputDetail.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-pdfReportArtifact.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-pdfReportArtifact.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-pdfReportArtifact.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-pdfReportArtifact.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-selectByFolder.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-selectByFolder.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-selectByFolder.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-selectByFolder.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-selectByTag.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-selectByTag.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-selectByTag.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-selectByTag.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-sourceFolder.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-sourceFolder.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-sourceFolder.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-sourceFolder.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabCommandStep/help-startupOptions.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-startupOptions.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabCommandStep/help-startupOptions.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-startupOptions.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-stmResultsArtifact.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-stmResultsArtifact.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-stmResultsArtifact.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-stmResultsArtifact.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-strict.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-strict.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-strict.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-strict.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-tapArtifact.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-tapArtifact.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-tapArtifact.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-tapArtifact.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-useParallel.html b/src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-useParallel.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-useParallel.html rename to src/main/resources/com/mathworks/ci/freestyle/RunMatlabTestsBuilder/help-useParallel.html diff --git a/src/main/resources/com/mathworks/ci/BuildOptions/config.jelly b/src/main/resources/com/mathworks/ci/freestyle/options/BuildOptions/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/BuildOptions/config.jelly rename to src/main/resources/com/mathworks/ci/freestyle/options/BuildOptions/config.jelly diff --git a/src/main/resources/com/mathworks/ci/SelectByFolder/config.jelly b/src/main/resources/com/mathworks/ci/freestyle/options/SelectByFolder/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/SelectByFolder/config.jelly rename to src/main/resources/com/mathworks/ci/freestyle/options/SelectByFolder/config.jelly diff --git a/src/main/resources/com/mathworks/ci/SourceFolder/config.jelly b/src/main/resources/com/mathworks/ci/freestyle/options/SourceFolder/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/SourceFolder/config.jelly rename to src/main/resources/com/mathworks/ci/freestyle/options/SourceFolder/config.jelly diff --git a/src/main/resources/com/mathworks/ci/StartupOptions/config.jelly b/src/main/resources/com/mathworks/ci/freestyle/options/StartupOptions/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/StartupOptions/config.jelly rename to src/main/resources/com/mathworks/ci/freestyle/options/StartupOptions/config.jelly diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabBuildStep/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabBuildStep/config.jelly rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabBuildStep/config.jelly diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabBuildStep/help-buildOptions.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-buildOptions.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabBuildStep/help-buildOptions.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabBuildStep/help-startupOptions.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-startupOptions.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabBuildStep/help-startupOptions.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-tasks.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabBuildStep/help-tasks.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabBuildStep/help-tasks.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabBuildStep/help-tasks.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabCommandStep/config.jelly b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabCommandStep/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabCommandStep/config.jelly rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabCommandStep/config.jelly diff --git a/src/main/resources/com/mathworks/ci/RunMatlabCommandStep/help-command.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabCommandStep/help-command.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabCommandStep/help-command.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabCommandStep/help-command.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-startupOptions.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabCommandStep/help-startupOptions.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsBuilder/help-startupOptions.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabCommandStep/help-startupOptions.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/config.jelly b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/config.jelly similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/config.jelly rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/config.jelly diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-codeCoverageCobertura.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-codeCoverageCobertura.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-codeCoverageCobertura.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-codeCoverageCobertura.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-loggingLevel.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-loggingLevel.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-loggingLevel.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-loggingLevel.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-modelCoverageCobertura.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-modelCoverageCobertura.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-modelCoverageCobertura.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-modelCoverageCobertura.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-outputDetail.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-outputDetail.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-outputDetail.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-outputDetail.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-selectByFolder.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-selectByFolder.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-selectByFolder.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-selectByFolder.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-selectByTag.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-selectByTag.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-selectByTag.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-selectByTag.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-sourceFolder.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-sourceFolder.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-sourceFolder.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-sourceFolder.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-startupOptions.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-startupOptions.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-startupOptions.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-startupOptions.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-strict.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-strict.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-strict.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-strict.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-testResultsJUnit.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-testResultsJUnit.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-testResultsJUnit.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-testResultsJUnit.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-testResultsPDF.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-testResultsPDF.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-testResultsPDF.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-testResultsPDF.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-testResultsSimulinkTest.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-testResultsSimulinkTest.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-testResultsSimulinkTest.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-testResultsSimulinkTest.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-testResultsTAP.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-testResultsTAP.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-testResultsTAP.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-testResultsTAP.html diff --git a/src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-useParallel.html b/src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-useParallel.html similarity index 100% rename from src/main/resources/com/mathworks/ci/RunMatlabTestsStep/help-useParallel.html rename to src/main/resources/com/mathworks/ci/pipeline/RunMatlabTestsStep/help-useParallel.html diff --git a/src/test/java/com/mathworks/ci/RunMatlabBuildStepTester.java b/src/test/java/com/mathworks/ci/RunMatlabBuildStepTester.java deleted file mode 100644 index 0a7cb379..00000000 --- a/src/test/java/com/mathworks/ci/RunMatlabBuildStepTester.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.mathworks.ci; - -/** - * Copyright 2022 The MathWorks, Inc. - * - */ - -import java.util.Set; -import org.jenkinsci.plugins.workflow.steps.StepContext; -import org.jenkinsci.plugins.workflow.steps.StepDescriptor; -import org.jenkinsci.plugins.workflow.steps.StepExecution; -import org.kohsuke.stapler.DataBoundConstructor; -import com.google.common.collect.ImmutableSet; -import hudson.EnvVars; -import hudson.Extension; -import hudson.FilePath; -import hudson.Launcher; -import hudson.model.Run; -import hudson.model.TaskListener; - -public class RunMatlabBuildStepTester extends RunMatlabBuildStep { - @DataBoundConstructor - public RunMatlabBuildStepTester() { - - } - - @Override - public StepExecution start(StepContext context) throws Exception { - return new TestStepExecution(context,this.getTasks(), this.getStartupOptions()); - } - - @Extension - public static class BuildStepTestDescriptor extends StepDescriptor { - - @Override - public Set> getRequiredContext() { - return ImmutableSet.of(TaskListener.class, FilePath.class, Launcher.class, - EnvVars.class, Run.class); - } - - @Override - public String getFunctionName() { - return "testMATLABBuild"; - } - } - -} diff --git a/src/test/java/com/mathworks/ci/RunMatlabCommandStepTester.java b/src/test/java/com/mathworks/ci/RunMatlabCommandStepTester.java deleted file mode 100644 index 9fc33535..00000000 --- a/src/test/java/com/mathworks/ci/RunMatlabCommandStepTester.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.mathworks.ci; - -/** - * Copyright 2020 The MathWorks, Inc. - * - */ - -import java.util.Set; -import org.jenkinsci.plugins.workflow.steps.StepContext; -import org.jenkinsci.plugins.workflow.steps.StepDescriptor; -import org.jenkinsci.plugins.workflow.steps.StepExecution; -import org.kohsuke.stapler.DataBoundConstructor; -import com.google.common.collect.ImmutableSet; -import hudson.EnvVars; -import hudson.Extension; -import hudson.FilePath; -import hudson.Launcher; -import hudson.model.Run; -import hudson.model.TaskListener; - -public class RunMatlabCommandStepTester extends RunMatlabCommandStep { - @DataBoundConstructor - public RunMatlabCommandStepTester(String command) { - super(command); - } - - @Override - public StepExecution start(StepContext context) throws Exception { - - return new TestStepExecution(context,this.getCommand(), this.getStartupOptions()); - } - - @Extension - public static class CommandStepTestDescriptor extends StepDescriptor { - - @Override - public Set> getRequiredContext() { - return ImmutableSet.of(TaskListener.class, FilePath.class, Launcher.class, - EnvVars.class, Run.class); - } - - @Override - public String getFunctionName() { - return "testMATLABCommand"; - } - } - -} diff --git a/src/test/java/com/mathworks/ci/RunMatlabTestsStepTester.java b/src/test/java/com/mathworks/ci/RunMatlabTestsStepTester.java deleted file mode 100644 index 6a170312..00000000 --- a/src/test/java/com/mathworks/ci/RunMatlabTestsStepTester.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.mathworks.ci; - -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import org.jenkinsci.plugins.workflow.steps.StepContext; -import org.jenkinsci.plugins.workflow.steps.StepDescriptor; -import org.jenkinsci.plugins.workflow.steps.StepExecution; -import org.kohsuke.stapler.DataBoundConstructor; -import com.google.common.collect.ImmutableSet; -import hudson.EnvVars; -import hudson.Extension; -import hudson.FilePath; -import hudson.Launcher; -import hudson.model.Run; -import hudson.model.TaskListener; - -public class RunMatlabTestsStepTester extends RunMatlabTestsStep { - - - @DataBoundConstructor - public RunMatlabTestsStepTester() { - - } - - @Override - public StepExecution start(StepContext context) throws Exception { - - return new TestStepExecution(context, getInputArgs(), getStartupOptions()); - } - - - @Extension - public static class CommandStepTestDescriptor extends StepDescriptor { - - @Override - public Set> getRequiredContext() { - return ImmutableSet.of(TaskListener.class, FilePath.class, Launcher.class, - EnvVars.class, Run.class); - } - - @Override - public String getFunctionName() { - return "testMATLABTests"; - } - } - - public String getInputArgs() { - List args = Arrays.asList(getTestResultsPDF(), getTestResultsTAP(), - getTestResultsJUnit(), getTestResultsSimulinkTest(), getCodeCoverageCobertura(), - getModelCoverageCobertura()); - - return String.join(",", args); - } -} diff --git a/src/test/java/com/mathworks/ci/TestStepExecution.java b/src/test/java/com/mathworks/ci/TestStepExecution.java deleted file mode 100644 index fcc82d22..00000000 --- a/src/test/java/com/mathworks/ci/TestStepExecution.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.mathworks.ci; -/** - * Copyright 2020 The MathWorks, Inc. - * - */ - -import java.io.IOException; -import org.jenkinsci.plugins.workflow.steps.StepContext; -import hudson.EnvVars; -import hudson.FilePath; -import hudson.Launcher; -import hudson.Launcher.ProcStarter; -import hudson.model.TaskListener; - -public class TestStepExecution extends MatlabRunTestsStepExecution { - - public TestStepExecution(StepContext context, String command, String startupOptions) { - super(context, command, startupOptions); - - } - - @Override - public ProcStarter getProcessToRunMatlabCommand(FilePath workspace, Launcher launcher, - TaskListener listener, EnvVars envVars, String matlabCommand, String startupOptions, String uniqueName) - throws IOException, InterruptedException { - // Get node specific tmp directory to copy matlab runner script - FilePath targetWorkspace = new FilePath(launcher.getChannel(), - workspace.getRemote() + "/" + MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME); - - ProcStarter matlabLauncher; - if (launcher.isUnix()) { - final String runnerScriptName = uniqueName + "/run_matlab_command_test.sh"; - matlabLauncher = launcher.launch().pwd(workspace).envs(envVars) - .cmds(MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME + "/" + runnerScriptName, matlabCommand).stdout(listener); - - // Copy runner .sh for linux platform in workspace. - copyFileInWorkspace("run_matlab_command_test.sh", runnerScriptName, targetWorkspace); - } else { - final String runnerScriptName = uniqueName + "\\run_matlab_command_test.bat"; - launcher = launcher.decorateByPrefix("cmd.exe", "/C"); - matlabLauncher = launcher.launch().pwd(workspace).envs(envVars) - .cmds(MatlabBuilderConstants.TEMP_MATLAB_FOLDER_NAME + "\\" + runnerScriptName, "\"" + matlabCommand + "\"") - .stdout(listener); - // Copy runner.bat for Windows platform in workspace. - copyFileInWorkspace("run_matlab_command_test.bat", runnerScriptName, targetWorkspace); - } - return matlabLauncher; - } -} diff --git a/src/test/java/com/mathworks/ci/BuildArtifactActionTest.java b/src/test/java/integ/com/mathworks/ci/BuildArtifactActionTest.java similarity index 99% rename from src/test/java/com/mathworks/ci/BuildArtifactActionTest.java rename to src/test/java/integ/com/mathworks/ci/BuildArtifactActionTest.java index 1bfadb4b..8c1fb4e7 100644 --- a/src/test/java/com/mathworks/ci/BuildArtifactActionTest.java +++ b/src/test/java/integ/com/mathworks/ci/BuildArtifactActionTest.java @@ -20,6 +20,8 @@ import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; +import com.mathworks.ci.freestyle.RunMatlabBuildBuilder; + public class BuildArtifactActionTest { private FreeStyleProject project; private UseMatlabVersionBuildWrapper buildWrapper; diff --git a/src/test/java/com/mathworks/ci/MatlabInstallationTest.java b/src/test/java/integ/com/mathworks/ci/MatlabInstallationTest.java similarity index 97% rename from src/test/java/com/mathworks/ci/MatlabInstallationTest.java rename to src/test/java/integ/com/mathworks/ci/MatlabInstallationTest.java index 8548de57..72e3c63e 100644 --- a/src/test/java/com/mathworks/ci/MatlabInstallationTest.java +++ b/src/test/java/integ/com/mathworks/ci/MatlabInstallationTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertEquals; import static org.jvnet.hudson.test.JenkinsRule.NO_PROPERTIES; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder; public class MatlabInstallationTest { @@ -118,10 +119,11 @@ public void verifyInstallationInPipeline() throws Exception { + " matlabroot = tool 'R2018b' \n" + " withEnv([\"PATH+MATLAB=$matlabroot/bin\"]) { \n" + " echo env.PATH \n" - + " testMATLABTests(testResultsPDF:'myresult/result.pdf')}}", true)); + + " runMATLABTests(testResultsPDF:'myresult/result.pdf')}}", true)); WorkflowRun build = project.scheduleBuild2(0).get(); - jenkins.assertBuildStatusSuccess(build); jenkins.assertLogContains("versioninfo", build); + jenkins.assertLogContains("2018b", build); + jenkins.assertLogContains("bin", build); } /* * Test to verify usage of MATLAB tool installation in freestyle project. diff --git a/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java similarity index 98% rename from src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java index 72f57c36..07002a11 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java @@ -1,7 +1,7 @@ package com.mathworks.ci; /** - * Copyright 2022-2023 The MathWorks, Inc. + * Copyright 2022-2024 The MathWorks, Inc. * */ @@ -34,6 +34,10 @@ import hudson.slaves.EnvironmentVariablesNodeProperty; import hudson.tasks.Builder; +import com.mathworks.ci.freestyle.RunMatlabBuildBuilder; +import com.mathworks.ci.freestyle.options.StartupOptions; +import com.mathworks.ci.freestyle.options.BuildOptions; + public class RunMatlabBuildBuilderTest { private static String matlabExecutorAbsolutePath; @@ -145,7 +149,7 @@ public void verifyMATLABlaunchedfromWorkspace() throws Exception { project.getBuildersList().add(this.scriptBuilder); FreeStyleBuild build = project.scheduleBuild2(0).get(); String workspace = build.getWorkspace().getName(); - jenkins.assertLogContains("[" + workspace + "]", build); + jenkins.assertLogContains(File.separator + workspace + File.separator, build); } /* diff --git a/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTester.java b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTester.java similarity index 98% rename from src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTester.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTester.java index 18bb8fe8..a52fb244 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabBuildBuilderTester.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTester.java @@ -23,6 +23,8 @@ import hudson.tasks.Builder; import net.sf.json.JSONObject; +import com.mathworks.ci.freestyle.RunMatlabBuildBuilder; + public class RunMatlabBuildBuilderTester extends RunMatlabBuildBuilder { private int buildResult; private EnvVars env; diff --git a/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildStepTest.java similarity index 89% rename from src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabBuildStepTest.java index bab80f74..c1a836e1 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabBuildStepTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildStepTest.java @@ -1,7 +1,7 @@ -package com.mathworks.ci; +package com.mathworks.ci.pipeline; /** - * Copyright 2022-2023 The MathWorks, Inc. + * Copyright 2022-2024 The MathWorks, Inc. * */ @@ -18,13 +18,12 @@ import hudson.FilePath; import hudson.slaves.DumbSlave; -public class RunMatlabBuildStepTest { +import com.mathworks.ci.Message; +public class RunMatlabBuildStepTest { private WorkflowJob project; - - @Rule public JenkinsRule j = new JenkinsRule(); @@ -64,13 +63,13 @@ public void verifyMATLABstartsInWorkspace() throws Exception { /* * Verify MATLAB is invoked when valid MATLAB is on system path. */ - @Test - public void verifyMATLABPathSet() throws Exception { - project.setDefinition( - new CpsFlowDefinition("node { testMATLABBuild() }", true)); - WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains("tester_started", build); - } + // @Test + // public void verifyMATLABPathSet() throws Exception { + // project.setDefinition( + // new CpsFlowDefinition("node { runMATLABBuild() }", true)); + // WorkflowRun build = project.scheduleBuild2(0).get(); + // j.assertLogContains("tester_started", build); + // } /* * Verify Pipeline script runs on Jenkins node with valid MATLAB @@ -79,12 +78,12 @@ public void verifyMATLABPathSet() throws Exception { public void verifyPipelineOnSlave() throws Exception { DumbSlave s = j.createOnlineSlave(); project.setDefinition(new CpsFlowDefinition( - "node('!master') { testMATLABBuild() }", true)); + "node('!master') { runMATLABBuild() }", true)); s.getWorkspaceFor(project); WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertBuildStatusSuccess(build); + j.assertLogNotContains("Running on Jenkins", build); } /* @@ -175,7 +174,6 @@ public void verifyExceptionStackTraceForNonZeroExitCode() throws Exception { WorkflowRun build = project.scheduleBuild2(0).get(); j.assertBuildStatus(Result.FAILURE, build); - j.assertLogContains("com.mathworks.ci.MatlabExecutionException", build); j.assertLogContains(String.format(Message.getValue("matlab.execution.exception.prefix"), 1), build); } @@ -185,10 +183,9 @@ public void verifyExceptionStackTraceForNonZeroExitCode() throws Exception { @Test public void verifyMATLABtempFolderGenerated() throws Exception { project.setDefinition( - new CpsFlowDefinition("node { testMATLABBuild() }", true)); + new CpsFlowDefinition("node { runMATLABBuild() }", true)); WorkflowRun build = project.scheduleBuild2(0).get(); j.assertLogContains(".matlab", build); - j.assertBuildStatusSuccess(build); } } diff --git a/src/test/java/com/mathworks/ci/RunMatlabCommandBuilderTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java similarity index 96% rename from src/test/java/com/mathworks/ci/RunMatlabCommandBuilderTest.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java index 78d9a79d..caf7cdc1 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabCommandBuilderTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java @@ -1,7 +1,7 @@ package com.mathworks.ci; /** - * Copyright 2019-2023 The MathWorks, Inc. + * Copyright 2019-2024 The MathWorks, Inc. * * Test class for RunMatlabCommandBuilderTest * @@ -36,6 +36,9 @@ import hudson.slaves.EnvironmentVariablesNodeProperty; import hudson.tasks.Builder; +import com.mathworks.ci.freestyle.RunMatlabCommandBuilder; +import com.mathworks.ci.freestyle.options.StartupOptions; + public class RunMatlabCommandBuilderTest { private static String matlabExecutorAbsolutePath; @@ -153,7 +156,7 @@ public void verifyMATLABlaunchedfromWorkspace() throws Exception { project.getBuildersList().add(this.scriptBuilder); FreeStyleBuild build = project.scheduleBuild2(0).get(); String workspace = build.getWorkspace().getName(); - jenkins.assertLogContains("[" + workspace + "]", build); + jenkins.assertLogContains(File.separator + workspace + File.separator, build); } /* diff --git a/src/test/java/com/mathworks/ci/RunMatlabCommandBuilderTester.java b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTester.java similarity index 95% rename from src/test/java/com/mathworks/ci/RunMatlabCommandBuilderTester.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTester.java index d24def54..8236c85d 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabCommandBuilderTester.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTester.java @@ -24,6 +24,8 @@ import hudson.tasks.Builder; import net.sf.json.JSONObject; +import com.mathworks.ci.freestyle.RunMatlabCommandBuilder; + public class RunMatlabCommandBuilderTester extends RunMatlabCommandBuilder { private int buildResult; private EnvVars env; diff --git a/src/test/java/com/mathworks/ci/RunMatlabCommandStepTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandStepTest.java similarity index 77% rename from src/test/java/com/mathworks/ci/RunMatlabCommandStepTest.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabCommandStepTest.java index c22e8c11..7cce2833 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabCommandStepTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandStepTest.java @@ -1,6 +1,6 @@ -package com.mathworks.ci; +package com.mathworks.ci.pipeline; /** - * Copyright 2020-2023 The MathWorks, Inc. + * Copyright 2020-2024 The MathWorks, Inc. * */ @@ -17,13 +17,12 @@ import hudson.FilePath; import hudson.slaves.DumbSlave; -public class RunMatlabCommandStepTest { +import com.mathworks.ci.Message; +public class RunMatlabCommandStepTest { private WorkflowJob project; - - @Rule public JenkinsRule j = new JenkinsRule(); @@ -32,7 +31,6 @@ public void testSetup() throws IOException { this.project = j.createProject(WorkflowJob.class); } - /* * Verify when MATLAB is not in PATH variable. */ @@ -67,13 +65,13 @@ public void verifyMATLABstartsInWorkspace() throws Exception { * */ - @Test - public void verifyMATLABPathSet() throws Exception { - project.setDefinition( - new CpsFlowDefinition("node { testMATLABCommand(command: 'pwd')}", true)); - WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains("tester_started", build); - } + // @Test + // public void verifyMATLABPathSet() throws Exception { + // project.setDefinition( + // new CpsFlowDefinition("node { runMATLABCommand(command: 'pwd')}", true)); + // WorkflowRun build = project.scheduleBuild2(0).get(); + // j.assertLogContains("tester_started", build); + // } /* * Verify Pipeline script runs on Slave with valid MATLAB @@ -84,12 +82,12 @@ public void verifyMATLABPathSet() throws Exception { public void verifyPipelineOnSlave() throws Exception { DumbSlave s = j.createOnlineSlave(); project.setDefinition(new CpsFlowDefinition( - "node('!master') { testMATLABCommand(command: 'pwd')}", true)); + "node('!master') { runMATLABCommand(command: 'pwd')}", true)); s.getWorkspaceFor(project); WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertBuildStatusSuccess(build); + j.assertLogNotContains("Running on Jenkins", build); } /* @@ -151,21 +149,6 @@ public void verifyExceptionForNonZeroExitCode() throws Exception { j.assertLogContains(String.format(Message.getValue("matlab.execution.exception.prefix"), 1), build); j.assertBuildStatusSuccess(build); } - - /* - * Test for verifying Run Matlab Command raises exception for non-zero exit code. - * */ - @Test - public void verifyExceptionStackTraceForNonZeroExitCode() throws Exception { - // exitMatlab is a mock command for run_matlab_command script to exit with 1. - project.setDefinition( - new CpsFlowDefinition("node { runMATLABCommand(command: 'exitMatlab')}", true)); - - WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertBuildStatus(Result.FAILURE, build); - j.assertLogContains("com.mathworks.ci.MatlabExecutionException", build); - j.assertLogContains(String.format(Message.getValue("matlab.execution.exception.prefix"), 1), build); - } /* * Verify .matlab folder is generated @@ -175,10 +158,9 @@ public void verifyExceptionStackTraceForNonZeroExitCode() throws Exception { @Test public void verifyMATLABtempFolderGenerated() throws Exception { project.setDefinition( - new CpsFlowDefinition("node { testMATLABCommand(command: 'pwd')}", true)); + new CpsFlowDefinition("node { runMATLABCommand(command: 'pwd')}", true)); WorkflowRun build = project.scheduleBuild2(0).get(); j.assertLogContains(".matlab", build); - j.assertBuildStatusSuccess(build); } } diff --git a/src/test/java/com/mathworks/ci/RunMatlabTestBuilderPersistenceTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabTestBuilderPersistenceTest.java similarity index 97% rename from src/test/java/com/mathworks/ci/RunMatlabTestBuilderPersistenceTest.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabTestBuilderPersistenceTest.java index 44526ab8..3aad1315 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabTestBuilderPersistenceTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabTestBuilderPersistenceTest.java @@ -1,6 +1,6 @@ package com.mathworks.ci; /** - * Copyright 2020 The MathWorks, Inc. + * Copyright 2020-2024 The MathWorks, Inc. * * Test class for RunMatlabTestsBuilder Persistence * @@ -15,6 +15,9 @@ import static org.junit.Assert.*; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder; +import com.mathworks.ci.freestyle.options.*; + public class RunMatlabTestBuilderPersistenceTest { private final String tapFilePath = "mytap/report.tap"; private final String pdfFilePath = "mypdf/report.pdf"; diff --git a/src/test/java/com/mathworks/ci/RunMatlabTestsBuilderTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTest.java similarity index 86% rename from src/test/java/com/mathworks/ci/RunMatlabTestsBuilderTest.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTest.java index 65472497..db28c64f 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabTestsBuilderTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTest.java @@ -1,6 +1,6 @@ package com.mathworks.ci; /** - * Copyright 2019-2023 The MathWorks, Inc. + * Copyright 2019-2024 The MathWorks, Inc. * * Test class for RunMatlabTestsBuilder * @@ -26,12 +26,12 @@ import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.html.HtmlSelect; import com.gargoylesoftware.htmlunit.javascript.host.html.HTMLSelectElement; -import com.mathworks.ci.RunMatlabTestsBuilder.CoberturaArtifact; -import com.mathworks.ci.RunMatlabTestsBuilder.JunitArtifact; -import com.mathworks.ci.RunMatlabTestsBuilder.ModelCovArtifact; -import com.mathworks.ci.RunMatlabTestsBuilder.PdfArtifact; -import com.mathworks.ci.RunMatlabTestsBuilder.StmResultsArtifact; -import com.mathworks.ci.RunMatlabTestsBuilder.TapArtifact; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder.CoberturaArtifact; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder.JunitArtifact; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder.ModelCovArtifact; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder.PdfArtifact; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder.StmResultsArtifact; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder.TapArtifact; import hudson.FilePath; import hudson.matrix.Axis; import hudson.matrix.AxisList; @@ -44,6 +44,9 @@ import hudson.model.Result; import hudson.tasks.Builder; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder; +import com.mathworks.ci.freestyle.options.StartupOptions; + import static org.junit.Assert.*; public class RunMatlabTestsBuilderTest { @@ -134,37 +137,6 @@ public void verifyBuildStepWithMatlabTestBuilder() throws Exception { Assert.assertTrue("Build step does not contain Run MATLAB Tests option", found); } - /* - * Test To verify MATLAB is launched using run matlab script for version above R2018b - * - */ - - @Test - public void verifyMATLABlaunchedWithDefaultArgumentsBatch() throws Exception { - this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); - project.getBuildWrappersList().add(this.buildWrapper); - project.getBuildersList().add(this.testBuilder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - jenkins.assertLogContains("run-matlab-command", build); - jenkins.assertLogContains("runner", build); - jenkins.assertLogContains("addpath(", build); - } - - /* - * Test To verify MATLAB is launched using run matlab script for version below R2018b - * on windows - */ - - @Test - public void verifyMATLABlaunchedWithDefaultArgumentsRWindows() throws Exception { - this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2017a"))); - project.getBuildWrappersList().add(this.buildWrapper); - project.getBuildersList().add(testBuilder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - jenkins.assertLogContains("run-matlab-command", build); - jenkins.assertLogContains("runner", build); - } - /* * Test to verify if job fails when invalid MATLAB path is provided and Exception is thrown */ @@ -385,13 +357,12 @@ public void verifyAllTestArtifactsParameters() throws Exception { project.getBuildersList().add(this.testBuilder); FreeStyleBuild build = project.scheduleBuild2(0).get(); jenkins.assertLogContains("run-matlab-command", build); - jenkins.assertLogContains("runner", build); - jenkins.assertLogNotContains("\'PDFTestReport\',\'mypdf/report.pdf\'",build); - jenkins.assertLogNotContains("\'TAPTestResults\',\'mytap/report.tap\'",build); - jenkins.assertLogNotContains("\'JUnitTestResults\',\'myjunit/report.xml\'",build); - jenkins.assertLogNotContains("\'SimulinkTestResults\',\'mystm/results.mldatx\'",build); - jenkins.assertLogNotContains("\'CoberturaCodeCoverage\',\'mycobertura/report.xml\'",build); - jenkins.assertLogNotContains("\'CoberturaModelCoverage\',\'mymodel/report.xml\'",build); + jenkins.assertLogContains("\'PDFTestReport\',\'mypdf/report.pdf\'",build); + jenkins.assertLogContains("\'TAPTestResults\',\'mytap/report.tap\'",build); + jenkins.assertLogContains("\'JUnitTestResults\',\'myjunit/report.xml\'",build); + jenkins.assertLogContains("\'SimulinkTestResults\',\'mystm/results.mldatx\'",build); + jenkins.assertLogContains("\'CoberturaCodeCoverage\',\'mycobertura/report.xml\'",build); + jenkins.assertLogContains("\'CoberturaModelCoverage\',\'mymodel/report.xml\'",build); } @@ -400,13 +371,17 @@ public void verifyAllTestArtifactsParameters() throws Exception { */ @Test - public void veriyEmptyParameters() throws Exception { - this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); + public void verifyEmptyParameters() throws Exception { + this.buildWrapper.setMatlabBuildWrapperContent( + new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); project.getBuildWrappersList().add(this.buildWrapper); project.getBuildersList().add(this.testBuilder); FreeStyleBuild build = project.scheduleBuild2(0).get(); jenkins.assertLogContains("run-matlab-command", build); - jenkins.assertLogContains("runner", build); + jenkins.assertLogNotContains("'OutputDetail'", build); + jenkins.assertLogNotContains("'PDFTestReport'", build); + jenkins.assertLogNotContains("'Strict'", build); + jenkins.assertLogNotContains("'SourceFolder'", build); } @@ -522,35 +497,9 @@ public void verifyMATLABfolderGenerated() throws Exception { Assert.assertTrue(matlabRunner.exists()); } - /* - * Test to verify if runner script is deleted from .matlab folder during MATLAB call - */ - @Test - public void verifyRunnerScriptDeleted() throws Exception { - this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); - project.getBuildWrappersList().add(this.buildWrapper); - project.getBuildersList().add(testBuilder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - jenkins.assertLogContains("delete('.matlab/", build); - } - - /* - * Test to verify if runner script is deleted from system temp directory during MATLAB call - */ - @Test - public void verifySystemTempDirDeleted() throws Exception { - this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); - project.getBuildWrappersList().add(this.buildWrapper); - project.getBuildersList().add(testBuilder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - jenkins.assertLogContains("rmdir(tmpDir,'s')", build); - } - - /* * Test to verify Use Parallel check box present. */ - @Test public void verifyUseParallelPresent() throws Exception { this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); diff --git a/src/test/java/com/mathworks/ci/RunMatlabTestsBuilderTester.java b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTester.java similarity index 95% rename from src/test/java/com/mathworks/ci/RunMatlabTestsBuilderTester.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTester.java index 51764247..cac180ba 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabTestsBuilderTester.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTester.java @@ -1,6 +1,6 @@ package com.mathworks.ci; /** - * Copyright 2019-2020 The MathWorks, Inc. + * Copyright 2019-2024 The MathWorks, Inc. * * Tester builder for RunMatlabTestsBuilder. * @@ -25,6 +25,8 @@ import hudson.tasks.Builder; import net.sf.json.JSONObject; +import com.mathworks.ci.freestyle.RunMatlabTestsBuilder; + public class RunMatlabTestsBuilderTester extends RunMatlabTestsBuilder { private Artifact tapArtifact = new NullArtifact();; diff --git a/src/test/java/com/mathworks/ci/RunMatlabTestsStepTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java similarity index 86% rename from src/test/java/com/mathworks/ci/RunMatlabTestsStepTest.java rename to src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java index c71df152..7d55873b 100644 --- a/src/test/java/com/mathworks/ci/RunMatlabTestsStepTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java @@ -1,7 +1,7 @@ -package com.mathworks.ci; +package com.mathworks.ci.pipeline; /** - * Copyright 2020-2023 The MathWorks, Inc. + * Copyright 2020-2024 The MathWorks, Inc. * */ @@ -19,6 +19,8 @@ import org.jvnet.hudson.test.JenkinsRule; import hudson.slaves.DumbSlave; +import com.mathworks.ci.Message; + public class RunMatlabTestsStepTest { private WorkflowJob project; @@ -51,9 +53,9 @@ public void verifyMATLABPathNotSet() throws Exception { @Test public void verifyMATLABPathSet() throws Exception { project.setDefinition(new CpsFlowDefinition( - "node {testMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); + "node {runMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains("tester_started", build); + j.assertLogContains("myresult/result.pdf", build); } /* @@ -64,10 +66,11 @@ public void verifyMATLABPathSet() throws Exception { public void verifyOnslave() throws Exception { DumbSlave s = j.createOnlineSlave(); project.setDefinition(new CpsFlowDefinition( - "node('!master') {testMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); + "node('!master') {runMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); s.getWorkspaceFor(project); WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertBuildStatusSuccess(build); + + j.assertLogNotContains("Running on Jenkins", build); } /* @@ -105,8 +108,8 @@ public void verifyCmdOptions() throws Exception { project.setDefinition(new CpsFlowDefinition( "node {runMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains("addpath(", build); - j.assertLogContains("runner", build); + j.assertLogContains("setenv('MW_ORIG_WORKING_FOLDER',", build); + j.assertLogContains("run-matlab-command", build); } /* @@ -118,7 +121,7 @@ public void verifyArtifactParameters() throws Exception { project.setDefinition(new CpsFlowDefinition( "node {runMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogNotContains("'PDFTestReport','myresult/result.pdf'", build); + j.assertLogContains("'PDFTestReport','myresult/result.pdf'", build); j.assertLogNotContains("TAPTestResults", build); j.assertLogNotContains("JUnitTestResults", build); j.assertLogNotContains("CoberturaCodeCoverage", build); @@ -135,7 +138,7 @@ public void verifyEmptyParameter() throws Exception { project.setDefinition(new CpsFlowDefinition( "node {runMATLABTests()}", true)); WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains("runner", build); + j.assertLogContains("run-matlab-command", build); j.assertLogNotContains("PDFReportPath", build); j.assertLogNotContains("TAPResultsPath", build); j.assertLogNotContains("JUnitResultsPath", build); @@ -160,9 +163,8 @@ public void verifyExceptionForNonZeroExitCode() throws Exception { @Test public void verifyMATLABtempFolderGenerated() throws Exception { project.setDefinition(new CpsFlowDefinition( - "node {testMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); + "node {runMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertBuildStatusSuccess(build); j.assertLogContains(".matlab", build); } @@ -176,31 +178,6 @@ public void verifyTestSelectByFolder () throws Exception { WorkflowRun build = project.scheduleBuild2(0).get(); j.assertLogContains("mytest1", build); j.assertLogContains("mytest2", build); - j.assertBuildStatusSuccess(build); - } - - /* - * Verify runner script deleted from .matlab folder during MATLAB call - */ - - @Test - public void verifyRunnerScriptDeletedFromWorkSpace() throws Exception { - project.setDefinition(new CpsFlowDefinition( - "node {runMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); - WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains("delete('.matlab/", build); - } - - /* - * Verify runner script deleted from system Tmp directory during MATLAB call - */ - - @Test - public void verifySystemTmpDirDeleted() throws Exception { - project.setDefinition(new CpsFlowDefinition( - "node {runMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); - WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains("rmdir(tmpDir,'s')", build); } /*@Integ Test @@ -212,7 +189,6 @@ public void verifyTestSelectByTag () throws Exception { "node {runMATLABTests(selectByTag: 'myTestTag')}", true)); WorkflowRun build = project.scheduleBuild2(0).get(); j.assertLogContains("myTestTag", build); - j.assertBuildStatusSuccess(build); } /*@Integ diff --git a/src/test/java/com/mathworks/ci/TestMessage.java b/src/test/java/integ/com/mathworks/ci/TestMessage.java similarity index 100% rename from src/test/java/com/mathworks/ci/TestMessage.java rename to src/test/java/integ/com/mathworks/ci/TestMessage.java diff --git a/src/test/java/com/mathworks/ci/UseMatlabVersionBuildWrapperTest.java b/src/test/java/integ/com/mathworks/ci/UseMatlabVersionBuildWrapperTest.java similarity index 100% rename from src/test/java/com/mathworks/ci/UseMatlabVersionBuildWrapperTest.java rename to src/test/java/integ/com/mathworks/ci/UseMatlabVersionBuildWrapperTest.java diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java new file mode 100644 index 00000000..ae2f5591 --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java @@ -0,0 +1,170 @@ +package com.mathworks.ci.actions; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Files; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.InOrder; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import hudson.FilePath; +import hudson.model.Run; +import hudson.model.TaskListener; + +import com.mathworks.ci.BuildArtifactAction; +import com.mathworks.ci.BuildConsoleAnnotator; +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.utilities.MatlabCommandRunner; +import com.mathworks.ci.parameters.BuildActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class RunMatlabBuildActionTest { + @Mock BuildActionParameters params; + @Mock BuildConsoleAnnotator annotator; + @Mock MatlabCommandRunner runner; + @Mock TaskListener listener; + @Mock PrintStream out; + @Mock Run build; + + @Mock FilePath tempFolder; + + private boolean setup = false; + private RunMatlabBuildAction action; + + @Before + public void init() { + if (!setup) { + setup = true; + action = new RunMatlabBuildAction(runner, annotator, params); + + when(runner.getTempFolder()).thenReturn(tempFolder); + when(tempFolder.getRemote()).thenReturn("/path/less/traveled"); + + when(params.getWorkspace()).thenReturn(tempFolder); + + when(params.getTaskListener()).thenReturn(listener); + when(listener.getLogger()).thenReturn(out); + + when(params.getBuild()).thenReturn(build); + } + } + + @Test + public void shouldCopyPluginsToTempDirectory() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + String DEFAULT_PLUGIN = + "+ciplugins/+jenkins/getDefaultPlugins.m"; + String BUILD_REPORT_PLUGIN = + "+ciplugins/+jenkins/BuildReportPlugin.m"; + String TASK_RUN_PROGRESS_PLUGIN = + "+ciplugins/+jenkins/TaskRunProgressPlugin.m"; + + InOrder inOrder = inOrder(runner); + + inOrder.verify(runner) + .copyFileToTempFolder(DEFAULT_PLUGIN, DEFAULT_PLUGIN); + inOrder.verify(runner) + .copyFileToTempFolder(BUILD_REPORT_PLUGIN, BUILD_REPORT_PLUGIN); + inOrder.verify(runner) + .copyFileToTempFolder(TASK_RUN_PROGRESS_PLUGIN, TASK_RUN_PROGRESS_PLUGIN); + } + + @Test + public void shouldOverrideDefaultPlugins() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + verify(runner).addEnvironmentVariable( + "MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE", + "ciplugins.jenkins.getDefaultPlugins"); + } + + @Test + public void shouldUseCustomAnnotator() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + verify(runner).redirectStdOut(annotator); + } + + @Test + public void shouldRunCorrectCommand() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + verify(runner).runMatlabCommand("addpath('/path/less/traveled'); buildtool"); + } + + @Test + public void shouldRunCommandWithTasksAndBuildOptions() throws IOException, InterruptedException, MatlabExecutionException { + doReturn("dishes groceries").when(params).getTasks(); + doReturn("-continueOnFailure -skip dishes").when(params) + .getBuildOptions(); + + action.run(); + + verify(runner).runMatlabCommand( + "addpath('/path/less/traveled'); " + + "buildtool dishes groceries " + + "-continueOnFailure -skip dishes"); + } + + @Test + public void shouldPrintAndRethrowMessage() throws IOException, InterruptedException, MatlabExecutionException { + doThrow(new MatlabExecutionException(12)).when(runner).runMatlabCommand(anyString()); + + try { + action.run(); + } catch (MatlabExecutionException e) { + verify(out).println(e.getMessage()); + assertEquals(12, e.getExitCode()); + }; + } + + @Test + public void shouldNotAddActionIfNoBuildResult() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + verify(build, never()).addAction(any(BuildArtifactAction.class)); + } + + @Test + public void shouldCopyBuildResultsToRootAndAddsAction() throws IOException, InterruptedException, MatlabExecutionException { + File tmp = Files.createTempDirectory("temp").toFile(); + tmp.deleteOnExit(); + + File matlab = new File(tmp, ".matlab"); + File json = new File(matlab, "buildArtifact.json"); + + matlab.mkdirs(); + json.createNewFile(); + + doReturn(new FilePath(tmp)).when(params).getWorkspace(); + doReturn(tmp).when(build).getRootDir(); + + boolean runTimeException = false; + try { + action.run(); + } catch (RuntimeException e) { + runTimeException = true; + } + + // Should throw for invalid file + assertTrue(runTimeException); + // Should have deleted original file + assertFalse(json.exists()); + // Should have copied file to root dir + assertTrue(new File(tmp, "buildArtifact.json").exists()); + } +} diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java new file mode 100644 index 00000000..1e3f4542 --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java @@ -0,0 +1,68 @@ +package com.mathworks.ci.actions; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; +import java.io.PrintStream; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import hudson.model.TaskListener; + +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.utilities.MatlabCommandRunner; +import com.mathworks.ci.parameters.RunActionParameters; + +@RunWith(MockitoJUnitRunner.Silent.class) +public class RunMatlabCommandActionTest { + @Mock RunActionParameters params; + @Mock MatlabCommandRunner runner; + @Mock PrintStream out; + @Mock TaskListener listener; + + private boolean setup = false; + private RunMatlabCommandAction action; + + @Before + public void init() { + if (!setup) { + setup = true; + action = new RunMatlabCommandAction(runner, params); + } + } + + @Test + public void runsGivenCommand() throws IOException, InterruptedException, MatlabExecutionException { + when(params.getCommand()).thenReturn("Sit!"); + + action.run(); + + verify(runner).runMatlabCommand("Sit!"); + } + + @Test + public void printsAndRethrowsMessage() throws IOException, InterruptedException, MatlabExecutionException { + // Falsely flagged as unecessary >:( + when(params.getTaskListener()).thenReturn(listener); + when(listener.getLogger()).thenReturn(out); + + doThrow(new MatlabExecutionException(12)).when(runner).runMatlabCommand(anyString()); + + try { + action.run(); + } catch (MatlabExecutionException e) { + verify(out).println(e.getMessage()); + assertEquals(12, e.getExitCode()); + }; + } +} diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java new file mode 100644 index 00000000..33fc609d --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java @@ -0,0 +1,172 @@ +package com.mathworks.ci.actions; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; +import java.io.PrintStream; + +import java.util.ArrayList; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.*; + +import org.mockito.Mock; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import hudson.FilePath; +import hudson.model.TaskListener; + +import com.mathworks.ci.MatlabBuilderConstants; +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.utilities.MatlabCommandRunner; +import com.mathworks.ci.parameters.TestActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class RunMatlabTestsActionTest { + @Mock TestActionParameters params; + @Mock MatlabCommandRunner runner; + @Mock PrintStream out; + @Mock TaskListener listener; + @Mock FilePath tempFolder; + + private boolean setup = false; + private RunMatlabTestsAction action; + + @Before + public void init() throws IOException, InterruptedException { + if (!setup) { + setup = true; + action = new RunMatlabTestsAction(runner, params); + + when(runner.getTempFolder()).thenReturn(tempFolder); + when(tempFolder.getRemote()).thenReturn("/gravel/path"); + when(runner.copyFileToTempFolder(anyString(), anyString())) + .thenReturn(tempFolder); + } + } + + @Test + public void shouldCopyGenscriptToTempDir() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + verify(runner).copyFileToTempFolder( + MatlabBuilderConstants.MATLAB_SCRIPT_GENERATOR, + "genscript.zip"); + verify(tempFolder).unzip(tempFolder); + } + + @Test + public void shouldAddTempFolderToPath() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(runner).runMatlabCommand(captor.capture()); + + assertThat(captor.getValue(), containsString("addpath('/gravel/path')")); + } + + @Test + public void shouldReplaceParamsCorrectlyWhenAllNull() throws IOException, InterruptedException, MatlabExecutionException { + // Keep parameters as null + action.run(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(runner).runMatlabCommand(captor.capture()); + + assertThat(captor.getValue(), containsString("genscript('Test')")); + } + + @Test + public void shouldReplaceParamsCorrectlyWithFewNull() throws IOException, InterruptedException, MatlabExecutionException { + // Set some params + doReturn("results.xml").when(params).getTestResultsJUnit(); + doReturn("cov.xml").when(params).getCodeCoverageCobertura(); + doReturn("true").when(params).getStrict(); + doReturn("Default").when(params).getLoggingLevel(); + doReturn("Concise").when(params).getOutputDetail(); + + ArrayList sourceFolders = new ArrayList(); + sourceFolders.add("src"); + sourceFolders.add("toolbox"); + doReturn(sourceFolders).when(params).getSourceFolder(); + + action.run(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(runner).runMatlabCommand(captor.capture()); + assertThat(captor.getValue(), containsString( + "genscript('Test','JUnitTestResults','results.xml'," + + "'CoberturaCodeCoverage','cov.xml'," + + "'Strict',true," + + "'LoggingLevel','Default'," + + "'OutputDetail','Concise'," + + "'SourceFolder',{'src','toolbox'})" + )); + } + + @Test + public void shouldReplaceParamsCorrectlyWithNoneNull() throws IOException, InterruptedException, MatlabExecutionException { + // Set all params + doReturn("results.pdf").when(params).getTestResultsPDF(); + doReturn("results.tap").when(params).getTestResultsTAP(); + doReturn("results.xml").when(params).getTestResultsJUnit(); + doReturn("cov.xml").when(params).getCodeCoverageCobertura(); + doReturn("results.sltest").when(params).getTestResultsSimulinkTest(); + doReturn("cov.model").when(params).getModelCoverageCobertura(); + doReturn("MyTag").when(params).getSelectByTag(); + doReturn("true").when(params).getUseParallel(); + doReturn("true").when(params).getStrict(); + doReturn("Default").when(params).getLoggingLevel(); + doReturn("Concise").when(params).getOutputDetail(); + + ArrayList sourceFolders = new ArrayList(); + sourceFolders.add("src"); + sourceFolders.add("toolbox"); + doReturn(sourceFolders).when(params).getSourceFolder(); + doReturn(sourceFolders).when(params).getSelectByFolder(); + + action.run(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); + verify(runner).runMatlabCommand(captor.capture()); + assertThat(captor.getValue(), containsString( + "genscript('Test'," + + "'PDFTestReport','results.pdf'," + + "'TAPTestResults','results.tap'," + + "'JUnitTestResults','results.xml'," + + "'CoberturaCodeCoverage','cov.xml'," + + "'SimulinkTestResults','results.sltest'," + + "'CoberturaModelCoverage','cov.model'," + + "'SelectByTag','MyTag'," + + "'UseParallel',true," + + "'Strict',true," + + "'LoggingLevel','Default'," + + "'OutputDetail','Concise'," + + "'SourceFolder',{'src','toolbox'}," + + "'SelectByFolder',{'src','toolbox'})" + )); + } + + @Test + public void printsAndRethrowsMessage() throws IOException, InterruptedException, MatlabExecutionException { + when(params.getTaskListener()).thenReturn(listener); + when(listener.getLogger()).thenReturn(out); + + doThrow(new MatlabExecutionException(12)).when(runner).runMatlabCommand(anyString()); + + try { + action.run(); + } catch (MatlabExecutionException e) { + verify(out).println(e.getMessage()); + assertEquals(12, e.getExitCode()); + }; + } +} diff --git a/src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabBuildBuilderUnitTest.java b/src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabBuildBuilderUnitTest.java new file mode 100644 index 00000000..02e38116 --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabBuildBuilderUnitTest.java @@ -0,0 +1,106 @@ +package com.mathworks.ci.freestyle; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import hudson.FilePath; +import hudson.Launcher; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.model.Result; + +import com.mathworks.ci.freestyle.options.StartupOptions; +import com.mathworks.ci.freestyle.options.BuildOptions; +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabBuildAction; +import com.mathworks.ci.parameters.BuildActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class RunMatlabBuildBuilderUnitTest { + @Mock + MatlabActionFactory factory; + + @Mock + RunMatlabBuildAction action; + + @Mock + Run build; + + @Mock + Launcher launcher; + + @Mock + TaskListener listener; + + @Mock + FilePath workspace; + + @Before + public void setup() throws IOException, InterruptedException { + doReturn(action).when(factory).createAction(any(BuildActionParameters.class)); + } + + @Test + public void shouldHandleNullCases() throws IOException, InterruptedException, MatlabExecutionException { + RunMatlabBuildBuilder builder = new RunMatlabBuildBuilder(factory); + + builder.perform(build, workspace, launcher, listener); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BuildActionParameters.class); + verify(factory).createAction(captor.capture()); + + BuildActionParameters actual = captor.getValue(); + + assertEquals("", actual.getStartupOptions()); + assertEquals(null, actual.getTasks()); + assertEquals(null, actual.getBuildOptions()); + verify(action).run(); + } + + @Test + public void shouldHandleMaximalCases() throws IOException, InterruptedException, MatlabExecutionException { + RunMatlabBuildBuilder builder = new RunMatlabBuildBuilder(factory); + builder.setTasks("laundry sweeping"); + builder.setBuildOptions(new BuildOptions("-continueOnFailure -skip laundry")); + builder.setStartupOptions(new StartupOptions("-nojvm -logfile mylog")); + + builder.perform(build, workspace, launcher, listener); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BuildActionParameters.class); + verify(factory).createAction(captor.capture()); + + BuildActionParameters actual = captor.getValue(); + + assertEquals("-nojvm -logfile mylog", actual.getStartupOptions()); + assertEquals("laundry sweeping", actual.getTasks()); + assertEquals("-continueOnFailure -skip laundry", actual.getBuildOptions()); + verify(action).run(); + } + + @Test + public void shouldMarkFailureWhenActionFails() throws IOException, InterruptedException, MatlabExecutionException { + RunMatlabBuildBuilder builder = new RunMatlabBuildBuilder(factory); + + doThrow(new MatlabExecutionException(12)).when(action).run(); + + builder.perform(build, workspace, launcher, listener); + + verify(build).setResult(Result.FAILURE); + } +} + diff --git a/src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabCommandBuilderUnitTest.java b/src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabCommandBuilderUnitTest.java new file mode 100644 index 00000000..3b15c754 --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabCommandBuilderUnitTest.java @@ -0,0 +1,102 @@ +package com.mathworks.ci.freestyle; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import hudson.FilePath; +import hudson.Launcher; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.model.Result; + +import com.mathworks.ci.freestyle.options.StartupOptions; +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabCommandAction; +import com.mathworks.ci.parameters.RunActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class RunMatlabCommandBuilderUnitTest { + @Mock + MatlabActionFactory factory; + + @Mock + RunMatlabCommandAction action; + + @Mock + Run build; + + @Mock + Launcher launcher; + + @Mock + TaskListener listener; + + @Mock + FilePath workspace; + + @Before + public void setup() throws IOException, InterruptedException { + doReturn(action).when(factory).createAction(any(RunActionParameters.class)); + } + + @Test + public void shouldHandleNullCases() throws IOException, InterruptedException, MatlabExecutionException { + RunMatlabCommandBuilder builder = new RunMatlabCommandBuilder(factory); + + builder.perform(build, workspace, launcher, listener); + + ArgumentCaptor captor = ArgumentCaptor.forClass(RunActionParameters.class); + verify(factory).createAction(captor.capture()); + + RunActionParameters actual = captor.getValue(); + + assertEquals("", actual.getStartupOptions()); + assertEquals(null, actual.getCommand()); + verify(action).run(); + } + + @Test + public void shouldHandleMaximalCases() throws IOException, InterruptedException, MatlabExecutionException { + RunMatlabCommandBuilder builder = new RunMatlabCommandBuilder(factory); + builder.setMatlabCommand("SHAKE"); + builder.setStartupOptions(new StartupOptions("-nojvm -logfile mylog")); + + builder.perform(build, workspace, launcher, listener); + + ArgumentCaptor captor = ArgumentCaptor.forClass(RunActionParameters.class); + verify(factory).createAction(captor.capture()); + + RunActionParameters actual = captor.getValue(); + + assertEquals("-nojvm -logfile mylog", actual.getStartupOptions()); + assertEquals("SHAKE", actual.getCommand()); + verify(action).run(); + } + + @Test + public void shouldMarkFailureWhenActionFails() throws IOException, InterruptedException, MatlabExecutionException { + RunMatlabCommandBuilder builder = new RunMatlabCommandBuilder(factory); + + doThrow(new MatlabExecutionException(12)).when(action).run(); + + builder.perform(build, workspace, launcher, listener); + + verify(build).setResult(Result.FAILURE); + } +} + diff --git a/src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabTestsBuilderUnitTest.java b/src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabTestsBuilderUnitTest.java new file mode 100644 index 00000000..a753cd85 --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/freestyle/RunMatlabTestsBuilderUnitTest.java @@ -0,0 +1,159 @@ +package com.mathworks.ci.freestyle; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; +import java.util.ArrayList; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.InjectMocks; +import org.mockito.ArgumentCaptor; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import hudson.FilePath; +import hudson.Launcher; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.model.Result; + +import com.mathworks.ci.freestyle.options.*; +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabTestsAction; +import com.mathworks.ci.parameters.TestActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class RunMatlabTestsBuilderUnitTest { + @Mock + MatlabActionFactory factory; + + @Mock + RunMatlabTestsAction action; + + @Mock + Run build; + + @Mock + Launcher launcher; + + @Mock + TaskListener listener; + + @Mock + FilePath workspace; + + @Before + public void setup() throws IOException, InterruptedException { + doReturn(action).when(factory).createAction(any(TestActionParameters.class)); + } + + @Test + public void shouldHandleNullCases() throws IOException, InterruptedException, MatlabExecutionException { + RunMatlabTestsBuilder builder = new RunMatlabTestsBuilder(factory); + + builder.perform(build, workspace, launcher, listener); + + ArgumentCaptor captor = ArgumentCaptor.forClass(TestActionParameters.class); + verify(factory).createAction(captor.capture()); + + TestActionParameters actual = captor.getValue(); + + assertEquals("", actual.getStartupOptions()); + assertEquals(null, actual.getTestResultsPDF()); + assertEquals(null, actual.getTestResultsTAP()); + assertEquals(null, actual.getTestResultsJUnit()); + assertEquals(null, actual.getCodeCoverageCobertura()); + assertEquals(null, actual.getTestResultsSimulinkTest()); + assertEquals(null, actual.getModelCoverageCobertura()); + assertEquals(null, actual.getSelectByTag()); + assertEquals(null, actual.getLoggingLevel()); + assertEquals(null, actual.getOutputDetail()); + assertEquals("false", actual.getUseParallel()); + assertEquals("false", actual.getStrict()); + assertEquals(null, actual.getSourceFolder()); + assertEquals(null, actual.getSelectByFolder()); + verify(action).run(); + } + + @Test + public void shouldHandleMaximalCases() throws IOException, InterruptedException, MatlabExecutionException { + RunMatlabTestsBuilder builder = new RunMatlabTestsBuilder(factory); + + ArrayList source = new ArrayList(); + source.add(new SourceFolderPaths("toolbox")); + source.add(new SourceFolderPaths("src")); + + ArrayList select = new ArrayList(); + select.add(new TestFolders("toolbox")); + select.add(new TestFolders("src")); + + builder.setStartupOptions(new StartupOptions("-nojvm -logfile mylog")); + builder.setPdfReportArtifact( + new RunMatlabTestsBuilder.PdfArtifact("pdf.pdf")); + builder.setTapArtifact( + new RunMatlabTestsBuilder.TapArtifact("tap.tap")); + builder.setJunitArtifact( + new RunMatlabTestsBuilder.JunitArtifact("results.xml")); + builder.setCoberturaArtifact( + new RunMatlabTestsBuilder.CoberturaArtifact("cov.xml")); + builder.setStmResultsArtifact( + new RunMatlabTestsBuilder.StmResultsArtifact("res.sltest")); + builder.setModelCoverageArtifact( + new RunMatlabTestsBuilder.ModelCovArtifact("cov.model")); + builder.setSelectByTag( + new RunMatlabTestsBuilder.SelectByTag("MyTag")); + builder.setSourceFolder( + new SourceFolder(source)); + builder.setSelectByFolder( + new SelectByFolder(select)); + builder.setLoggingLevel("Concise"); + builder.setOutputDetail("Concise"); + builder.setUseParallel(true); + builder.setStrict(true); + + builder.perform(build, workspace, launcher, listener); + + ArgumentCaptor captor = ArgumentCaptor.forClass(TestActionParameters.class); + verify(factory).createAction(captor.capture()); + + TestActionParameters actual = captor.getValue(); + + assertEquals("-nojvm -logfile mylog", actual.getStartupOptions()); + assertEquals("pdf.pdf", actual.getTestResultsPDF()); + assertEquals("tap.tap", actual.getTestResultsTAP()); + assertEquals("results.xml", actual.getTestResultsJUnit()); + assertEquals("cov.xml", actual.getCodeCoverageCobertura()); + assertEquals("res.sltest", actual.getTestResultsSimulinkTest()); + assertEquals("cov.model", actual.getModelCoverageCobertura()); + assertEquals("MyTag", actual.getSelectByTag()); + assertEquals("Concise", actual.getLoggingLevel()); + assertEquals("Concise", actual.getOutputDetail()); + assertEquals("true", actual.getUseParallel()); + assertEquals("true", actual.getStrict()); + assertEquals(2, actual.getSourceFolder().size()); + assertEquals(2, actual.getSelectByFolder().size()); + verify(action).run(); + } + + @Test + public void shouldMarkFailureWhenActionFails() throws IOException, InterruptedException, MatlabExecutionException { + RunMatlabTestsBuilder builder = new RunMatlabTestsBuilder(factory); + + doThrow(new MatlabExecutionException(12)).when(action).run(); + + builder.perform(build, workspace, launcher, listener); + + verify(build).setResult(Result.FAILURE); + } +} + diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.MatlabBuildStepExecutionUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.MatlabBuildStepExecutionUnitTest.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..9defa966121258fb1a6ab170f1ec8ccdaad3da05 GIT binary patch literal 12288 zcmeI2?`s@I7{{mD)*rQ2EC}rj86$zckef}eQiRl+G^7|IrcIO9H$^AAle@|7ukOy? z55x+-sVMr^3i?{Gf?`2@<=>$1e9_Ps;tO90z7`68XLm2TOZE~9wNx_8eRgv@zn=Nd zv-9kcXLaK8`~rQI)d-H~2pPR~PgI(x$&ZW2Ny2@>>mtxayB#f8R$X_JH)_?1)2D{l zyx!~3UKc@A21(WD%Hylm$V=-ou#?!al}MDm&Rg701F38$^lemXw8OZW*p9R#83|7Y z!d}Rlo=c_YUQ!~O>j)=RG7MJGY#E&}-N|rUOo>ro|0!^koT^Pu=y|_9@)AA%{L225 zz|7bvU=%P47zK<1MggOMQNSp$j}=hS0rCOn|5%~Ha&bMd?OJ>_7o&htz$jo8FbWt2 zi~>dhqkvJsC}0#Y3K#|chYE0)kZX?3Hcs;0zL*8!3FRl`12?sw?P+lzzP@zhr!)v2>A)z244dg907;G zLGaHJLOuj1!3pr~)36DA0d9hK!8>3S{Ph$eKZB3J4IqI7R>9j~<4Ho6z(w#nI17G# zf{H9HM-UL&cr8c z4Sj}jcbpdU8>d0)dHrYDtF4dHRZlv!6-t*TjWG4xH+bNBVkWaGn}!VPR)s1(ql9iM zF;3?f`@cZOI8Gxa+`hZRCQskX2A|f+S-Fxs7G{_zkYB`V?pn&d#2TsU`N<#^i@oI= z8K)7Cxu3AQP?<7|*~%rBUNt>seGK;EcNI^X11*2n(lezs$W<47gR{vc=j~m=g=Gij}g8hWetNc)&$x z;(F?fK+R^IpD8urY%w%!7_83L!gyADy;a(-cp`RxAReeEk8Cd2NZBfs`NSU1zQ8-u z=iV$&1lIh~boKoCy|%zAG(KT@u}Ew z2KO5sC3o8p5Zn}k+mgU`v>D<`Vh+lqt!Hk}n9_?J=LEJTLG)gpou(H;r%9L6pl^xt zU6$sNBp*7jme(tsNc<>_6~^$H-%D_2j%3->o&^Y2D)rRRmie3$Rwl^atxEJ6 z-YBoU^Hm8Ep_o?~*IAL}ttXWwcqdG!aj$t{n$1k?FosAce3lm9=rB< ze+cp81_Hr>BebU;kN~L#A+G!oe*s)LkQ*F0bKz2n@7UgCop>9N3M$H2`K+@$zutW3 z`Mr(uR;R8kEYfFKo#1+mkRLv|BTjFeBVR9_Br*2|ZwaZJ?sj#WZmrpz=IwfI>fG7U zJ>M8iXs-*o;mWw?bLH{XTIeM$SK4vp*h<98UgsTdC(>266ZkedwYx#I5!;Syhi)i5 zR|mIF%8qxjJC$K7zOs50>{bO`t+3E^_hv&^yK3! z`%M6|U!#Cgz$jo8FbWt2i~>dhqrkpaK!pd$n^53juEM4KeqhHve`{_=0i%FXz$jo8 zFbWt2i~>dhqkvJsC}0#Y3j7Zh;7vk~9U>%n5XR&G|AW8(Hy*&& z@Blan{yav=TVNcFf!hzGFSr4&gC=mmQ{a!IgnSRa12@49a23id;v9Go|sE5N;l!kmQ|rj?F+0^wt(!;a(yN9+7)nek2vfPxrMV!F5XAtYGt%g17->Wyja(9l9$U$zB)+3P+%n+ zzM3IvZ9q@pXY#RJMmD)+(Qxa!t`r~i8IroRb1`m|cG0Vqnv*RwmnQ!m zwq#9FcEmUWefovTvksXTmo(@vA=_)}!gb~bZ0PAgBb~GXerO{I`;psfD_WnbKV7BE iZJ`~reN|V<(*@};Voy#I5^`q)1^gvWmRHfwkiP&YvIi6Z literal 0 HcmV?d00001 diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.MatlabRunTestsStepExecutionUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.MatlabRunTestsStepExecutionUnitTest.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..4ee4f521ff2a346c33587ee4ff7c5c391ca2a5cc GIT binary patch literal 12288 zcmeI2O>Z1E7{^@%h_?cwCy=NNmC$UI^(0$VA#EuMt5gIjN-1f2KpdP|XLpiW&oK7v z3y2~(rUJf4K?3p83ts@PoB%Z^PJ974f%^B@n{1NVo+FC)1n&rGhK{@X?YQ1<&+~4hK6mNjbjw@g1;Z^N zw_~a5J+2eJQO}a16U$KLQK*H|;TG@nu#mA1qqG;os5?mWZ52jwn8le$VkyFva_aR$ zu3?6HTZ?RID565gsl0)i<|#AlOn1kRcm+Rv z0k42pz$@St@CtYZyaK0N0iB&8A3=f#oD7TZe&*2Kee^f4fLFjP;1%!+cm=!yUIDLw zSHLUa74Qmp1^$N$@HQd;JWR;>N8mjE|3CiwfA=Xu?tx#xH{dJq1-Jt~1D}FEco$p- z&w*zF0lQBU@-?^(cEDTU8aNOBI7`U4;C(Ox>)---5bQod$X)O`*a5dd6a4--#=t%B zGk6F5^%x<4g4w3UMSMyV?t_ zHEj3L_^)j8QdX4b|IU&SyAoH{8c%}g6{%N}my@^2DX@#P`rPNvF}W88L(xE5e= zGuGX}_!#T-O*4jPQsgcN35k1InrpnK$9m%qXBNe_I?K{yReRE$I?+b0Sd}Cv&#F*p z`Xp<7^rS~+xvkAM$G&K>JWmh#Vuy0O!*25rEN%^Ks#gq{o!)<^>04)U z$|gz(gLEbY_@b>e8|87Qt7&7d@$xKP>k5;Y-J7OMo-WIXk#J^)kc>y$XyC8NG1o=k GB=-R(L?4m> literal 0 HcmV?d00001 diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabBuildStepUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabBuildStepUnitTest.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..1fcbb502a7b0ec9f8882b53cec786533134fdb69 GIT binary patch literal 12288 zcmeI2&u<$=6vwCB_)$Rg0=K~+VMq0B>XZs$Ap#*lkW3Is=#|Ot)E;~GM|Wl&BLw^f zRB#8u4FnR19=LMif8YQ&ZdCjO2#N3Pu2aYHmI}lH<&FH^wRh&do%fkHE3Nzv*WcP1 z@MlDip*_slC!hbR9-Ula-|t>vR>n#WRpPtu)TWW{M$siX>UGzzY&4I2f9^0Ct7M`R z+l{3&^01qkVyKhA=3(HJb-`FpWl$vA1z{Qo7&JOc^N9^Y9b`IFMkgwGvq%P|^^1iz z(VkP;0SxwGF1&g3EU1SFoK*tn*+%cux{v;e*5mxbBL`;{1jS7RhyW2F0z`la5CI}U z1kNM@mz`rDAo6?a=tX@#w{)(5(uoKV0U|&IhyW2F0z`la5CI}U1c(3;_#YCG5o6cy zWo-LCOdkLL&)@%ld5E!}p`W0e(6`Xn&{xn6=tF1<9Y7mU4|)u`^&n%vK{uiApc_yG zZ9>mOPeXs4XY2=P3~A^o==TR0`v&?F`U3hCdK-EYx^+KeKSCcvA3=TSS?E{H`7>w$ zy#o0dUV^9*0U|&IhyW2F0z`la{Ko{|V;rqI`ft)&mAmchg*3L^>V|3JbW*6@sFl8-FdC0OIC-DNs8 z+W%b&H5x9F^_hIUuub{!kJ1I{SGLpe|J~BOUYNUIm(4*MPWT>DVXMkxUgvYaoExjx zKQ!3IE7D|Mw~YngL>yPO8@0Vh?b6qLAFd@T7o~XzZ;Wx4=8mWNP}F7Qp%zsIxfQ-n z{F+IRu&-2R#loDh0t=RL5xBjZZe%Ng{*trf_UCyKQ@@UKJL4N=M literal 0 HcmV?d00001 diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabCommandStepUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabCommandStepUnitTest.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..6b2dca0040ac815ed36a3fc0073f4927b2d32eda GIT binary patch literal 12288 zcmeI2F>ljA6vwYDNI(mM1;lccB`L%%DXJ<}NJUj73Y4Ih!hChE$+fo6*yl6|0TT=e z*x8ud0l~lu6MO*%1`tSy2^RPS{4aJOl%!>0fIh1~yXl?Zz5CtSQq;FNdUfDDiUGC&5% z02v?y+u4AL2G}hK*pW*(mR|=pT=S1~Ap>N943GgbKnBPF86X2>fDDiUGC&6YK?9=3 z*x_A_eFXOZ|DEsu@AfkG7Q6vZ!DFxv*1!XBA2h)N7z1T+2z(i0>=k$k?t^p`@GlVA*d-NV=uunyM1BjAC9;KOdl-h(^fHgLgbdXATof@1 zUyY2DLeYNC3rq{e;v};}*yGn>N}*nE2E63!`jYY`x2L}0=8cF=8dW2sbci7km9=By z^jk%1r6s-8c0_Lc6fgAeP)tw&>m)XK!PB9UEz=!2Yn5ih=)*lz@0w_@GFxtgA)8RH z@?Pz^_qNnLRFp3I%HvI~YCLJ^)UTaE&8{zJMN0+3pB9NM6uD`{dNtvdmM7bG`1Q7# zDO=Nbw!y*!NycZpS5lHTPS0v9iWIWib14f!*yJD z@(OWJIazUd;@A@KC10;%kIN`=y0XFpl;4T%Z?Mg5fFK*j$%k`BCOe(FTbFH>d8bcT zN(ND7PG}syG literal 0 HcmV?d00001 diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabTestsStepUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabTestsStepUnitTest.java.swp new file mode 100644 index 0000000000000000000000000000000000000000..3bea411fb831fa5258ce6be3275186221276ae1d GIT binary patch literal 12288 zcmeI2&u<$=6vrn(Nei@8t;&hRVlGZvuhXPdk;0D#Hx;FIQ#A<{;8j5YrpKTf_`JV=D)QmaKh)l_tK8cwCrIBK=0 zD^tg3hWC7}=dij)y>-VE71xr?TCMmjY&l+41a?(YA**Xv$Et>&Bda!dtLW6;;K916 z+D_GXe99b;RxgBJJ+fYgg;0QqtGon1NUGCLfNd$?j6pDaCL z96Ydc4<&B=2K=@5!(FO=m!7 zKxaT_KxaT_KxaT_KxaT_KxaT_KxaT_;4aL7)ga_!#C=%(2LS&5-~0am+oOd13T}a~ z!I$83a2>o2u7OLy2QPzJ@EAA*{@F*!PvAQE4ETV9fDP~*7zaN-jB!C7>;<ksZA%B4z;6rc)yb4yp5pWp%ybE&#?}Ia7AGrAdA@6{5U>ErI zenQ>=XTW~&3v&D^@W2eH0G0RMU>y9P*A-&mieJ@FmJl?M3ztHRiE@*(1`S5&B90io z6f49BItQU z%ot?_W;O2Fj>wL+7)n2sC#kfYJ2gGaTc~$wou!?^QR|z_Rx3NdB&E1t5UtHSrpp_Y zWo+x}PK|eHfSR5fU&Y5823CQafC^JERgjbMqe^TpP!Tdz-8gQDVw`n#tH64W{2mDv}pf@lQbrYA(|9hfQR8{`?Ncexo_e`25LJ1;!PRuXS9b!g#CcFlwlm zjHe}O;gj$eed%ydWIU+}&fDs~dPZF;X&@4T8P6EBt5mk#Qii}tBrm+gwNWUNQa+;c zsD&=IL*)yGur3$$m=GwZGKC7PY;#Z2u1x!mTL%OluM#39^R13)Id6B{3O2cAT8&1z zBspiRyjx27$+V+NEZsIA1lHzRN64p_Abzj)tdaD_96h>W476v`v=w2zaHs_(HEypp zy+{n{l35K(z4ao;S4R6q9ec~C(t0Ug3Ub^HQFUp14ahM{2`3}rQcChUX8D?phEmeZ zu}BRRD>NEm=gvxxQCFqeV!uj#QCFqVoUVQHD&^`iWj9z?XsE{^d71`W)#Ic@=ZCAz zv5gLQ8ir`|kTqVgyauCntLwNHt674UCk)vR_=YeRx;BmUZd{IxPpCx2;vKRDdm&?) zoo>X(6UQ-TZXHni8Xaz)UfkL!&}d9n0sa{^?r#Q8t1XS`sp(@!jO8{}2fp@2RV8nn Z_H2_>Cnxd6+p^bj*w6W#k}CQ+@-L8Y1{?qY literal 0 HcmV?d00001 diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/MatlabBuildStepExecutionUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabBuildStepExecutionUnitTest.java new file mode 100644 index 00000000..f0524be1 --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabBuildStepExecutionUnitTest.java @@ -0,0 +1,84 @@ +package com.mathworks.ci.pipeline; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import org.jenkinsci.plugins.workflow.steps.StepContext; + +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabBuildAction; +import com.mathworks.ci.parameters.BuildActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class MatlabBuildStepExecutionUnitTest { + @Mock StepContext context; + @Mock MatlabActionFactory factory; + @Mock RunMatlabBuildAction action; + + @Before + public void setup() throws IOException, InterruptedException { + when(factory.createAction(any(BuildActionParameters.class))).thenReturn(action); + } + + @Test + public void shouldHandleNullCases() throws Exception, IOException, InterruptedException, MatlabExecutionException { + MatlabBuildStepExecution ex = new MatlabBuildStepExecution(factory, context, null, null, null); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BuildActionParameters.class); + + ex.run(); + + verify(factory).createAction(captor.capture()); + + BuildActionParameters params = captor.getValue(); + assertEquals(null, params.getStartupOptions()); + assertEquals(null, params.getTasks()); + assertEquals(null, params.getBuildOptions()); + + verify(action).run(); + } + + @Test + public void shouldHandleMaximalCases() throws Exception, IOException, InterruptedException, MatlabExecutionException { + MatlabBuildStepExecution ex = new MatlabBuildStepExecution(factory, context, "mytask", "-nojvm -nodisplay", "-continueOnFailure"); + + ex.run(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BuildActionParameters.class); + + verify(factory).createAction(captor.capture()); + + BuildActionParameters params = captor.getValue(); + assertEquals("-nojvm -nodisplay", params.getStartupOptions()); + assertEquals("mytask", params.getTasks()); + assertEquals("-continueOnFailure", params.getBuildOptions()); + + verify(action).run(); + } + + @Test + public void shouldHandleActionThrowing() throws Exception, IOException, InterruptedException, MatlabExecutionException { + MatlabBuildStepExecution ex = new MatlabBuildStepExecution(factory, context, null, null, null); + + doThrow(new MatlabExecutionException(12)).when(action).run(); + + ex.run(); + + verify(context).onFailure(any(MatlabExecutionException.class)); + } +} diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/MatlabCommandStepExecutionUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabCommandStepExecutionUnitTest.java new file mode 100644 index 00000000..30bad312 --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabCommandStepExecutionUnitTest.java @@ -0,0 +1,82 @@ +package com.mathworks.ci.pipeline; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import org.jenkinsci.plugins.workflow.steps.StepContext; + +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabCommandAction; +import com.mathworks.ci.parameters.RunActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class MatlabCommandStepExecutionUnitTest { + @Mock StepContext context; + @Mock MatlabActionFactory factory; + @Mock RunMatlabCommandAction action; + + @Before + public void setup() throws IOException, InterruptedException { + when(factory.createAction(any(RunActionParameters.class))).thenReturn(action); + } + + @Test + public void shouldHandleNullCases() throws Exception, IOException, InterruptedException, MatlabExecutionException { + MatlabCommandStepExecution ex = new MatlabCommandStepExecution(factory, context, null, null); + + ArgumentCaptor captor = ArgumentCaptor.forClass(RunActionParameters.class); + + ex.run(); + + verify(factory).createAction(captor.capture()); + + RunActionParameters params = captor.getValue(); + assertEquals(null, params.getStartupOptions()); + assertEquals(null, params.getCommand()); + + verify(action).run(); + } + + @Test + public void shouldHandleMaximalCases() throws Exception, IOException, InterruptedException, MatlabExecutionException { + MatlabCommandStepExecution ex = new MatlabCommandStepExecution(factory, context, "mycommand", "-nojvm -nodisplay"); + + ex.run(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(RunActionParameters.class); + + verify(factory).createAction(captor.capture()); + + RunActionParameters params = captor.getValue(); + assertEquals("-nojvm -nodisplay", params.getStartupOptions()); + assertEquals("mycommand", params.getCommand()); + + verify(action).run(); + } + + @Test + public void shouldHandleActionThrowing() throws Exception, IOException, InterruptedException, MatlabExecutionException { + MatlabCommandStepExecution ex = new MatlabCommandStepExecution(factory, context, null, null); + + doThrow(new MatlabExecutionException(12)).when(action).run(); + + ex.run(); + + verify(context).onFailure(any(MatlabExecutionException.class)); + } +} diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/MatlabRunTestsStepExecutionUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabRunTestsStepExecutionUnitTest.java new file mode 100644 index 00000000..91bab561 --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabRunTestsStepExecutionUnitTest.java @@ -0,0 +1,65 @@ +package com.mathworks.ci.pipeline; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; + +import org.junit.Test; +import org.junit.Before; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import org.jenkinsci.plugins.workflow.steps.StepContext; + +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.actions.MatlabActionFactory; +import com.mathworks.ci.actions.RunMatlabTestsAction; +import com.mathworks.ci.parameters.TestActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class MatlabRunTestsStepExecutionUnitTest { + @Mock StepContext context; + @Mock MatlabActionFactory factory; + @Mock RunMatlabTestsAction action; + @Mock TestActionParameters params; + + @Before + public void setup() throws IOException, InterruptedException { + when(factory.createAction(any(TestActionParameters.class))).thenReturn(action); + } + + @Test + public void shouldHandleOnlyCase() throws Exception, IOException, InterruptedException, MatlabExecutionException { + MatlabRunTestsStepExecution ex = new MatlabRunTestsStepExecution(factory, context, params); + + ArgumentCaptor captor = ArgumentCaptor.forClass(TestActionParameters.class); + + ex.run(); + + verify(factory).createAction(captor.capture()); + + TestActionParameters params = captor.getValue(); + assertEquals(this.params, params); + + verify(action).run(); + } + + @Test + public void shouldHandleActionThrowing() throws Exception, IOException, InterruptedException, MatlabExecutionException { + MatlabRunTestsStepExecution ex = new MatlabRunTestsStepExecution(factory, context, params); + + doThrow(new MatlabExecutionException(12)).when(action).run(); + + ex.run(); + + verify(context).onFailure(any(MatlabExecutionException.class)); + } +} diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabBuildStepUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabBuildStepUnitTest.java new file mode 100644 index 00000000..f53904cd --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabBuildStepUnitTest.java @@ -0,0 +1,46 @@ +package com.mathworks.ci.pipeline; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import org.jenkinsci.plugins.workflow.steps.StepContext; + +@RunWith(MockitoJUnitRunner.class) +public class RunMatlabBuildStepUnitTest { + @Mock StepContext context; + + @Test + public void shouldHandleNullCase() throws Exception { + RunMatlabBuildStep step = new RunMatlabBuildStep(); + MatlabBuildStepExecution ex = (MatlabBuildStepExecution)step.start(context); + + assertEquals("", ex.getParameters().getStartupOptions()); + assertEquals("", ex.getParameters().getTasks()); + assertEquals("", ex.getParameters().getBuildOptions()); + } + + @Test + public void shouldHandleMaximalCase() throws Exception { + RunMatlabBuildStep step = new RunMatlabBuildStep(); + step.setStartupOptions("-nojvm -logfile file"); + step.setTasks("vacuum bills"); + step.setBuildOptions("-continueOnFailure"); + + MatlabBuildStepExecution ex = (MatlabBuildStepExecution)step.start(context); + + assertEquals("-nojvm -logfile file", ex.getParameters().getStartupOptions()); + assertEquals("vacuum bills", ex.getParameters().getTasks()); + assertEquals("-continueOnFailure", ex.getParameters().getBuildOptions()); + } +} diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabCommandStepUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabCommandStepUnitTest.java new file mode 100644 index 00000000..17e192ff --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabCommandStepUnitTest.java @@ -0,0 +1,43 @@ +package com.mathworks.ci.pipeline; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import org.jenkinsci.plugins.workflow.steps.StepContext; + +@RunWith(MockitoJUnitRunner.class) +public class RunMatlabCommandStepUnitTest { + @Mock StepContext context; + + @Test + public void shouldHandleNullCase() throws Exception { + RunMatlabCommandStep step = new RunMatlabCommandStep("SPEAK"); + MatlabCommandStepExecution ex = (MatlabCommandStepExecution)step.start(context); + + assertEquals("", ex.getParameters().getStartupOptions()); + assertEquals("SPEAK", ex.getParameters().getCommand()); + } + + @Test + public void shouldHandleMaximalCase() throws Exception { + RunMatlabCommandStep step = new RunMatlabCommandStep("ROLL OVER"); + step.setStartupOptions("-nojvm -logfile file"); + + MatlabCommandStepExecution ex = (MatlabCommandStepExecution)step.start(context); + + assertEquals("-nojvm -logfile file", ex.getParameters().getStartupOptions()); + assertEquals("ROLL OVER", ex.getParameters().getCommand()); + } +} diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabTestsStepUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabTestsStepUnitTest.java new file mode 100644 index 00000000..c5861edc --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabTestsStepUnitTest.java @@ -0,0 +1,91 @@ +package com.mathworks.ci.pipeline; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; + +import java.util.ArrayList; + +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.junit.Assert.*; + +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import org.jenkinsci.plugins.workflow.steps.StepContext; + +import com.mathworks.ci.parameters.TestActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class RunMatlabTestsStepUnitTest { + @Mock StepContext context; + + @Test + public void shouldHandleNullCase() throws Exception { + RunMatlabTestsStep step = new RunMatlabTestsStep(); + MatlabRunTestsStepExecution ex = (MatlabRunTestsStepExecution)step.start(context); + + TestActionParameters params = ex.getParameters(); + assertEquals("", params.getStartupOptions()); + assertEquals(null, params.getTestResultsPDF()); + assertEquals(null, params.getTestResultsTAP()); + assertEquals(null, params.getTestResultsJUnit()); + assertEquals(null, params.getCodeCoverageCobertura()); + assertEquals(null, params.getTestResultsSimulinkTest()); + assertEquals(null, params.getModelCoverageCobertura()); + assertEquals(null, params.getSelectByTag()); + assertEquals(null, params.getLoggingLevel()); + assertEquals(null, params.getOutputDetail()); + assertEquals("false", params.getUseParallel()); + assertEquals("false", params.getStrict()); + assertEquals(null, params.getSourceFolder()); + assertEquals(null, params.getSelectByFolder()); + } + + @Test + public void shouldHandleMaximalCase() throws Exception { + RunMatlabTestsStep step = new RunMatlabTestsStep(); + step.setStartupOptions("-nojvm -logfile file"); + step.setTestResultsPDF("res.pdf"); + step.setTestResultsTAP("res.tap"); + step.setTestResultsJUnit("res.xml"); + step.setCodeCoverageCobertura("cov.xml"); + step.setTestResultsSimulinkTest("res.sltest"); + step.setModelCoverageCobertura("cov.model"); + step.setSelectByTag("MyTag"); + step.setLoggingLevel("Concise"); + step.setOutputDetail("Concise"); + step.setUseParallel(true); + step.setStrict(true); + + ArrayList folders = new ArrayList(); + folders.add("src"); + folders.add("toolbox"); + + step.setSourceFolder(folders); + step.setSelectByFolder(folders); + + MatlabRunTestsStepExecution ex = (MatlabRunTestsStepExecution)step.start(context); + + TestActionParameters params = ex.getParameters(); + assertEquals("-nojvm -logfile file", params.getStartupOptions()); + assertEquals("res.pdf", params.getTestResultsPDF()); + assertEquals("res.tap", params.getTestResultsTAP()); + assertEquals("res.xml", params.getTestResultsJUnit()); + assertEquals("cov.xml", params.getCodeCoverageCobertura()); + assertEquals("res.sltest", params.getTestResultsSimulinkTest()); + assertEquals("cov.model", params.getModelCoverageCobertura()); + assertEquals("MyTag", params.getSelectByTag()); + assertEquals("Concise", params.getLoggingLevel()); + assertEquals("Concise", params.getOutputDetail()); + assertEquals("true", params.getUseParallel()); + assertEquals("true", params.getStrict()); + assertEquals(folders, params.getSourceFolder()); + assertEquals(folders, params.getSelectByFolder()); + } +} diff --git a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java new file mode 100644 index 00000000..badc149c --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java @@ -0,0 +1,288 @@ +package com.mathworks.ci.utilities; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.File; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.IOException; +import java.util.List; + +import hudson.FilePath; +import hudson.EnvVars; +import hudson.Launcher; +import hudson.Launcher.ProcStarter; +import hudson.model.TaskListener; +import hudson.util.ArgumentListBuilder; + +import org.junit.Test; +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +import org.junit.Assert; +import org.junit.runner.RunWith; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.CoreMatchers.containsString; + +import org.mockito.Mock; +import org.mockito.stubbing.Answer; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.ArgumentCaptor; +import org.mockito.junit.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import com.mathworks.ci.MatlabExecutionException; +import com.mathworks.ci.parameters.MatlabActionParameters; + +@RunWith(MockitoJUnitRunner.class) +public class MatlabCommandRunnerTest { + + @Mock private FilePath workspace; + @Mock private Launcher launcher; + @Mock private ProcStarter procStarter; + private EnvVars env; + @Mock private TaskListener listener; + @Mock private PrintStream logger; + @Mock private MatlabActionParameters params; + + @Rule + public TemporaryFolder tempDir = new TemporaryFolder(); + + private MatlabCommandRunner runner; + + @Before + public void initialize() throws IOException, InterruptedException { + env = new EnvVars(); + + when(params.getWorkspace()).thenReturn(workspace); + when(params.getLauncher()).thenReturn(launcher); + when(params.getEnvVars()).thenReturn(env); + when(params.getTaskListener()).thenReturn(listener); + when(params.getStartupOptions()).thenReturn(""); + + when(launcher.getChannel()).thenReturn(null); + when(workspace.getRemote()).thenReturn(tempDir.getRoot().getAbsolutePath()); + when(listener.getLogger()).thenReturn(logger); + + doReturn(false).when(launcher).isUnix(); + when(launcher.launch()).thenReturn(procStarter); + when(procStarter.cmds(anyString())).thenReturn(procStarter); + when(procStarter.cmds(any(ArgumentListBuilder.class))).thenReturn(procStarter); + when(procStarter.masks(anyBoolean())).thenReturn(procStarter); + when(procStarter.envs(any(EnvVars.class))).thenReturn(procStarter); + doReturn(procStarter).when(procStarter) + .stdout(any(OutputStream.class)); + when(procStarter.join()).thenReturn(0); + } + + @Test + public void validConstructorDoesNotThrow() throws IOException, InterruptedException { + MatlabCommandRunner runner = new MatlabCommandRunner(params); + Assert.assertNotNull(runner); + } + + @Test + public void constructorUsesParamsForTempFolder() throws IOException, InterruptedException { + MatlabCommandRunner runner = new MatlabCommandRunner(params); + verify(params, times(1)).getLauncher(); + verify(params, times(1)).getWorkspace(); + } + + @Test + public void correctTempFolderLocation() throws IOException, InterruptedException { + runner = new MatlabCommandRunner(params); + FilePath tmp = runner.getTempFolder(); + + Assert.assertThat( + tmp.getRemote(), + startsWith(new File(tempDir.getRoot(), ".matlab").getAbsolutePath())); + } + + @Test + public void prepareRunnerExecutableLinux() throws IOException, InterruptedException { + runner = new MatlabCommandRunner(params); + + doReturn(true).when(launcher).isUnix(); + when(procStarter.stdout(any(OutputStream.class))).thenAnswer( + new Answer() { + public Object answer(InvocationOnMock invocation) throws IOException { + Object[] args = invocation.getArguments(); + OutputStream s = (OutputStream)args[0]; + + String tag = "Linux"; + s.write(tag.getBytes()); + return procStarter; + } + }); + + FilePath f = runner.prepareRunnerExecutable(); + + Assert.assertTrue(f.exists()); + Assert.assertEquals( + runner.getTempFolder().getRemote() + + "/run-matlab-command", + f.getRemote()); + } + + @Test + public void prepareRunnerExecutableMac() throws IOException, InterruptedException { + runner = new MatlabCommandRunner(params); + + doReturn(true).when(launcher).isUnix(); + + FilePath f = runner.prepareRunnerExecutable(); + + Assert.assertTrue(f.exists()); + Assert.assertEquals( + runner.getTempFolder().getRemote() + + "/run-matlab-command", + f.getRemote()); + } + + @Test + public void prepareRunnerExecutableWindows() throws IOException, InterruptedException { + runner = new MatlabCommandRunner(params); + + FilePath f = runner.prepareRunnerExecutable(); + + Assert.assertTrue(f.exists()); + Assert.assertEquals( + runner.getTempFolder().getRemote() + + "/run-matlab-command.exe", + f.getRemote()); + } + + @Test + public void createFileWithContentWorks() throws IOException, InterruptedException { + runner = new MatlabCommandRunner(params); + + String content = "I'm a $pecia1 $tri^g"; + FilePath f = runner.createFileWithContent(content); + + String expected = "cd(getenv('MW_ORIG_WORKING_FOLDER'));\n" + + content; + + Assert.assertTrue(f.exists()); + Assert.assertThat(f.getRemote(), + startsWith(runner.getTempFolder().getRemote())); + Assert.assertEquals(f.readToString(), expected); + } + + @Test + public void copyFileFromResourcePathWorks() throws IOException, InterruptedException { + runner = new MatlabCommandRunner(params); + + FilePath f = runner.copyFileToTempFolder("testcontent.txt", "target.txt"); + + Assert.assertTrue(f.exists()); + Assert.assertEquals("This has text!\n", f.readToString()); + } + + @Test + public void runWorksInBasicCase() throws IOException, InterruptedException, MatlabExecutionException { + runner = new MatlabCommandRunner(params); + + String myCommand = "OBEY"; + runner.runMatlabCommand(myCommand); + + String exe = runner.getTempFolder().getRemote() + + "/run-matlab-command.exe"; + String cmd = "setenv('MW_ORIG_WORKING_FOLDER', cd('" + + runner.getTempFolder().getRemote() + + "'));script_"; + + ArgumentCaptor captor = ArgumentCaptor.forClass(ArgumentListBuilder.class); + verify(procStarter).cmds(captor.capture()); + + List cmds = captor.getValue().toList(); + Assert.assertEquals(3, cmds.size()); + Assert.assertEquals(exe, cmds.get(0)); + Assert.assertThat(cmds.get(1), startsWith(cmd)); + } + + @Test + public void runUsesWorkspaceLocationAsWD() throws IOException, InterruptedException, MatlabExecutionException { + runner = new MatlabCommandRunner(params); + + runner.runMatlabCommand("COMMAND"); + + verify(procStarter).pwd(workspace); + } + + @Test + public void runWorksWithAddedEnvVars() throws IOException, InterruptedException, MatlabExecutionException { + runner = new MatlabCommandRunner(params); + + String myCommand = "OBEY"; + runner.addEnvironmentVariable("MYVAR", "MYVALUE"); + runner.runMatlabCommand(myCommand); + + ArgumentCaptor captor = ArgumentCaptor.forClass(EnvVars.class); + verify(procStarter).envs(captor.capture()); + + EnvVars cmds = captor.getValue(); + Assert.assertEquals("MYVALUE", cmds.get("MYVAR")); + } + + @Test + public void runShouldExpandAddedEnvVars() throws IOException, InterruptedException, MatlabExecutionException { + runner = new MatlabCommandRunnerTester(params); + + String myCommand = "STAY"; + runner.addEnvironmentVariable("COMMAND", myCommand); + FilePath f = runner.createFileWithContent("$COMMAND"); + + Assert.assertThat(f.readToString(), containsString(myCommand)); + } + + @Test + public void runWorksWithStartupOptions() throws IOException, InterruptedException, MatlabExecutionException { + runner = new MatlabCommandRunner(params); + + doReturn("-nojvm -logfile mylog.log") + .when(params).getStartupOptions(); + + String myCommand = "OBEY"; + runner.runMatlabCommand(myCommand); + + ArgumentCaptor captor = ArgumentCaptor.forClass(ArgumentListBuilder.class); + verify(procStarter).cmds(captor.capture()); + + List cmds = captor.getValue().toList(); + Assert.assertEquals(5, cmds.size()); + Assert.assertEquals("-nojvm", cmds.get(2)); + Assert.assertEquals("-logfile", cmds.get(3)); + Assert.assertEquals("mylog.log", cmds.get(4)); + } + + @Test + public void runWorksWithRedirectedOutput() throws IOException, InterruptedException, MatlabExecutionException { + OutputStream out = mock(OutputStream.class); + + runner = new MatlabCommandRunner(params); + runner.redirectStdOut(out); + + runner.runMatlabCommand("some pig"); + + ArgumentCaptor captor = ArgumentCaptor.forClass(OutputStream.class); + verify(procStarter).stdout(captor.capture()); + + Assert.assertEquals(out, captor.getValue()); + } + + @Test + public void runThrowsCorrectCodeOnError() throws IOException, InterruptedException { + runner = new MatlabCommandRunner(params); + + doReturn(8).when(procStarter).join(); + + try { + runner.runMatlabCommand("Open sesame"); + } catch (MatlabExecutionException e) { + Assert.assertEquals(8, e.getExitCode()); + } + } +} diff --git a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTester.java b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTester.java new file mode 100644 index 00000000..d8502b8e --- /dev/null +++ b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTester.java @@ -0,0 +1,26 @@ +package com.mathworks.ci.utilities; + +/** + * Copyright 2024, The MathWorks Inc. + * + */ + +import java.io.IOException; +import hudson.FilePath; +import com.mathworks.ci.parameters.MatlabActionParameters; + +public class MatlabCommandRunnerTester extends MatlabCommandRunner { + public MatlabCommandRunnerTester(MatlabActionParameters params) throws IOException, InterruptedException { + super(params); + } + + @Override + public FilePath prepareRunnerExecutable() throws IOException, InterruptedException { + return super.prepareRunnerExecutable(); + } + + @Override + public FilePath createFileWithContent(String content) throws IOException, InterruptedException { + return super.createFileWithContent(content); + } +} diff --git a/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..1f0955d4 --- /dev/null +++ b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline diff --git a/src/test/resources/testcontent.txt b/src/test/resources/testcontent.txt new file mode 100644 index 00000000..37a8be18 --- /dev/null +++ b/src/test/resources/testcontent.txt @@ -0,0 +1 @@ +This has text! From 42796f06dc90883cfce0d03192adf13d854cb728 Mon Sep 17 00:00:00 2001 From: sameagen Date: Mon, 25 Mar 2024 11:50:20 -0400 Subject: [PATCH 11/52] Remove swap files --- .../.MatlabBuildStepExecutionUnitTest.java.swp | Bin 12288 -> 0 bytes ....MatlabCommandStepExecutionUnitTest.java.swp | Bin 12288 -> 0 bytes ...MatlabRunTestsStepExecutionUnitTest.java.swp | Bin 12288 -> 0 bytes .../.RunMatlabBuildStepUnitTest.java.swp | Bin 12288 -> 0 bytes .../.RunMatlabCommandStepUnitTest.java.swp | Bin 12288 -> 0 bytes .../.RunMatlabTestsStepUnitTest.java.swp | Bin 12288 -> 0 bytes 6 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.MatlabBuildStepExecutionUnitTest.java.swp delete mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.MatlabCommandStepExecutionUnitTest.java.swp delete mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.MatlabRunTestsStepExecutionUnitTest.java.swp delete mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabBuildStepUnitTest.java.swp delete mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabCommandStepUnitTest.java.swp delete mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabTestsStepUnitTest.java.swp diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.MatlabBuildStepExecutionUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.MatlabBuildStepExecutionUnitTest.java.swp deleted file mode 100644 index 9defa966121258fb1a6ab170f1ec8ccdaad3da05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2?`s@I7{{mD)*rQ2EC}rj86$zckef}eQiRl+G^7|IrcIO9H$^AAle@|7ukOy? z55x+-sVMr^3i?{Gf?`2@<=>$1e9_Ps;tO90z7`68XLm2TOZE~9wNx_8eRgv@zn=Nd zv-9kcXLaK8`~rQI)d-H~2pPR~PgI(x$&ZW2Ny2@>>mtxayB#f8R$X_JH)_?1)2D{l zyx!~3UKc@A21(WD%Hylm$V=-ou#?!al}MDm&Rg701F38$^lemXw8OZW*p9R#83|7Y z!d}Rlo=c_YUQ!~O>j)=RG7MJGY#E&}-N|rUOo>ro|0!^koT^Pu=y|_9@)AA%{L225 zz|7bvU=%P47zK<1MggOMQNSp$j}=hS0rCOn|5%~Ha&bMd?OJ>_7o&htz$jo8FbWt2 zi~>dhqkvJsC}0#Y3K#|chYE0)kZX?3Hcs;0zL*8!3FRl`12?sw?P+lzzP@zhr!)v2>A)z244dg907;G zLGaHJLOuj1!3pr~)36DA0d9hK!8>3S{Ph$eKZB3J4IqI7R>9j~<4Ho6z(w#nI17G# zf{H9HM-UL&cr8c z4Sj}jcbpdU8>d0)dHrYDtF4dHRZlv!6-t*TjWG4xH+bNBVkWaGn}!VPR)s1(ql9iM zF;3?f`@cZOI8Gxa+`hZRCQskX2A|f+S-Fxs7G{_zkYB`V?pn&d#2TsU`N<#^i@oI= z8K)7Cxu3AQP?<7|*~%rBUNt>seGK;EcNI^X11*2n(lezs$W<47gR{vc=j~m=g=Gij}g8hWetNc)&$x z;(F?fK+R^IpD8urY%w%!7_83L!gyADy;a(-cp`RxAReeEk8Cd2NZBfs`NSU1zQ8-u z=iV$&1lIh~boKoCy|%zAG(KT@u}Ew z2KO5sC3o8p5Zn}k+mgU`v>D<`Vh+lqt!Hk}n9_?J=LEJTLG)gpou(H;r%9L6pl^xt zU6$sNBp*7jme(tsNc<>_6~^$H-%D_2j%3->o&^Y2D)rRRmie3$Rwl^atxEJ6 z-YBoU^Hm8Ep_o?~*IAL}ttXWwcqdG!aj$t{n$1k?FosAce3lm9=rB< ze+cp81_Hr>BebU;kN~L#A+G!oe*s)LkQ*F0bKz2n@7UgCop>9N3M$H2`K+@$zutW3 z`Mr(uR;R8kEYfFKo#1+mkRLv|BTjFeBVR9_Br*2|ZwaZJ?sj#WZmrpz=IwfI>fG7U zJ>M8iXs-*o;mWw?bLH{XTIeM$SK4vp*h<98UgsTdC(>266ZkedwYx#I5!;Syhi)i5 zR|mIF%8qxjJC$K7zOs50>{bO`t+3E^_hv&^yK3! z`%M6|U!#Cgz$jo8FbWt2i~>dhqrkpaK!pd$n^53juEM4KeqhHve`{_=0i%FXz$jo8 zFbWt2i~>dhqkvJsC}0#Y3j7Zh;7vk~9U>%n5XR&G|AW8(Hy*&& z@Blan{yav=TVNcFf!hzGFSr4&gC=mmQ{a!IgnSRa12@49a23id;v9Go|sE5N;l!kmQ|rj?F+0^wt(!;a(yN9+7)nek2vfPxrMV!F5XAtYGt%g17->Wyja(9l9$U$zB)+3P+%n+ zzM3IvZ9q@pXY#RJMmD)+(Qxa!t`r~i8IroRb1`m|cG0Vqnv*RwmnQ!m zwq#9FcEmUWefovTvksXTmo(@vA=_)}!gb~bZ0PAgBb~GXerO{I`;psfD_WnbKV7BE iZJ`~reN|V<(*@};Voy#I5^`q)1^gvWmRHfwkiP&YvIi6Z diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.MatlabRunTestsStepExecutionUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.MatlabRunTestsStepExecutionUnitTest.java.swp deleted file mode 100644 index 4ee4f521ff2a346c33587ee4ff7c5c391ca2a5cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2O>Z1E7{^@%h_?cwCy=NNmC$UI^(0$VA#EuMt5gIjN-1f2KpdP|XLpiW&oK7v z3y2~(rUJf4K?3p83ts@PoB%Z^PJ974f%^B@n{1NVo+FC)1n&rGhK{@X?YQ1<&+~4hK6mNjbjw@g1;Z^N zw_~a5J+2eJQO}a16U$KLQK*H|;TG@nu#mA1qqG;os5?mWZ52jwn8le$VkyFva_aR$ zu3?6HTZ?RID565gsl0)i<|#AlOn1kRcm+Rv z0k42pz$@St@CtYZyaK0N0iB&8A3=f#oD7TZe&*2Kee^f4fLFjP;1%!+cm=!yUIDLw zSHLUa74Qmp1^$N$@HQd;JWR;>N8mjE|3CiwfA=Xu?tx#xH{dJq1-Jt~1D}FEco$p- z&w*zF0lQBU@-?^(cEDTU8aNOBI7`U4;C(Ox>)---5bQod$X)O`*a5dd6a4--#=t%B zGk6F5^%x<4g4w3UMSMyV?t_ zHEj3L_^)j8QdX4b|IU&SyAoH{8c%}g6{%N}my@^2DX@#P`rPNvF}W88L(xE5e= zGuGX}_!#T-O*4jPQsgcN35k1InrpnK$9m%qXBNe_I?K{yReRE$I?+b0Sd}Cv&#F*p z`Xp<7^rS~+xvkAM$G&K>JWmh#Vuy0O!*25rEN%^Ks#gq{o!)<^>04)U z$|gz(gLEbY_@b>e8|87Qt7&7d@$xKP>k5;Y-J7OMo-WIXk#J^)kc>y$XyC8NG1o=k GB=-R(L?4m> diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabBuildStepUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabBuildStepUnitTest.java.swp deleted file mode 100644 index 1fcbb502a7b0ec9f8882b53cec786533134fdb69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2&u<$=6vwCB_)$Rg0=K~+VMq0B>XZs$Ap#*lkW3Is=#|Ot)E;~GM|Wl&BLw^f zRB#8u4FnR19=LMif8YQ&ZdCjO2#N3Pu2aYHmI}lH<&FH^wRh&do%fkHE3Nzv*WcP1 z@MlDip*_slC!hbR9-Ula-|t>vR>n#WRpPtu)TWW{M$siX>UGzzY&4I2f9^0Ct7M`R z+l{3&^01qkVyKhA=3(HJb-`FpWl$vA1z{Qo7&JOc^N9^Y9b`IFMkgwGvq%P|^^1iz z(VkP;0SxwGF1&g3EU1SFoK*tn*+%cux{v;e*5mxbBL`;{1jS7RhyW2F0z`la5CI}U z1kNM@mz`rDAo6?a=tX@#w{)(5(uoKV0U|&IhyW2F0z`la5CI}U1c(3;_#YCG5o6cy zWo-LCOdkLL&)@%ld5E!}p`W0e(6`Xn&{xn6=tF1<9Y7mU4|)u`^&n%vK{uiApc_yG zZ9>mOPeXs4XY2=P3~A^o==TR0`v&?F`U3hCdK-EYx^+KeKSCcvA3=TSS?E{H`7>w$ zy#o0dUV^9*0U|&IhyW2F0z`la{Ko{|V;rqI`ft)&mAmchg*3L^>V|3JbW*6@sFl8-FdC0OIC-DNs8 z+W%b&H5x9F^_hIUuub{!kJ1I{SGLpe|J~BOUYNUIm(4*MPWT>DVXMkxUgvYaoExjx zKQ!3IE7D|Mw~YngL>yPO8@0Vh?b6qLAFd@T7o~XzZ;Wx4=8mWNP}F7Qp%zsIxfQ-n z{F+IRu&-2R#loDh0t=RL5xBjZZe%Ng{*trf_UCyKQ@@UKJL4N=M diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabCommandStepUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabCommandStepUnitTest.java.swp deleted file mode 100644 index 6b2dca0040ac815ed36a3fc0073f4927b2d32eda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2F>ljA6vwYDNI(mM1;lccB`L%%DXJ<}NJUj73Y4Ih!hChE$+fo6*yl6|0TT=e z*x8ud0l~lu6MO*%1`tSy2^RPS{4aJOl%!>0fIh1~yXl?Zz5CtSQq;FNdUfDDiUGC&5% z02v?y+u4AL2G}hK*pW*(mR|=pT=S1~Ap>N943GgbKnBPF86X2>fDDiUGC&6YK?9=3 z*x_A_eFXOZ|DEsu@AfkG7Q6vZ!DFxv*1!XBA2h)N7z1T+2z(i0>=k$k?t^p`@GlVA*d-NV=uunyM1BjAC9;KOdl-h(^fHgLgbdXATof@1 zUyY2DLeYNC3rq{e;v};}*yGn>N}*nE2E63!`jYY`x2L}0=8cF=8dW2sbci7km9=By z^jk%1r6s-8c0_Lc6fgAeP)tw&>m)XK!PB9UEz=!2Yn5ih=)*lz@0w_@GFxtgA)8RH z@?Pz^_qNnLRFp3I%HvI~YCLJ^)UTaE&8{zJMN0+3pB9NM6uD`{dNtvdmM7bG`1Q7# zDO=Nbw!y*!NycZpS5lHTPS0v9iWIWib14f!*yJD z@(OWJIazUd;@A@KC10;%kIN`=y0XFpl;4T%Z?Mg5fFK*j$%k`BCOe(FTbFH>d8bcT zN(ND7PG}syG diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabTestsStepUnitTest.java.swp b/src/test/java/unit/com/mathworks/ci/pipeline/.RunMatlabTestsStepUnitTest.java.swp deleted file mode 100644 index 3bea411fb831fa5258ce6be3275186221276ae1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2&u<$=6vrn(Nei@8t;&hRVlGZvuhXPdk;0D#Hx;FIQ#A<{;8j5YrpKTf_`JV=D)QmaKh)l_tK8cwCrIBK=0 zD^tg3hWC7}=dij)y>-VE71xr?TCMmjY&l+41a?(YA**Xv$Et>&Bda!dtLW6;;K916 z+D_GXe99b;RxgBJJ+fYgg;0QqtGon1NUGCLfNd$?j6pDaCL z96Ydc4<&B=2K=@5!(FO=m!7 zKxaT_KxaT_KxaT_KxaT_KxaT_KxaT_;4aL7)ga_!#C=%(2LS&5-~0am+oOd13T}a~ z!I$83a2>o2u7OLy2QPzJ@EAA*{@F*!PvAQE4ETV9fDP~*7zaN-jB!C7>;<ksZA%B4z;6rc)yb4yp5pWp%ybE&#?}Ia7AGrAdA@6{5U>ErI zenQ>=XTW~&3v&D^@W2eH0G0RMU>y9P*A-&mieJ@FmJl?M3ztHRiE@*(1`S5&B90io z6f49BItQU z%ot?_W;O2Fj>wL+7)n2sC#kfYJ2gGaTc~$wou!?^QR|z_Rx3NdB&E1t5UtHSrpp_Y zWo+x}PK|eHfSR5fU&Y5823CQafC^JERgjbMqe^TpP!Tdz-8gQDVw`n#tH64W{2mDv}pf@lQbrYA(|9hfQR8{`?Ncexo_e`25LJ1;!PRuXS9b!g#CcFlwlm zjHe}O;gj$eed%ydWIU+}&fDs~dPZF;X&@4T8P6EBt5mk#Qii}tBrm+gwNWUNQa+;c zsD&=IL*)yGur3$$m=GwZGKC7PY;#Z2u1x!mTL%OluM#39^R13)Id6B{3O2cAT8&1z zBspiRyjx27$+V+NEZsIA1lHzRN64p_Abzj)tdaD_96h>W476v`v=w2zaHs_(HEypp zy+{n{l35K(z4ao;S4R6q9ec~C(t0Ug3Ub^HQFUp14ahM{2`3}rQcChUX8D?phEmeZ zu}BRRD>NEm=gvxxQCFqeV!uj#QCFqVoUVQHD&^`iWj9z?XsE{^d71`W)#Ic@=ZCAz zv5gLQ8ir`|kTqVgyauCntLwNHt674UCk)vR_=YeRx;BmUZd{IxPpCx2;vKRDdm&?) zoo>X(6UQ-TZXHni8Xaz)UfkL!&}d9n0sa{^?r#Q8t1XS`sp(@!jO8{}2fp@2RV8nn Z_H2_>Cnxd6+p^bj*w6W#k}CQ+@-L8Y1{?qY From cda9e05b60c3b38b7ff451967f2d2f3a09ecc32c Mon Sep 17 00:00:00 2001 From: sameagen Date: Mon, 25 Mar 2024 11:58:10 -0400 Subject: [PATCH 12/52] Change reference to be own class --- .../java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java index 07002a11..ef1b04e1 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java @@ -104,7 +104,7 @@ private String getMatlabroot(String version) throws URISyntaxException { } private URL getResource(String resource) { - return RunMatlabTestsBuilderTest.class.getClassLoader().getResource(resource); + return RunMatlabBuildBuilderTest.class.getClassLoader().getResource(resource); } /* From 568e5fde65bc882cd3c8bcaf2969cc28968ae0ea Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 26 Mar 2024 13:35:44 +0530 Subject: [PATCH 13/52] Preparing for next release (#309) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 83868f62..4699ba7a 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ matlab - 2.12.1-SNAPSHOT + 2.13.1-SNAPSHOT hpi From 0ffd9c699530d5cfb24e44af9d47683977ef7582 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:05:46 +0530 Subject: [PATCH 14/52] Synch master (#310) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration From c856e864d62c22c7ba37cce70d3a88bcea10ed6b Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:27:07 +0530 Subject: [PATCH 15/52] Synch master (#311) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration From 3f1b828c1485de7887f2cb2c1afd2aa7f9815267 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:57:03 +0530 Subject: [PATCH 16/52] Synch dev_main (#312) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Release 2.13.0 (#306) * Initial fix * Added support for build visualization (Latest) (#268) * Added support for build visualization * Fixed findbug issues * Fixed findbug issues * Fixed findbug issues * Deleted failuresummary.jelly * Refactored tests * Refactored jelly file * Updated as per review comments * updated jelly as per review comment * Using overide plugin method to generate json file * Updated as per review comment * Updated as per review comment * Added log updater plugin * Added log link support * Fixed spotbug issue * Renamed plugin packages * Changed data types for artifact data * empty * Fixed test failure * Fixed Merge conflicts * Fixed spotbug issue * Updated as per review comments * Updated as per review comments * Updated as per review comments * Updated as per review comments * Build visulization support for pipeline (#278) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 * 2.11.2 snapshot qualification (#296) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 * Add build options (#294) * add build options * update gitignore * add tests for build options * add fixes and more tests * fix tests * modify help text * fix help text * minor text fix * fix null error and formatting * remove buildOptions check from EnvVarSupport test * add env variables support for build options and formatting fixes * minor fixes * documenting MATLAB build options and MATLAB build result * Fixed issue 298 (#300) * adding a new screenshot for build results and minor updates (#304) --------- Co-authored-by: sameagen Co-authored-by: sameagen-MW <122639681+sameagen-MW@users.noreply.github.com> Co-authored-by: Tushar Sharma <150027500+tsharmaMW@users.noreply.github.com> Co-authored-by: mw-hrastega <48831250+mw-hrastega@users.noreply.github.com> * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration * Preparing for next release (#309) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration * Synch master (#310) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration * Synch master (#311) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration --------- Co-authored-by: sameagen Co-authored-by: sameagen-MW <122639681+sameagen-MW@users.noreply.github.com> Co-authored-by: Tushar Sharma <150027500+tsharmaMW@users.noreply.github.com> Co-authored-by: mw-hrastega <48831250+mw-hrastega@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 83868f62..4699ba7a 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ matlab - 2.12.1-SNAPSHOT + 2.13.1-SNAPSHOT hpi From 08b7cf574dd4f31c62d1132d41db45943e98d7ab Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:59:34 +0530 Subject: [PATCH 17/52] [maven-release-plugin] prepare release matlab-2.12.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4699ba7a..9d0622f6 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ scm:git:ssh://github.com/jenkinsci/matlab-plugin.git scm:git:ssh://git@github.com/jenkinsci/matlab-plugin.git http://github.com/jenkinsci/matlab-plugin - HEAD + matlab-2.12.0 From d43036c5fcb09e66c06f64caf96601ae8c2dad2b Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:59:40 +0530 Subject: [PATCH 18/52] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9d0622f6..4699ba7a 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ scm:git:ssh://github.com/jenkinsci/matlab-plugin.git scm:git:ssh://git@github.com/jenkinsci/matlab-plugin.git http://github.com/jenkinsci/matlab-plugin - matlab-2.12.0 + HEAD From f65c0bda6a6701da8aa6a42110098d0ee8b69123 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 26 Mar 2024 12:13:00 +0530 Subject: [PATCH 19/52] [maven-release-plugin] prepare release matlab-2.13.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4699ba7a..c4353b5c 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ scm:git:ssh://github.com/jenkinsci/matlab-plugin.git scm:git:ssh://git@github.com/jenkinsci/matlab-plugin.git http://github.com/jenkinsci/matlab-plugin - HEAD + matlab-2.13.0 From ce7cccae162f756c69688e2513ac19e135754b67 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 26 Mar 2024 12:13:07 +0530 Subject: [PATCH 20/52] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c4353b5c..4699ba7a 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ scm:git:ssh://github.com/jenkinsci/matlab-plugin.git scm:git:ssh://git@github.com/jenkinsci/matlab-plugin.git http://github.com/jenkinsci/matlab-plugin - matlab-2.13.0 + HEAD From df90dd812f152c3e28c020cfd50018b6c4d3fe16 Mon Sep 17 00:00:00 2001 From: sameagen Date: Fri, 15 Dec 2023 11:30:10 -0500 Subject: [PATCH 21/52] Initial fix --- src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java b/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java index b09ebf4b..6bbd6ab6 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java +++ b/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java @@ -151,7 +151,6 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, try { matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, bca, envVars, "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'));"+ uniqueBuildFile, options, uniqueTmpFldrName); - listener.getLogger() .println("#################### Starting command output ####################"); From 19c9fe0215a25ee82a33e2dbf9ec8603db1e0841 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Wed, 17 Jan 2024 10:42:46 +0530 Subject: [PATCH 22/52] Added support for build visualization (Latest) (#268) * Added support for build visualization * Fixed findbug issues * Fixed findbug issues * Fixed findbug issues * Deleted failuresummary.jelly * Refactored tests * Refactored jelly file * Updated as per review comments * updated jelly as per review comment * Using overide plugin method to generate json file * Updated as per review comment * Updated as per review comment * Added log updater plugin * Added log link support * Fixed spotbug issue * Renamed plugin packages * Changed data types for artifact data * empty * Fixed test failure * Fixed Merge conflicts * Fixed spotbug issue * Updated as per review comments * Updated as per review comments * Updated as per review comments * Updated as per review comments --- src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java b/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java index 6bbd6ab6..b09ebf4b 100644 --- a/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java +++ b/src/main/java/com/mathworks/ci/RunMatlabBuildBuilder.java @@ -151,6 +151,7 @@ private int execMatlabCommand(FilePath workspace, Launcher launcher, try { matlabLauncher = getProcessToRunMatlabCommand(workspace, launcher, bca, envVars, "setenv('MW_ORIG_WORKING_FOLDER', cd('"+ uniqueTmpFolderPath.getRemote().replaceAll("'", "''") +"'));"+ uniqueBuildFile, options, uniqueTmpFldrName); + listener.getLogger() .println("#################### Starting command output ####################"); From 083f25799c52db1ad55658a09a2ad76c3e4093c8 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:04:10 +0530 Subject: [PATCH 23/52] Build visulization support for pipeline (#278) --- .../resources/com/mathworks/ci/BuildArtifactAction/index.jelly | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly index c8cf845c..56910569 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly @@ -59,7 +59,7 @@ - ${p.taskName} + ${p.taskName} From 7a366db90910f1b75e8ed94cd86fe55d7deb10b5 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:49:27 +0530 Subject: [PATCH 24/52] 2.11.2 snapshot qualification (#296) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 --- .../resources/com/mathworks/ci/BuildArtifactAction/index.jelly | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly index 56910569..c8cf845c 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/index.jelly @@ -59,7 +59,7 @@ - ${p.taskName} + ${p.taskName} From a60ac39572cdbc4dae44a7db18365166afd76218 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:57:11 +0530 Subject: [PATCH 25/52] Dev main (#313) * Initial fix * Added support for build visualization (Latest) (#268) * Added support for build visualization * Fixed findbug issues * Fixed findbug issues * Fixed findbug issues * Deleted failuresummary.jelly * Refactored tests * Refactored jelly file * Updated as per review comments * updated jelly as per review comment * Using overide plugin method to generate json file * Updated as per review comment * Updated as per review comment * Added log updater plugin * Added log link support * Fixed spotbug issue * Renamed plugin packages * Changed data types for artifact data * empty * Fixed test failure * Fixed Merge conflicts * Fixed spotbug issue * Updated as per review comments * Updated as per review comments * Updated as per review comments * Updated as per review comments * Build visulization support for pipeline (#278) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 * 2.11.2 snapshot qualification (#296) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 * Add build options (#294) * add build options * update gitignore * add tests for build options * add fixes and more tests * fix tests * modify help text * fix help text * minor text fix * fix null error and formatting * remove buildOptions check from EnvVarSupport test * add env variables support for build options and formatting fixes * minor fixes * documenting MATLAB build options and MATLAB build result * Fixed issue 298 (#300) * adding a new screenshot for build results and minor updates (#304) * Synch dev_main (#312) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Release 2.13.0 (#306) * Initial fix * Added support for build visualization (Latest) (#268) * Added support for build visualization * Fixed findbug issues * Fixed findbug issues * Fixed findbug issues * Deleted failuresummary.jelly * Refactored tests * Refactored jelly file * Updated as per review comments * updated jelly as per review comment * Using overide plugin method to generate json file * Updated as per review comment * Updated as per review comment * Added log updater plugin * Added log link support * Fixed spotbug issue * Renamed plugin packages * Changed data types for artifact data * empty * Fixed test failure * Fixed Merge conflicts * Fixed spotbug issue * Updated as per review comments * Updated as per review comments * Updated as per review comments * Updated as per review comments * Build visulization support for pipeline (#278) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 * 2.11.2 snapshot qualification (#296) * Fixed issue 281 (#284) * Update the maven release (#286) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * Added summary page warnning * Updated summary warnning * Fixed Summary page issues * Fixed issue 292 * Fixed 289 as per comment * Fixed error message issue 288 * Fixed 289 * Add build options (#294) * add build options * update gitignore * add tests for build options * add fixes and more tests * fix tests * modify help text * fix help text * minor text fix * fix null error and formatting * remove buildOptions check from EnvVarSupport test * add env variables support for build options and formatting fixes * minor fixes * documenting MATLAB build options and MATLAB build result * Fixed issue 298 (#300) * adding a new screenshot for build results and minor updates (#304) --------- Co-authored-by: sameagen Co-authored-by: sameagen-MW <122639681+sameagen-MW@users.noreply.github.com> Co-authored-by: Tushar Sharma <150027500+tsharmaMW@users.noreply.github.com> Co-authored-by: mw-hrastega <48831250+mw-hrastega@users.noreply.github.com> * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration * Preparing for next release (#309) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration * Synch master (#310) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration * Synch master (#311) * [maven-release-plugin] prepare release matlab-2.12.0 * [maven-release-plugin] prepare for next development iteration * [maven-release-plugin] prepare release matlab-2.13.0 * [maven-release-plugin] prepare for next development iteration --------- Co-authored-by: sameagen Co-authored-by: sameagen-MW <122639681+sameagen-MW@users.noreply.github.com> Co-authored-by: Tushar Sharma <150027500+tsharmaMW@users.noreply.github.com> Co-authored-by: mw-hrastega <48831250+mw-hrastega@users.noreply.github.com> --------- Co-authored-by: sameagen Co-authored-by: sameagen-MW <122639681+sameagen-MW@users.noreply.github.com> Co-authored-by: Tushar Sharma <150027500+tsharmaMW@users.noreply.github.com> Co-authored-by: mw-hrastega <48831250+mw-hrastega@users.noreply.github.com> From 3655190c15e9c3c849cdfbcacd21ecd4911bc991 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 26 Mar 2024 18:04:27 +0530 Subject: [PATCH 26/52] Revert "Dev main (#313)" This reverts commit a60ac39572cdbc4dae44a7db18365166afd76218. From d166cd8c15234dde31454b70b6389b6bf59abdab Mon Sep 17 00:00:00 2001 From: sameagen Date: Tue, 26 Mar 2024 10:48:13 -0400 Subject: [PATCH 27/52] Rearrange pipeline step parameter creation order to avoid serialization issues --- .../ci/parameters/MatlabActionParameters.java | 8 +- .../ci/pipeline/MatlabBuildStepExecution.java | 23 +++-- .../pipeline/MatlabCommandStepExecution.java | 22 ++--- .../pipeline/MatlabRunTestsStepExecution.java | 29 ++++-- .../ci/pipeline/RunMatlabBuildStep.java | 7 +- .../ci/pipeline/RunMatlabCommandStep.java | 10 +- .../ci/pipeline/RunMatlabTestsStep.java | 23 +---- .../ci/utilities/MatlabCommandRunner.java | 4 +- .../MatlabBuildStepExecutionUnitTest.java | 21 +++-- .../MatlabCommandStepExecutionUnitTest.java | 23 +++-- .../MatlabRunTestsStepExecutionUnitTest.java | 72 ++++++++++++++- .../pipeline/RunMatlabBuildStepUnitTest.java | 46 ---------- .../RunMatlabCommandStepUnitTest.java | 43 --------- .../pipeline/RunMatlabTestsStepUnitTest.java | 91 ------------------- 14 files changed, 161 insertions(+), 261 deletions(-) delete mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabBuildStepUnitTest.java delete mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabCommandStepUnitTest.java delete mode 100644 src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabTestsStepUnitTest.java diff --git a/src/main/java/com/mathworks/ci/parameters/MatlabActionParameters.java b/src/main/java/com/mathworks/ci/parameters/MatlabActionParameters.java index 09856214..65a0623a 100644 --- a/src/main/java/com/mathworks/ci/parameters/MatlabActionParameters.java +++ b/src/main/java/com/mathworks/ci/parameters/MatlabActionParameters.java @@ -14,12 +14,12 @@ * */ -public class MatlabActionParameters implements Serializable { - private transient Run build; +public class MatlabActionParameters { + private Run build; private FilePath workspace; private EnvVars env; - private transient Launcher launcher; - private transient TaskListener listener; + private Launcher launcher; + private TaskListener listener; private String startupOptions; diff --git a/src/main/java/com/mathworks/ci/pipeline/MatlabBuildStepExecution.java b/src/main/java/com/mathworks/ci/pipeline/MatlabBuildStepExecution.java index a9d8e7ea..a8ab3f64 100644 --- a/src/main/java/com/mathworks/ci/pipeline/MatlabBuildStepExecution.java +++ b/src/main/java/com/mathworks/ci/pipeline/MatlabBuildStepExecution.java @@ -19,25 +19,28 @@ public class MatlabBuildStepExecution extends SynchronousNonBlockingStepExecutio private static final long serialVersionUID = 4771831219402275744L; - private BuildActionParameters params; private MatlabActionFactory factory; - public MatlabBuildStepExecution(MatlabActionFactory factory, StepContext context, String tasks, String startupOptions, String buildOptions) throws IOException, InterruptedException { - super(context); + private RunMatlabBuildStep step; + + public MatlabBuildStepExecution(MatlabActionFactory factory, StepContext ctx, RunMatlabBuildStep step) throws IOException, InterruptedException { + super(ctx); - this.params = new BuildActionParameters(context, startupOptions, tasks, buildOptions); this.factory = factory; + this.step = step; } - public MatlabBuildStepExecution(StepContext context, String tasks, String startupOptions, String buildOptions) throws IOException, InterruptedException { - this(new MatlabActionFactory(), context, tasks, startupOptions, buildOptions); - } - - public BuildActionParameters getParameters() { - return this.params; + public MatlabBuildStepExecution(StepContext ctx, RunMatlabBuildStep step) throws IOException, InterruptedException { + this(new MatlabActionFactory(), ctx, step); } @Override public Void run() throws Exception { + BuildActionParameters params = new BuildActionParameters( + getContext(), + step.getStartupOptions(), + step.getTasks(), + step.getBuildOptions()); + RunMatlabBuildAction action = factory.createAction(params); try { action.run(); diff --git a/src/main/java/com/mathworks/ci/pipeline/MatlabCommandStepExecution.java b/src/main/java/com/mathworks/ci/pipeline/MatlabCommandStepExecution.java index 88f702d3..fc37a9de 100644 --- a/src/main/java/com/mathworks/ci/pipeline/MatlabCommandStepExecution.java +++ b/src/main/java/com/mathworks/ci/pipeline/MatlabCommandStepExecution.java @@ -18,30 +18,26 @@ public class MatlabCommandStepExecution extends SynchronousNonBlockingStepExecut private static final long serialVersionUID = 1957239693658914450L; - private String command; - private String startupOptions; - - private RunActionParameters params; - private MatlabActionFactory factory; + private RunMatlabCommandStep step; - public MatlabCommandStepExecution(MatlabActionFactory factory, StepContext context, String command, String startupOptions) throws IOException, InterruptedException { + public MatlabCommandStepExecution(MatlabActionFactory factory, StepContext context, RunMatlabCommandStep step) throws IOException, InterruptedException { super(context); - this.params = new RunActionParameters(context, startupOptions, command); this.factory = factory; + this.step = step; } - public MatlabCommandStepExecution(StepContext context, String command, String startupOptions) throws IOException, InterruptedException { - this(new MatlabActionFactory(), context, command, startupOptions); - } - - public RunActionParameters getParameters() { - return this.params; + public MatlabCommandStepExecution(StepContext context, RunMatlabCommandStep step) throws IOException, InterruptedException { + this(new MatlabActionFactory(), context, step); } @Override public Void run() throws Exception { + RunActionParameters params = new RunActionParameters( + getContext(), + step.getStartupOptions(), + step.getCommand()); RunMatlabCommandAction action = factory.createAction(params); try { diff --git a/src/main/java/com/mathworks/ci/pipeline/MatlabRunTestsStepExecution.java b/src/main/java/com/mathworks/ci/pipeline/MatlabRunTestsStepExecution.java index 2476554f..2f604fd1 100644 --- a/src/main/java/com/mathworks/ci/pipeline/MatlabRunTestsStepExecution.java +++ b/src/main/java/com/mathworks/ci/pipeline/MatlabRunTestsStepExecution.java @@ -20,26 +20,39 @@ public class MatlabRunTestsStepExecution extends SynchronousNonBlockingStepExecu private static final long serialVersionUID = 6704588180717665100L; - private TestActionParameters params; private MatlabActionFactory factory; + private RunMatlabTestsStep step; - public MatlabRunTestsStepExecution(MatlabActionFactory factory, StepContext context, TestActionParameters params) throws IOException, InterruptedException { + public MatlabRunTestsStepExecution(MatlabActionFactory factory, StepContext context, RunMatlabTestsStep step) throws IOException, InterruptedException { super(context); - this.params = params; this.factory = factory; + this.step = step; } - public MatlabRunTestsStepExecution(StepContext context, TestActionParameters params) throws IOException, InterruptedException { - this(new MatlabActionFactory(), context, params); + public MatlabRunTestsStepExecution(StepContext context, RunMatlabTestsStep step) throws IOException, InterruptedException { + this(new MatlabActionFactory(), context, step); } - public TestActionParameters getParameters() { - return this.params; - } @Override public Void run() throws Exception { + TestActionParameters params = new TestActionParameters( + getContext(), + step.getStartupOptions(), + step.getTestResultsPDF(), + step.getTestResultsTAP(), + step.getTestResultsJUnit(), + step.getCodeCoverageCobertura(), + step.getTestResultsSimulinkTest(), + step.getModelCoverageCobertura(), + step.getSelectByTag(), + step.getLoggingLevel(), + step.getOutputDetail(), + step.getUseParallel(), + step.getStrict(), + step.getSourceFolder(), + step.getSelectByFolder()); RunMatlabTestsAction action = factory.createAction(params); try { action.run(); diff --git a/src/main/java/com/mathworks/ci/pipeline/RunMatlabBuildStep.java b/src/main/java/com/mathworks/ci/pipeline/RunMatlabBuildStep.java index ab65936b..a978fbe8 100644 --- a/src/main/java/com/mathworks/ci/pipeline/RunMatlabBuildStep.java +++ b/src/main/java/com/mathworks/ci/pipeline/RunMatlabBuildStep.java @@ -5,6 +5,7 @@ * */ +import java.io.Serializable; import java.util.Set; import org.jenkinsci.plugins.workflow.steps.Step; import org.jenkinsci.plugins.workflow.steps.StepContext; @@ -23,7 +24,9 @@ import com.mathworks.ci.Message; -public class RunMatlabBuildStep extends Step { +public class RunMatlabBuildStep extends Step implements Serializable { + + private static final long serialVersionUID = 1L; private String tasks; private String startupOptions; @@ -63,7 +66,7 @@ public void setBuildOptions (String buildOptions) { @Override public StepExecution start(StepContext context) throws Exception { - return new MatlabBuildStepExecution(context, getTasks(), getStartupOptions(), getBuildOptions()); + return new MatlabBuildStepExecution(context, this); } @Extension diff --git a/src/main/java/com/mathworks/ci/pipeline/RunMatlabCommandStep.java b/src/main/java/com/mathworks/ci/pipeline/RunMatlabCommandStep.java index 95b08c65..470bba23 100644 --- a/src/main/java/com/mathworks/ci/pipeline/RunMatlabCommandStep.java +++ b/src/main/java/com/mathworks/ci/pipeline/RunMatlabCommandStep.java @@ -1,10 +1,11 @@ package com.mathworks.ci.pipeline; /** - * Copyright 2020-2023 The MathWorks, Inc. + * Copyright 2020-2024 The MathWorks, Inc. * */ +import java.io.Serializable; import java.util.Set; import org.jenkinsci.plugins.workflow.steps.Step; import org.jenkinsci.plugins.workflow.steps.StepContext; @@ -23,8 +24,10 @@ import com.mathworks.ci.Message; -public class RunMatlabCommandStep extends Step { +public class RunMatlabCommandStep extends Step implements Serializable { + private static final long serialVersionUID = 1L; + private String command; private String startupOptions = ""; @@ -33,7 +36,6 @@ public RunMatlabCommandStep(String command) { this.command = command; } - public String getCommand() { return this.command; } @@ -49,7 +51,7 @@ public String getStartupOptions() { @Override public StepExecution start(StepContext context) throws Exception { - return new MatlabCommandStepExecution(context, getCommand(), getStartupOptions()); + return new MatlabCommandStepExecution(context, this); } @Extension diff --git a/src/main/java/com/mathworks/ci/pipeline/RunMatlabTestsStep.java b/src/main/java/com/mathworks/ci/pipeline/RunMatlabTestsStep.java index af5b3b8e..6350b8e3 100644 --- a/src/main/java/com/mathworks/ci/pipeline/RunMatlabTestsStep.java +++ b/src/main/java/com/mathworks/ci/pipeline/RunMatlabTestsStep.java @@ -4,6 +4,7 @@ * */ +import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -27,7 +28,9 @@ import com.mathworks.ci.Message; import com.mathworks.ci.parameters.TestActionParameters; -public class RunMatlabTestsStep extends Step { +public class RunMatlabTestsStep extends Step implements Serializable { + + private static final long serialVersionUID = 1L; private String testResultsPDF; private String testResultsTAP; @@ -179,23 +182,7 @@ public void setStartupOptions(String startupOptions) { @Override public StepExecution start(StepContext context) throws Exception { - TestActionParameters params = new TestActionParameters( - context, - this.getStartupOptions(), - this.getTestResultsPDF(), - this.getTestResultsTAP(), - this.getTestResultsJUnit(), - this.getCodeCoverageCobertura(), - this.getTestResultsSimulinkTest(), - this.getModelCoverageCobertura(), - this.getSelectByTag(), - this.getLoggingLevel(), - this.getOutputDetail(), - this.getUseParallel(), - this.getStrict(), - this.getSourceFolder(), - this.getSelectByFolder()); - return new MatlabRunTestsStepExecution(context, params); + return new MatlabRunTestsStepExecution(context, this); } @Extension diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java index 85921e38..9961c113 100644 --- a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -48,7 +48,9 @@ public MatlabCommandRunner(MatlabActionParameters params) throws IOException, In new Thread(() -> { try { tempFolder.deleteRecursive(); - } catch(Exception e) {} + } catch(Exception e) { + System.err.println(e.toString()); + } })); } diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/MatlabBuildStepExecutionUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabBuildStepExecutionUnitTest.java index f0524be1..5699646d 100644 --- a/src/test/java/unit/com/mathworks/ci/pipeline/MatlabBuildStepExecutionUnitTest.java +++ b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabBuildStepExecutionUnitTest.java @@ -37,7 +37,7 @@ public void setup() throws IOException, InterruptedException { @Test public void shouldHandleNullCases() throws Exception, IOException, InterruptedException, MatlabExecutionException { - MatlabBuildStepExecution ex = new MatlabBuildStepExecution(factory, context, null, null, null); + MatlabBuildStepExecution ex = new MatlabBuildStepExecution(factory, context, new RunMatlabBuildStep()); ArgumentCaptor captor = ArgumentCaptor.forClass(BuildActionParameters.class); @@ -46,16 +46,21 @@ public void shouldHandleNullCases() throws Exception, IOException, InterruptedEx verify(factory).createAction(captor.capture()); BuildActionParameters params = captor.getValue(); - assertEquals(null, params.getStartupOptions()); - assertEquals(null, params.getTasks()); - assertEquals(null, params.getBuildOptions()); + assertEquals("", params.getStartupOptions()); + assertEquals("", params.getTasks()); + assertEquals("", params.getBuildOptions()); verify(action).run(); } @Test public void shouldHandleMaximalCases() throws Exception, IOException, InterruptedException, MatlabExecutionException { - MatlabBuildStepExecution ex = new MatlabBuildStepExecution(factory, context, "mytask", "-nojvm -nodisplay", "-continueOnFailure"); + RunMatlabBuildStep step = new RunMatlabBuildStep(); + step.setStartupOptions("-nojvm -logfile file"); + step.setTasks("vacuum bills"); + step.setBuildOptions("-continueOnFailure"); + + MatlabBuildStepExecution ex = new MatlabBuildStepExecution(factory, context, step); ex.run(); @@ -64,8 +69,8 @@ public void shouldHandleMaximalCases() throws Exception, IOException, Interrupte verify(factory).createAction(captor.capture()); BuildActionParameters params = captor.getValue(); - assertEquals("-nojvm -nodisplay", params.getStartupOptions()); - assertEquals("mytask", params.getTasks()); + assertEquals("-nojvm -logfile file", params.getStartupOptions()); + assertEquals("vacuum bills", params.getTasks()); assertEquals("-continueOnFailure", params.getBuildOptions()); verify(action).run(); @@ -73,7 +78,7 @@ public void shouldHandleMaximalCases() throws Exception, IOException, Interrupte @Test public void shouldHandleActionThrowing() throws Exception, IOException, InterruptedException, MatlabExecutionException { - MatlabBuildStepExecution ex = new MatlabBuildStepExecution(factory, context, null, null, null); + MatlabBuildStepExecution ex = new MatlabBuildStepExecution(factory, context, new RunMatlabBuildStep()); doThrow(new MatlabExecutionException(12)).when(action).run(); diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/MatlabCommandStepExecutionUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabCommandStepExecutionUnitTest.java index 30bad312..518b6c13 100644 --- a/src/test/java/unit/com/mathworks/ci/pipeline/MatlabCommandStepExecutionUnitTest.java +++ b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabCommandStepExecutionUnitTest.java @@ -37,16 +37,18 @@ public void setup() throws IOException, InterruptedException { @Test public void shouldHandleNullCases() throws Exception, IOException, InterruptedException, MatlabExecutionException { - MatlabCommandStepExecution ex = new MatlabCommandStepExecution(factory, context, null, null); - - ArgumentCaptor captor = ArgumentCaptor.forClass(RunActionParameters.class); + MatlabCommandStepExecution ex = new MatlabCommandStepExecution( + factory, + context, + new RunMatlabCommandStep(null)); ex.run(); + ArgumentCaptor captor = ArgumentCaptor.forClass(RunActionParameters.class); verify(factory).createAction(captor.capture()); RunActionParameters params = captor.getValue(); - assertEquals(null, params.getStartupOptions()); + assertEquals("", params.getStartupOptions()); assertEquals(null, params.getCommand()); verify(action).run(); @@ -54,16 +56,18 @@ public void shouldHandleNullCases() throws Exception, IOException, InterruptedEx @Test public void shouldHandleMaximalCases() throws Exception, IOException, InterruptedException, MatlabExecutionException { - MatlabCommandStepExecution ex = new MatlabCommandStepExecution(factory, context, "mycommand", "-nojvm -nodisplay"); + RunMatlabCommandStep step = new RunMatlabCommandStep("mycommand"); + step.setStartupOptions("-nojvm -logfile file"); + + MatlabCommandStepExecution ex = new MatlabCommandStepExecution(factory, context, step); ex.run(); ArgumentCaptor captor = ArgumentCaptor.forClass(RunActionParameters.class); - verify(factory).createAction(captor.capture()); RunActionParameters params = captor.getValue(); - assertEquals("-nojvm -nodisplay", params.getStartupOptions()); + assertEquals("-nojvm -logfile file", params.getStartupOptions()); assertEquals("mycommand", params.getCommand()); verify(action).run(); @@ -71,7 +75,10 @@ public void shouldHandleMaximalCases() throws Exception, IOException, Interrupte @Test public void shouldHandleActionThrowing() throws Exception, IOException, InterruptedException, MatlabExecutionException { - MatlabCommandStepExecution ex = new MatlabCommandStepExecution(factory, context, null, null); + MatlabCommandStepExecution ex = new MatlabCommandStepExecution( + factory, + context, + new RunMatlabCommandStep(null)); doThrow(new MatlabExecutionException(12)).when(action).run(); diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/MatlabRunTestsStepExecutionUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabRunTestsStepExecutionUnitTest.java index 91bab561..fe9d18fd 100644 --- a/src/test/java/unit/com/mathworks/ci/pipeline/MatlabRunTestsStepExecutionUnitTest.java +++ b/src/test/java/unit/com/mathworks/ci/pipeline/MatlabRunTestsStepExecutionUnitTest.java @@ -6,6 +6,7 @@ */ import java.io.IOException; +import java.util.ArrayList; import org.junit.Test; import org.junit.Before; @@ -29,7 +30,6 @@ public class MatlabRunTestsStepExecutionUnitTest { @Mock StepContext context; @Mock MatlabActionFactory factory; @Mock RunMatlabTestsAction action; - @Mock TestActionParameters params; @Before public void setup() throws IOException, InterruptedException { @@ -37,24 +37,86 @@ public void setup() throws IOException, InterruptedException { } @Test - public void shouldHandleOnlyCase() throws Exception, IOException, InterruptedException, MatlabExecutionException { - MatlabRunTestsStepExecution ex = new MatlabRunTestsStepExecution(factory, context, params); + public void shouldHandleNullCase() throws Exception, IOException, InterruptedException, MatlabExecutionException { + RunMatlabTestsStep step = new RunMatlabTestsStep(); + MatlabRunTestsStepExecution ex = new MatlabRunTestsStepExecution(factory, context, step); + + ex.run(); ArgumentCaptor captor = ArgumentCaptor.forClass(TestActionParameters.class); + verify(factory).createAction(captor.capture()); + + TestActionParameters params = captor.getValue(); + assertEquals("", params.getStartupOptions()); + assertEquals(null, params.getTestResultsPDF()); + assertEquals(null, params.getTestResultsTAP()); + assertEquals(null, params.getTestResultsJUnit()); + assertEquals(null, params.getCodeCoverageCobertura()); + assertEquals(null, params.getTestResultsSimulinkTest()); + assertEquals(null, params.getModelCoverageCobertura()); + assertEquals(null, params.getSelectByTag()); + assertEquals(null, params.getLoggingLevel()); + assertEquals(null, params.getOutputDetail()); + assertEquals("false", params.getUseParallel()); + assertEquals("false", params.getStrict()); + assertEquals(null, params.getSourceFolder()); + assertEquals(null, params.getSelectByFolder()); + verify(action).run(); + } + + @Test + public void shouldHandleMaximalCase() throws Exception, IOException, InterruptedException, MatlabExecutionException { + RunMatlabTestsStep step = new RunMatlabTestsStep(); + step.setStartupOptions("-nojvm -logfile file"); + step.setTestResultsPDF("res.pdf"); + step.setTestResultsTAP("res.tap"); + step.setTestResultsJUnit("res.xml"); + step.setCodeCoverageCobertura("cov.xml"); + step.setTestResultsSimulinkTest("res.sltest"); + step.setModelCoverageCobertura("cov.model"); + step.setSelectByTag("MyTag"); + step.setLoggingLevel("Concise"); + step.setOutputDetail("Concise"); + step.setUseParallel(true); + step.setStrict(true); + + ArrayList folders = new ArrayList(); + folders.add("src"); + folders.add("toolbox"); + + step.setSourceFolder(folders); + step.setSelectByFolder(folders); + + MatlabRunTestsStepExecution ex = new MatlabRunTestsStepExecution(factory, context, step); + ex.run(); + ArgumentCaptor captor = ArgumentCaptor.forClass(TestActionParameters.class); verify(factory).createAction(captor.capture()); TestActionParameters params = captor.getValue(); - assertEquals(this.params, params); + assertEquals("-nojvm -logfile file", params.getStartupOptions()); + assertEquals("res.pdf", params.getTestResultsPDF()); + assertEquals("res.tap", params.getTestResultsTAP()); + assertEquals("res.xml", params.getTestResultsJUnit()); + assertEquals("cov.xml", params.getCodeCoverageCobertura()); + assertEquals("res.sltest", params.getTestResultsSimulinkTest()); + assertEquals("cov.model", params.getModelCoverageCobertura()); + assertEquals("MyTag", params.getSelectByTag()); + assertEquals("Concise", params.getLoggingLevel()); + assertEquals("Concise", params.getOutputDetail()); + assertEquals("true", params.getUseParallel()); + assertEquals("true", params.getStrict()); + assertEquals(folders, params.getSourceFolder()); + assertEquals(folders, params.getSelectByFolder()); verify(action).run(); } @Test public void shouldHandleActionThrowing() throws Exception, IOException, InterruptedException, MatlabExecutionException { - MatlabRunTestsStepExecution ex = new MatlabRunTestsStepExecution(factory, context, params); + MatlabRunTestsStepExecution ex = new MatlabRunTestsStepExecution(factory, context, new RunMatlabTestsStep()); doThrow(new MatlabExecutionException(12)).when(action).run(); diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabBuildStepUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabBuildStepUnitTest.java deleted file mode 100644 index f53904cd..00000000 --- a/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabBuildStepUnitTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.mathworks.ci.pipeline; - -/** - * Copyright 2024, The MathWorks Inc. - * - */ - -import java.io.IOException; - -import org.junit.Test; -import org.junit.runner.RunWith; -import static org.junit.Assert.*; - -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -import org.jenkinsci.plugins.workflow.steps.StepContext; - -@RunWith(MockitoJUnitRunner.class) -public class RunMatlabBuildStepUnitTest { - @Mock StepContext context; - - @Test - public void shouldHandleNullCase() throws Exception { - RunMatlabBuildStep step = new RunMatlabBuildStep(); - MatlabBuildStepExecution ex = (MatlabBuildStepExecution)step.start(context); - - assertEquals("", ex.getParameters().getStartupOptions()); - assertEquals("", ex.getParameters().getTasks()); - assertEquals("", ex.getParameters().getBuildOptions()); - } - - @Test - public void shouldHandleMaximalCase() throws Exception { - RunMatlabBuildStep step = new RunMatlabBuildStep(); - step.setStartupOptions("-nojvm -logfile file"); - step.setTasks("vacuum bills"); - step.setBuildOptions("-continueOnFailure"); - - MatlabBuildStepExecution ex = (MatlabBuildStepExecution)step.start(context); - - assertEquals("-nojvm -logfile file", ex.getParameters().getStartupOptions()); - assertEquals("vacuum bills", ex.getParameters().getTasks()); - assertEquals("-continueOnFailure", ex.getParameters().getBuildOptions()); - } -} diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabCommandStepUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabCommandStepUnitTest.java deleted file mode 100644 index 17e192ff..00000000 --- a/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabCommandStepUnitTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.mathworks.ci.pipeline; - -/** - * Copyright 2024, The MathWorks Inc. - * - */ - -import java.io.IOException; - -import org.junit.Test; -import org.junit.runner.RunWith; -import static org.junit.Assert.*; - -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; -import static org.mockito.Mockito.*; - -import org.jenkinsci.plugins.workflow.steps.StepContext; - -@RunWith(MockitoJUnitRunner.class) -public class RunMatlabCommandStepUnitTest { - @Mock StepContext context; - - @Test - public void shouldHandleNullCase() throws Exception { - RunMatlabCommandStep step = new RunMatlabCommandStep("SPEAK"); - MatlabCommandStepExecution ex = (MatlabCommandStepExecution)step.start(context); - - assertEquals("", ex.getParameters().getStartupOptions()); - assertEquals("SPEAK", ex.getParameters().getCommand()); - } - - @Test - public void shouldHandleMaximalCase() throws Exception { - RunMatlabCommandStep step = new RunMatlabCommandStep("ROLL OVER"); - step.setStartupOptions("-nojvm -logfile file"); - - MatlabCommandStepExecution ex = (MatlabCommandStepExecution)step.start(context); - - assertEquals("-nojvm -logfile file", ex.getParameters().getStartupOptions()); - assertEquals("ROLL OVER", ex.getParameters().getCommand()); - } -} diff --git a/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabTestsStepUnitTest.java b/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabTestsStepUnitTest.java deleted file mode 100644 index c5861edc..00000000 --- a/src/test/java/unit/com/mathworks/ci/pipeline/RunMatlabTestsStepUnitTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.mathworks.ci.pipeline; - -/** - * Copyright 2024, The MathWorks Inc. - * - */ - -import java.io.IOException; - -import java.util.ArrayList; - -import org.junit.Test; -import org.junit.runner.RunWith; -import static org.junit.Assert.*; - -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; -import static org.mockito.Mockito.*; - -import org.jenkinsci.plugins.workflow.steps.StepContext; - -import com.mathworks.ci.parameters.TestActionParameters; - -@RunWith(MockitoJUnitRunner.class) -public class RunMatlabTestsStepUnitTest { - @Mock StepContext context; - - @Test - public void shouldHandleNullCase() throws Exception { - RunMatlabTestsStep step = new RunMatlabTestsStep(); - MatlabRunTestsStepExecution ex = (MatlabRunTestsStepExecution)step.start(context); - - TestActionParameters params = ex.getParameters(); - assertEquals("", params.getStartupOptions()); - assertEquals(null, params.getTestResultsPDF()); - assertEquals(null, params.getTestResultsTAP()); - assertEquals(null, params.getTestResultsJUnit()); - assertEquals(null, params.getCodeCoverageCobertura()); - assertEquals(null, params.getTestResultsSimulinkTest()); - assertEquals(null, params.getModelCoverageCobertura()); - assertEquals(null, params.getSelectByTag()); - assertEquals(null, params.getLoggingLevel()); - assertEquals(null, params.getOutputDetail()); - assertEquals("false", params.getUseParallel()); - assertEquals("false", params.getStrict()); - assertEquals(null, params.getSourceFolder()); - assertEquals(null, params.getSelectByFolder()); - } - - @Test - public void shouldHandleMaximalCase() throws Exception { - RunMatlabTestsStep step = new RunMatlabTestsStep(); - step.setStartupOptions("-nojvm -logfile file"); - step.setTestResultsPDF("res.pdf"); - step.setTestResultsTAP("res.tap"); - step.setTestResultsJUnit("res.xml"); - step.setCodeCoverageCobertura("cov.xml"); - step.setTestResultsSimulinkTest("res.sltest"); - step.setModelCoverageCobertura("cov.model"); - step.setSelectByTag("MyTag"); - step.setLoggingLevel("Concise"); - step.setOutputDetail("Concise"); - step.setUseParallel(true); - step.setStrict(true); - - ArrayList folders = new ArrayList(); - folders.add("src"); - folders.add("toolbox"); - - step.setSourceFolder(folders); - step.setSelectByFolder(folders); - - MatlabRunTestsStepExecution ex = (MatlabRunTestsStepExecution)step.start(context); - - TestActionParameters params = ex.getParameters(); - assertEquals("-nojvm -logfile file", params.getStartupOptions()); - assertEquals("res.pdf", params.getTestResultsPDF()); - assertEquals("res.tap", params.getTestResultsTAP()); - assertEquals("res.xml", params.getTestResultsJUnit()); - assertEquals("cov.xml", params.getCodeCoverageCobertura()); - assertEquals("res.sltest", params.getTestResultsSimulinkTest()); - assertEquals("cov.model", params.getModelCoverageCobertura()); - assertEquals("MyTag", params.getSelectByTag()); - assertEquals("Concise", params.getLoggingLevel()); - assertEquals("Concise", params.getOutputDetail()); - assertEquals("true", params.getUseParallel()); - assertEquals("true", params.getStrict()); - assertEquals(folders, params.getSourceFolder()); - assertEquals(folders, params.getSelectByFolder()); - } -} From 30270b1340cabc0391ca51749262385ee8038bae Mon Sep 17 00:00:00 2001 From: sameagen Date: Tue, 26 Mar 2024 14:35:36 -0400 Subject: [PATCH 28/52] Fix Windows path-based test failures --- .../ci/utilities/MatlabCommandRunner.java | 6 +++++- .../mathworks/ci/RunMatlabBuildBuilderTest.java | 2 +- .../ci/RunMatlabCommandBuilderTest.java | 2 +- .../ci/utilities/MatlabCommandRunnerTest.java | 17 +++++++++++------ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java index 9961c113..2d7941a3 100644 --- a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -5,6 +5,7 @@ * */ +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -36,7 +37,10 @@ public MatlabCommandRunner(MatlabActionParameters params) throws IOException, In this.additionalEnvVars = new HashMap(); // Create MATLAB folder - FilePath matlabFolder = new FilePath(params.getLauncher().getChannel(), params.getWorkspace().getRemote() + "/.matlab"); + FilePath matlabFolder = new FilePath( + params.getLauncher().getChannel(), params.getWorkspace().getRemote() + + File.separator + + ".matlab"); matlabFolder.mkdirs(); // Create temp folder diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java index ef1b04e1..edb3a9a6 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java @@ -149,7 +149,7 @@ public void verifyMATLABlaunchedfromWorkspace() throws Exception { project.getBuildersList().add(this.scriptBuilder); FreeStyleBuild build = project.scheduleBuild2(0).get(); String workspace = build.getWorkspace().getName(); - jenkins.assertLogContains(File.separator + workspace + File.separator, build); + jenkins.assertLogContains("[" + workspace + "]", build); } /* diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java index caf7cdc1..5398935f 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java @@ -156,7 +156,7 @@ public void verifyMATLABlaunchedfromWorkspace() throws Exception { project.getBuildersList().add(this.scriptBuilder); FreeStyleBuild build = project.scheduleBuild2(0).get(); String workspace = build.getWorkspace().getName(); - jenkins.assertLogContains(File.separator + workspace + File.separator, build); + jenkins.assertLogContains(File.separator + workspace, build); } /* diff --git a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java index badc149c..7a085c3e 100644 --- a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java +++ b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java @@ -95,10 +95,11 @@ public void constructorUsesParamsForTempFolder() throws IOException, Interrupted public void correctTempFolderLocation() throws IOException, InterruptedException { runner = new MatlabCommandRunner(params); FilePath tmp = runner.getTempFolder(); + FilePath expected = new FilePath(new File(tempDir.getRoot(), ".matlab")); Assert.assertThat( tmp.getRemote(), - startsWith(new File(tempDir.getRoot(), ".matlab").getAbsolutePath())); + startsWith(expected.getRemote())); } @Test @@ -123,7 +124,8 @@ public Object answer(InvocationOnMock invocation) throws IOException { Assert.assertTrue(f.exists()); Assert.assertEquals( runner.getTempFolder().getRemote() - + "/run-matlab-command", + + File.separator + + "run-matlab-command", f.getRemote()); } @@ -138,7 +140,8 @@ public void prepareRunnerExecutableMac() throws IOException, InterruptedExceptio Assert.assertTrue(f.exists()); Assert.assertEquals( runner.getTempFolder().getRemote() - + "/run-matlab-command", + + File.separator + + "run-matlab-command", f.getRemote()); } @@ -151,7 +154,8 @@ public void prepareRunnerExecutableWindows() throws IOException, InterruptedExce Assert.assertTrue(f.exists()); Assert.assertEquals( runner.getTempFolder().getRemote() - + "/run-matlab-command.exe", + + File.separator + + "run-matlab-command.exe", f.getRemote()); } @@ -178,7 +182,7 @@ public void copyFileFromResourcePathWorks() throws IOException, InterruptedExcep FilePath f = runner.copyFileToTempFolder("testcontent.txt", "target.txt"); Assert.assertTrue(f.exists()); - Assert.assertEquals("This has text!\n", f.readToString()); + Assert.assertThat(f.readToString(), startsWith("This has text!")); } @Test @@ -189,7 +193,8 @@ public void runWorksInBasicCase() throws IOException, InterruptedException, Matl runner.runMatlabCommand(myCommand); String exe = runner.getTempFolder().getRemote() - + "/run-matlab-command.exe"; + + File.separator + + "run-matlab-command.exe"; String cmd = "setenv('MW_ORIG_WORKING_FOLDER', cd('" + runner.getTempFolder().getRemote() + "'));script_"; From fec8204d01345574ef989bdc77cb23e82ed2e3fd Mon Sep 17 00:00:00 2001 From: sameagen Date: Fri, 29 Mar 2024 11:46:42 -0400 Subject: [PATCH 29/52] Change Frm -> From --- src/main/java/com/mathworks/ci/Utilities.java | 6 +++--- .../java/com/mathworks/ci/actions/RunMatlabTestsAction.java | 4 ++-- .../com/mathworks/ci/utilities/MatlabCommandRunner.java | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/mathworks/ci/Utilities.java b/src/main/java/com/mathworks/ci/Utilities.java index 5ca11296..8e6371b8 100644 --- a/src/main/java/com/mathworks/ci/Utilities.java +++ b/src/main/java/com/mathworks/ci/Utilities.java @@ -1,7 +1,7 @@ package com.mathworks.ci; /** - * Copyright 2020 The MathWorks, Inc. + * Copyright 2020-2024 The MathWorks, Inc. * * Utility class for common methods. * @@ -24,7 +24,7 @@ public class Utilities { - public static String getCellArrayFrmList(List listOfStr){ + public static String getCellArrayFromList(List listOfStr){ // Ignore empty string values in the list Predicate isEmpty = String::isEmpty; Predicate isNotEmpty = isEmpty.negate(); @@ -35,7 +35,7 @@ public static String getCellArrayFrmList(List listOfStr){ return "{" + String.join(",", filteredListOfStr) + "}"; } - public static void addMatlabToEnvPathFrmAxis(Computer cmp, TaskListener listener, EnvVars env) + public static void addMatlabToEnvPathFromAxis(Computer cmp, TaskListener listener, EnvVars env) throws IOException, InterruptedException { String name = env.get(Message.getValue("Axis.matlab.key")); diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java index 833902b6..d3d3aea0 100644 --- a/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java @@ -70,14 +70,14 @@ private String getParameterString() { if (this.params.getSourceFolder() != null) { sourceFolders = this.params.getSourceFolder().size() == 0 ? null - : Utilities.getCellArrayFrmList(this.params.getSourceFolder()); + : Utilities.getCellArrayFromList(this.params.getSourceFolder()); } String selectFolders = null; if (this.params.getSelectByFolder() != null) { selectFolders = this.params.getSelectByFolder().size() == 0 ? null - : Utilities.getCellArrayFrmList(this.params.getSelectByFolder()); + : Utilities.getCellArrayFromList(this.params.getSelectByFolder()); } // All string-based fields diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java index 2d7941a3..52fd35f8 100644 --- a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -86,7 +86,7 @@ public void runMatlabCommand(String command) throws IOException, InterruptedExce // Add custom environment vars EnvVars env = getEnvVars(); - Utilities.addMatlabToEnvPathFrmAxis( + Utilities.addMatlabToEnvPathFromAxis( Computer.currentComputer(), this.params.getTaskListener(), env); From 135e56cf8a7bbfe2ca4306b348bb170ee5981481 Mon Sep 17 00:00:00 2001 From: sameagen Date: Mon, 1 Apr 2024 16:35:53 -0400 Subject: [PATCH 30/52] Address Mark's feedback. Adjust file separators --- .../java/com/mathworks/ci/actions/RunMatlabBuildAction.java | 5 +++-- .../java/com/mathworks/ci/actions/RunMatlabTestsAction.java | 2 +- .../com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java index d60f3d91..9cfa0a41 100644 --- a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java @@ -85,13 +85,14 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep // Handle build result Run build = this.params.getBuild(); - FilePath jsonFile = new FilePath(params.getWorkspace(), ".matlab/buildArtifact.json"); + FilePath jsonFile = new FilePath(params.getWorkspace(), ".matlab" + File.separator + "buildArtifact.json"); if (jsonFile.exists()) { FilePath rootLocation = new FilePath( new File( build.getRootDir() .getAbsolutePath() - + "/buildArtifact.json")); + + File.separator + + "buildArtifact.json")); jsonFile.copyTo(rootLocation); jsonFile.delete(); build.addAction(new BuildArtifactAction(build, this.params.getWorkspace())); diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java index d3d3aea0..d9228d66 100644 --- a/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java @@ -54,7 +54,7 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep } private String singleQuotify(String in) { - return "'" + in + "'"; + return "'" + in.replace("'", "''") + "'"; } // Concatenate the input arguments, try to keep this function as diff --git a/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java b/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java index e49e4c06..ab599de9 100644 --- a/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java +++ b/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java @@ -204,7 +204,7 @@ public SelectByTag getSelectByTag() { return this.selectByTag; } - public String getSelectByTagPath() { + public String getSelectByTagAsString() { return this.selectByTag == null ? null : selectByTag.getTestTag(); @@ -381,7 +381,7 @@ public void perform(@Nonnull Run build, @Nonnull FilePath workspace, this.getCoberturaReportFilePath(), this.getStmResultsFilePath(), this.getModelCoverageFilePath(), - this.getSelectByTagPath(), + this.getSelectByTagAsString(), this.getLoggingLevel(), this.getOutputDetail(), this.getUseParallel(), From b8a2888d2e58f080cf2f08eeea3b0b56714231c2 Mon Sep 17 00:00:00 2001 From: sameagen Date: Fri, 12 Apr 2024 11:10:37 -0400 Subject: [PATCH 31/52] Create workspace folder if it does not exist. --- .../java/com/mathworks/ci/utilities/MatlabCommandRunner.java | 5 +++++ .../com/mathworks/ci/utilities/MatlabCommandRunnerTest.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java index 52fd35f8..1f6f233a 100644 --- a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -36,6 +36,11 @@ public MatlabCommandRunner(MatlabActionParameters params) throws IOException, In this.params = params; this.additionalEnvVars = new HashMap(); + // Handle case where workspace doesn't exist + if (!params.getWorkspace().exists()) { + params.getWorkspace().mkdirs(); + } + // Create MATLAB folder FilePath matlabFolder = new FilePath( params.getLauncher().getChannel(), params.getWorkspace().getRemote() diff --git a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java index 7a085c3e..742afc81 100644 --- a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java +++ b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java @@ -88,7 +88,7 @@ public void validConstructorDoesNotThrow() throws IOException, InterruptedExcept public void constructorUsesParamsForTempFolder() throws IOException, InterruptedException { MatlabCommandRunner runner = new MatlabCommandRunner(params); verify(params, times(1)).getLauncher(); - verify(params, times(1)).getWorkspace(); + verify(params, times(3)).getWorkspace(); } @Test From 0f06f4e0fff5e99cbfc49fcf2b7bc5a55bac8f91 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:35:43 +0530 Subject: [PATCH 32/52] Patch fix for file error issue --- .../resources/+ciplugins/+jenkins/BuildReportPlugin.m | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m index ccdfbd94..29208423 100644 --- a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m +++ b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m @@ -6,7 +6,13 @@ function runTaskGraph(plugin, pluginData) runTaskGraph@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData); - fID = fopen(fullfile(getenv("WORKSPACE"),'.matlab/buildArtifact.json'), 'w'); + [fID, msg] = fopen(fullfile(getenv("WORKSPACE"),'.matlab/buildArtifact.json'), 'w'); + + if fID == -1 + warning('BuildTool:artifactFileWarnning','Could not open a file for Jenkins build result table due to: %s', msg); + fID = 1; + end + taskDetails = struct(); for idx = 1:numel(pluginData.TaskResults) taskDetails(idx).name = pluginData.TaskResults(idx).Name; From 748264756ba9d2ca0c10c5700cda0e9363582ab4 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:17:27 +0530 Subject: [PATCH 33/52] UPdated the fID logic --- .../+ciplugins/+jenkins/BuildReportPlugin.m | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m index 29208423..e496c5a2 100644 --- a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m +++ b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m @@ -6,26 +6,24 @@ function runTaskGraph(plugin, pluginData) runTaskGraph@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData); - [fID, msg] = fopen(fullfile(getenv("WORKSPACE"),'.matlab/buildArtifact.json'), 'w'); + [fID, msg] = fopen(fullfile(pwd,'buildArtifact.json'), 'w'); if fID == -1 warning('BuildTool:artifactFileWarnning','Could not open a file for Jenkins build result table due to: %s', msg); - fID = 1; + else + taskDetails = struct(); + for idx = 1:numel(pluginData.TaskResults) + taskDetails(idx).name = pluginData.TaskResults(idx).Name; + taskDetails(idx).description = pluginData.TaskGraph.Tasks(idx).Description; + taskDetails(idx).failed = pluginData.TaskResults(idx).Failed; + taskDetails(idx).skipped = pluginData.TaskResults(idx).Skipped; + taskDetails(idx).duration = string(pluginData.TaskResults(idx).Duration); + end + a = struct("taskDetails",taskDetails); + s = jsonencode(a,"PrettyPrint",true); + fprintf(fID, '%s',s); + fclose(fID); end - - taskDetails = struct(); - for idx = 1:numel(pluginData.TaskResults) - taskDetails(idx).name = pluginData.TaskResults(idx).Name; - taskDetails(idx).description = pluginData.TaskGraph.Tasks(idx).Description; - taskDetails(idx).failed = pluginData.TaskResults(idx).Failed; - taskDetails(idx).skipped = pluginData.TaskResults(idx).Skipped; - taskDetails(idx).duration = string(pluginData.TaskResults(idx).Duration); - end - a = struct("taskDetails",taskDetails); - s = jsonencode(a,"PrettyPrint",true); - fprintf(fID, '%s',s); - fclose(fID); end - end end \ No newline at end of file From 26d6104ef5daa7b7800b5bd9306398cc17d80818 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:18:40 +0530 Subject: [PATCH 34/52] UPdated the fID logic --- src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m index e496c5a2..9bba8690 100644 --- a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m +++ b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m @@ -6,7 +6,7 @@ function runTaskGraph(plugin, pluginData) runTaskGraph@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData); - [fID, msg] = fopen(fullfile(pwd,'buildArtifact.json'), 'w'); + [fID, msg] = fopen(fullfile(getenv("WORKSPACE"),'.matlab/buildArtifact.json'), 'w'); if fID == -1 warning('BuildTool:artifactFileWarnning','Could not open a file for Jenkins build result table due to: %s', msg); From a5f8cf2b754c284afd38e67c068a4250d7749c92 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:29:08 +0530 Subject: [PATCH 35/52] Removed extra spaces --- .../resources/+ciplugins/+jenkins/BuildReportPlugin.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m index 9bba8690..193b0144 100644 --- a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m +++ b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m @@ -18,11 +18,11 @@ function runTaskGraph(plugin, pluginData) taskDetails(idx).failed = pluginData.TaskResults(idx).Failed; taskDetails(idx).skipped = pluginData.TaskResults(idx).Skipped; taskDetails(idx).duration = string(pluginData.TaskResults(idx).Duration); - end - a = struct("taskDetails",taskDetails); - s = jsonencode(a,"PrettyPrint",true); - fprintf(fID, '%s',s); - fclose(fID); + end + a = struct("taskDetails",taskDetails); + s = jsonencode(a,"PrettyPrint",true); + fprintf(fID, '%s',s); + fclose(fID); end end end From de5db98a940833f04006e69a8b120b15eba12080 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Wed, 17 Apr 2024 10:15:08 +0530 Subject: [PATCH 36/52] Updated as per review comments --- src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m index 193b0144..da06ebd2 100644 --- a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m +++ b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m @@ -6,11 +6,12 @@ function runTaskGraph(plugin, pluginData) runTaskGraph@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData); - [fID, msg] = fopen(fullfile(getenv("WORKSPACE"),'.matlab/buildArtifact.json'), 'w'); + [fID, msg] = fopen(fullfile(getenv("WORKSPACE"),".matlab/buildArtifact.json"), "w"); if fID == -1 - warning('BuildTool:artifactFileWarnning','Could not open a file for Jenkins build result table due to: %s', msg); + warning('ciplugins:jenkins:BuildReportPlugin:UnableToOpenFile','Could not open a file for Jenkins build result table due to: %s', msg); else + closeFile = onCleanup(@()fclose(fID)); taskDetails = struct(); for idx = 1:numel(pluginData.TaskResults) taskDetails(idx).name = pluginData.TaskResults(idx).Name; @@ -22,7 +23,6 @@ function runTaskGraph(plugin, pluginData) a = struct("taskDetails",taskDetails); s = jsonencode(a,"PrettyPrint",true); fprintf(fID, '%s',s); - fclose(fID); end end end From cd32354aa393ec3fe2d42577781513a33d68a86e Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Thu, 18 Apr 2024 10:15:31 +0530 Subject: [PATCH 37/52] Updated as per review comments --- src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m index da06ebd2..8e810e57 100644 --- a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m +++ b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m @@ -9,7 +9,7 @@ function runTaskGraph(plugin, pluginData) [fID, msg] = fopen(fullfile(getenv("WORKSPACE"),".matlab/buildArtifact.json"), "w"); if fID == -1 - warning('ciplugins:jenkins:BuildReportPlugin:UnableToOpenFile','Could not open a file for Jenkins build result table due to: %s', msg); + warning("ciplugins:jenkins:BuildReportPlugin:UnableToOpenFile","Could not open a file for Jenkins build result table due to: %s", msg); else closeFile = onCleanup(@()fclose(fID)); taskDetails = struct(); @@ -21,8 +21,8 @@ function runTaskGraph(plugin, pluginData) taskDetails(idx).duration = string(pluginData.TaskResults(idx).Duration); end a = struct("taskDetails",taskDetails); - s = jsonencode(a,"PrettyPrint",true); - fprintf(fID, '%s',s); + s = jsonencode(a,PrettyPrint=true); + fprintf(fID, "%s",s); end end end From cdc789610f8c81d7dcf1c3e297c49f0797a7199e Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:15:26 +0530 Subject: [PATCH 38/52] Updated the error message in summary page --- .../com/mathworks/ci/BuildArtifactAction/summary.jelly | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly index ee5beef9..4a8a757b 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly @@ -9,7 +9,7 @@

MATLAB Build Results

-
Unable to run a MATLAB build.
+
Unable to generate build artifact.

Tasks run: ${it.totalCount}

From fbd69c0258621d47f4dc32018771e97671e7ac61 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:18:58 +0530 Subject: [PATCH 39/52] Updated the error message in summary page --- .../com/mathworks/ci/BuildArtifactAction/summary.jelly | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly index 4a8a757b..b738b03f 100644 --- a/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly +++ b/src/main/resources/com/mathworks/ci/BuildArtifactAction/summary.jelly @@ -9,7 +9,7 @@

MATLAB Build Results

-
Unable to generate build artifact.
+
Unable to generate a build artifact.

Tasks run: ${it.totalCount}

From f18a4765ed6072e1bfad2390671cd7f12d04ed6c Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:32:50 +0530 Subject: [PATCH 40/52] [maven-release-plugin] prepare release matlab-2.13.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4699ba7a..df4f1a2c 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ matlab - 2.13.1-SNAPSHOT + 2.13.1 hpi @@ -46,7 +46,7 @@ scm:git:ssh://github.com/jenkinsci/matlab-plugin.git scm:git:ssh://git@github.com/jenkinsci/matlab-plugin.git http://github.com/jenkinsci/matlab-plugin - HEAD + matlab-2.13.1 From edef7cc431eb6ee081f4d850562f5f48fde6aa60 Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:32:57 +0530 Subject: [PATCH 41/52] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index df4f1a2c..87e5e2a2 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ matlab - 2.13.1 + 2.13.2-SNAPSHOT hpi @@ -46,7 +46,7 @@ scm:git:ssh://github.com/jenkinsci/matlab-plugin.git scm:git:ssh://git@github.com/jenkinsci/matlab-plugin.git http://github.com/jenkinsci/matlab-plugin - matlab-2.13.1 + HEAD From 476e48e6ac4f292ea69248f3921a1dac5c469270 Mon Sep 17 00:00:00 2001 From: sameagen Date: Wed, 24 Apr 2024 12:40:11 -0400 Subject: [PATCH 42/52] Add clarification comments for action test setup --- .../unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java | 1 + .../com/mathworks/ci/actions/RunMatlabCommandActionTest.java | 1 + .../unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java | 1 + 3 files changed, 3 insertions(+) diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java index ae2f5591..70c57cc7 100644 --- a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java @@ -44,6 +44,7 @@ public class RunMatlabBuildActionTest { private boolean setup = false; private RunMatlabBuildAction action; + // Not using @BeforeClass to avoid static fields. @Before public void init() { if (!setup) { diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java index 1e3f4542..732422d3 100644 --- a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java @@ -33,6 +33,7 @@ public class RunMatlabCommandActionTest { private boolean setup = false; private RunMatlabCommandAction action; + // Not using @BeforeClass to avoid static fields. @Before public void init() { if (!setup) { diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java index 33fc609d..85de29e9 100644 --- a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java @@ -40,6 +40,7 @@ public class RunMatlabTestsActionTest { private boolean setup = false; private RunMatlabTestsAction action; + // Not using @BeforeClass to avoid static fields. @Before public void init() throws IOException, InterruptedException { if (!setup) { From 601c5a26e90f92c228a0bc05f1794bd360354dbc Mon Sep 17 00:00:00 2001 From: Nikhil Bhoski <47204011+nbhoski@users.noreply.github.com> Date: Mon, 27 May 2024 23:24:50 +0530 Subject: [PATCH 43/52] Fixed issue #320 --- .../com/mathworks/ci/BuildArtifactAction.java | 7 +------ .../ci/actions/RunMatlabBuildAction.java | 2 +- .../mathworks/ci/BuildArtifactActionTest.java | 20 +++++++++---------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/mathworks/ci/BuildArtifactAction.java b/src/main/java/com/mathworks/ci/BuildArtifactAction.java index ad359725..815f6606 100644 --- a/src/main/java/com/mathworks/ci/BuildArtifactAction.java +++ b/src/main/java/com/mathworks/ci/BuildArtifactAction.java @@ -21,16 +21,14 @@ public class BuildArtifactAction implements Action { private Run build; - private FilePath workspace; private int totalCount; private int skipCount; private int failCount; private static final String ROOT_ELEMENT = "taskDetails"; private static final String BUILD_ARTIFACT_FILE = "buildArtifact.json"; - public BuildArtifactAction(Run build, FilePath workspace) { + public BuildArtifactAction(Run build) { this.build = build; - this.workspace = workspace; // Setting the counts of task when Action is created. try{ @@ -130,9 +128,6 @@ public void setOwner(Run owner) { this.build = owner; } - public FilePath getWorkspace() { - return this.workspace; - } private void setCounts() throws InterruptedException, ParseException { List artifactData = new ArrayList(); diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java index 9cfa0a41..93ccb68d 100644 --- a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java @@ -95,7 +95,7 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep + "buildArtifact.json")); jsonFile.copyTo(rootLocation); jsonFile.delete(); - build.addAction(new BuildArtifactAction(build, this.params.getWorkspace())); + build.addAction(new BuildArtifactAction(build)); } } } diff --git a/src/test/java/integ/com/mathworks/ci/BuildArtifactActionTest.java b/src/test/java/integ/com/mathworks/ci/BuildArtifactActionTest.java index 8c1fb4e7..5232607f 100644 --- a/src/test/java/integ/com/mathworks/ci/BuildArtifactActionTest.java +++ b/src/test/java/integ/com/mathworks/ci/BuildArtifactActionTest.java @@ -71,7 +71,7 @@ private URL getResource(String resource) { @Test public void verifyBuildArtifactsReturned() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { FreeStyleBuild build = getFreestyleBuild(); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); List ba = ac.getBuildArtifact(); @@ -87,7 +87,7 @@ public void verifyBuildArtifactsReturned() throws ExecutionException, Interrupte @Test public void verifyFailedCount() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { FreeStyleBuild build = getFreestyleBuild(); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); List ba = ac.getBuildArtifact(); @@ -103,7 +103,7 @@ public void verifyFailedCount() throws ExecutionException, InterruptedException, @Test public void verifySkipCount() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { FreeStyleBuild build = getFreestyleBuild(); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); List ba = ac.getBuildArtifact(); @@ -118,7 +118,7 @@ public void verifySkipCount() throws ExecutionException, InterruptedException, U @Test public void verifyDurationIsAccurate() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { FreeStyleBuild build = getFreestyleBuild(); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); List ba = ac.getBuildArtifact(); @@ -133,7 +133,7 @@ public void verifyDurationIsAccurate() throws ExecutionException, InterruptedExc @Test public void verifyTaskDescriptionIsAccurate() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { FreeStyleBuild build = getFreestyleBuild(); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); List ba = ac.getBuildArtifact(); @@ -148,7 +148,7 @@ public void verifyTaskDescriptionIsAccurate() throws ExecutionException, Interru @Test public void verifyTaskNameIsAccurate() throws ExecutionException, InterruptedException, URISyntaxException, IOException, ParseException { FreeStyleBuild build = getFreestyleBuild(); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); List ba = ac.getBuildArtifact(); @@ -165,7 +165,7 @@ public void verifyTotalTaskCountIsAccurate() throws ExecutionException, Interrup FreeStyleBuild build = getFreestyleBuild(); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts.t2/buildArtifact.json","buildArtifact.json",artifactRoot); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); Assert.assertEquals("Total task count is not correct",1,ac.getTotalCount()); } @@ -179,7 +179,7 @@ public void verifyTotalTaskCountIsAccurate2() throws ExecutionException, Interru FreeStyleBuild build = getFreestyleBuild(); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); Assert.assertEquals("Total task count is not correct",3,ac.getTotalCount()); } @@ -193,7 +193,7 @@ public void verifyTotalFailedTaskCountIsAccurate() throws ExecutionException, In FreeStyleBuild build = getFreestyleBuild(); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); Assert.assertEquals("Total task count is not correct",3,ac.getTotalCount()); Assert.assertEquals("Total task failed count is not correct",1,ac.getFailCount()); } @@ -207,7 +207,7 @@ public void verifyTotalSkipTaskCountIsAccurate() throws ExecutionException, Inte FreeStyleBuild build = getFreestyleBuild(); FilePath artifactRoot = new FilePath(build.getRootDir()); copyFileInWorkspace("buildArtifacts/t1/buildArtifact.json","buildArtifact.json",artifactRoot); - BuildArtifactAction ac = new BuildArtifactAction(build,build.getWorkspace()); + BuildArtifactAction ac = new BuildArtifactAction(build); Assert.assertEquals("Total task count is not correct",3,ac.getTotalCount()); Assert.assertEquals("Total task skip count is not correct",1,ac.getSkipCount()); } From 767b0bb8fe1a06cd95768ff9957fc64fd27d3e45 Mon Sep 17 00:00:00 2001 From: sameagen Date: Tue, 11 Jun 2024 15:57:05 -0400 Subject: [PATCH 44/52] Fix MatlabCommandRunner --- .../mathworks/ci/utilities/MatlabCommandRunner.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java index 1f6f233a..921274fd 100644 --- a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -5,7 +5,6 @@ * */ -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -36,16 +35,15 @@ public MatlabCommandRunner(MatlabActionParameters params) throws IOException, In this.params = params; this.additionalEnvVars = new HashMap(); + FilePath workspace = params.getWorkspace(); + // Handle case where workspace doesn't exist - if (!params.getWorkspace().exists()) { - params.getWorkspace().mkdirs(); + if (!workspace.exists()) { + workspace.mkdirs(); } // Create MATLAB folder - FilePath matlabFolder = new FilePath( - params.getLauncher().getChannel(), params.getWorkspace().getRemote() - + File.separator - + ".matlab"); + FilePath matlabFolder = new FilePath(workspace, ".matlab"); matlabFolder.mkdirs(); // Create temp folder From 8e6040d1512989872634255323a9e497ab56e2b5 Mon Sep 17 00:00:00 2001 From: sameagen Date: Tue, 11 Jun 2024 16:31:07 -0400 Subject: [PATCH 45/52] Update unit tests --- .../ci/utilities/MatlabCommandRunnerTest.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java index 742afc81..7dcc695b 100644 --- a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java +++ b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java @@ -40,7 +40,6 @@ @RunWith(MockitoJUnitRunner.class) public class MatlabCommandRunnerTest { - @Mock private FilePath workspace; @Mock private Launcher launcher; @Mock private ProcStarter procStarter; private EnvVars env; @@ -57,14 +56,12 @@ public class MatlabCommandRunnerTest { public void initialize() throws IOException, InterruptedException { env = new EnvVars(); - when(params.getWorkspace()).thenReturn(workspace); + doReturn(new FilePath(tempDir.getRoot())).when(params).getWorkspace(); when(params.getLauncher()).thenReturn(launcher); when(params.getEnvVars()).thenReturn(env); when(params.getTaskListener()).thenReturn(listener); when(params.getStartupOptions()).thenReturn(""); - when(launcher.getChannel()).thenReturn(null); - when(workspace.getRemote()).thenReturn(tempDir.getRoot().getAbsolutePath()); when(listener.getLogger()).thenReturn(logger); doReturn(false).when(launcher).isUnix(); @@ -87,8 +84,7 @@ public void validConstructorDoesNotThrow() throws IOException, InterruptedExcept @Test public void constructorUsesParamsForTempFolder() throws IOException, InterruptedException { MatlabCommandRunner runner = new MatlabCommandRunner(params); - verify(params, times(1)).getLauncher(); - verify(params, times(3)).getWorkspace(); + verify(params, times(1)).getWorkspace(); } @Test @@ -214,7 +210,7 @@ public void runUsesWorkspaceLocationAsWD() throws IOException, InterruptedExcept runner.runMatlabCommand("COMMAND"); - verify(procStarter).pwd(workspace); + verify(procStarter).pwd(new FilePath(tempDir.getRoot())); } @Test From 9663700af5613d776b8aed611963370dbcefef8f Mon Sep 17 00:00:00 2001 From: sameagen Date: Thu, 13 Jun 2024 14:14:41 -0400 Subject: [PATCH 46/52] Update run-matlab-command version, add maca support --- pom.xml | 22 +++++++++-- .../ci/utilities/MatlabCommandRunner.java | 17 ++++++-- .../ci/utilities/MatlabCommandRunnerTest.java | 39 ++++++++++++++++--- 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index 40f11548..2bc6b4dc 100644 --- a/pom.xml +++ b/pom.xml @@ -124,7 +124,7 @@ wget - https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v1/glnxa64/run-matlab-command + https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v2/glnxa64/run-matlab-command false ${basedir}/src/main/resources/glnxa64 true @@ -132,19 +132,33 @@ - get-matlab-runner-mac + get-matlab-runner-maci validate wget - https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v1/maci64/run-matlab-command + https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v2/maci64/run-matlab-command false ${basedir}/src/main/resources/maci64 true true + + get-matlab-runner-maca + validate + + wget + + + https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v2/maca64/run-matlab-command + false + ${basedir}/src/main/resources/maca64 + true + true + + get-matlab-runner-windows validate @@ -152,7 +166,7 @@ wget - https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v1/win64/run-matlab-command.exe + https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v2/win64/run-matlab-command.exe false ${basedir}/src/main/resources/win64 true diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java index 921274fd..fbcafc57 100644 --- a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -68,6 +68,8 @@ public MatlabCommandRunner(MatlabActionParameters params) throws IOException, In */ public void runMatlabCommand(String command) throws IOException, InterruptedException, MatlabExecutionException { + System.err.println("START"); + this.params.getTaskListener().getLogger() .println("\n#################### Starting command output ####################"); @@ -191,15 +193,24 @@ protected FilePath prepareRunnerExecutable() throws IOException, InterruptedExce if (launcher.isUnix()) { // Run uname to check if we're on Linux ByteArrayOutputStream kernelStream = new ByteArrayOutputStream(); + + ArgumentListBuilder args = new ArgumentListBuilder(); + args.add("uname"); + args.add("-s"); + args.add("-m"); + launcher.launch() - .cmds("uname") - .masks(true) + .cmds(args) + .masks(true, true, true) .stdout(kernelStream) .join(); String runnerSource; - if (kernelStream.toString("UTF-8").contains("Linux")) { + String kernelArch = kernelStream.toString("UTF-8"); + if (kernelArch.contains("Linux")) { runnerSource = "glnxa64/run-matlab-command"; + } else if (kernelArch.contains("arm64")) { + runnerSource = "maca64/run-matlab-command"; } else { runnerSource = "maci64/run-matlab-command"; } diff --git a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java index 7dcc695b..780c5812 100644 --- a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java +++ b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java @@ -66,9 +66,9 @@ public void initialize() throws IOException, InterruptedException { doReturn(false).when(launcher).isUnix(); when(launcher.launch()).thenReturn(procStarter); - when(procStarter.cmds(anyString())).thenReturn(procStarter); when(procStarter.cmds(any(ArgumentListBuilder.class))).thenReturn(procStarter); - when(procStarter.masks(anyBoolean())).thenReturn(procStarter); + when(procStarter.masks(anyBoolean(), anyBoolean(), anyBoolean())) + .thenReturn(procStarter); when(procStarter.envs(any(EnvVars.class))).thenReturn(procStarter); doReturn(procStarter).when(procStarter) .stdout(any(OutputStream.class)); @@ -99,7 +99,23 @@ public void correctTempFolderLocation() throws IOException, InterruptedException } @Test - public void prepareRunnerExecutableLinux() throws IOException, InterruptedException { + public void prepareRunnerExecutableMaci() throws IOException, InterruptedException { + runner = new MatlabCommandRunner(params); + + doReturn(true).when(launcher).isUnix(); + + FilePath f = runner.prepareRunnerExecutable(); + + Assert.assertTrue(f.exists()); + Assert.assertEquals( + runner.getTempFolder().getRemote() + + File.separator + + "run-matlab-command", + f.getRemote()); + } + + @Test + public void prepareRunnerExecutableMaca() throws IOException, InterruptedException { runner = new MatlabCommandRunner(params); doReturn(true).when(launcher).isUnix(); @@ -109,7 +125,7 @@ public Object answer(InvocationOnMock invocation) throws IOException { Object[] args = invocation.getArguments(); OutputStream s = (OutputStream)args[0]; - String tag = "Linux"; + String tag = "arm64"; s.write(tag.getBytes()); return procStarter; } @@ -126,10 +142,21 @@ public Object answer(InvocationOnMock invocation) throws IOException { } @Test - public void prepareRunnerExecutableMac() throws IOException, InterruptedException { + public void prepareRunnerExecutableLinux() throws IOException, InterruptedException { runner = new MatlabCommandRunner(params); - doReturn(true).when(launcher).isUnix(); + doReturn(true).when(launcher).isUnix(); + when(procStarter.stdout(any(OutputStream.class))).thenAnswer( + new Answer() { + public Object answer(InvocationOnMock invocation) throws IOException { + Object[] args = invocation.getArguments(); + OutputStream s = (OutputStream)args[0]; + + String tag = "Linux"; + s.write(tag.getBytes()); + return procStarter; + } + }); FilePath f = runner.prepareRunnerExecutable(); From 88bdb17a2017283afff5007221358a85631ab65e Mon Sep 17 00:00:00 2001 From: sameagen Date: Thu, 13 Jun 2024 15:14:50 -0400 Subject: [PATCH 47/52] Add artifact aliases --- .../ci/freestyle/RunMatlabTestsBuilder.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java b/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java index ab599de9..4868d83a 100644 --- a/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java +++ b/src/main/java/com/mathworks/ci/freestyle/RunMatlabTestsBuilder.java @@ -311,6 +311,25 @@ public static void addAliases() { Items.XSTREAM2.addCompatibilityAlias("com.mathworks.ci.RunMatlabTestsBuilder", RunMatlabTestsBuilder.class); Items.XSTREAM2.addCompatibilityAlias("com.mathworks.ci.SourceFolderPaths", SourceFolderPaths.class); Items.XSTREAM2.addCompatibilityAlias("com.mathworks.ci.TestFolders", TestFolders.class); + + Items.XSTREAM2.addCompatibilityAlias( + "com.mathworks.ci.RunMatlabTestsBuilder$PdfArtifact", + RunMatlabTestsBuilder.PdfArtifact.class); + Items.XSTREAM2.addCompatibilityAlias( + "com.mathworks.ci.RunMatlabTestsBuilder$JunitArtifact", + RunMatlabTestsBuilder.JunitArtifact.class); + Items.XSTREAM2.addCompatibilityAlias( + "com.mathworks.ci.RunMatlabTestsBuilder$TapArtifact", + RunMatlabTestsBuilder.TapArtifact.class); + Items.XSTREAM2.addCompatibilityAlias( + "com.mathworks.ci.RunMatlabTestsBuilder$CoberturaArtifact", + RunMatlabTestsBuilder.CoberturaArtifact.class); + Items.XSTREAM2.addCompatibilityAlias( + "com.mathworks.ci.RunMatlabTestsBuilder$StmResultsArtifact", + RunMatlabTestsBuilder.StmResultsArtifact.class); + Items.XSTREAM2.addCompatibilityAlias( + "com.mathworks.ci.RunMatlabTestsBuilder$ModelCovArtifact", + RunMatlabTestsBuilder.ModelCovArtifact.class); } // Overridden Method used to show the text under build dropdown From 36f6ee3e11bf630b41d2114515f582784f24e92a Mon Sep 17 00:00:00 2001 From: sameagen Date: Wed, 26 Jun 2024 15:47:02 -0400 Subject: [PATCH 48/52] Shift from using shutdown hooks to explicit removal --- .../ci/actions/RunMatlabBuildAction.java | 8 ++++++++ .../ci/actions/RunMatlabCommandAction.java | 10 +++++++++- .../ci/actions/RunMatlabTestsAction.java | 10 +++++++++- .../ci/utilities/MatlabCommandRunner.java | 20 ++++++------------- .../ci/utilities/MatlabCommandRunnerTest.java | 16 +++++++++++++++ 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java index 93ccb68d..483497bf 100644 --- a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java @@ -81,6 +81,14 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep throw(e); } finally { annotator.forceEol(); + + try { + this.runner.removeTempFolder(); + } catch (Exception e) { + // Don't want to override more important error + // thrown in catch block + System.err.println(e.toString()); + } } // Handle build result diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabCommandAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabCommandAction.java index 82ec5bf2..3ec0e1c5 100644 --- a/src/main/java/com/mathworks/ci/actions/RunMatlabCommandAction.java +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabCommandAction.java @@ -31,6 +31,14 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep this.params.getTaskListener().getLogger() .println(e.getMessage()); throw(e); - } + } finally { + try { + this.runner.removeTempFolder(); + } catch (Exception e) { + // Don't want to override more important error + // thrown in catch block + System.err.println(e.toString()); + } + } } } diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java index d9228d66..bacf79ad 100644 --- a/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabTestsAction.java @@ -50,7 +50,15 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep .getLogger() .println(e.getMessage()); throw(e); - } + } finally { + try { + this.runner.removeTempFolder(); + } catch (Exception e) { + // Don't want to override more important error + // thrown in catch block + System.err.println(e.toString()); + } + } } private String singleQuotify(String in) { diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java index fbcafc57..fb427cba 100644 --- a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -48,17 +48,6 @@ public MatlabCommandRunner(MatlabActionParameters params) throws IOException, In // Create temp folder this.tempFolder = matlabFolder.createTempDir("tempDir", null); - - // If we hit an error during shutdown while cleaning up - // there's not too much that we can do. - Runtime.getRuntime().addShutdownHook( - new Thread(() -> { - try { - tempFolder.deleteRecursive(); - } catch(Exception e) { - System.err.println(e.toString()); - } - })); } /** @@ -67,9 +56,6 @@ public MatlabCommandRunner(MatlabActionParameters params) throws IOException, In * @param command The command to run */ public void runMatlabCommand(String command) throws IOException, InterruptedException, MatlabExecutionException { - - System.err.println("START"); - this.params.getTaskListener().getLogger() .println("\n#################### Starting command output ####################"); @@ -159,6 +145,12 @@ public FilePath getTempFolder() { return tempFolder; } + public void removeTempFolder() throws IOException, InterruptedException { + if (tempFolder.exists()) { + tempFolder.deleteRecursive(); + } + } + /** * Creates a file with the specified content in the temporary folder. * diff --git a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java index 780c5812..6941820b 100644 --- a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java +++ b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java @@ -98,6 +98,22 @@ public void correctTempFolderLocation() throws IOException, InterruptedException startsWith(expected.getRemote())); } + @Test + public void removeTempFolderDeletesContents() throws IOException, InterruptedException { + runner = new MatlabCommandRunner(params); + + FilePath t = runner.getTempFolder(); + FilePath f = runner.copyFileToTempFolder("testcontent.txt", "target.txt"); + + Assert.assertTrue(t.exists()); + Assert.assertTrue(f.exists()); + + runner.removeTempFolder(); + + Assert.assertFalse(t.exists()); + Assert.assertFalse(f.exists()); + } + @Test public void prepareRunnerExecutableMaci() throws IOException, InterruptedException { runner = new MatlabCommandRunner(params); From ed3d87fa2ab49f025d9a9f5ce70f46bab8845104 Mon Sep 17 00:00:00 2001 From: sameagen Date: Wed, 26 Jun 2024 15:48:26 -0400 Subject: [PATCH 49/52] Add extra test cases --- .../com/mathworks/ci/actions/RunMatlabBuildActionTest.java | 7 +++++++ .../mathworks/ci/actions/RunMatlabCommandActionTest.java | 7 +++++++ .../com/mathworks/ci/actions/RunMatlabTestsActionTest.java | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java index 70c57cc7..1ceb13f9 100644 --- a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java @@ -168,4 +168,11 @@ public void shouldCopyBuildResultsToRootAndAddsAction() throws IOException, Inte // Should have copied file to root dir assertTrue(new File(tmp, "buildArtifact.json").exists()); } + + @Test + public void shouldRemoveTempFolder() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + verify(runner).removeTempFolder(); + } } diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java index 732422d3..c6c41885 100644 --- a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabCommandActionTest.java @@ -66,4 +66,11 @@ public void printsAndRethrowsMessage() throws IOException, InterruptedException, assertEquals(12, e.getExitCode()); }; } + + @Test + public void shouldRemoveTempFolder() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + verify(runner).removeTempFolder(); + } } diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java index 85de29e9..16d984fb 100644 --- a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabTestsActionTest.java @@ -170,4 +170,11 @@ public void printsAndRethrowsMessage() throws IOException, InterruptedException, assertEquals(12, e.getExitCode()); }; } + + @Test + public void shouldRemoveTempFolder() throws IOException, InterruptedException, MatlabExecutionException { + action.run(); + + verify(runner).removeTempFolder(); + } } From 5fb8b970fa4161f6dfe3dcfffb99c6fe3203f9e6 Mon Sep 17 00:00:00 2001 From: sameagen Date: Thu, 27 Jun 2024 17:38:15 -0400 Subject: [PATCH 50/52] Switch to using a temporary directory on the agent external to the workspace. --- .../ci/utilities/MatlabCommandRunner.java | 7 ++++--- .../mathworks/ci/RunMatlabBuildBuilderTest.java | 14 -------------- .../com/mathworks/ci/RunMatlabBuildStepTest.java | 12 ------------ .../mathworks/ci/RunMatlabCommandBuilderTest.java | 14 -------------- .../com/mathworks/ci/RunMatlabCommandStepTest.java | 14 -------------- .../mathworks/ci/RunMatlabTestsBuilderTest.java | 13 ------------- .../com/mathworks/ci/RunMatlabTestsStepTest.java | 12 ------------ .../ci/utilities/MatlabCommandRunnerTest.java | 5 ++++- 8 files changed, 8 insertions(+), 83 deletions(-) diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java index fb427cba..cfbc30a3 100644 --- a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -18,6 +18,7 @@ import hudson.Launcher; import hudson.Launcher.ProcStarter; import hudson.model.Computer; +import hudson.slaves.WorkspaceList; import hudson.util.ArgumentListBuilder; import com.mathworks.ci.Utilities; @@ -43,11 +44,11 @@ public MatlabCommandRunner(MatlabActionParameters params) throws IOException, In } // Create MATLAB folder - FilePath matlabFolder = new FilePath(workspace, ".matlab"); - matlabFolder.mkdirs(); + FilePath tmpRoot = WorkspaceList.tempDir(workspace); + tmpRoot.mkdirs(); // Create temp folder - this.tempFolder = matlabFolder.createTempDir("tempDir", null); + this.tempFolder = tmpRoot.createTempDir("matlab", null); } /** diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java index edb3a9a6..69b6ee44 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildBuilderTest.java @@ -356,18 +356,4 @@ public void verifyMatrixBuildPasses() throws Exception { jenkins.assertLogContains("R2018b completed", build); jenkins.assertBuildStatus(Result.SUCCESS, build); } - - /* - * Test to verify if .matlab temp folder generated in workspace. - */ - @Test - public void verifyMATLABtmpFolderGenerated() throws Exception { - this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); - project.getBuildWrappersList().add(this.buildWrapper); - scriptBuilder.setTasks(""); - project.getBuildersList().add(this.scriptBuilder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - File matlabRunner = new File(build.getWorkspace() + File.separator + ".matlab"); - Assert.assertTrue(matlabRunner.exists()); - } } diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabBuildStepTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildStepTest.java index c1a836e1..8deb0ca0 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabBuildStepTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabBuildStepTest.java @@ -176,16 +176,4 @@ public void verifyExceptionStackTraceForNonZeroExitCode() throws Exception { j.assertBuildStatus(Result.FAILURE, build); j.assertLogContains(String.format(Message.getValue("matlab.execution.exception.prefix"), 1), build); } - - /* - * Verify .matlab folder is generated - */ - @Test - public void verifyMATLABtempFolderGenerated() throws Exception { - project.setDefinition( - new CpsFlowDefinition("node { runMATLABBuild() }", true)); - - WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains(".matlab", build); - } } diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java index 5398935f..75c6e8f1 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandBuilderTest.java @@ -377,18 +377,4 @@ public void verifyMultispecialChar() throws Exception { jenkins.assertLogContains("Generating MATLAB script with content", build); jenkins.assertLogContains(expectedCommand, build); } - - /* - * Test to verify if .matlab temp folder generated in workspace. - */ - @Test - public void verifyMATLABtmpFolderGenerated() throws Exception { - this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); - project.getBuildWrappersList().add(this.buildWrapper); - scriptBuilder.setMatlabCommand("pwd"); - project.getBuildersList().add(this.scriptBuilder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - File matlabRunner = new File(build.getWorkspace() + File.separator + ".matlab"); - Assert.assertTrue(matlabRunner.exists()); - } } diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabCommandStepTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandStepTest.java index 7cce2833..a42f419d 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabCommandStepTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabCommandStepTest.java @@ -149,18 +149,4 @@ public void verifyExceptionForNonZeroExitCode() throws Exception { j.assertLogContains(String.format(Message.getValue("matlab.execution.exception.prefix"), 1), build); j.assertBuildStatusSuccess(build); } - - /* - * Verify .matlab folder is generated - * - */ - - @Test - public void verifyMATLABtempFolderGenerated() throws Exception { - project.setDefinition( - new CpsFlowDefinition("node { runMATLABCommand(command: 'pwd')}", true)); - - WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains(".matlab", build); - } } diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTest.java index db28c64f..97b5fc73 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsBuilderTest.java @@ -484,19 +484,6 @@ public void verifyMATLABscratchFileGenerated() throws Exception { Assert.assertFalse(matlabRunner.exists()); } - /* - * Test to verify if .matlab gets created in workspace. - */ - @Test - public void verifyMATLABfolderGenerated() throws Exception { - this.buildWrapper.setMatlabBuildWrapperContent(new MatlabBuildWrapperContent(Message.getValue("matlab.custom.location"), getMatlabroot("R2018b"))); - project.getBuildWrappersList().add(this.buildWrapper); - project.getBuildersList().add(testBuilder); - FreeStyleBuild build = project.scheduleBuild2(0).get(); - File matlabRunner = new File(build.getWorkspace() + File.separator + ".matlab"); - Assert.assertTrue(matlabRunner.exists()); - } - /* * Test to verify Use Parallel check box present. */ diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java index 7d55873b..0c49d86f 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java @@ -156,18 +156,6 @@ public void verifyExceptionForNonZeroExitCode() throws Exception { j.assertLogContains(String.format(Message.getValue("matlab.execution.exception.prefix"), 1), build); } - /* - * Verify .matlab folder created - */ - - @Test - public void verifyMATLABtempFolderGenerated() throws Exception { - project.setDefinition(new CpsFlowDefinition( - "node {runMATLABTests(testResultsPDF:'myresult/result.pdf')}", true)); - WorkflowRun build = project.scheduleBuild2(0).get(); - j.assertLogContains(".matlab", build); - } - /*@Integ Test * Verify default command options for test Filter using selectByFolder option */ diff --git a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java index 6941820b..4c0087b2 100644 --- a/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java +++ b/src/test/java/unit/com/mathworks/ci/utilities/MatlabCommandRunnerTest.java @@ -16,6 +16,7 @@ import hudson.Launcher; import hudson.Launcher.ProcStarter; import hudson.model.TaskListener; +import hudson.slaves.WorkspaceList; import hudson.util.ArgumentListBuilder; import org.junit.Test; @@ -91,8 +92,10 @@ public void constructorUsesParamsForTempFolder() throws IOException, Interrupted public void correctTempFolderLocation() throws IOException, InterruptedException { runner = new MatlabCommandRunner(params); FilePath tmp = runner.getTempFolder(); - FilePath expected = new FilePath(new File(tempDir.getRoot(), ".matlab")); + + FilePath expected = WorkspaceList.tempDir(new FilePath(tempDir.getRoot())); + Assert.assertTrue(tmp.exists()); Assert.assertThat( tmp.getRemote(), startsWith(expected.getRemote())); From af091014c558210b12035a24b1d4b7b8bba007d1 Mon Sep 17 00:00:00 2001 From: sameagen Date: Mon, 8 Jul 2024 13:05:24 -0400 Subject: [PATCH 51/52] Update build action to use new temp folder for build report --- .../com/mathworks/ci/BuildArtifactAction.java | 2 +- .../ci/actions/RunMatlabBuildAction.java | 32 ++++++++++--------- .../+ciplugins/+jenkins/BuildReportPlugin.m | 5 ++- .../ci/actions/RunMatlabBuildActionTest.java | 22 ++++++------- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/mathworks/ci/BuildArtifactAction.java b/src/main/java/com/mathworks/ci/BuildArtifactAction.java index 815f6606..801aa2af 100644 --- a/src/main/java/com/mathworks/ci/BuildArtifactAction.java +++ b/src/main/java/com/mathworks/ci/BuildArtifactAction.java @@ -60,7 +60,7 @@ public String getUrlName() { public List getBuildArtifact() throws ParseException, InterruptedException, IOException { List artifactData = new ArrayList(); - FilePath fl = new FilePath(new File(build.getRootDir().getAbsolutePath() + "/" + BUILD_ARTIFACT_FILE)); + FilePath fl = new FilePath(new File(build.getRootDir().getAbsolutePath(), BUILD_ARTIFACT_FILE)); try (InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(fl.toURI())), "UTF-8")) { Object obj = new JSONParser().parse(reader); JSONObject jo = (JSONObject) obj; diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java index 483497bf..422326c8 100644 --- a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java @@ -54,6 +54,9 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep runner.addEnvironmentVariable( "MW_MATLAB_BUILDTOOL_DEFAULT_PLUGINS_FCN_OVERRIDE", "ciplugins.jenkins.getDefaultPlugins"); + runner.addEnvironmentVariable( + "MW_MATLAB_TEMP_FOLDER", + runner.getTempFolder().toString()); // Redirect output to the build annotator runner.redirectStdOut(annotator); @@ -75,6 +78,20 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep try { runner.runMatlabCommand(command); + + // Handle build result + Run build = this.params.getBuild(); + FilePath jsonFile = new FilePath(runner.getTempFolder(), "buildArtifact.json"); + if (jsonFile.exists()) { + FilePath rootLocation = new FilePath( + new File( + build.getRootDir().getAbsolutePath(), + "buildArtifact.json") + ); + jsonFile.copyTo(rootLocation); + jsonFile.delete(); + build.addAction(new BuildArtifactAction(build)); + } } catch (Exception e) { this.params.getTaskListener().getLogger() .println(e.getMessage()); @@ -90,20 +107,5 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep System.err.println(e.toString()); } } - - // Handle build result - Run build = this.params.getBuild(); - FilePath jsonFile = new FilePath(params.getWorkspace(), ".matlab" + File.separator + "buildArtifact.json"); - if (jsonFile.exists()) { - FilePath rootLocation = new FilePath( - new File( - build.getRootDir() - .getAbsolutePath() - + File.separator - + "buildArtifact.json")); - jsonFile.copyTo(rootLocation); - jsonFile.delete(); - build.addAction(new BuildArtifactAction(build)); - } } } diff --git a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m index 8e810e57..a9935e67 100644 --- a/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m +++ b/src/main/resources/+ciplugins/+jenkins/BuildReportPlugin.m @@ -6,8 +6,7 @@ function runTaskGraph(plugin, pluginData) runTaskGraph@matlab.buildtool.plugins.BuildRunnerPlugin(plugin, pluginData); - [fID, msg] = fopen(fullfile(getenv("WORKSPACE"),".matlab/buildArtifact.json"), "w"); - + [fID, msg] = fopen(fullfile(getenv("MW_MATLAB_TEMP_FOLDER"),"buildArtifact.json"), "w"); if fID == -1 warning("ciplugins:jenkins:BuildReportPlugin:UnableToOpenFile","Could not open a file for Jenkins build result table due to: %s", msg); else @@ -26,4 +25,4 @@ function runTaskGraph(plugin, pluginData) end end end -end \ No newline at end of file +end diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java index 1ceb13f9..27826240 100644 --- a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java @@ -54,8 +54,6 @@ public void init() { when(runner.getTempFolder()).thenReturn(tempFolder); when(tempFolder.getRemote()).thenReturn("/path/less/traveled"); - when(params.getWorkspace()).thenReturn(tempFolder); - when(params.getTaskListener()).thenReturn(listener); when(listener.getLogger()).thenReturn(out); @@ -137,22 +135,22 @@ public void shouldPrintAndRethrowMessage() throws IOException, InterruptedExcept public void shouldNotAddActionIfNoBuildResult() throws IOException, InterruptedException, MatlabExecutionException { action.run(); - verify(build, never()).addAction(any(BuildArtifactAction.class)); + verify(build, never()).addAction(any(BuildArtifactAction.class)); } @Test - public void shouldCopyBuildResultsToRootAndAddsAction() throws IOException, InterruptedException, MatlabExecutionException { + public void shouldCopyBuildResultsToRootAndAddAction() throws IOException, InterruptedException, MatlabExecutionException { File tmp = Files.createTempDirectory("temp").toFile(); tmp.deleteOnExit(); + + File dest = Files.createTempDirectory("dest").toFile(); + dest.deleteOnExit(); - File matlab = new File(tmp, ".matlab"); - File json = new File(matlab, "buildArtifact.json"); - - matlab.mkdirs(); + File json = new File(tmp, "buildArtifact.json"); json.createNewFile(); - - doReturn(new FilePath(tmp)).when(params).getWorkspace(); - doReturn(tmp).when(build).getRootDir(); + + doReturn(new FilePath(tmp)).when(runner).getTempFolder(); + doReturn(dest).when(build).getRootDir(); boolean runTimeException = false; try { @@ -166,7 +164,7 @@ public void shouldCopyBuildResultsToRootAndAddsAction() throws IOException, Inte // Should have deleted original file assertFalse(json.exists()); // Should have copied file to root dir - assertTrue(new File(tmp, "buildArtifact.json").exists()); + assertTrue(new File(dest, "buildArtifact.json").exists()); } @Test From ffdc30b5766f22824f45c79a73e05b9be8e9e085 Mon Sep 17 00:00:00 2001 From: sameagen Date: Mon, 8 Jul 2024 14:13:48 -0400 Subject: [PATCH 52/52] Publish build results even if MATLAB exited with nonzero exit code --- .../ci/actions/RunMatlabBuildAction.java | 34 +++++++++++-------- .../ci/actions/RunMatlabBuildActionTest.java | 9 +---- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java index 422326c8..822be96e 100644 --- a/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java +++ b/src/main/java/com/mathworks/ci/actions/RunMatlabBuildAction.java @@ -78,20 +78,6 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep try { runner.runMatlabCommand(command); - - // Handle build result - Run build = this.params.getBuild(); - FilePath jsonFile = new FilePath(runner.getTempFolder(), "buildArtifact.json"); - if (jsonFile.exists()) { - FilePath rootLocation = new FilePath( - new File( - build.getRootDir().getAbsolutePath(), - "buildArtifact.json") - ); - jsonFile.copyTo(rootLocation); - jsonFile.delete(); - build.addAction(new BuildArtifactAction(build)); - } } catch (Exception e) { this.params.getTaskListener().getLogger() .println(e.getMessage()); @@ -100,11 +86,29 @@ public void run() throws IOException, InterruptedException, MatlabExecutionExcep annotator.forceEol(); try { - this.runner.removeTempFolder(); + // Handle build result + Run build = this.params.getBuild(); + FilePath jsonFile = new FilePath(runner.getTempFolder(), "buildArtifact.json"); + if (jsonFile.exists()) { + FilePath rootLocation = new FilePath( + new File( + build.getRootDir().getAbsolutePath(), + "buildArtifact.json") + ); + jsonFile.copyTo(rootLocation); + jsonFile.delete(); + build.addAction(new BuildArtifactAction(build)); + } } catch (Exception e) { // Don't want to override more important error // thrown in catch block System.err.println(e.toString()); + } finally { + try { + this.runner.removeTempFolder(); + } catch (Exception e) { + System.err.println(e.toString()); + } } } } diff --git a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java index 27826240..5455a94c 100644 --- a/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java +++ b/src/test/java/unit/com/mathworks/ci/actions/RunMatlabBuildActionTest.java @@ -152,15 +152,8 @@ public void shouldCopyBuildResultsToRootAndAddAction() throws IOException, Inter doReturn(new FilePath(tmp)).when(runner).getTempFolder(); doReturn(dest).when(build).getRootDir(); - boolean runTimeException = false; - try { - action.run(); - } catch (RuntimeException e) { - runTimeException = true; - } + action.run(); - // Should throw for invalid file - assertTrue(runTimeException); // Should have deleted original file assertFalse(json.exists()); // Should have copied file to root dir