diff --git a/pom.xml b/pom.xml index 4c7117bd..397eb8ab 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 org.jenkins-ci.plugins @@ -9,7 +11,7 @@ matlab - 2.15.1-SNAPSHOT + 2.16.0-SNAPSHOT hpi MATLAB Plugin @@ -56,8 +58,6 @@ 2.387 ${jenkins.baseline}.3 - - High @@ -132,8 +132,7 @@ org.jenkins-ci.tools maven-hpi-plugin - + com.googlecode.maven-download-plugin download-maven-plugin @@ -146,7 +145,8 @@ wget - https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v2/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 @@ -160,7 +160,8 @@ wget - https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v2/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 @@ -174,7 +175,8 @@ wget - https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v2/maca64/run-matlab-command + + https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v2/maca64/run-matlab-command false ${basedir}/src/main/resources/maca64 true @@ -188,7 +190,8 @@ wget - https://ssd.mathworks.com/supportfiles/ci/run-matlab-command/v2/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 @@ -202,7 +205,8 @@ wget - https://ssd.mathworks.com/supportfiles/ci/matlab-script-generator/v0/matlab-script-generator.zip + + https://ssd.mathworks.com/supportfiles/ci/matlab-script-generator/v0/matlab-script-generator.zip false ${basedir}/src/main/resources true @@ -214,8 +218,8 @@ - + org.eclipse.m2e lifecycle-mapping diff --git a/src/main/java/com/mathworks/ci/BuildTargetNote.java b/src/main/java/com/mathworks/ci/BuildTargetNote.java index cf3062c9..2b8752cb 100644 --- a/src/main/java/com/mathworks/ci/BuildTargetNote.java +++ b/src/main/java/com/mathworks/ci/BuildTargetNote.java @@ -5,7 +5,6 @@ */ import com.google.common.annotations.VisibleForTesting; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.MarkupText; import hudson.console.ConsoleAnnotationDescriptor; @@ -15,7 +14,6 @@ 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() { diff --git a/src/main/java/com/mathworks/ci/MatlabInstallation.java b/src/main/java/com/mathworks/ci/MatlabInstallation.java index 5cace624..006a7eac 100644 --- a/src/main/java/com/mathworks/ci/MatlabInstallation.java +++ b/src/main/java/com/mathworks/ci/MatlabInstallation.java @@ -6,7 +6,6 @@ * Describable class for adding MATLAB installations in Jenkins Global Tool configuration. */ -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.CopyOnWrite; import hudson.EnvVars; import hudson.Extension; @@ -15,15 +14,12 @@ import hudson.model.EnvironmentSpecific; import hudson.model.Node; import hudson.model.TaskListener; -import hudson.remoting.VirtualChannel; import hudson.slaves.NodeSpecific; import hudson.tools.ToolDescriptor; import hudson.tools.ToolInstallation; import hudson.tools.ToolProperty; import java.io.File; import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import javax.annotation.CheckForNull; @@ -62,22 +58,13 @@ public MatlabInstallation forNode(@Nonnull Node node, TaskListener log) throws I return new MatlabInstallation(getName(), translateFor(node, log), getProperties().toList()); } - @SuppressFBWarnings(value = { - "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" }, justification = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE: Its false positive scenario for sport bug which is fixed in later versions " - + "https://github.com/spotbugs/spotbugs/issues/1843") @Override public void buildEnvVars(EnvVars env) { - String pathToExecutable = getHome() + "/bin"; - env.put("PATH+matlabroot", pathToExecutable); - Jenkins jenkinsInstance = Jenkins.getInstanceOrNull(); - if (jenkinsInstance != null) { - if (jenkinsInstance.getChannel() != null) { - FilePath batchExecutablePath = new FilePath(jenkinsInstance.getChannel(), getHome()); - if (batchExecutablePath.getParent() != null) { - env.put("PATH+matlab_batch", batchExecutablePath.getParent().getRemote()); - } - } + String home = getHome(); + if (home == null) { + return; } + env.put("PATH+matlabroot", home + "/bin"); } public static MatlabInstallation[] getAll() { diff --git a/src/main/java/com/mathworks/ci/MatlabReleaseInfo.java b/src/main/java/com/mathworks/ci/MatlabReleaseInfo.java index 0636ce66..92d8da6f 100644 --- a/src/main/java/com/mathworks/ci/MatlabReleaseInfo.java +++ b/src/main/java/com/mathworks/ci/MatlabReleaseInfo.java @@ -9,7 +9,9 @@ import java.io.InputStream; import java.io.InputStreamReader; +import java.io.IOException; import java.io.BufferedReader; +import java.lang.InterruptedException; import java.nio.charset.StandardCharsets; import java.nio.file.NotDirectoryException; import java.util.HashMap; @@ -25,7 +27,7 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.xml.sax.SAXException; import hudson.FilePath; public class MatlabReleaseInfo { @@ -74,11 +76,6 @@ public boolean verLessThan(double version) throws MatlabVersionNotFoundException } } - @SuppressFBWarnings(value = { "REC_CATCH_EXCEPTION", - "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE" }, justification = "REC_CATCH_EXCEPTION: Irrespective of exception type, intention is to handle it in same way." - + - " Also, there is no intention to propagate any runtime exception up in the hierarchy." + - "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE: This is a false positive reported by spotbugs for JDK 11 for try-with-resources block.") private Map getVersionInfoFromFile() throws MatlabVersionNotFoundException { if (MapUtils.isEmpty(versionInfoCache)) { try { @@ -139,7 +136,7 @@ private Map getVersionInfoFromFile() throws MatlabVersionNotFoun // Update the versionInfoCache with actual version extracted from Contents.m versionInfoCache.put(VERSION_TAG, actualVersion); } - } catch (Exception e) { + } catch (InterruptedException | IOException | ParserConfigurationException | SAXException e) { throw new MatlabVersionNotFoundException( Message.getValue("Releaseinfo.matlab.version.not.found.error"), e); } diff --git a/src/main/java/com/mathworks/ci/MatlabVersionNotFoundException.java b/src/main/java/com/mathworks/ci/MatlabVersionNotFoundException.java index fe790f69..a43298e6 100644 --- a/src/main/java/com/mathworks/ci/MatlabVersionNotFoundException.java +++ b/src/main/java/com/mathworks/ci/MatlabVersionNotFoundException.java @@ -11,4 +11,8 @@ public class MatlabVersionNotFoundException extends Exception { MatlabVersionNotFoundException(String errorMessage, Throwable err) { super(errorMessage, err); } + + MatlabVersionNotFoundException(String errorMessage) { + super(errorMessage); + } } diff --git a/src/main/java/com/mathworks/ci/UseMatlabVersionBuildWrapper.java b/src/main/java/com/mathworks/ci/UseMatlabVersionBuildWrapper.java index 12178b3c..553046c9 100644 --- a/src/main/java/com/mathworks/ci/UseMatlabVersionBuildWrapper.java +++ b/src/main/java/com/mathworks/ci/UseMatlabVersionBuildWrapper.java @@ -197,39 +197,23 @@ public void setUp(Context context, Run build, FilePath workspace, Launcher if (!matlabExecutablePath.exists()) { throw new MatlabNotFoundError(Message.getValue("matlab.not.found.error")); } - // Add matlab-batch executable in path - FilePath batchExecutable = getNthParentFilePath(matlabExecutablePath, 3); - if (batchExecutable != null && batchExecutable.exists()) { - context.env("PATH+matlab_batch", batchExecutable.getRemote()); + FilePath matlabBinDir = matlabExecutablePath.getParent(); + if (matlabBinDir == null) { + throw new MatlabNotFoundError(Message.getValue("matlab.not.found.error")); } // Add "matlabroot" without bin as env variable which will be available across // the build. context.env("matlabroot", nodeSpecificMatlab); // Add matlab bin to path to invoke MATLAB directly on command line. - context.env("PATH+matlabroot", matlabExecutablePath.getParent().getRemote()); + context.env("PATH+matlabroot", matlabBinDir.getRemote()); ; listener.getLogger().println("\n" + String.format(Message.getValue("matlab.added.to.path.from"), - matlabExecutablePath.getParent().getRemote()) + "\n"); + matlabBinDir.getRemote()) + "\n"); } private String getNodeSpecificExecutable(Launcher launcher) { return (launcher.isUnix()) ? "/bin/matlab" : "\\bin\\matlab.exe"; } - public static FilePath getNthParentFilePath(FilePath path, int levels) { - if (path == null || levels < 0) { - return null; - } - - FilePath currentPath = path; - for (int i = 0; i < levels; i++) { - if (currentPath == null) { - return null; - } - currentPath = currentPath.getParent(); - } - return currentPath; - } - } diff --git a/src/main/java/com/mathworks/ci/Utilities.java b/src/main/java/com/mathworks/ci/Utilities.java index 999649f0..dec4012c 100644 --- a/src/main/java/com/mathworks/ci/Utilities.java +++ b/src/main/java/com/mathworks/ci/Utilities.java @@ -40,20 +40,14 @@ public static void addMatlabToEnvPathFromAxis(Computer cmp, TaskListener listene return; } - FilePath matlabRoot = getNodeSpecificHome(name, - cmp.getNode(), listener, env); + FilePath matlabRoot = getNodeSpecificHome(name, cmp.getNode(), listener, env); - if (matlabRoot != null && matlabRoot.getParent().exists()) { - env.put("PATH+matlab_batch", matlabRoot.getParent().getRemote()); - } - - String matlabExecutablePath = getNodeSpecificHome(name, - cmp.getNode(), listener, env).getRemote() + ((Boolean.TRUE.equals(cmp.isUnix())) ? "/bin" : "\\bin"); - env.put("PATH+matlabroot", matlabExecutablePath); + FilePath matlabBin = new FilePath(matlabRoot, "bin"); + env.put("PATH+matlabroot", matlabBin.getRemote()); // Specify which MATLAB was added to path. listener.getLogger().println( - "\n" + String.format(Message.getValue("matlab.added.to.path.from"), matlabExecutablePath) + "\n"); + "\n" + String.format(Message.getValue("matlab.added.to.path.from"), matlabBin.getRemote()) + "\n"); } public static FilePath getNodeSpecificHome(String instName, Node node, TaskListener listener, EnvVars env) diff --git a/src/main/java/com/mathworks/ci/tools/MatlabInstaller.java b/src/main/java/com/mathworks/ci/tools/MatlabInstaller.java index 0a9e8bee..f4fc2bb3 100644 --- a/src/main/java/com/mathworks/ci/tools/MatlabInstaller.java +++ b/src/main/java/com/mathworks/ci/tools/MatlabInstaller.java @@ -8,8 +8,6 @@ import com.mathworks.ci.Message; import com.mathworks.ci.utilities.GetSystemProperties; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - import hudson.Extension; import hudson.FilePath; import hudson.Launcher; @@ -17,13 +15,14 @@ import hudson.model.Node; import hudson.model.TaskListener; +import hudson.remoting.VirtualChannel; import hudson.tools.ToolInstaller; import hudson.tools.ToolInstallation; import hudson.tools.ToolInstallerDescriptor; - import hudson.util.ArgumentListBuilder; import hudson.util.FormValidation; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; @@ -70,48 +69,73 @@ public void setProducts(String products) { @Override public FilePath performInstallation(ToolInstallation tool, Node node, TaskListener log) throws IOException, InterruptedException { - FilePath destination = preferredLocation(tool, node); + FilePath toolRoot = preferredLocation(tool, node); + makeDir(toolRoot); + + String extension = ""; String[] systemProperties = getSystemProperties(node); - FilePath matlabRootPath; + FilePath matlabRoot; if (systemProperties[0].toLowerCase().contains("os x")) { - matlabRootPath = new FilePath(destination, this.getRelease() + ".app"); + matlabRoot = new FilePath(toolRoot, this.getRelease() + ".app"); } else { - matlabRootPath = new FilePath(destination, this.getRelease()); + matlabRoot = new FilePath(toolRoot, this.getRelease()); } String platform = getPlatform(systemProperties[0], systemProperties[1]); - getFreshCopyOfExecutables(platform, destination); - - makeDir(matlabRootPath); - int result = installUsingMpm(node, this.getRelease(), matlabRootPath, this.getProducts(), log); - if (result == 0) { - log.getLogger().println( - "MATLAB installation of version " + this.getRelease() - + " using mpm completed successfully!"); + if (platform == "win64") { + extension = ".exe"; } - return matlabRootPath; + + // Create temp directory + FilePath tempDir = toolRoot.createTempDir("", ""); + + // Download mpm and matlab-batch to temp directory + FilePath mpm = fetchMpm(platform, tempDir); + FilePath matlabBatch = fetchMatlabBatch(platform, tempDir); + + // Install with mpm + mpmInstall(mpm, this.getRelease(), this.getProducts(), matlabRoot, node, log); + + // Copy downloaded matlab-batch to tool directory + FilePath matlabBin = new FilePath(matlabRoot, "bin"); + matlabBatch.copyTo(new FilePath(matlabBin, "matlab-batch" + extension)); + + // Delete temp directory + tempDir.deleteRecursive(); + + return matlabRoot; } - private int installUsingMpm(Node node, String release, FilePath destination, String products, TaskListener log) + private void mpmInstall(FilePath mpmPath, String release, String products, FilePath destination, Node node, + TaskListener log) throws IOException, InterruptedException { - + makeDir(destination); Launcher matlabInstaller = node.createLauncher(log); ProcStarter installerProc = matlabInstaller.launch(); ArgumentListBuilder args = new ArgumentListBuilder(); - args.add(destination.getParent().getRemote() + getNodeSpecificMPMExecutor(node)); + args.add(mpmPath.getRemote()); args.add("install"); appendReleaseToArguments(release, args, log); args.add("--destination=" + destination.getRemote()); addMatlabProductsToArgs(args, products); - installerProc.pwd(destination).cmds(args).stdout(log); + + ByteArrayOutputStream err = new ByteArrayOutputStream(); + installerProc.pwd(destination).cmds(args).stdout(log).stderr(err); + int result; try { result = installerProc.join(); } catch (Exception e) { - log.getLogger().println("MATLAB installation failed " + e.getMessage()); throw new InstallationFailedException(e.getMessage()); } - return result; + if (result != 0) { + String errString = err.toString(StandardCharsets.UTF_8); + if (errString.contains("already installed")) { + log.getLogger().println(errString); + } else { + throw new InstallationFailedException(errString); + } + } } private void makeDir(FilePath path) throws IOException, InterruptedException { @@ -146,60 +170,66 @@ private void appendReleaseToArguments(String release, ArgumentListBuilder args, args.add("--release=" + actualRelease); } - private void getFreshCopyOfExecutables(String platform, FilePath expectedPath) + private FilePath fetchMpm(String platform, FilePath destination) throws IOException, InterruptedException { - FilePath matlabBatchPath = new FilePath(expectedPath, "matlab-batch"); - FilePath mpmPath = new FilePath(expectedPath, "mpm"); - URL mpmUrl; - URL matlabBatchUrl; + String extension = ""; switch (platform) { case "glnxa64": mpmUrl = new URL(Message.getValue("tools.matlab.mpm.installer.linux")); - matlabBatchUrl = new URL(Message.getValue("tools.matlab.batch.executable.linux")); break; case "maci64": mpmUrl = new URL(Message.getValue("tools.matlab.mpm.installer.maci64")); - matlabBatchUrl = new URL(Message.getValue("tools.matlab.batch.executable.maci64")); break; case "maca64": mpmUrl = new URL(Message.getValue("tools.matlab.mpm.installer.maca64")); - matlabBatchUrl = new URL(Message.getValue("tools.matlab.batch.executable.maca64")); break; default: throw new InstallationFailedException("Unsupported OS"); } - // Handle the concurrency issues due to same name. - FilePath tempMatlabBatchPath = new FilePath(expectedPath, "temp-matlab-batch"); - FilePath tempMpmPath = new FilePath(expectedPath, "temp-mpm"); + // Download mpm + FilePath mpmPath = new FilePath(destination, "mpm" + extension); try { - tempMpmPath.copyFrom(mpmUrl.openStream()); - tempMpmPath.chmod(0777); - tempMatlabBatchPath.copyFrom(matlabBatchUrl.openStream()); - tempMatlabBatchPath.chmod(0777); - - tempMpmPath.renameTo(mpmPath); - tempMatlabBatchPath.renameTo(matlabBatchPath); - + mpmPath.copyFrom(mpmUrl.openStream()); + mpmPath.chmod(0777); } catch (IOException | InterruptedException e) { - e.printStackTrace(); - } finally { - // Clean up temporary files if they exist - tempMatlabBatchPath.delete(); - tempMpmPath.delete(); + throw new InstallationFailedException("Unable to setup mpm."); } + + return mpmPath; } - @SuppressFBWarnings(value = { - "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" }, justification = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE: Its false positive scenario for sport bug which is fixed in later versions " - + "https://github.com/spotbugs/spotbugs/issues/1843") - private String getNodeSpecificMPMExecutor(Node node) { - if (!node.toComputer().isUnix()) { - return "\\mpm.exe"; + private FilePath fetchMatlabBatch(String platform, FilePath destination) + throws IOException, InterruptedException { + URL matlabBatchUrl; + String extension = ""; + + switch (platform) { + case "glnxa64": + matlabBatchUrl = new URL(Message.getValue("tools.matlab.batch.executable.linux")); + break; + case "maci64": + matlabBatchUrl = new URL(Message.getValue("tools.matlab.batch.executable.maci64")); + break; + case "maca64": + matlabBatchUrl = new URL(Message.getValue("tools.matlab.batch.executable.maca64")); + break; + default: + throw new InstallationFailedException("Unsupported OS"); } - return "/mpm"; + + // Download matlab-batch + FilePath matlabBatchPath = new FilePath(destination, "matlab-batch" + extension); + try { + matlabBatchPath.copyFrom(matlabBatchUrl.openStream()); + matlabBatchPath.chmod(0777); + } catch (IOException | InterruptedException e) { + throw new InstallationFailedException("Unable to setup matlab-batch."); + } + + return matlabBatchPath; } private void addMatlabProductsToArgs(ArgumentListBuilder args, String products) @@ -207,7 +237,6 @@ private void addMatlabProductsToArgs(ArgumentListBuilder args, String products) args.add("--products"); if (products.isEmpty()) { args.add(DEFAULT_PRODUCT); - } else { if (!products.contains(DEFAULT_PRODUCT)) { args.add(DEFAULT_PRODUCT); @@ -235,11 +264,12 @@ public String getPlatform(String os, String architecture) throws InstallationFai } } - @SuppressFBWarnings(value = { - "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" }, justification = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE: Its false positive scenario for sport bug which is fixed in later versions " - + "https://github.com/spotbugs/spotbugs/issues/1843") private String[] getSystemProperties(Node node) throws IOException, InterruptedException { - String[] properties = node.getChannel() + VirtualChannel channel = node.getChannel(); + if (channel == null) { + throw new InstallationFailedException("Unable to connect to Node"); + } + String[] properties = channel .call(new GetSystemProperties("os.name", "os.arch", "os.version")); return properties; } diff --git a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java index b756df39..9b8f8ba9 100644 --- a/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java +++ b/src/main/java/com/mathworks/ci/utilities/MatlabCommandRunner.java @@ -43,6 +43,9 @@ public MatlabCommandRunner(MatlabActionParameters params) throws IOException, In // Create MATLAB folder FilePath tmpRoot = WorkspaceList.tempDir(workspace); + if (tmpRoot == null) { + throw new IOException("Unable to create temporary directory in workspace."); + } tmpRoot.mkdirs(); // Create temp folder diff --git a/src/main/resources/com/mathworks/ci/MatlabInstallation/help-home.html b/src/main/resources/com/mathworks/ci/MatlabInstallation/help-home.html new file mode 100644 index 00000000..73111f9a --- /dev/null +++ b/src/main/resources/com/mathworks/ci/MatlabInstallation/help-home.html @@ -0,0 +1,7 @@ +
+ Enter the full path to the MATLAB root folder, which is returned by the matlabroot function.

Example:

Windows:
C:\Program Files\MATLAB\R2019a
+ Linux:
/usr/local/MATLAB/R2019a
+ Mac:
/Applications/MATLAB_R2019a.app
+

+ Note: If the job runs on a remote agent, you must specify the full path to MATLAB root folder on the remote agent.

+
\ No newline at end of file diff --git a/src/main/resources/com/mathworks/ci/tools/MatlabInstaller/help-release.html b/src/main/resources/com/mathworks/ci/tools/MatlabInstaller/help-release.html index 804233bf..e87d0382 100644 --- a/src/main/resources/com/mathworks/ci/tools/MatlabInstaller/help-release.html +++ b/src/main/resources/com/mathworks/ci/tools/MatlabInstaller/help-release.html @@ -14,9 +14,4 @@ Example: latest
Example: R2023bU4

-

- Note: The plugin does not install dependencies on a Linux platform. If you are using a Linux platform, - verify that the required software is available before installing products using MATLAB Package Manager. For more information, see - Get MATLAB Package Manager. -

- \ No newline at end of file + diff --git a/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java index be30c713..8e8595ca 100644 --- a/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java +++ b/src/test/java/integ/com/mathworks/ci/RunMatlabTestsStepTest.java @@ -128,7 +128,8 @@ public void verifyArtifactParameters() throws Exception { } /* - * Verify runMatlabTests runs with empty parameters when nothing no artifact selected + * Verify runMatlabTests runs with empty parameters when nothing no artifact + * selected */ @Test