├── .github ├── CODEOWNERS ├── dependabot.yml ├── release-drafter.yml └── workflows │ └── jenkins-security-scan.yml ├── .gitignore ├── .mvn ├── extensions.xml └── maven.config ├── Jenkinsfile ├── README.md ├── checkstyle.xml ├── docs └── images │ ├── nodejs_buildstep_menu.png │ ├── nodejs_buildstep_script.png │ ├── nodejs_choose_configfile.png │ ├── nodejs_npm_configfile.png │ ├── nodejs_npm_to_path.png │ └── nodejs_tools_configuration.png ├── license.header ├── pom.xml └── src ├── main ├── java │ └── jenkins │ │ └── plugins │ │ └── nodejs │ │ ├── NodeJSBuildWrapper.java │ │ ├── NodeJSCommandInterpreter.java │ │ ├── NodeJSConstants.java │ │ ├── NodeJSDescriptorUtils.java │ │ ├── NodeJSPlugin.java │ │ ├── NodeJSUtils.java │ │ ├── cache │ │ ├── CacheLocationLocator.java │ │ ├── CacheLocationLocatorDescriptor.java │ │ ├── DefaultCacheLocationLocator.java │ │ ├── PerExecutorCacheLocationLocator.java │ │ └── PerJobCacheLocationLocator.java │ │ ├── configfiles │ │ ├── NPMConfig.java │ │ ├── NPMRegistry.java │ │ ├── Npmrc.java │ │ ├── RegistryHelper.java │ │ └── VerifyConfigProviderException.java │ │ ├── package.html │ │ └── tools │ │ ├── CPU.java │ │ ├── DetectionFailedException.java │ │ ├── InstallableComparator.java │ │ ├── InstallerPathResolver.java │ │ ├── MirrorNodeJSInstaller.java │ │ ├── NodeJSInstallation.java │ │ ├── NodeJSInstaller.java │ │ ├── NodeJSVersion.java │ │ ├── NodeJSVersionRange.java │ │ ├── Platform.java │ │ ├── ToolsUtils.java │ │ └── pathresolvers │ │ └── LatestInstallerPathResolver.java ├── resources │ ├── index.jelly │ └── jenkins │ │ └── plugins │ │ └── nodejs │ │ ├── Messages.properties │ │ ├── Messages_fr.properties │ │ ├── Messages_it.properties │ │ ├── NodeJSBuildWrapper │ │ ├── config.jelly │ │ ├── config.properties │ │ └── config_it.properties │ │ ├── NodeJSCommandInterpreter │ │ ├── config.jelly │ │ ├── config.properties │ │ └── config_it.properties │ │ ├── configfiles │ │ ├── NPMConfig │ │ │ ├── NPMConfigProvider │ │ │ │ ├── newInstanceDetail.jelly │ │ │ │ └── newInstanceDetail.properties │ │ │ ├── edit-config.jelly │ │ │ ├── edit-config.properties │ │ │ ├── show-config.jelly │ │ │ └── show-config.properties │ │ ├── NPMRegistry │ │ │ ├── config.jelly │ │ │ ├── config.properties │ │ │ ├── help-credentialsId.html │ │ │ ├── help-scopes.html │ │ │ ├── help-url.html │ │ │ ├── show.jelly │ │ │ └── show.properties │ │ └── template.npmrc │ │ └── tools │ │ ├── MirrorNodeJSInstaller │ │ ├── config.jelly │ │ ├── config.properties │ │ ├── help-credentialsId.html │ │ └── help-mirrorURL.html │ │ └── NodeJSInstaller │ │ ├── config.jelly │ │ ├── config.properties │ │ └── global_it.properties └── webapp │ └── help.html └── test ├── java └── jenkins │ └── plugins │ └── nodejs │ ├── CIBuilderHelper.java │ ├── CredentialMaskingTest.java │ ├── JCasCTest.java │ ├── NodeJSBuildWrapperTest.java │ ├── NodeJSCommandInterpreterTest.java │ ├── NodeJSSerialisationTest.java │ ├── NpmrcFileSupplyTest.java │ ├── SimpleNodeJSCommandInterpreterTest.java │ ├── TestCacheLocationLocator.java │ ├── VerifyEnvVariableBuilder.java │ ├── cache │ └── CacheLocationLocatorTest.java │ ├── configfiles │ ├── NPMConfigTest.java │ ├── NPMConfigValidationTest.java │ ├── NPMRegistryValidator2Test.java │ ├── NPMRegistryValidatorTest.java │ ├── NpmrcTest.java │ ├── RegistryHelperCredentialsTest.java │ └── RegistryHelperTest.java │ └── tools │ ├── CPUTest.java │ ├── InstallerPathResolversTest.java │ ├── MirrorNodeJSInstallerTest.java │ ├── NodeJSInstallationMockitoTest.java │ ├── NodeJSInstallationTest.java │ ├── NodeJSInstallerProxyTest.java │ ├── NodeJSInstallerTest.java │ └── ToolsUtilsTest.java └── resources ├── jenkins └── plugins │ └── nodejs │ ├── NodeJSSerialisationTest │ ├── test_reloading_job_configuration_contains_saved_cache_strategy_buildWrapper │ │ └── jobs │ │ │ └── test │ │ │ └── config.xml │ ├── test_reloading_job_configuration_contains_saved_cache_strategy_interpreter │ │ └── jobs │ │ │ └── test │ │ │ └── config.xml │ ├── test_serialisation_is_compatible_with_version_1_2_x_buildWrapper │ │ └── jobs │ │ │ └── test │ │ │ └── config.xml │ └── test_serialisation_is_compatible_with_version_1_2_x_interpreter │ │ └── jobs │ │ └── test │ │ └── config.xml │ ├── configfiles │ └── npmrc.config │ ├── configuration-as-code.yaml │ ├── dsl │ ├── NodeJSBuild.pipeline │ └── NodeJSInstallation.pipeline │ └── tools │ ├── NodeJSInstallationTest │ └── test_load_at_startup │ │ └── jenkins.plugins.nodejs.tools.NodeJSInstallation.xml │ ├── expectedURLs.txt │ └── test.tar.gz └── updates └── jenkins.plugins.nodejs.tools.NodeJSInstaller.json /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jenkinsci/nodejs-plugin-developers 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 8 | target-branch: master 9 | reviewers: 10 | - nfalco79 11 | labels: 12 | - dependencies 13 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | _extends: .github 2 | tag-template: nodejs-$NEXT_PATCH_VERSION 3 | name-template: $NEXT_PATCH_VERSION 4 | version-template: $MAJOR.$MINOR.$PATCH 5 | -------------------------------------------------------------------------------- /.github/workflows/jenkins-security-scan.yml: -------------------------------------------------------------------------------- 1 | name: Jenkins Security Scan 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | pull_request: 9 | types: [ opened, synchronize, reopened ] 10 | workflow_dispatch: 11 | 12 | permissions: 13 | security-events: write 14 | contents: read 15 | actions: read 16 | 17 | jobs: 18 | security-scan: 19 | uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2 20 | with: 21 | java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate. 22 | java-version: 17 # What version of Java to set up for the build. 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /target 3 | /.settings 4 | /.classpath 5 | /work 6 | *.iml 7 | .idea 8 | /.checkstyle 9 | -------------------------------------------------------------------------------- /.mvn/extensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | io.jenkins.tools.incrementals 4 | git-changelist-maven-extension 5 | 1.8 6 | 7 | 8 | -------------------------------------------------------------------------------- /.mvn/maven.config: -------------------------------------------------------------------------------- 1 | -Pconsume-incrementals 2 | -Pmight-produce-incrementals 3 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | // see https://github.com/jenkins-infra/pipeline-library 4 | buildPlugin(useContainerAgent: true, configurations: [ 5 | [platform: 'linux', jdk: 21], 6 | [platform: 'windows', jdk: 17], 7 | ]) 8 | -------------------------------------------------------------------------------- /checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/images/nodejs_buildstep_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/nodejs-plugin/2f4929d6ecfd4d09b947a50a0ca0095ed175d0e4/docs/images/nodejs_buildstep_menu.png -------------------------------------------------------------------------------- /docs/images/nodejs_buildstep_script.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/nodejs-plugin/2f4929d6ecfd4d09b947a50a0ca0095ed175d0e4/docs/images/nodejs_buildstep_script.png -------------------------------------------------------------------------------- /docs/images/nodejs_choose_configfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/nodejs-plugin/2f4929d6ecfd4d09b947a50a0ca0095ed175d0e4/docs/images/nodejs_choose_configfile.png -------------------------------------------------------------------------------- /docs/images/nodejs_npm_configfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/nodejs-plugin/2f4929d6ecfd4d09b947a50a0ca0095ed175d0e4/docs/images/nodejs_npm_configfile.png -------------------------------------------------------------------------------- /docs/images/nodejs_npm_to_path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/nodejs-plugin/2f4929d6ecfd4d09b947a50a0ca0095ed175d0e4/docs/images/nodejs_npm_to_path.png -------------------------------------------------------------------------------- /docs/images/nodejs_tools_configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/nodejs-plugin/2f4929d6ecfd4d09b947a50a0ca0095ed175d0e4/docs/images/nodejs_tools_configuration.png -------------------------------------------------------------------------------- /license.header: -------------------------------------------------------------------------------- 1 | ^.+$ 2 | ^.{0,3}The MIT License$ 3 | ^.{0,3}$ 4 | ^.{0,3}Copyright \(c\) \d{4}, .+$ 5 | ^.{0,3}$ 6 | ^.{0,3}Permission is hereby granted, free of charge, to any person obtaining a copy$ 7 | ^.{0,3}of this software and associated documentation files \(the "Software"\), to deal$ 8 | ^.{0,3}in the Software without restriction, including without limitation the rights$ 9 | ^.{0,3}to use, copy, modify, merge, publish, distribute, sublicense, and/or sell$ 10 | ^.{0,3}copies of the Software, and to permit persons to whom the Software is$ 11 | ^.{0,3}furnished to do so, subject to the following conditions:$ 12 | ^.{0,3}$ 13 | ^.{0,3}The above copyright notice and this permission notice shall be included in$ 14 | ^.{0,3}all copies or substantial portions of the Software.$ 15 | ^.{0,3}$ 16 | ^.{0,3}THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR$ 17 | ^.{0,3}IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,$ 18 | ^.{0,3}FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE$ 19 | ^.{0,3}AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER$ 20 | ^.{0,3}LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,$ 21 | ^.{0,3}OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN$ 22 | ^.{0,3}THE SOFTWARE.$ -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/NodeJSConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | public final class NodeJSConstants { 27 | 28 | private NodeJSConstants() { 29 | // constructor 30 | } 31 | 32 | /** 33 | * Default extension for javascript file. 34 | */ 35 | public static final String JAVASCRIPT_EXT = ".js"; 36 | 37 | /** 38 | * Default NPM registry. 39 | */ 40 | public static final String DEFAULT_NPM_REGISTRY = "registry.npmjs.org"; 41 | 42 | /** 43 | * The name of environment variable that point to the NodeJS installation 44 | * home. 45 | */ 46 | public static final String ENVVAR_NODEJS_HOME = "NODEJS_HOME"; 47 | 48 | /** 49 | * Alias for NODEJS_HOME. 50 | */ 51 | public static final String ENVVAR_NODE_HOME = "NODE_HOME"; 52 | 53 | /** 54 | * The name of environment variable that contribute the PATH value. 55 | */ 56 | public static final String ENVVAR_NODEJS_PATH = "PATH+NODEJS"; 57 | 58 | /** 59 | * The location of NPM cache. 60 | */ 61 | public static final String NPM_CACHE_LOCATION = "npm_config_cache"; 62 | 63 | /** 64 | * The location of user-level configuration settings. 65 | */ 66 | public static final String NPM_USERCONFIG = "npm_config_userconfig"; 67 | 68 | /** 69 | * Force npm to always require authentication when accessing the registry, 70 | * even for GET requests. 71 | *

72 | * Default: false
73 | * Type: Boolean 74 | *

75 | */ 76 | public static final String NPM_SETTINGS_ALWAYS_AUTH = "always-auth"; 77 | /** 78 | * The base URL of the npm package registry. 79 | *

80 | * Default: https://registry.npmjs.org/
81 | * Type: url 82 | *

83 | */ 84 | public static final String NPM_SETTINGS_REGISTRY = "registry"; 85 | 86 | /* since npm 9 each of these entries must be scoped with a registry */ 87 | /** 88 | * The authentication base64 string >USER<:>PASSWORD< used to 89 | * login to the global registry. 90 | */ 91 | public static final String NPM_SETTINGS_AUTH = "_auth"; 92 | /** 93 | * The authentication token used to login to the global registry or scoped 94 | * registry. 95 | */ 96 | public static final String NPM_SETTINGS_AUTHTOKEN = "_authToken"; 97 | /** 98 | * The user name used to login to the scoped registry. 99 | */ 100 | public static final String NPM_SETTINGS_USER = "username"; 101 | /** 102 | * The authentication base64 string >PASSWORD< used to 103 | * login to the scoped registry. 104 | */ 105 | public static final String NPM_SETTINGS_PASSWORD = "_password"; 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/NodeJSDescriptorUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import edu.umd.cs.findbugs.annotations.CheckForNull; 27 | import edu.umd.cs.findbugs.annotations.NonNull; 28 | import edu.umd.cs.findbugs.annotations.Nullable; 29 | 30 | import org.jenkinsci.lib.configprovider.model.Config; 31 | import org.jenkinsci.plugins.configfiles.ConfigFiles; 32 | 33 | import hudson.model.ItemGroup; 34 | import hudson.util.FormValidation; 35 | import hudson.util.ListBoxModel; 36 | import jenkins.plugins.nodejs.configfiles.NPMConfig; 37 | import jenkins.plugins.nodejs.configfiles.NPMConfig.NPMConfigProvider; 38 | import jenkins.plugins.nodejs.configfiles.VerifyConfigProviderException; 39 | 40 | /*package*/ final class NodeJSDescriptorUtils { 41 | 42 | private NodeJSDescriptorUtils() { 43 | } 44 | 45 | /** 46 | * Get all NPMConfig defined for the given context. 47 | * 48 | * @param context the context where lookup the config files 49 | * @return a collection of user npmrc files found for the given context 50 | * always including a system default. 51 | */ 52 | @NonNull 53 | public static ListBoxModel getConfigs(@Nullable ItemGroup context) { 54 | ListBoxModel items = new ListBoxModel(); 55 | items.add(Messages.NPMConfig_default(), ""); 56 | for (Config config : ConfigFiles.getConfigsInContext(context, NPMConfigProvider.class)) { 57 | items.add(config.name, config.id); 58 | } 59 | return items; 60 | } 61 | 62 | /** 63 | * Verify that the given configId exists in the given context. 64 | * 65 | * @param context where lookup 66 | * @param configId the identifier of an npmrc file 67 | * @return an validation form for the given npmrc file identifier, otherwise 68 | * returns {@code ok} if the identifier does not exists for the 69 | * given context. 70 | */ 71 | public static FormValidation checkConfig(@Nullable ItemGroup context, @CheckForNull String configId) { 72 | if (configId != null) { 73 | Config config = ConfigFiles.getByIdOrNull(context, configId); 74 | if (config != null) { 75 | try { 76 | ((NPMConfig) config).doVerify(); 77 | } catch (VerifyConfigProviderException e) { 78 | return FormValidation.error(e.getMessage()); 79 | } 80 | } 81 | } 82 | return FormValidation.ok(); 83 | } 84 | 85 | } -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/NodeJSPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco, Frédéric Camblor 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import hudson.Plugin; 27 | import hudson.model.Items; 28 | 29 | import java.io.IOException; 30 | 31 | import edu.umd.cs.findbugs.annotations.NonNull; 32 | import edu.umd.cs.findbugs.annotations.Nullable; 33 | 34 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 35 | import jenkins.model.Jenkins; 36 | import jenkins.plugins.nodejs.tools.NodeJSInstallation; 37 | import jenkins.plugins.nodejs.tools.NodeJSInstallation.DescriptorImpl; 38 | 39 | /** 40 | * @author fcamblor 41 | * @author Nikolas Falco 42 | * @deprecated Do not use this anymore. This class will be removed, actually is 43 | * kept to migrate persistence. 44 | */ 45 | @Deprecated 46 | public class NodeJSPlugin extends Plugin { 47 | 48 | private NodeJSInstallation[] installations; 49 | 50 | @Override 51 | public void start() throws Exception { 52 | super.start(); 53 | Items.XSTREAM2.addCompatibilityAlias("jenkins.plugins.nodejs.tools.NpmPackagesBuildWrapper", NodeJSBuildWrapper.class); 54 | Items.XSTREAM2.addCompatibilityAlias("jenkins.plugins.nodejs.NodeJsCommandInterpreter", NodeJSCommandInterpreter.class); 55 | try { 56 | load(); 57 | } catch (IOException e) { // NOSONAR 58 | // ignore read XStream errors 59 | } 60 | } 61 | 62 | @SuppressFBWarnings("UWF_NULL_FIELD") 63 | @Override 64 | public void postInitialize() throws Exception { 65 | super.postInitialize(); 66 | // If installations have been read in nodejs.xml, let's convert them to 67 | // the default persistence 68 | if (installations != null) { 69 | setInstallations(installations); 70 | getConfigXml().delete(); 71 | installations = null; 72 | } 73 | } 74 | 75 | /** 76 | * Get all available NodeJS defined installation. 77 | * 78 | * @return an array of defined {@link NodeJSInstallation} 79 | * @deprecated Use {@link NodeJSUtils#getInstallations()} instead of this. 80 | */ 81 | @Deprecated 82 | @NonNull 83 | public NodeJSInstallation[] getInstallations() { 84 | return NodeJSUtils.getInstallations(); 85 | } 86 | 87 | @Nullable 88 | public NodeJSInstallation findInstallationByName(@Nullable String name) { 89 | return NodeJSUtils.getNodeJS(name); 90 | } 91 | 92 | /** 93 | * Set the NodeJS installation. 94 | * 95 | * @param installations an array of {@link NodeJSInstallation} 96 | * @deprecated You should not set manually system NodeJS installation, in 97 | * case use the standard 98 | * {@link Jenkins#getDescriptorByType(Class) 99 | * #setInstallations(NodeJSInstallation[])} 100 | */ 101 | @Deprecated 102 | public void setInstallations(@NonNull NodeJSInstallation[] installations) { 103 | DescriptorImpl descriptor = Jenkins.getActiveInstance().getDescriptorByType(NodeJSInstallation.DescriptorImpl.class); 104 | if (descriptor != null) { 105 | descriptor.setInstallations(installations != null ? installations : new NodeJSInstallation[0]); 106 | descriptor.save(); 107 | } 108 | } 109 | 110 | } -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/NodeJSUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import edu.umd.cs.findbugs.annotations.NonNull; 27 | import edu.umd.cs.findbugs.annotations.Nullable; 28 | 29 | import jenkins.model.Jenkins; 30 | import jenkins.plugins.nodejs.tools.NodeJSInstallation; 31 | import jenkins.plugins.nodejs.tools.NodeJSInstallation.DescriptorImpl; 32 | 33 | /*package*/final class NodeJSUtils { 34 | 35 | private NodeJSUtils() { 36 | // default constructor 37 | } 38 | 39 | /** 40 | * Gets the NodeJS to invoke, or null to invoke the default one. 41 | * 42 | * @param name 43 | * the name of NodeJS installation 44 | * @return a NodeJS installation for the given name if exists, {@code null} 45 | * otherwise. 46 | */ 47 | @Nullable 48 | public static NodeJSInstallation getNodeJS(@Nullable String name) { 49 | if (name != null) { 50 | for (NodeJSInstallation installation : getInstallations()) { 51 | if (name.equals(installation.getName())) 52 | return installation; 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | /** 59 | * Get all NodeJS installation defined in Jenkins. 60 | * 61 | * @return an array of NodeJS tool installation 62 | */ 63 | @NonNull 64 | public static NodeJSInstallation[] getInstallations() { 65 | DescriptorImpl descriptor = Jenkins.get().getDescriptorByType(NodeJSInstallation.DescriptorImpl.class); 66 | if (descriptor == null) { 67 | throw new IllegalStateException("Impossible retrieve NodeJSInstallation descriptor"); 68 | } 69 | return descriptor.getInstallations(); 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/cache/CacheLocationLocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2019, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.cache; 25 | 26 | import hudson.ExtensionPoint; 27 | import hudson.FilePath; 28 | import hudson.model.AbstractDescribableImpl; 29 | import edu.umd.cs.findbugs.annotations.NonNull; 30 | 31 | /** 32 | * Strategy pattern that decides the location of the NPM cache location for a 33 | * build. 34 | */ 35 | public abstract class CacheLocationLocator extends AbstractDescribableImpl implements ExtensionPoint { 36 | 37 | /** 38 | * Called during the build on the master to determine the location of the 39 | * local cache location. 40 | * 41 | * @param workspace 42 | * the workspace file path locator 43 | * @return null to let NPM uses its default location. Otherwise this must be 44 | * located on the same node as described by this path. 45 | */ 46 | public abstract FilePath locate(@NonNull FilePath workspace); 47 | 48 | @Override 49 | public CacheLocationLocatorDescriptor getDescriptor() { 50 | return (CacheLocationLocatorDescriptor) super.getDescriptor(); 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/cache/CacheLocationLocatorDescriptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2019, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.cache; 25 | 26 | import hudson.model.Descriptor; 27 | 28 | public class CacheLocationLocatorDescriptor extends Descriptor { 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/cache/DefaultCacheLocationLocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2019, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.cache; 25 | 26 | import hudson.Extension; 27 | import hudson.FilePath; 28 | import edu.umd.cs.findbugs.annotations.NonNull; 29 | import jenkins.plugins.nodejs.Messages; 30 | import org.jenkinsci.Symbol; 31 | import org.kohsuke.stapler.DataBoundConstructor; 32 | 33 | /** 34 | * Uses NPM's default global cache, which is actually {@code ~/.npm} on Unix 35 | * system or {@code %APP_DATA%\npm-cache} on Windows system. 36 | */ 37 | public class DefaultCacheLocationLocator extends CacheLocationLocator { 38 | 39 | @DataBoundConstructor 40 | public DefaultCacheLocationLocator() { 41 | } 42 | 43 | @Override 44 | public FilePath locate(@NonNull FilePath workspace) { 45 | return null; 46 | } 47 | 48 | @Extension 49 | @Symbol("default") 50 | public static class DescriptorImpl extends CacheLocationLocatorDescriptor { 51 | @Override 52 | public String getDisplayName() { 53 | return Messages.DefaultCacheLocationLocator_displayName(); 54 | } 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/cache/PerExecutorCacheLocationLocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2019, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.cache; 25 | 26 | import hudson.Extension; 27 | import hudson.FilePath; 28 | import hudson.model.Computer; 29 | import hudson.model.Executor; 30 | import hudson.model.Node; 31 | import edu.umd.cs.findbugs.annotations.NonNull; 32 | import jenkins.plugins.nodejs.Messages; 33 | import org.jenkinsci.Symbol; 34 | import org.kohsuke.stapler.DataBoundConstructor; 35 | 36 | /** 37 | * Relocates the NPM's default cache to a folder specific for the executor in 38 | * the node home folder {@code ~/npm-cache/$executorNumber}. 39 | */ 40 | public class PerExecutorCacheLocationLocator extends CacheLocationLocator { 41 | 42 | @DataBoundConstructor 43 | public PerExecutorCacheLocationLocator() { 44 | } 45 | 46 | @Override 47 | public FilePath locate(@NonNull FilePath workspace) { 48 | final Computer computer = workspace.toComputer(); 49 | if (computer == null) { 50 | throw new IllegalStateException(Messages.NodeJSBuilders_nodeOffline()); 51 | } 52 | final Node node = computer.getNode(); 53 | if (node == null) { 54 | throw new IllegalStateException(Messages.NodeJSBuilders_nodeOffline()); 55 | } 56 | final FilePath rootPath = node.getRootPath(); 57 | final Executor executor = Executor.currentExecutor(); 58 | if (rootPath == null || executor == null) { 59 | return null; 60 | } 61 | return rootPath.child("npm-cache/" + executor.getNumber()); 62 | } 63 | 64 | @Extension 65 | @Symbol("executor") 66 | public static class DescriptorImpl extends CacheLocationLocatorDescriptor { 67 | @Override 68 | public String getDisplayName() { 69 | return Messages.ExecutorCacheLocationLocator_displayName(); 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/cache/PerJobCacheLocationLocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2019, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.cache; 25 | 26 | import hudson.Extension; 27 | import hudson.FilePath; 28 | import edu.umd.cs.findbugs.annotations.NonNull; 29 | import jenkins.plugins.nodejs.Messages; 30 | import org.jenkinsci.Symbol; 31 | import org.kohsuke.stapler.DataBoundConstructor; 32 | 33 | /** 34 | * Relocates the NPM's default cache to the workspace folder. This allow clean 35 | * unused packages when the job is gone. 36 | */ 37 | public class PerJobCacheLocationLocator extends CacheLocationLocator { 38 | 39 | @DataBoundConstructor 40 | public PerJobCacheLocationLocator() { 41 | } 42 | 43 | @Override 44 | public FilePath locate(@NonNull FilePath workspace) { 45 | return workspace.child(".npm"); 46 | } 47 | 48 | @Extension 49 | @Symbol("workspace") 50 | public static class DescriptorImpl extends CacheLocationLocatorDescriptor { 51 | @Override 52 | public String getDisplayName() { 53 | return Messages.JobCacheLocationLocator_displayName(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/configfiles/NPMConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.configfiles; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStream; 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | import java.util.Map; 31 | 32 | import org.apache.commons.io.IOUtils; 33 | import org.apache.commons.lang.StringUtils; 34 | import org.jenkinsci.lib.configprovider.AbstractConfigProviderImpl; 35 | import org.jenkinsci.lib.configprovider.model.Config; 36 | import org.jenkinsci.lib.configprovider.model.ContentType; 37 | import org.kohsuke.stapler.DataBoundConstructor; 38 | import org.kohsuke.stapler.DataBoundSetter; 39 | 40 | import com.cloudbees.plugins.credentials.common.StandardCredentials; 41 | 42 | import edu.umd.cs.findbugs.annotations.NonNull; 43 | import hudson.AbortException; 44 | import hudson.Extension; 45 | import hudson.FilePath; 46 | import hudson.Util; 47 | import hudson.model.Run; 48 | import hudson.model.TaskListener; 49 | import jenkins.plugins.nodejs.Messages; 50 | 51 | /** 52 | * A config/provider to handle the special case of a npmrc config file 53 | * 54 | * @author Nikolas Falco 55 | * @since 1.0 56 | */ 57 | public class NPMConfig extends Config { 58 | private static final long serialVersionUID = 1L; 59 | 60 | private final List registries; 61 | private boolean npm9Format = false; 62 | 63 | @DataBoundConstructor 64 | public NPMConfig(@NonNull String id, String name, String comment, String content, List registries) { 65 | super(id, Util.fixEmptyAndTrim(name), Util.fixEmptyAndTrim(comment), Util.fixEmptyAndTrim(content)); 66 | this.registries = registries == null ? new ArrayList(3) : registries; 67 | } 68 | 69 | public List getRegistries() { 70 | return registries; 71 | } 72 | 73 | /** 74 | * Perform a validation of the configuration. 75 | *

76 | * If validation pass then no {@link VerifyConfigProviderException} will be 77 | * raised. 78 | * 79 | * @throws VerifyConfigProviderException 80 | * in case this configuration is not valid. 81 | */ 82 | public void doVerify() throws VerifyConfigProviderException { 83 | // check if more than registry is setup to be global 84 | NPMRegistry globalRegistry = null; 85 | 86 | for (NPMRegistry registry : registries) { 87 | registry.doVerify(); 88 | 89 | if (!registry.isHasScopes()) { 90 | if (globalRegistry != null) { 91 | throw new VerifyConfigProviderException(Messages.NPMConfig_verifyTooGlobalRegistry()); 92 | } 93 | globalRegistry = registry; 94 | } 95 | } 96 | } 97 | 98 | public boolean isNpm9Format() { 99 | return npm9Format; 100 | } 101 | 102 | /** 103 | * Sets if the generated .npmrc format is compatible with NPM version 9. 104 | * 105 | * @param npm9Format enable NPM version 9 or not 106 | */ 107 | @DataBoundSetter 108 | public void setNpm9Format(boolean npm9Format) { 109 | this.npm9Format = npm9Format; 110 | } 111 | 112 | @Extension 113 | public static class NPMConfigProvider extends AbstractConfigProviderImpl { 114 | 115 | public NPMConfigProvider() { 116 | load(); 117 | } 118 | 119 | @Override 120 | public ContentType getContentType() { 121 | return null; 122 | } 123 | 124 | @Override 125 | public String getDisplayName() { 126 | return Messages.NPMConfig_displayName(); 127 | } 128 | 129 | @Override 130 | public Config newConfig(@NonNull String configId) { 131 | return new NPMConfig(configId, "MyNpmrcConfig", "user config", loadTemplateContent(), null); 132 | } 133 | 134 | protected String loadTemplateContent() { 135 | try (InputStream is = this.getClass().getResourceAsStream("template.npmrc")) { 136 | return IOUtils.toString(is, "UTF-8"); 137 | } catch (IOException e) { // NOSONAR 138 | return null; 139 | } 140 | } 141 | 142 | @Override 143 | public String supplyContent(Config configFile, Run build, FilePath workDir, TaskListener listener, List tempFiles) throws IOException { 144 | String fileContent = configFile.content; 145 | if (configFile instanceof NPMConfig) { 146 | NPMConfig config = (NPMConfig) configFile; 147 | 148 | List registries = config.getRegistries(); 149 | RegistryHelper helper = new RegistryHelper(registries); 150 | if (!registries.isEmpty()) { 151 | listener.getLogger().println("Adding all registry entries"); 152 | Map registry2Credentials = helper.resolveCredentials(build); 153 | fileContent = helper.fillRegistry(fileContent, registry2Credentials, config.npm9Format); 154 | } 155 | 156 | try { 157 | if (StringUtils.isNotBlank(fileContent)) { // NOSONAR 158 | config.doVerify(); 159 | } 160 | } catch (VerifyConfigProviderException e) { 161 | throw new AbortException("Invalid user config: " + e.getMessage()); 162 | } 163 | } 164 | return fileContent; 165 | } 166 | 167 | @Override 168 | public @NonNull List getSensitiveContentForMasking(Config configFile, Run build) { 169 | List sensitiveContent = new ArrayList<>(); 170 | if (configFile instanceof NPMConfig) { 171 | NPMConfig config = (NPMConfig) configFile; 172 | List registries = config.getRegistries(); 173 | if (!registries.isEmpty()) { 174 | RegistryHelper helper = new RegistryHelper(registries); 175 | sensitiveContent = helper.secretsForMasking(build); 176 | } 177 | } 178 | return sensitiveContent; 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/configfiles/VerifyConfigProviderException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.configfiles; 25 | 26 | /** 27 | * Signals an error in the a user configuration file when 28 | * {@link NPMConfig#doVerify()} is called. 29 | * 30 | * @author Nikolas Falco 31 | * @since 1.0 32 | */ 33 | @SuppressWarnings("serial") 34 | public class VerifyConfigProviderException extends Exception { 35 | 36 | /** 37 | * Constructs a new exception with the specified detail message. 38 | * 39 | * @param message 40 | * the failure message. 41 | */ 42 | public VerifyConfigProviderException(String message) { 43 | super(message); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 28 | 29 | 30 | 31 | Classes implementing Jenkins API used in NodeJS Plugin. 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/tools/CPU.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import java.io.ByteArrayOutputStream; 27 | import java.io.File; 28 | import java.io.IOException; 29 | import java.nio.charset.Charset; 30 | import java.util.Locale; 31 | import java.util.Map; 32 | 33 | import edu.umd.cs.findbugs.annotations.NonNull; 34 | import edu.umd.cs.findbugs.annotations.Nullable; 35 | 36 | import org.apache.commons.io.output.NullOutputStream; 37 | 38 | import hudson.FilePath; 39 | import hudson.Launcher; 40 | import hudson.Proc; 41 | import hudson.model.Computer; 42 | import hudson.model.Node; 43 | import hudson.remoting.VirtualChannel; 44 | import hudson.util.StreamTaskListener; 45 | import jenkins.MasterToSlaveFileCallable; 46 | import jenkins.plugins.nodejs.Messages; 47 | 48 | /** 49 | * CPU type. 50 | */ 51 | public enum CPU { 52 | i386, amd64, armv7l, armv6l, arm64, ppc64; 53 | 54 | /** 55 | * Determines the CPU of the given node. 56 | * 57 | * @param node 58 | * the computer node 59 | * @return a CPU value of the architecture of the given node 60 | * @throws DetectionFailedException 61 | * when the current CPU node is not supported. 62 | */ 63 | public static CPU of(@NonNull Node node) throws DetectionFailedException { 64 | try { 65 | Computer computer = node.toComputer(); 66 | if (computer == null) { 67 | throw new DetectionFailedException(Messages.SystemTools_nodeNotAvailable(node.getDisplayName())); 68 | } 69 | return detect(computer, computer.getSystemProperties()); 70 | } catch (IOException | InterruptedException e) { 71 | throw new DetectionFailedException(Messages.SystemTools_failureOnProperties(), e); 72 | } 73 | } 74 | 75 | /** 76 | * Determines the CPU of the current JVM. 77 | * 78 | * @return the current CPU 79 | * @throws DetectionFailedException 80 | * when the current platform node is not supported. 81 | */ 82 | public static CPU current() throws DetectionFailedException { 83 | return detect(null, System.getProperties()); 84 | } 85 | 86 | private static CPU detect(@Nullable Computer computer, Map systemProperties) throws DetectionFailedException { 87 | String arch = ((String) systemProperties.get("os.arch")).toLowerCase(Locale.ENGLISH); 88 | if (arch.contains("amd64") || arch.contains("86_64")) { 89 | return amd64; 90 | } 91 | if (arch.contains("86")) { 92 | return i386; 93 | } 94 | if (arch.contains("arm")) { 95 | // try to get the specific architecture of arm CPU 96 | try { 97 | FilePath rootPath = new FilePath((computer != null ? computer.getChannel() : null), "/"); 98 | arch = rootPath.act(new ArchitectureCallable()); 99 | } catch (IOException | InterruptedException e) { 100 | throw new DetectionFailedException(Messages.CPU_unknown(arch), e); 101 | } 102 | switch (arch) { 103 | case "armv7l": 104 | return armv7l; 105 | case "armv6l": 106 | return armv6l; 107 | case "arm64": 108 | return arm64; 109 | } 110 | } 111 | if ("aarch64".equalsIgnoreCase(arch)) { 112 | return arm64; 113 | } 114 | if (arch.contains("ppc")) { 115 | return ppc64; 116 | } 117 | throw new DetectionFailedException(Messages.CPU_unknown(arch)); 118 | } 119 | 120 | /** 121 | * Returns the machine hardware name for the current Linux computer. 122 | * 123 | * @author Nikolas Falco 124 | */ 125 | /* package */static class ArchitectureCallable extends MasterToSlaveFileCallable { 126 | private static final long serialVersionUID = 1L; 127 | 128 | @Override 129 | public String invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { 130 | Charset charset = Charset.defaultCharset(); 131 | 132 | FilePath basePath = new FilePath(f); 133 | Launcher launcher = basePath.createLauncher(new StreamTaskListener(NullOutputStream.NULL_OUTPUT_STREAM, charset)); 134 | 135 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 136 | 137 | Proc starter = launcher.launch().cmdAsSingleString("uname -m").stdout(baos).start(); 138 | int exitCode = starter.join(); 139 | if (exitCode != 0) { 140 | throw new IOException("Fail to execute 'uname -m' because: " + baos.toString(charset.name())); 141 | } 142 | 143 | return new String(baos.toByteArray(), charset).trim(); 144 | } 145 | }; 146 | 147 | } -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/tools/DetectionFailedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import java.io.IOException; 27 | 28 | /** 29 | * Indicates the failure to detect the OS or CPU. 30 | */ 31 | @SuppressWarnings("serial") 32 | public final class DetectionFailedException extends IOException { 33 | DetectionFailedException(String message) { 34 | super(message); 35 | } 36 | 37 | public DetectionFailedException(String message, Throwable cause) { 38 | super(message, cause); 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/tools/InstallableComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2021, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import java.io.Serializable; 27 | import java.util.Comparator; 28 | 29 | import hudson.tools.DownloadFromUrlInstaller.Installable; 30 | 31 | /** 32 | * Comparator to sort Installable unit based on NodeJS version. 33 | * 34 | * @author Nikolas Falco 35 | */ 36 | /* package */ class InstallableComparator implements Comparator, Serializable { 37 | private static final long serialVersionUID = 1L; 38 | 39 | @Override 40 | public int compare(Installable o1, Installable o2) { 41 | return NodeJSVersion.parseVersion(o1.id).compareTo(NodeJSVersion.parseVersion(o2.id)) * -1; 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/tools/InstallerPathResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco, Frédéric Camblor 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import jenkins.plugins.nodejs.tools.pathresolvers.LatestInstallerPathResolver; 27 | 28 | /** 29 | * Contract to resolve parts of an URL path given some specific inputs. 30 | * 31 | * @author fcamblor 32 | * @author Nikolas Falco 33 | */ 34 | public interface InstallerPathResolver { 35 | /** 36 | * Resolve the URL path for the given parameters. 37 | * 38 | * @param version 39 | * string version of an installable unit 40 | * @param platform 41 | * of the node where this installable is designed 42 | * @param cpu 43 | * of the node where this installable is designed 44 | * @return the relative path URL for the given specifics 45 | */ 46 | String resolvePathFor(String version, Platform platform, CPU cpu); 47 | 48 | /** 49 | * Factory that return lookup for an implementation of {@link InstallerPathResolver}. 50 | */ 51 | public static class Factory { 52 | /** 53 | * Return an implementation adapt for the given installable. 54 | * 55 | * @param id an installable 56 | * @return an instance of {@link InstallerPathResolver} 57 | * @throws IllegalArgumentException 58 | * in case the given installable is not supported. 59 | */ 60 | public static InstallerPathResolver findResolverFor(String id) { 61 | if (isVersionBlacklisted(id)) { 62 | throw new IllegalArgumentException("Provided version (" + id + ") installer structure not (yet) supported !"); 63 | } else { 64 | return new LatestInstallerPathResolver(); 65 | } 66 | } 67 | 68 | public static boolean isVersionBlacklisted(String version){ 69 | NodeJSVersion nodeJSVersion = NodeJSVersion.parseVersion(version); 70 | return new NodeJSVersionRange("[0, 0.8.6)").includes(nodeJSVersion) || NodeJSVersion.parseVersion("0.9.0").equals(nodeJSVersion); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/tools/Platform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import java.io.IOException; 27 | import java.util.Locale; 28 | import java.util.Map; 29 | 30 | import hudson.model.Computer; 31 | import hudson.model.Node; 32 | import jenkins.plugins.nodejs.Messages; 33 | 34 | /** 35 | * Supported platform. 36 | */ 37 | public enum Platform { 38 | LINUX("node", "npm", "bin"), WINDOWS("node.exe", "npm.cmd", ""), OSX("node", "npm", "bin"), SUNOS("node", "npm", "bin"), AIX("node", "npm", "bin"); 39 | 40 | /** 41 | * Choose the file name suitable for the downloaded Node bundle. 42 | */ 43 | public final String nodeFileName; 44 | /** 45 | * Choose the file name suitable for the npm bundled with NodeJS. 46 | */ 47 | public final String npmFileName; 48 | /** 49 | * Choose the folder path suitable bin folder of the bundle. 50 | */ 51 | public final String binFolder; 52 | 53 | Platform(String nodeFileName, String npmFileName, String binFolder) { 54 | this.nodeFileName = nodeFileName; 55 | this.npmFileName = npmFileName; 56 | this.binFolder = binFolder; 57 | } 58 | 59 | public boolean is(String line) { 60 | return line.contains(name()); 61 | } 62 | 63 | /** 64 | * Determines the platform of the given node. 65 | * 66 | * @param node 67 | * the computer node 68 | * @return a platform value that represent the given node 69 | * @throws DetectionFailedException 70 | * when the current platform node is not supported. 71 | */ 72 | public static Platform of(Node node) throws DetectionFailedException { 73 | try { 74 | Computer computer = node.toComputer(); 75 | if (computer == null) { 76 | throw new DetectionFailedException(Messages.SystemTools_nodeNotAvailable(node.getDisplayName())); 77 | } 78 | return detect(computer.getSystemProperties()); 79 | } catch (IOException | InterruptedException e) { 80 | throw new DetectionFailedException(Messages.SystemTools_failureOnProperties(), e); 81 | } 82 | } 83 | 84 | public static Platform current() throws DetectionFailedException { 85 | return detect(System.getProperties()); 86 | } 87 | 88 | private static Platform detect(Map systemProperties) throws DetectionFailedException { 89 | String arch = ((String) systemProperties.get("os.name")).toLowerCase(Locale.ENGLISH); 90 | if (arch.contains("linux")) { 91 | return LINUX; 92 | } 93 | if (arch.contains("windows")) { 94 | return WINDOWS; 95 | } 96 | if (arch.contains("mac")) { 97 | return OSX; 98 | } 99 | if (arch.contains("sunos")) { 100 | return SUNOS; 101 | } 102 | if (arch.contains("aix")) { 103 | return AIX; 104 | } 105 | throw new DetectionFailedException(Messages.Platform_unknown(arch)); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/jenkins/plugins/nodejs/tools/ToolsUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import java.io.IOException; 27 | import java.util.Arrays; 28 | import java.util.Collections; 29 | import java.util.List; 30 | import java.util.stream.Collectors; 31 | 32 | import hudson.model.Node; 33 | import hudson.model.DownloadService.Downloadable; 34 | import hudson.tools.DownloadFromUrlInstaller.Installable; 35 | import hudson.tools.DownloadFromUrlInstaller.InstallableList; 36 | import jenkins.plugins.nodejs.Messages; 37 | import net.sf.json.JSONObject; 38 | 39 | /*package */ class ToolsUtils { 40 | 41 | private ToolsUtils() { 42 | } 43 | 44 | public static Platform getPlatform(Node node) throws DetectionFailedException { 45 | return Platform.of(node); 46 | } 47 | 48 | public static CPU getCPU(Node node) throws DetectionFailedException { 49 | return getCPU(node, false); 50 | } 51 | 52 | public static CPU getCPU(Node node, boolean force32bit) throws DetectionFailedException { 53 | CPU nodeCPU = CPU.of(node); 54 | if (force32bit) { 55 | if (!support32Bit(nodeCPU)) { 56 | throw new DetectionFailedException(Messages.SystemTools_unsupported32bitArchitecture()); 57 | } 58 | 59 | // force 32 bit architecture 60 | if (nodeCPU == CPU.amd64) { 61 | nodeCPU = CPU.i386; 62 | } 63 | } 64 | return nodeCPU; 65 | } 66 | 67 | private static boolean support32Bit(CPU cpu) { 68 | switch (cpu) { 69 | case armv6l: 70 | // 64bit start with ARMv8 71 | case armv7l: 72 | case i386: 73 | case amd64: 74 | return true; 75 | default: 76 | return false; 77 | } 78 | } 79 | 80 | public static List getInstallable() throws IOException { 81 | List installables = Collections.emptyList(); 82 | 83 | Downloadable downloadable = Downloadable.get("hudson.plugins.nodejs.tools.NodeJSInstaller"); 84 | if (downloadable != null) { 85 | JSONObject d = downloadable.getData(); 86 | if (d != null) { 87 | installables = Arrays.asList(((InstallableList) JSONObject.toBean(d, InstallableList.class)).list).stream() // 88 | .filter(i -> !InstallerPathResolver.Factory.isVersionBlacklisted(i.id)) // 89 | .sorted(new InstallableComparator()) // 90 | .collect(Collectors.toList()); 91 | } 92 | } 93 | return installables; 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 24 | 28 | 29 |

30 | NodeJS Plugin executes NodeJS script as a build step. 31 |
-------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/Messages.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | NodeJSInstaller.DescriptorImpl.displayName=Install from nodejs.org 25 | NodeJSInstaller.FailedToInstallNodeJS=Failed to install NodeJS. Exit code={0} 26 | NodeJSInstaller.installFromCache=Installing NodeJS from {0} to {1} on {2} 27 | NodeJSInstaller.failedToUnpack=Failed to unpack {0} ({1} bytes read) 28 | NodeJSInstallation.displayName=NodeJS 29 | NodeJSBuildWrapper.displayName=Provide Node & npm bin/ folder to PATH 30 | NodeJSCommandInterpreter.displayName=Execute NodeJS script 31 | NodeJSCommandInterpreter.commandFailed=command execution failed 32 | NodeJSBuilders.noExecutableFound=Couldn\u2019t find any executable in "{0}" 33 | NodeJSBuilders.noInstallationFound=No installation {0} found. Please define one in manager Jenkins. 34 | NodeJSBuilders.nodeOffline=Cannot get installation for node, since it is not online 35 | NPMConfig.displayName=Npm config file 36 | NPMConfig.verifyTooGlobalRegistry=Too many registries configured as global (no scope assigned), at most one is allowed. 37 | NPMConfig.default=- use system default - 38 | NPMRegistry.DescriptorImpl.emptyCredentialsId=Credentials is required 39 | NPMRegistry.DescriptorImpl.invalidCredentialsId=Current credentials does not exists 40 | NPMRegistry.DescriptorImpl.emptyRegistryURL=Registry URL is required 41 | NPMRegistry.DescriptorImpl.invalidRegistryURL=Invalid URL, should start with https:// 42 | NPMRegistry.DescriptorImpl.emptyScopes=Scopes is required 43 | NPMRegistry.DescriptorImpl.invalidScopes=Invalid scope 44 | NPMRegistry.DescriptorImpl.invalidCharInScopes=Remove the '@' character from scope 45 | CPU.unknown=Unknown CPU architecture: {0} 46 | Platform.unknown=Unknown OS name: {0} 47 | SystemTools.nodeNotAvailable=Node could be offline or there are no executor defined for Node {0} 48 | SystemTools.failureOnProperties=Error getting system properties on remote Node 49 | SystemTools.unsupported32bitArchitecture=NodeJS does not have a 32bit package available for the current node 50 | JobCacheLocationLocator.displayName=Local to the workspace 51 | ExecutorCacheLocationLocator.displayName=Local to the executor 52 | DefaultCacheLocationLocator.displayName=Default (~/.npm or %APP_DATA%\\npm-cache) 53 | InstallerPathResolver.unsupportedOS=Unresolvable nodeJS installer for version={0}, platform={1} 54 | InstallerPathResolver.unsupportedArch=Unresolvable nodeJS installer for version={0}, cpu={1}, platform={2} 55 | MirrorNodeJSInstaller.invalidCredentialsId=Credentials {0} does not exists 56 | MirrorNodeJSInstaller.DescriptorImpl.displayName=Install from nodejs.org mirror 57 | MirrorNodeJSInstaller.DescriptorImpl.emptyMirrorURL=The Mirror URL field cannot be empty. 58 | MirrorNodeJSInstaller.DescriptorImpl.invalidURL=Malformed URL -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/Messages_fr.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Fr\uFFFDd\uFFFDric Camblor 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | NodeJSInstaller.DescriptorImpl.displayName=Installer depuis nodejs.org 25 | NodeJSInstaller.FailedToInstallNodeJS=Echec de l'installation de NodeJS. Code de sortie={0} 26 | NodeJSInstallation.displayName=NodeJS 27 | NodeJSBuildWrapper.displayName=Ajouter le r\u00E9pertoire bin/ de Node/npm au PATH 28 | NodeJSCommandInterpreter.displayName=Ex\uFFFDcuter le script NodeJS 29 | NodeJSCommandInterpreter.noExecutable=Impossible de trouver un ex\uFFFDcutable dans {0} 30 | NodeJSCommandInterpreter.noInstallation=Aucune installation {0} trouv\uFFFDe. Veuillez en d\uFFFDfinir un dans le manager Jenkins. 31 | NodeJSCommandInterpreter.nodeOffline=Impossible d''obtenir pour l'installation du noeud, car il est pas en ligne 32 | NPMConfig.displayName=Fichier Npm de configuration 33 | NPMConfig.verifyTooGlobalRegistry=Trop de registres configur\uFFFDs comme globaux (pas de port\uFFFDe attribu\uFFFDe), au maximum un est autoris\uFFFD. 34 | NPMConfig.default=utiliser le syst\u00E8me par d\uFFFDfaut 35 | -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/Messages_it.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/nodejs-plugin/2f4929d6ecfd4d09b947a50a0ca0095ed175d0e4/src/main/resources/jenkins/plugins/nodejs/Messages_it.properties -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/NodeJSBuildWrapper/config.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/NodeJSBuildWrapper/config.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | nodeJSInstallationName.title=NodeJS Installation 25 | nodeJSInstallationName.description=Specify needed nodejs installation where npm installed packages will be provided to the PATH 26 | configId.title=npmrc file 27 | configId.cacheLocation=Cache location -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/NodeJSBuildWrapper/config_it.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | nodeJSInstallationName.title=Installazione NodeJS 25 | nodeJSInstallationName.description=Selezionando l''installazione NodeJS dove sono presenti i packages npm di cui hai bisogno, questi verranno aggiunti al PATH di sistema 26 | nodeJSInstallationName.emptyValue=- usa il default di sistema - 27 | configId.title=npmrc file 28 | configId.cacheLocation=Cache location -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/NodeJSCommandInterpreter/config.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/NodeJSCommandInterpreter/config.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | nodeJSInstallationName.title=NodeJS Installation 25 | nodeJSInstallationName.description=Specify nodejs installation where npm installed packages to execute the script 26 | nodeJSInstallationName.emptyValue=- use system default - 27 | command.title=Script 28 | configId.title=npmrc file 29 | configId.cacheLocation=Cache location -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/NodeJSCommandInterpreter/config_it.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | nodeJSInstallationName.title=Installazione NodeJS 25 | nodeJSInstallationName.description=Seleziona l''installazione NodeJS dove sono presenti i packages npm di cui hai bisogno per eseguire lo script 26 | nodeJSInstallationName.emptyValue=- use system default - 27 | command.title=Script 28 | configId.title=npmrc file 29 | configId.cacheLocation=Cache location -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMConfig/NPMConfigProvider/newInstanceDetail.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | ${%description} 27 | -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMConfig/NPMConfigProvider/newInstanceDetail.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | description=a npmrc config file (an ini-formatted list of key = value parameters) -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMConfig/edit-config.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 28 | 29 |

${%description}

30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
-------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMConfig/edit-config.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | description=

For a list of available configuration options, see npm-config.

\ 25 |

All npm config files are an ini-formatted list of key \= value parameters. Environment variables can be replaced using $VARIABLE_NAME.
\ 26 | Array values are specified by adding "[]" after the key name. For example\:\ 27 |

    \ 28 |
  • key[] \= "first value"
  • \ 29 |
  • key[] \= "second value"
  • \ 30 |

31 | registry.title=NPM Registry 32 | registry.format=Enforce NPM version 9 registry format 33 | content.title=Content -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMConfig/show-config.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
    68 | 69 |
  • 70 | 71 |
  • 72 |
    73 |
74 |
75 | 76 | 77 | 78 | 79 | 80 |
81 |
82 |
83 |
84 | 85 | 86 | 87 | 88 |
-------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMConfig/show-config.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | content.title=Content 25 | registry.title=NPM Registry 26 | registry.url=URL 27 | registry.format=Enforce NPM version 9 registry format 28 | registry.global=Global registry 29 | registry.scoped=This registry has the following scopes 30 | registry.scopes=Scopes -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMRegistry/config.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 | 43 |
44 |
45 |
-------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMRegistry/config.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | url.title=URL 25 | scopes.section.title=Use this registry for specific scoped packages 26 | scopes.title=Registry scopes 27 | scopes.description=a space separated list of scopes 28 | credentialsId.title=Credentials 29 | btnDelete.label=Delete -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMRegistry/help-credentialsId.html: -------------------------------------------------------------------------------- 1 | 24 |
25 |

The credentials to be assigned to the defined registry. The 26 | credentials can be the plaintext password or the encrypted version of 27 | it if you use a private registry (like Artifactory or Nexus)

28 |
-------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMRegistry/help-scopes.html: -------------------------------------------------------------------------------- 1 | 24 |
25 | A space separated list of scope. A scope follows the usual rules for 26 | package names (url-safe characters, no leading dots or underscores).
27 |

28 | In package names is preceded by an @-symbol and followed by a slash, 29 | e.g. @somescope/somepackagename. Scopes are a way of grouping 30 | related packages together, and also affect a few things about the way 31 | npm treats the package. 32 |

33 |
-------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMRegistry/help-url.html: -------------------------------------------------------------------------------- 1 | 24 |
25 | To resolve packages by name and version, npm talks to a registry 26 | website that implements the CommonJS Package Registry specification for 27 | reading package info. 28 |

29 | The registry URL used is determined by the scope of the package (see npm-scope). If no scope 31 | is specified, the default registry is used, which is supplied by the 32 | registry config parameter 33 |

34 |
-------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMRegistry/show.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/NPMRegistry/show.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | url.title=URL 25 | scopes.section.title=Use this registry for specific scoped packages 26 | scopes.title=Registry scopes 27 | scopes.description=a space separated list of scopes 28 | credentialsId.title=Credentials 29 | btnDelete.label=Delete -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/configfiles/template.npmrc: -------------------------------------------------------------------------------- 1 | ; Force npm to always require authentication when accessing the registry, even for GET requests. 2 | ; always-auth = false 3 | 4 | ; The location of npm's cache directory. See npm-cache (https://docs.npmjs.com/cli/cache) 5 | ; Default: Windows: %AppData%\npm-cache, Posix: ~/.npm 6 | ; cache = 7 | 8 | ; What level of logs to report. On failure, all logs are written to npm-debug.log in the current working directory. 9 | ; Any logs of a higher level than the setting are shown. The default is "warn", which shows warn and error output. 10 | ; Default: "warn" 11 | ; Values: "silent", "error", "warn", "http", "info", "verbose", "silly" 12 | ; loglevel = 13 | 14 | ; The config file to read for global config options. 15 | ; Default: {prefix}/etc/npmrc 16 | ; globalconfig = 17 | 18 | ; The location to install global items. If set on the command line, then it forces non-global commands to run in the specified folder. 19 | ; Default: see npm-folders (https://docs.npmjs.com/files/folders) 20 | ; prefix = 21 | 22 | ; The base URL of the npm package registry. 23 | ; Default: https://registry.npmjs.org/ 24 | ; registry = 25 | 26 | ; If set to false, then ignore npm-shrinkwrap.json files when installing. 27 | ; Default: true 28 | ; shrinkwrap = -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/tools/MirrorNodeJSInstaller/config.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/tools/MirrorNodeJSInstaller/config.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2021, Riain Condon 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | mirrorURL.title=Mirror URL 25 | mirrorURL.description=Enter the URL of a mirror for the public NodeJS downloads repo here. You may need to do this if you use services like Artifactory to mirror public repos. 26 | credentials.title=Credentials 27 | credentials.description=Credentials for the nodejs.org mirror if required. -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/tools/MirrorNodeJSInstaller/help-credentialsId.html: -------------------------------------------------------------------------------- 1 | 24 |
25 |

Credentials for the nodejs.org mirror if required. Only basic authentication is supported.

26 |
-------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/tools/MirrorNodeJSInstaller/help-mirrorURL.html: -------------------------------------------------------------------------------- 1 | 24 |
25 | A nodejs.org mirror URL from where download a valid 26 | installable package of NodeJS in case there are 27 | limitations or restrictions and you are not able 28 | to reach the official NodeJS.org distribution site. 29 |
-------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/tools/NodeJSInstaller/config.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/tools/NodeJSInstaller/config.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | id.title=Version 25 | npmPackages.title=Global npm packages to install 26 | npmPackages.description=Specify list of packages to install globally -- see npm install -g. Note that you can fix the package's version by using the syntax `packageName@version` 27 | npmPackagesRefreshHours.title=Global npm packages refresh hours 28 | npmPackagesRefreshHours.description=Duration, in hours, before 2 npm cache update. Note that 0 will always update npm cache 29 | force32Bit.title=Force 32bit architecture 30 | force32Bit.description=For the underlying architecture, if available, force the installation of the 32bit package. Otherwise the build will fail -------------------------------------------------------------------------------- /src/main/resources/jenkins/plugins/nodejs/tools/NodeJSInstaller/global_it.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2016, Nikolas Falco 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | 24 | NodeJS\ installation=Installazioni NodeJS 25 | List\ of\ NodeJS\ installations\ on\ this\ system=Lista delle installazioni di NodeJS nel sistema -------------------------------------------------------------------------------- /src/main/webapp/help.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | Executes a NodeJS script for building the project. 4 | The script will be run with the workspace as the current directory. 5 |

6 |

7 | The build is considered a failure if the script exits with a non-zero exit code. 8 |

9 |
-------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/CIBuilderHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import hudson.ExtensionList; 27 | 28 | import hudson.Launcher; 29 | import hudson.model.AbstractBuild; 30 | import hudson.model.Descriptor; 31 | import hudson.model.TaskListener; 32 | import hudson.tasks.Builder; 33 | import jenkins.plugins.nodejs.tools.NodeJSInstallation; 34 | 35 | /* package */ final class CIBuilderHelper { 36 | 37 | public static interface Verifier { 38 | void verify(AbstractBuild build, Launcher launcher, TaskListener listener) throws Exception; 39 | } 40 | 41 | public static NodeJSCommandInterpreter createMock(String command, NodeJSInstallation installation) { 42 | return createMock(command, installation, null, null); 43 | } 44 | 45 | public static NodeJSCommandInterpreter createMock(String command, NodeJSInstallation installation, String configId) { 46 | return createMock(command, installation, configId, null); 47 | } 48 | 49 | public static NodeJSCommandInterpreter createMock(String command, NodeJSInstallation installation, String configId, 50 | Verifier verifier) { 51 | MockCommandInterpreterBuilder spy = new MockCommandInterpreterBuilder(command, installation.getName(), configId); 52 | ExtensionList.lookupSingleton(NodeJSInstallation.DescriptorImpl.class).setInstallations(installation); 53 | spy.setVerifier(verifier); 54 | return spy; 55 | } 56 | 57 | static class MockCommandInterpreterBuilder extends NodeJSCommandInterpreter { 58 | 59 | // transient to ensure serialisation 60 | private transient CIBuilderHelper.Verifier verifier; 61 | 62 | private MockCommandInterpreterBuilder(String command, String nodeJSInstallationName, String configId) { 63 | super(command, nodeJSInstallationName, configId); 64 | } 65 | 66 | @Override 67 | protected boolean internalPerform(AbstractBuild build, Launcher launcher, TaskListener listener) throws InterruptedException { 68 | if (verifier != null) { 69 | try { 70 | verifier.verify(build, launcher, listener); 71 | } catch (Exception e) { 72 | throw new RuntimeException(e); 73 | } 74 | } 75 | return true; 76 | } 77 | 78 | private void setVerifier(Verifier verifier) { 79 | this.verifier = verifier; 80 | } 81 | 82 | @Override 83 | public Descriptor getDescriptor() { 84 | return ExtensionList.lookupSingleton(NodeJSCommandInterpreter.NodeJsDescriptor.class); 85 | } 86 | 87 | } 88 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/JCasCTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2020, Evaristo Gutierrez 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import static org.hamcrest.MatcherAssert.assertThat; 27 | import static org.hamcrest.Matchers.allOf; 28 | import static org.hamcrest.Matchers.arrayWithSize; 29 | import static org.hamcrest.Matchers.containsInAnyOrder; 30 | import static org.hamcrest.Matchers.equalTo; 31 | import static org.hamcrest.Matchers.hasProperty; 32 | import static org.hamcrest.Matchers.hasSize; 33 | import static org.hamcrest.Matchers.instanceOf; 34 | import static org.junit.Assert.assertEquals; 35 | import static org.junit.Assert.assertTrue; 36 | 37 | import java.util.List; 38 | 39 | import org.jenkinsci.lib.configprovider.model.Config; 40 | import org.jenkinsci.plugins.configfiles.ConfigFiles; 41 | import org.junit.Assert; 42 | import org.jvnet.hudson.test.RestartableJenkinsRule; 43 | 44 | import hudson.tools.BatchCommandInstaller; 45 | import hudson.tools.CommandInstaller; 46 | import hudson.tools.InstallSourceProperty; 47 | import hudson.tools.ToolDescriptor; 48 | import hudson.tools.ToolInstallation; 49 | import hudson.tools.ToolProperty; 50 | import hudson.tools.ToolPropertyDescriptor; 51 | import hudson.tools.ZipExtractionInstaller; 52 | import hudson.util.DescribableList; 53 | import io.jenkins.plugins.casc.misc.RoundTripAbstractTest; 54 | import jenkins.model.Jenkins; 55 | import jenkins.plugins.nodejs.configfiles.NPMConfig; 56 | import jenkins.plugins.nodejs.configfiles.NPMRegistry; 57 | import jenkins.plugins.nodejs.tools.NodeJSInstallation; 58 | import jenkins.plugins.nodejs.tools.NodeJSInstaller; 59 | 60 | public class JCasCTest extends RoundTripAbstractTest { 61 | 62 | @Override 63 | protected void assertConfiguredAsExpected(RestartableJenkinsRule restartableJenkinsRule, String s) { 64 | checkConfigFile(restartableJenkinsRule.j.jenkins); 65 | checkInstallations(restartableJenkinsRule.j.jenkins); 66 | } 67 | 68 | private void checkConfigFile(Jenkins j) { 69 | Config config = ConfigFiles.getByIdOrNull(j, "myconfigfile"); 70 | assertThat(config, instanceOf(NPMConfig.class)); 71 | 72 | NPMConfig npmConfig = (NPMConfig) config; 73 | assertEquals("myComment", npmConfig.comment); 74 | assertEquals("myContent", npmConfig.content); 75 | assertEquals("myConfig", npmConfig.name); 76 | assertEquals(true, npmConfig.isNpm9Format()); 77 | 78 | List registries = npmConfig.getRegistries(); 79 | Assert.assertTrue(registries.size() == 1); 80 | 81 | NPMRegistry registry = registries.get(0); 82 | assertTrue(registry.isHasScopes()); 83 | assertEquals("myScope", registry.getScopes()); 84 | assertEquals("registryUrl", registry.getUrl()); 85 | } 86 | 87 | private void checkInstallations(Jenkins j) { 88 | final ToolDescriptor descriptor = (ToolDescriptor) j.getDescriptor(NodeJSInstallation.class); 89 | final ToolInstallation[] installations = descriptor.getInstallations(); 90 | assertThat(installations, arrayWithSize(2)); 91 | 92 | ToolInstallation withInstaller = installations[0]; 93 | assertEquals("myNode", withInstaller.getName()); 94 | 95 | final DescribableList, ToolPropertyDescriptor> properties = withInstaller.getProperties(); 96 | assertThat(properties, hasSize(1)); 97 | final ToolProperty property = properties.get(0); 98 | 99 | assertThat(((InstallSourceProperty)property).installers, 100 | containsInAnyOrder( 101 | allOf(instanceOf(NodeJSInstaller.class), 102 | hasProperty("npmPackagesRefreshHours", equalTo(75L)), 103 | hasProperty("npmPackages", equalTo("globalPackages")), 104 | hasProperty("force32Bit", equalTo(true))), 105 | allOf(instanceOf(CommandInstaller.class), 106 | hasProperty("command", equalTo("install npm")), 107 | hasProperty("toolHome", equalTo("/my/path/1")), 108 | hasProperty("label", equalTo("npm command"))), 109 | allOf(instanceOf(ZipExtractionInstaller.class), 110 | hasProperty("url", equalTo("http://fake.com")), 111 | hasProperty("subdir", equalTo("/my/path/2")), 112 | hasProperty("label", equalTo("npm zip"))), 113 | allOf(instanceOf(BatchCommandInstaller.class), 114 | hasProperty("command", equalTo("run batch command")), 115 | hasProperty("toolHome", equalTo("/my/path/3")), 116 | hasProperty("label", equalTo("npm batch"))) 117 | )); 118 | 119 | ToolInstallation withoutInstaller = installations[1]; 120 | assertThat(withoutInstaller, 121 | allOf( 122 | hasProperty("name", equalTo("anotherNodeWithNoInstall")), 123 | hasProperty("home", equalTo("/onePath") 124 | ))); 125 | } 126 | 127 | @Override 128 | protected String stringInLogExpected() { 129 | return "Setting class jenkins.plugins.nodejs.configfiles.NPMConfig.id"; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/NodeJSSerialisationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2019, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import org.assertj.core.api.Assertions; 27 | import org.junit.Rule; 28 | import org.junit.Test; 29 | import org.junit.rules.TemporaryFolder; 30 | import org.jvnet.hudson.test.Issue; 31 | import org.jvnet.hudson.test.JenkinsRule; 32 | import org.jvnet.hudson.test.recipes.LocalData; 33 | 34 | import hudson.model.FreeStyleProject; 35 | import jenkins.plugins.nodejs.cache.DefaultCacheLocationLocator; 36 | import jenkins.plugins.nodejs.cache.PerJobCacheLocationLocator; 37 | 38 | public class NodeJSSerialisationTest { 39 | 40 | @Rule 41 | public JenkinsRule j = new JenkinsRule(); 42 | @Rule 43 | public TemporaryFolder fileRule = new TemporaryFolder(); 44 | 45 | /** 46 | * Verify that the serialisation is backward compatible. 47 | */ 48 | @LocalData 49 | @Test 50 | @Issue("JENKINS-57844") 51 | public void test_serialisation_is_compatible_with_version_1_2_x_interpreter() throws Exception { 52 | FreeStyleProject prj = j.jenkins.getAllItems(hudson.model.FreeStyleProject.class) // 53 | .stream() // 54 | .filter(p -> "test".equals(p.getName())) // 55 | .findFirst().get(); 56 | 57 | NodeJSCommandInterpreter step = prj.getBuildersList().get(NodeJSCommandInterpreter.class); 58 | Assertions.assertThat(step.getCacheLocationStrategy()).isInstanceOf(DefaultCacheLocationLocator.class); 59 | } 60 | 61 | /** 62 | * Verify reloading jenkins job configuration use the saved cache strategy instead reset to default. 63 | */ 64 | @LocalData 65 | @Test 66 | @Issue("JENKINS-58029") 67 | public void test_reloading_job_configuration_contains_saved_cache_strategy_interpreter() throws Exception { 68 | FreeStyleProject prj = j.jenkins.getAllItems(hudson.model.FreeStyleProject.class) // 69 | .stream() // 70 | .filter(p -> "test".equals(p.getName())) // 71 | .findFirst().get(); 72 | 73 | NodeJSCommandInterpreter step = prj.getBuildersList().get(NodeJSCommandInterpreter.class); 74 | Assertions.assertThat(step.getCacheLocationStrategy()).isInstanceOf(PerJobCacheLocationLocator.class); 75 | } 76 | 77 | /** 78 | * Verify that the serialisation is backward compatible. 79 | */ 80 | @LocalData 81 | @Test 82 | @Issue("JENKINS-57844") 83 | public void test_serialisation_is_compatible_with_version_1_2_x_buildWrapper() throws Exception { 84 | FreeStyleProject prj = j.jenkins.getAllItems(hudson.model.FreeStyleProject.class) // 85 | .stream() // 86 | .filter(p -> "test".equals(p.getName())) // 87 | .findFirst().get(); 88 | 89 | NodeJSBuildWrapper step = prj.getBuildWrappersList().get(NodeJSBuildWrapper.class); 90 | Assertions.assertThat(step.getCacheLocationStrategy()).isInstanceOf(DefaultCacheLocationLocator.class); 91 | } 92 | 93 | /** 94 | * Verify reloading jenkins job configuration use the saved cache strategy instead reset to default. 95 | */ 96 | @LocalData 97 | @Test 98 | @Issue("JENKINS-58029") 99 | public void test_reloading_job_configuration_contains_saved_cache_strategy_buildWrapper() throws Exception { 100 | FreeStyleProject prj = j.jenkins.getAllItems(hudson.model.FreeStyleProject.class) // 101 | .stream() // 102 | .filter(p -> "test".equals(p.getName())) // 103 | .findFirst().get(); 104 | 105 | NodeJSBuildWrapper step = prj.getBuildWrappersList().get(NodeJSBuildWrapper.class); 106 | Assertions.assertThat(step.getCacheLocationStrategy()).isInstanceOf(PerJobCacheLocationLocator.class); 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/NpmrcFileSupplyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import static org.junit.Assert.assertEquals; 27 | import static org.junit.Assert.assertTrue; 28 | 29 | import java.io.File; 30 | import java.util.ArrayList; 31 | import java.util.Arrays; 32 | import java.util.List; 33 | 34 | import org.jenkinsci.lib.configprovider.model.Config; 35 | import org.jenkinsci.lib.configprovider.model.ConfigFile; 36 | import org.jenkinsci.lib.configprovider.model.ConfigFileManager; 37 | import org.jenkinsci.plugins.configfiles.GlobalConfigFiles; 38 | import org.junit.Rule; 39 | import org.junit.Test; 40 | import org.jvnet.hudson.test.JenkinsRule; 41 | 42 | import com.cloudbees.plugins.credentials.CredentialsScope; 43 | import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials; 44 | import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; 45 | 46 | import hudson.FilePath; 47 | import hudson.model.FreeStyleBuild; 48 | import hudson.model.Descriptor.FormException; 49 | import jenkins.plugins.nodejs.configfiles.NPMConfig; 50 | import jenkins.plugins.nodejs.configfiles.NPMRegistry; 51 | import jenkins.plugins.nodejs.configfiles.Npmrc; 52 | 53 | public class NpmrcFileSupplyTest { 54 | 55 | @Rule 56 | public JenkinsRule j = new JenkinsRule(); 57 | 58 | @Test 59 | public void test_supply_npmrc_with_registry() throws Exception { 60 | StandardUsernameCredentials user = createUser("test-user-id", "myuser", "mypassword"); 61 | NPMRegistry privateRegistry = new NPMRegistry("https://private.organization.com/", user.getId(), null); 62 | NPMRegistry officalRegistry = new NPMRegistry("https://registry.npmjs.org/", null, "@user1 user2"); 63 | 64 | Config config = createSetting("mytest", "email=guest@example.com", Arrays.asList(privateRegistry, officalRegistry)); 65 | 66 | FreeStyleBuild build = j.buildAndAssertSuccess(j.createFreeStyleProject()); 67 | 68 | FilePath npmrcFile = ConfigFileManager.provisionConfigFile(new ConfigFile(config.id, null, true), null, build, build.getWorkspace(), j.createTaskListener(), new ArrayList(1)); 69 | assertTrue(npmrcFile.exists()); 70 | assertTrue(npmrcFile.length() > 0); 71 | 72 | Npmrc npmrc = Npmrc.load(new File(npmrcFile.getRemote())); 73 | assertTrue("Missing setting email", npmrc.contains("email")); 74 | assertEquals("Unexpected value from settings email", "guest@example.com", npmrc.get("email")); 75 | } 76 | 77 | private StandardUsernameCredentials createUser(String id, String username, String password) throws FormException { 78 | return new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, id, null, username, password); 79 | } 80 | 81 | private Config createSetting(String id, String content, List registries) { 82 | Config config = new NPMConfig(id, null, null, content, registries); 83 | 84 | GlobalConfigFiles globalConfigFiles = j.jenkins.getExtensionList(GlobalConfigFiles.class) 85 | .get(GlobalConfigFiles.class); 86 | globalConfigFiles.save(config); 87 | return config; 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/SimpleNodeJSCommandInterpreterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import hudson.FilePath; 27 | import hudson.model.Descriptor; 28 | import jenkins.plugins.nodejs.Messages; 29 | import jenkins.plugins.nodejs.tools.NodeJSInstallation; 30 | import hudson.tasks.Builder; 31 | import hudson.tools.ToolProperty; 32 | 33 | import org.junit.Before; 34 | import org.junit.Rule; 35 | import org.junit.Test; 36 | import org.junit.rules.TemporaryFolder; 37 | 38 | import java.io.IOException; 39 | import java.util.Collections; 40 | 41 | import static org.junit.Assert.*; 42 | 43 | public class SimpleNodeJSCommandInterpreterTest { 44 | 45 | private static final String COMMAND = "var sys = require('sys'); sys.puts('build number: ' + process.env['BUILD_NUMBER']);"; 46 | 47 | private NodeJSCommandInterpreter interpreter; 48 | private Descriptor descriptor; 49 | private NodeJSInstallation installation; 50 | 51 | @Rule 52 | public TemporaryFolder tempFolder = new TemporaryFolder(); 53 | 54 | @Before 55 | public void setUp() { 56 | installation = new NodeJSInstallation("11.0.0", "", Collections.>emptyList()); 57 | interpreter = new NodeJSCommandInterpreter(COMMAND, installation.getName(), null); 58 | descriptor = new NodeJSCommandInterpreter.NodeJsDescriptor(); 59 | } 60 | 61 | @Test 62 | public void testGetContentsShouldGiveExpectedValue() { 63 | assertEquals(COMMAND, interpreter.getCommand()); 64 | } 65 | 66 | @Test 67 | public void testGetContentWithEmptyCommandShouldGiveExpectedValue() { 68 | assertEquals("", new NodeJSCommandInterpreter("", installation.getName(), null).getCommand()); 69 | } 70 | 71 | @Test 72 | public void testGetContentWithNullCommandShouldGiveExpectedValue() { 73 | assertNull(new NodeJSCommandInterpreter(null, installation.getName(), null).getCommand()); 74 | } 75 | 76 | @Test 77 | public void testGetFileExtensionShouldGiveExpectedValue() throws IOException, InterruptedException { 78 | assertEquals(true, interpreter.createScriptFile(new FilePath(tempFolder.newFolder())).getName().endsWith(".js")); 79 | } 80 | 81 | @Test 82 | public void testGetDescriptorShouldGiveExpectedValue() { 83 | assertNotNull(descriptor); 84 | assertTrue(descriptor instanceof Descriptor); 85 | } 86 | 87 | @Test 88 | public void testDescriptorGetDisplayNameShouldGiveExpectedValue() { 89 | assertEquals(Messages.NodeJSCommandInterpreter_displayName(), descriptor.getDisplayName()); 90 | } 91 | 92 | @Test 93 | public void testDescriptorGetHelpFileShouldGiveExpectedValue() { 94 | assertEquals("/plugin/nodejs/help.html", descriptor.getHelpFile()); 95 | } 96 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/TestCacheLocationLocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2019, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import hudson.Extension; 27 | import hudson.FilePath; 28 | import java.io.File; 29 | import jenkins.plugins.nodejs.cache.CacheLocationLocator; 30 | import jenkins.plugins.nodejs.cache.CacheLocationLocatorDescriptor; 31 | 32 | public class TestCacheLocationLocator extends CacheLocationLocator { 33 | 34 | private File location; 35 | 36 | public TestCacheLocationLocator(File location) { 37 | this.location = location; 38 | } 39 | 40 | @Override 41 | public FilePath locate(FilePath workspace) { 42 | return new FilePath(location); 43 | } 44 | 45 | @Extension 46 | public static class DescriptorImpl extends CacheLocationLocatorDescriptor { 47 | @Override 48 | public String getDisplayName() { 49 | return "test cache locator"; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/VerifyEnvVariableBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs; 25 | 26 | import static org.junit.Assert.*; 27 | 28 | import java.io.File; 29 | import java.io.IOException; 30 | 31 | import hudson.EnvVars; 32 | import hudson.Launcher; 33 | import hudson.model.AbstractBuild; 34 | import hudson.model.BuildListener; 35 | import hudson.tasks.Builder; 36 | 37 | abstract class VerifyEnvVariableBuilder extends Builder { 38 | @Override 39 | public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { 40 | EnvVars env = build.getEnvironment(listener); 41 | verify(env); 42 | return true; 43 | } 44 | 45 | public abstract void verify(EnvVars env); 46 | 47 | public static final class FileVerifier extends VerifyEnvVariableBuilder { 48 | @Override 49 | public void verify(EnvVars env) { 50 | String var = NodeJSConstants.NPM_USERCONFIG; 51 | String value = env.get(var); 52 | 53 | assertTrue("variable " + var + " not set", env.containsKey(var)); 54 | assertNotNull("empty value for environment variable " + var, value); 55 | assertTrue("file of variable " + var + " does not exists or is not a file", new File(value).isFile()); 56 | } 57 | } 58 | 59 | public static final class EnvVarVerifier extends VerifyEnvVariableBuilder { 60 | 61 | private final String name; 62 | private final String value; 63 | 64 | public EnvVarVerifier(String name, String value) { 65 | this.name = name; 66 | this.value = value; 67 | } 68 | 69 | @Override 70 | public void verify(EnvVars env) { 71 | String envValue = env.get(name); 72 | 73 | assertTrue("variable " + name + " not set", env.containsKey(name)); 74 | assertEquals(value, envValue); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/cache/CacheLocationLocatorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.cache; 25 | 26 | import hudson.FilePath; 27 | import hudson.model.Computer; 28 | import hudson.model.Executor; 29 | import hudson.model.Node; 30 | import org.junit.Assert; 31 | import org.junit.Before; 32 | import org.junit.Rule; 33 | import org.junit.Test; 34 | import org.junit.rules.TemporaryFolder; 35 | import org.mockito.MockedStatic; 36 | 37 | import static org.mockito.Mockito.mock; 38 | import static org.mockito.Mockito.mockStatic; 39 | import static org.mockito.Mockito.when; 40 | 41 | public class CacheLocationLocatorTest { 42 | 43 | @Rule 44 | public TemporaryFolder fileRule = new TemporaryFolder(); 45 | private FilePath workspace; 46 | 47 | @Before 48 | public void setup() throws Exception { 49 | workspace = new FilePath(fileRule.newFolder()); 50 | } 51 | 52 | @Test 53 | public void test_default() { 54 | Assert.assertNull("expect null location path", new DefaultCacheLocationLocator().locate(workspace)); 55 | } 56 | 57 | @Test 58 | public void test_per_job() throws Exception { 59 | Assert.assertEquals("expect the same location path passes as input", workspace.child(".npm"), new PerJobCacheLocationLocator().locate(workspace)); 60 | } 61 | 62 | @Test 63 | public void test_per_executor() throws Exception { 64 | FilePath wc = mock(FilePath.class); 65 | Executor executor = mock(Executor.class); 66 | int executorNumber = 7; 67 | when(executor.getNumber()).thenReturn(executorNumber); 68 | 69 | try (MockedStatic staticExecutor = mockStatic(Executor.class)) { 70 | staticExecutor.when(Executor::currentExecutor).thenReturn(executor); 71 | 72 | Computer computer = mock(Computer.class); 73 | Node node = mock(Node.class); 74 | when(computer.getNode()).thenReturn(node); 75 | FilePath rootPath = new FilePath(fileRule.newFolder()); 76 | when(node.getRootPath()).thenReturn(rootPath); 77 | when(wc.toComputer()).thenReturn(computer); 78 | 79 | FilePath expectedLocation = rootPath.child("npm-cache").child(String.valueOf(executorNumber)); 80 | Assert.assertEquals("expect null location path", expectedLocation, new PerExecutorCacheLocationLocator().locate(wc)); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/configfiles/NPMConfigTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.configfiles; 25 | 26 | import static org.junit.Assert.assertNotNull; 27 | 28 | import org.assertj.core.api.Assertions; 29 | import org.jenkinsci.lib.configprovider.model.Config; 30 | import org.junit.Rule; 31 | import org.junit.Test; 32 | import org.jvnet.hudson.test.JenkinsRule; 33 | 34 | import hudson.model.Descriptor; 35 | import jenkins.plugins.nodejs.configfiles.NPMConfig.NPMConfigProvider; 36 | 37 | public class NPMConfigTest { 38 | 39 | @Rule 40 | public JenkinsRule j = new JenkinsRule(); 41 | 42 | @Test 43 | public void test_load_template() { 44 | Descriptor descriptor = j.jenkins.getDescriptor(NPMConfig.class); 45 | assertNotNull("NPMConfig descriptor not registered", descriptor); 46 | Assertions.assertThat(descriptor).isInstanceOf(NPMConfigProvider.class).describedAs("Unexpected descriptor class"); 47 | 48 | NPMConfigProvider provider = (NPMConfigProvider) descriptor; 49 | Config config = provider.newConfig("testId"); 50 | Assertions.assertThat(config).isInstanceOf(NPMConfig.class).describedAs("Unexpected config class"); 51 | Assertions.assertThat(config.content).isNotBlank().describedAs("Expected the default template, instead got empty"); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/configfiles/NPMConfigValidationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.configfiles; 25 | 26 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; 27 | import static org.junit.Assert.assertEquals; 28 | import static org.junit.Assert.assertNotNull; 29 | import static org.junit.Assert.assertNull; 30 | 31 | import java.util.Arrays; 32 | 33 | import org.junit.Test; 34 | 35 | public class NPMConfigValidationTest { 36 | 37 | @Test 38 | public void test_new_config() { 39 | String id = "test_id"; 40 | NPMConfig config = new NPMConfig(id, "", "", "", null); 41 | assertEquals(id, config.id); 42 | assertNull(config.name); 43 | assertNull(config.comment); 44 | assertNull(config.content); 45 | assertNotNull(config.getRegistries()); 46 | } 47 | 48 | @Test 49 | public void test_too_many_global_registries() throws Exception { 50 | NPMRegistry privateRegistry = new NPMRegistry("https://private.organization.com/", null, null); 51 | NPMRegistry officalRegistry = new NPMRegistry("https://registry.npmjs.org/", null, null); 52 | 53 | NPMConfig config = new NPMConfig("too_many_registry", null, null, null, Arrays.asList(privateRegistry, officalRegistry)); 54 | 55 | assertThatExceptionOfType(VerifyConfigProviderException.class) // 56 | .isThrownBy(() -> config.doVerify()); 57 | } 58 | 59 | @Test 60 | public void test_empty_URL() throws Exception { 61 | NPMRegistry registry = new NPMRegistry("", null, null); 62 | 63 | NPMConfig config = new NPMConfig("empty_URL", null, null, null, Arrays.asList(registry)); 64 | 65 | assertThatExceptionOfType(VerifyConfigProviderException.class) // 66 | .isThrownBy(() -> config.doVerify()); 67 | } 68 | 69 | @Test 70 | public void test_no_exception_if_URL_has_variable() throws Exception { 71 | NPMRegistry registry = new NPMRegistry("${URL}", null, null); 72 | 73 | NPMConfig config = new NPMConfig("no_exception_if_URL_has_variable", null, null, null, Arrays.asList(registry)); 74 | config.doVerify(); 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/configfiles/NPMRegistryValidator2Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.configfiles; 25 | 26 | import static org.mockito.ArgumentMatchers.any; 27 | import static org.mockito.ArgumentMatchers.anyString; 28 | import static org.mockito.ArgumentMatchers.isA; 29 | import static org.mockito.Mockito.mock; 30 | import static org.mockito.Mockito.when; 31 | 32 | import java.util.Arrays; 33 | import java.util.HashMap; 34 | import java.util.List; 35 | import java.util.Map; 36 | 37 | import org.assertj.core.api.Assertions; 38 | import org.junit.ClassRule; 39 | import org.junit.Test; 40 | import org.jvnet.hudson.test.JenkinsRule; 41 | 42 | import com.cloudbees.plugins.credentials.Credentials; 43 | import com.cloudbees.plugins.credentials.CredentialsScope; 44 | import com.cloudbees.plugins.credentials.SystemCredentialsProvider; 45 | import com.cloudbees.plugins.credentials.domains.Domain; 46 | import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; 47 | 48 | import hudson.model.FreeStyleProject; 49 | import hudson.model.Item; 50 | import hudson.security.Permission; 51 | import hudson.util.FormValidation; 52 | import hudson.util.FormValidation.Kind; 53 | import jenkins.plugins.nodejs.configfiles.NPMRegistry.DescriptorImpl; 54 | 55 | /** 56 | * Test input form validation. 57 | * 58 | * @author Nikolas Falco 59 | */ 60 | public class NPMRegistryValidator2Test { 61 | 62 | 63 | @ClassRule 64 | public static JenkinsRule rule = new JenkinsRule(); 65 | 66 | @Test 67 | public void test_credentials_ok() throws Exception { 68 | String credentialsId = "secret"; 69 | Credentials credentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, credentialsId, "", "user", "password"); 70 | Map> credentialsMap = new HashMap<>(); 71 | credentialsMap.put(Domain.global(), Arrays.asList(credentials)); 72 | SystemCredentialsProvider.getInstance().setDomainCredentialsMap(credentialsMap); 73 | 74 | FreeStyleProject prj = mock(FreeStyleProject.class); 75 | when(prj.hasPermission(isA(Permission.class))).thenReturn(true); 76 | 77 | DescriptorImpl descriptor = mock(DescriptorImpl.class); 78 | when(descriptor.doCheckCredentialsId(any(Item.class), (String) any(), anyString())).thenCallRealMethod(); 79 | 80 | String serverURL = "http://acme.com"; 81 | 82 | FormValidation result = descriptor.doCheckCredentialsId(prj, credentialsId, serverURL); 83 | Assertions.assertThat(result.kind).isEqualTo(Kind.OK); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/configfiles/NPMRegistryValidatorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.configfiles; 25 | 26 | import static org.mockito.ArgumentMatchers.any; 27 | import static org.mockito.ArgumentMatchers.anyString; 28 | import static org.mockito.ArgumentMatchers.isA; 29 | import static org.mockito.Mockito.mock; 30 | import static org.mockito.Mockito.when; 31 | 32 | import org.assertj.core.api.Assertions; 33 | import org.junit.Test; 34 | 35 | import hudson.model.FreeStyleProject; 36 | import hudson.model.Item; 37 | import hudson.security.Permission; 38 | import hudson.util.FormValidation; 39 | import hudson.util.FormValidation.Kind; 40 | import jenkins.plugins.nodejs.Messages; 41 | import jenkins.plugins.nodejs.configfiles.NPMRegistry.DescriptorImpl; 42 | 43 | /** 44 | * Test input form validation. 45 | * 46 | * @author Nikolas Falco 47 | */ 48 | public class NPMRegistryValidatorTest { 49 | 50 | @Test 51 | public void test_empty_scopes() throws Exception { 52 | DescriptorImpl descriptor = new DescriptorImpl(); 53 | 54 | FormValidation result = descriptor.doCheckScopes(true, ""); 55 | Assertions.assertThat(result.kind).isEqualTo(Kind.ERROR); 56 | Assertions.assertThat(result.getMessage()).isEqualTo(Messages.NPMRegistry_DescriptorImpl_emptyScopes()); 57 | } 58 | 59 | @Test 60 | public void test_scopes_with_at_in_name() throws Exception { 61 | DescriptorImpl descriptor = new DescriptorImpl(); 62 | 63 | FormValidation result = descriptor.doCheckScopes(true, "@scope1"); 64 | Assertions.assertThat(result.kind).isEqualTo(Kind.WARNING); 65 | Assertions.assertThat(result.getMessage()).isEqualTo(Messages.NPMRegistry_DescriptorImpl_invalidCharInScopes()); 66 | } 67 | 68 | @Test 69 | public void test_invalid_scopes() throws Exception { 70 | DescriptorImpl descriptor = new DescriptorImpl(); 71 | 72 | FormValidation result = descriptor.doCheckScopes(true, "@"); 73 | Assertions.assertThat(result.kind).isEqualTo(Kind.ERROR); 74 | Assertions.assertThat(result.getMessage()).isEqualTo(Messages.NPMRegistry_DescriptorImpl_invalidScopes()); 75 | } 76 | 77 | @Test 78 | public void test_scopes_ok() throws Exception { 79 | DescriptorImpl descriptor = new DescriptorImpl(); 80 | 81 | FormValidation result = descriptor.doCheckScopes(true, "scope1 scope2 scope3"); 82 | Assertions.assertThat(result.kind).isEqualTo(Kind.OK); 83 | } 84 | 85 | @Test 86 | public void test_empty_server_url() throws Exception { 87 | DescriptorImpl descriptor = new DescriptorImpl(); 88 | 89 | FormValidation result = descriptor.doCheckUrl(""); 90 | Assertions.assertThat(result.kind).isEqualTo(Kind.ERROR); 91 | Assertions.assertThat(result.getMessage()).isEqualTo(Messages.NPMRegistry_DescriptorImpl_emptyRegistryURL()); 92 | } 93 | 94 | @Test 95 | public void test_server_url_that_contains_variable() throws Exception { 96 | DescriptorImpl descriptor = new DescriptorImpl(); 97 | 98 | FormValidation result = descriptor.doCheckUrl("${REGISTRY_URL}/root"); 99 | Assertions.assertThat(result.kind).isEqualTo(Kind.OK); 100 | result = descriptor.doCheckUrl("http://${SERVER_NAME}/root"); 101 | Assertions.assertThat(result.kind).isEqualTo(Kind.OK); 102 | result = descriptor.doCheckUrl("http://acme.com/${CONTEXT_ROOT}"); 103 | Assertions.assertThat(result.kind).isEqualTo(Kind.OK); 104 | } 105 | 106 | @Test 107 | public void test_empty_server_url_is_ok() throws Exception { 108 | DescriptorImpl descriptor = new DescriptorImpl(); 109 | 110 | FormValidation result = descriptor.doCheckUrl("http://acme.com"); 111 | Assertions.assertThat(result.kind).isEqualTo(Kind.OK); 112 | } 113 | 114 | @Test 115 | public void test_server_url_invalid_protocol() throws Exception { 116 | DescriptorImpl descriptor = new DescriptorImpl(); 117 | 118 | FormValidation result = descriptor.doCheckUrl("hpp://acme.com/root"); 119 | Assertions.assertThat(result.kind).isEqualTo(Kind.ERROR); 120 | Assertions.assertThat(result.getMessage()).isEqualTo(Messages.NPMRegistry_DescriptorImpl_invalidRegistryURL()); 121 | } 122 | 123 | @Test 124 | public void test_invalid_credentials() throws Exception { 125 | FreeStyleProject prj = mock(FreeStyleProject.class); 126 | when(prj.hasPermission(isA(Permission.class))).thenReturn(true); 127 | 128 | DescriptorImpl descriptor = mock(DescriptorImpl.class); 129 | when(descriptor.doCheckCredentialsId(any(Item.class), (String) any(), anyString())).thenCallRealMethod(); 130 | 131 | String credentialsId = "secret"; 132 | String serverURL = "http://acme.com"; 133 | 134 | FormValidation result = descriptor.doCheckCredentialsId(prj, credentialsId, serverURL); 135 | Assertions.assertThat(result.kind).isEqualTo(Kind.ERROR); 136 | Assertions.assertThat(result.getMessage()).isEqualTo(Messages.NPMRegistry_DescriptorImpl_invalidCredentialsId()); 137 | 138 | when(prj.hasPermission(isA(Permission.class))).thenReturn(false); 139 | result = descriptor.doCheckCredentialsId(prj, credentialsId, serverURL); 140 | Assertions.assertThat(result.kind).isEqualTo(Kind.OK); 141 | } 142 | 143 | @Test 144 | public void test_empty_credentials() throws Exception { 145 | FreeStyleProject prj = mock(FreeStyleProject.class); 146 | when(prj.hasPermission(isA(Permission.class))).thenReturn(true); 147 | 148 | DescriptorImpl descriptor = mock(DescriptorImpl.class); 149 | when(descriptor.doCheckCredentialsId(any(Item.class), (String) any(), anyString())).thenCallRealMethod(); 150 | 151 | String serverURL = "http://acme.com"; 152 | 153 | FormValidation result = descriptor.doCheckCredentialsId(prj, "", serverURL); 154 | Assertions.assertThat(result.kind).isEqualTo(Kind.WARNING); 155 | Assertions.assertThat(result.getMessage()).isEqualTo(Messages.NPMRegistry_DescriptorImpl_emptyCredentialsId()); 156 | result = descriptor.doCheckCredentialsId(prj, null, serverURL); 157 | Assertions.assertThat(result.kind).isEqualTo(Kind.WARNING); 158 | Assertions.assertThat(result.getMessage()).isEqualTo(Messages.NPMRegistry_DescriptorImpl_emptyCredentialsId()); 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/configfiles/NpmrcTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.configfiles; 25 | 26 | import static org.junit.Assert.assertEquals; 27 | import static org.junit.Assert.assertFalse; 28 | import static org.junit.Assert.assertTrue; 29 | 30 | import java.io.File; 31 | import java.io.FileInputStream; 32 | import java.io.IOException; 33 | import java.io.InputStream; 34 | import java.util.List; 35 | 36 | import org.apache.commons.io.IOUtils; 37 | import org.junit.Before; 38 | import org.junit.Rule; 39 | import org.junit.Test; 40 | import org.junit.rules.TemporaryFolder; 41 | 42 | public class NpmrcTest { 43 | 44 | @Rule 45 | public TemporaryFolder folder = new TemporaryFolder(); 46 | private File file; 47 | 48 | @Before 49 | public void setUp() throws IOException { 50 | InputStream is = null; 51 | try { 52 | is = getClass().getResourceAsStream("npmrc.config"); 53 | file = folder.newFile(".npmrc"); 54 | hudson.util.IOUtils.copy(is, file); 55 | } finally { 56 | IOUtils.closeQuietly(is); 57 | } 58 | } 59 | 60 | @Test 61 | public void testLoad() throws Exception { 62 | Npmrc npmrc = Npmrc.load(file); 63 | assertTrue(npmrc.contains("always-auth")); 64 | assertEquals("true", npmrc.get("always-auth")); 65 | assertEquals("\"/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/Node_6.x\"", 66 | npmrc.get("prefix")); 67 | } 68 | 69 | @Test 70 | public void testAvoidParseError() throws Exception { 71 | Npmrc npmrc = Npmrc.load(file); 72 | assertFalse(npmrc.contains("browser")); 73 | } 74 | 75 | @Test 76 | public void testSave() throws Exception { 77 | String testKey = "test"; 78 | String testValue = "value"; 79 | 80 | Npmrc npmrc = Npmrc.load(file); 81 | npmrc.set(testKey, testValue); 82 | npmrc.save(file); 83 | 84 | // reload content 85 | npmrc = Npmrc.load(file); 86 | assertTrue(npmrc.contains(testKey)); 87 | assertEquals(testValue, npmrc.get(testKey)); 88 | } 89 | 90 | @Test 91 | public void testCommandAtLast() throws Exception { 92 | String comment = "test comment"; 93 | 94 | Npmrc npmrc = Npmrc.load(file); 95 | npmrc.addComment(comment); 96 | npmrc.save(file); 97 | 98 | try (InputStream is = new FileInputStream(file)) { 99 | List lines = IOUtils.readLines(is, "UTF-8"); 100 | assertEquals(';' + comment, lines.get(lines.size() - 1)); 101 | } 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/configfiles/RegistryHelperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.configfiles; 25 | 26 | import static org.junit.Assert.assertEquals; 27 | import static org.junit.Assert.assertFalse; 28 | 29 | import java.util.Arrays; 30 | import java.util.Map; 31 | 32 | import org.assertj.core.api.Assertions; 33 | import org.jenkinsci.plugins.plaincredentials.StringCredentials; 34 | import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl; 35 | import org.junit.Before; 36 | import org.junit.ClassRule; 37 | import org.junit.Test; 38 | import org.jvnet.hudson.test.JenkinsRule; 39 | 40 | import com.cloudbees.plugins.credentials.CredentialsProvider; 41 | import com.cloudbees.plugins.credentials.CredentialsScope; 42 | import com.cloudbees.plugins.credentials.CredentialsStore; 43 | import com.cloudbees.plugins.credentials.common.StandardCredentials; 44 | import com.cloudbees.plugins.credentials.common.StandardUsernameCredentials; 45 | import com.cloudbees.plugins.credentials.domains.Domain; 46 | import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; 47 | 48 | import hudson.model.FreeStyleBuild; 49 | import hudson.util.Secret; 50 | 51 | public class RegistryHelperTest { 52 | 53 | @ClassRule 54 | public static JenkinsRule j = new JenkinsRule(); 55 | 56 | private StandardUsernameCredentials user; 57 | private StringCredentials token; 58 | 59 | @Before 60 | public void setUp() throws Exception { 61 | user = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "privateId", "dummy desc", "myuser", "mypassword"); 62 | token = new StringCredentialsImpl(CredentialsScope.GLOBAL, "privateToken", "dummy desc", Secret.fromString("mysecret")); 63 | CredentialsStore store = CredentialsProvider.lookupStores(j.getInstance()).iterator().next(); 64 | store.addCredentials(Domain.global(), user); 65 | store.addCredentials(Domain.global(), token); 66 | } 67 | 68 | @Test 69 | public void test_registry_credentials_resolution() throws Exception { 70 | NPMRegistry privateRegistry = new NPMRegistry("https://private.organization.com/", user.getId(), null); 71 | NPMRegistry officalRegistry = new NPMRegistry("https://registry.npmjs.org/", null, "@user1 user2"); 72 | 73 | FreeStyleBuild build = j.createFreeStyleProject().createExecutable(); 74 | 75 | RegistryHelper helper = new RegistryHelper(Arrays.asList(privateRegistry, officalRegistry)); 76 | Map resolvedCredentials = helper.resolveCredentials(build); 77 | assertFalse(resolvedCredentials.isEmpty()); 78 | assertEquals(1, resolvedCredentials.size()); 79 | 80 | Assertions.assertThat(resolvedCredentials.keySet().contains(privateRegistry.getUrl())); 81 | Assertions.assertThat(resolvedCredentials.get(privateRegistry.getUrl())).isEqualTo(user); 82 | } 83 | 84 | @Test 85 | public void test_registry_auth_token_credentials_resolution() throws Exception { 86 | NPMRegistry privateRegistry = new NPMRegistry("https://private.organization.com/", token.getId(), null); 87 | NPMRegistry officalRegistry = new NPMRegistry("https://registry.npmjs.org/", token.getId(), "@user1 user2"); 88 | 89 | FreeStyleBuild build = j.createFreeStyleProject().createExecutable(); 90 | 91 | RegistryHelper helper = new RegistryHelper(Arrays.asList(privateRegistry, officalRegistry)); 92 | Map resolvedCredentials = helper.resolveCredentials(build); 93 | assertFalse(resolvedCredentials.isEmpty()); 94 | assertEquals(2, resolvedCredentials.size()); 95 | 96 | Assertions.assertThat(resolvedCredentials.keySet().contains(privateRegistry.getUrl())); 97 | Assertions.assertThat(resolvedCredentials.get(privateRegistry.getUrl())).isEqualTo(token); 98 | Assertions.assertThat(resolvedCredentials.get(officalRegistry.getUrl())).isEqualTo(token); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/tools/CPUTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2021, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import org.assertj.core.api.Assertions; 27 | import org.junit.Test; 28 | import org.jvnet.hudson.test.Issue; 29 | 30 | public class CPUTest { 31 | 32 | @Test 33 | @Issue("JENKINS-64311") 34 | public void verify_aarch64() throws DetectionFailedException { 35 | String systemProperty = "os.arch"; 36 | 37 | String current = System.setProperty(systemProperty, "aarch64"); 38 | try { 39 | Assertions.assertThat(CPU.current()).isEqualTo(CPU.arm64); 40 | } finally { 41 | if (current != null) { 42 | System.setProperty(systemProperty, current); 43 | } else { 44 | System.clearProperty(systemProperty); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/tools/InstallerPathResolversTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import static org.junit.Assert.assertTrue; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.net.HttpURLConnection; 31 | import java.net.URL; 32 | import java.nio.charset.StandardCharsets; 33 | import java.util.ArrayList; 34 | import java.util.Collection; 35 | import java.util.TreeSet; 36 | 37 | import org.apache.commons.io.IOUtils; 38 | import org.assertj.core.api.Assertions; 39 | import org.junit.Test; 40 | import org.junit.runner.RunWith; 41 | import org.junit.runners.Parameterized; 42 | 43 | import com.google.common.base.Charsets; 44 | import com.google.common.io.Resources; 45 | 46 | import hudson.tools.DownloadFromUrlInstaller; 47 | import net.sf.json.JSONArray; 48 | import net.sf.json.JSONObject; 49 | 50 | @RunWith(Parameterized.class) 51 | public class InstallerPathResolversTest { 52 | private static Collection expectedURLs; 53 | 54 | private DownloadFromUrlInstaller.Installable installable; 55 | private final Platform platform; 56 | private final CPU cpu; 57 | private final boolean testDownload = false; 58 | private final boolean showDownloadURL = false; 59 | 60 | public InstallerPathResolversTest(DownloadFromUrlInstaller.Installable installable, Platform platform, CPU cpu, String testName) { 61 | this.installable = installable; 62 | this.platform = platform; 63 | this.cpu = cpu; 64 | } 65 | 66 | @Parameterized.Parameters(name = "{index}: {3}") 67 | public static Collection data() throws Exception { 68 | Collection testPossibleParams = new ArrayList(); 69 | 70 | try (InputStream is = InstallerPathResolversTest.class.getResourceAsStream("expectedURLs.txt")) { 71 | expectedURLs = new TreeSet<>(IOUtils.readLines(is, StandardCharsets.UTF_8)); 72 | } 73 | 74 | String installablesJSONStr = Resources.toString(Resources.getResource("updates/jenkins.plugins.nodejs.tools.NodeJSInstaller.json"), Charsets.UTF_8); 75 | JSONArray installables = JSONObject.fromObject(installablesJSONStr).getJSONArray("list"); 76 | for (int i = 0; i < installables.size(); i++) { 77 | DownloadFromUrlInstaller.Installable installable = (DownloadFromUrlInstaller.Installable) installables.getJSONObject(i).toBean(DownloadFromUrlInstaller.Installable.class); 78 | 79 | // Not testing pre-0.8.6 version because at the moment, installer 80 | // structure is not handled 81 | if (InstallerPathResolver.Factory.isVersionBlacklisted(installable.id)) { 82 | continue; 83 | } 84 | 85 | for (Platform platform : Platform.values()) { 86 | for (CPU cpu : CPU.values()) { 87 | if (cpu.name().equals("arm64") && (platform == Platform.WINDOWS || platform == Platform.SUNOS)) { 88 | // arm64 are only supported on linux and OSX 89 | continue; 90 | } 91 | if ((cpu.name().equals("armv6l") || cpu.name().equals("armv7l")) && platform != Platform.LINUX) { 92 | // armXl are only supported on linux 93 | continue; 94 | } 95 | if (platform == Platform.AIX && !cpu.name().equals("ppc64")) { 96 | // AIX only supports ppc64 97 | continue; 98 | } 99 | String testName = String.format("version=%s,cpu=%s,platform=%s", installable.id, cpu.name(), platform.name()); 100 | testPossibleParams.add(new Object[] { installable, platform, cpu, testName }); 101 | } 102 | } 103 | } 104 | 105 | return testPossibleParams; 106 | } 107 | 108 | @Test 109 | public void shouldNodeJSInstallerResolvedPathExist() throws IOException { 110 | InstallerPathResolver installerPathResolver = InstallerPathResolver.Factory.findResolverFor(this.installable.id); 111 | try { 112 | String path = installerPathResolver.resolvePathFor(installable.id, this.platform, this.cpu); 113 | URL url = new URL(installable.url + path); 114 | 115 | if (testDownload) { 116 | assertDownload(url); 117 | } else { 118 | Assertions.assertThat(expectedURLs).contains(url.toString()); 119 | } 120 | 121 | if (showDownloadURL) { 122 | System.out.println(url); 123 | } 124 | } catch (IllegalArgumentException e) { 125 | // some combo of platform and cpu are not supported by nodejs 126 | } 127 | } 128 | 129 | private void assertDownload(URL url) throws IOException { 130 | HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); 131 | try { 132 | urlConnection.setRequestMethod("GET"); 133 | urlConnection.setConnectTimeout(2000); 134 | urlConnection.connect(); 135 | int code = urlConnection.getResponseCode(); 136 | assertTrue(code >= 200 && code < 300); 137 | } finally { 138 | if (urlConnection != null) { 139 | urlConnection.disconnect(); 140 | } 141 | } 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/tools/MirrorNodeJSInstallerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import static org.mockito.ArgumentMatchers.any; 27 | import static org.mockito.Mockito.mock; 28 | import static org.mockito.Mockito.spy; 29 | import static org.mockito.Mockito.verify; 30 | import static org.mockito.Mockito.when; 31 | 32 | import java.io.IOException; 33 | import java.util.Arrays; 34 | import java.util.HashMap; 35 | import java.util.List; 36 | import java.util.Map; 37 | 38 | import org.assertj.core.api.Assertions; 39 | import org.junit.ClassRule; 40 | import org.junit.Test; 41 | import org.jvnet.hudson.test.JenkinsRule; 42 | import org.mockito.ArgumentCaptor; 43 | 44 | import com.cloudbees.plugins.credentials.Credentials; 45 | import com.cloudbees.plugins.credentials.CredentialsScope; 46 | import com.cloudbees.plugins.credentials.SystemCredentialsProvider; 47 | import com.cloudbees.plugins.credentials.domains.Domain; 48 | import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; 49 | 50 | import hudson.FilePath; 51 | import hudson.model.Node; 52 | import hudson.model.TaskListener; 53 | import hudson.tools.ToolInstallation; 54 | import hudson.tools.ToolInstallerDescriptor; 55 | import hudson.tools.DownloadFromUrlInstaller.Installable; 56 | 57 | public class MirrorNodeJSInstallerTest { 58 | 59 | @ClassRule 60 | public static JenkinsRule r = new JenkinsRule(); 61 | 62 | public static class MockMirrorNodeJSInstaller extends MirrorNodeJSInstaller { 63 | 64 | private Installable installable; 65 | 66 | public MockMirrorNodeJSInstaller(Installable installable, String mirrorURL) { 67 | super(installable.id, mirrorURL, null, 0); 68 | this.installable = installable; 69 | } 70 | 71 | @Override 72 | public boolean isUpToDate(FilePath expectedLocation, Installable i) throws IOException, InterruptedException { 73 | return true; 74 | } 75 | 76 | @SuppressWarnings({ "rawtypes", "unchecked" }) 77 | @Override 78 | public ToolInstallerDescriptor getDescriptor() { 79 | hudson.tools.DownloadFromUrlInstaller.DescriptorImpl descriptor = mock(hudson.tools.DownloadFromUrlInstaller.DescriptorImpl.class); 80 | try { 81 | when(descriptor.getInstallables()).thenReturn((List) Arrays.asList(installable)); 82 | } catch (IOException e) { 83 | } 84 | return descriptor; 85 | } 86 | } 87 | 88 | @Test 89 | public void verify_mirror_url_replacing() throws Exception { 90 | String installationId = "8.2.1"; 91 | String mirror = "http://npm.taobao.org/mirrors/node/"; 92 | 93 | Installable installable = new Installable(); 94 | installable.id = installationId; 95 | installable.url = "https://nodejs.org/dist/v8.2.1/"; 96 | 97 | MockMirrorNodeJSInstaller installer = spy(new MockMirrorNodeJSInstaller(installable, mirror)); 98 | 99 | ToolInstallation tool = mock(ToolInstallation.class); 100 | when(tool.getHome()).thenReturn("home"); 101 | 102 | Node node = r.getInstance().getComputer("").getNode(); 103 | installer.performInstallation(tool, node, mock(TaskListener.class)); 104 | 105 | ArgumentCaptor captor = ArgumentCaptor.forClass(Installable.class); 106 | verify(installer).isUpToDate(any(FilePath.class), captor.capture()); 107 | Assertions.assertThat(captor.getValue().url).startsWith("http://npm.taobao.org/mirrors/node/v8.2.1/node-v8.2.1"); 108 | } 109 | 110 | @Test 111 | public void verify_credentials_on_mirror_url() throws Exception { 112 | String credentialsId = "secret"; 113 | String installationId = "8.2.1"; 114 | String mirror = "http://npm.taobao.org/mirrors/node/"; 115 | 116 | Installable installable = new Installable(); 117 | installable.id = installationId; 118 | installable.url = "https://nodejs.org/dist/v8.2.1/"; 119 | 120 | Credentials credentials = new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, credentialsId, "", "user", "password"); 121 | Map> credentialsMap = new HashMap<>(); 122 | credentialsMap.put(Domain.global(), Arrays.asList(credentials)); 123 | SystemCredentialsProvider.getInstance().setDomainCredentialsMap(credentialsMap); 124 | 125 | MockMirrorNodeJSInstaller installer = spy(new MockMirrorNodeJSInstaller(installable, mirror)); 126 | installer.setCredentialsId(credentialsId); 127 | 128 | ToolInstallation tool = mock(ToolInstallation.class); 129 | when(tool.getHome()).thenReturn("home"); 130 | 131 | Node node = r.getInstance().getComputer("").getNode(); 132 | installer.performInstallation(tool, node, mock(TaskListener.class)); 133 | 134 | ArgumentCaptor captor = ArgumentCaptor.forClass(Installable.class); 135 | verify(installer).isUpToDate(any(FilePath.class), captor.capture()); 136 | Assertions.assertThat(captor.getValue().url).startsWith("http://user:password@npm.taobao.org/mirrors/node/node-v8.2.1"); 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/tools/NodeJSInstallationMockitoTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import static jenkins.plugins.nodejs.NodeJSConstants.*; 27 | import static org.junit.Assert.assertEquals; 28 | import static org.junit.Assert.assertNull; 29 | import static org.mockito.Mockito.anyMap; 30 | import static org.mockito.Mockito.anyString; 31 | import static org.mockito.Mockito.never; 32 | import static org.mockito.Mockito.spy; 33 | import static org.mockito.Mockito.verify; 34 | 35 | import hudson.EnvVars; 36 | import hudson.Functions; 37 | import org.junit.Test; 38 | import org.jvnet.hudson.test.Issue; 39 | 40 | public class NodeJSInstallationMockitoTest { 41 | 42 | /** 43 | * Ensure the use of {@link EnvVars#put(String, String)} instead 44 | * {@code EnvVars#override(String, String)} to respect the 45 | * {@link ToolInstallation#buildEnvVars(EnvVars)) API documentation. 46 | *

47 | * A lot stuff rely on that logic. 48 | */ 49 | @Issue("JENKINS-41947") 50 | @Test 51 | public void test_installer_environment() throws Exception { 52 | String nodeJSHome = "/home/nodejs"; 53 | String bin = nodeJSHome + "/bin"; 54 | 55 | NodeJSInstallation installer = spy(new NodeJSInstallation("test", nodeJSHome, null)); 56 | 57 | EnvVars env = spy(new EnvVars()); 58 | installer.buildEnvVars(env); 59 | verify(env, never()).override(anyString(), anyString()); 60 | verify(env, never()).overrideAll(anyMap()); 61 | 62 | assertEquals("Unexpected value for " + ENVVAR_NODEJS_HOME, nodeJSHome, env.get(ENVVAR_NODEJS_HOME)); 63 | assertEquals("Unexpected value for " + ENVVAR_NODE_HOME, nodeJSHome, env.get(ENVVAR_NODE_HOME)); 64 | assertEquals("Unexpected value for " + ENVVAR_NODEJS_PATH, Functions.isWindows() ? nodeJSHome : bin, env.get(ENVVAR_NODEJS_PATH)); 65 | assertNull("PATH variable should not appear in this environment", env.get("PATH")); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/tools/NodeJSInstallationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import org.htmlunit.html.HtmlButton; 27 | import org.htmlunit.html.HtmlForm; 28 | import org.htmlunit.html.HtmlPage; 29 | import hudson.model.Computer; 30 | import hudson.tools.InstallSourceProperty; 31 | import hudson.tools.ToolProperty; 32 | import hudson.tools.ToolPropertyDescriptor; 33 | import hudson.util.DescribableList; 34 | import java.io.File; 35 | import java.io.IOException; 36 | import java.lang.reflect.Method; 37 | import jenkins.model.Jenkins; 38 | import jenkins.plugins.nodejs.tools.NodeJSInstallation.DescriptorImpl; 39 | import org.junit.Rule; 40 | import org.junit.Test; 41 | import org.jvnet.hudson.test.Issue; 42 | import org.jvnet.hudson.test.JenkinsRule; 43 | import org.jvnet.hudson.test.recipes.LocalData; 44 | import org.xml.sax.SAXException; 45 | 46 | import static org.junit.Assert.assertEquals; 47 | import static org.junit.Assert.assertFalse; 48 | import static org.junit.Assert.assertNotNull; 49 | import static org.junit.Assert.assertNull; 50 | import static org.junit.Assert.assertTrue; 51 | 52 | public class NodeJSInstallationTest { 53 | 54 | @Rule 55 | public JenkinsRule r = new JenkinsRule(); 56 | 57 | /** 58 | * Verify node executable is begin initialised correctly on a slave 59 | * node where {@link Computer#currentComputer()} is {@code null}. 60 | */ 61 | @Issue("JENKINS-42232") 62 | @Test 63 | public void test_executable_resolved_on_slave_node() throws Exception { 64 | assertNull(Computer.currentComputer()); 65 | NodeJSInstallation installation = new NodeJSInstallation("test_executable_resolved_on_slave_node", "/home/nodejs", null); 66 | Method method = installation.getClass().getDeclaredMethod("getPlatform"); 67 | method.setAccessible(true); 68 | Platform platform = (Platform) method.invoke(installation); 69 | assertEquals(Platform.current(), platform); 70 | } 71 | 72 | /** 73 | * Verify that the singleton installation descriptor load data from disk 74 | * when its constructor is called. 75 | */ 76 | @LocalData 77 | @Test 78 | @Issue("JENKINS-41535") 79 | public void test_load_at_startup() throws Exception { 80 | File jenkinsHome = r.jenkins.getRootDir(); 81 | File installationsFile = new File(jenkinsHome, NodeJSInstallation.class.getName() + ".xml"); 82 | 83 | assertTrue("NodeJS installations file has not been copied", installationsFile.exists()); 84 | verify(); 85 | } 86 | 87 | /** 88 | * Simulates the addition of the new NodeJS via UI and makes sure it works 89 | * and persistent file was created. 90 | */ 91 | @Test 92 | @Issue("JENKINS-41535") 93 | public void test_persist_of_nodejs_installation() throws Exception { 94 | File jenkinsHome = r.jenkins.getRootDir(); 95 | File installationsFile = new File(jenkinsHome, NodeJSInstallation.class.getName() + ".xml"); 96 | 97 | assertFalse("NodeJS installations file already exists", installationsFile.exists()); 98 | 99 | HtmlPage p = getConfigurePage(); 100 | HtmlForm f = p.getFormByName("config"); 101 | HtmlButton b = r.getButtonByCaption(f, "Add NodeJS"); 102 | b.click(); 103 | r.findPreviousInputElement(b, "name").setValue("myNode"); 104 | r.findPreviousInputElement(b, "home").setValue("/tmp/foo"); 105 | r.submit(f); 106 | verify(); 107 | 108 | assertTrue("NodeJS installations file has not been saved", installationsFile.exists()); 109 | 110 | // another submission and verify it survives a roundtrip 111 | p = getConfigurePage(); 112 | f = p.getFormByName("config"); 113 | r.submit(f); 114 | verify(); 115 | } 116 | 117 | private HtmlPage getConfigurePage() throws IOException, SAXException { 118 | return Jenkins.getVersion().toString().startsWith("2") ? 119 | r.createWebClient().goTo("configureTools") 120 | : r.createWebClient().goTo("configure"); 121 | } 122 | 123 | private void verify() throws Exception { 124 | NodeJSInstallation[] l = r.get(DescriptorImpl.class).getInstallations(); 125 | assertEquals(1, l.length); 126 | r.assertEqualBeans(l[0], new NodeJSInstallation("myNode", "/tmp/foo", JenkinsRule.NO_PROPERTIES), "name,home"); 127 | 128 | // by default we should get the auto installer 129 | DescribableList, ToolPropertyDescriptor> props = l[0].getProperties(); 130 | assertEquals(1, props.size()); 131 | InstallSourceProperty isp = props.get(InstallSourceProperty.class); 132 | assertEquals(1, isp.installers.size()); 133 | assertNotNull(isp.installers.get(NodeJSInstaller.class)); 134 | } 135 | 136 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/tools/NodeJSInstallerProxyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import java.lang.reflect.Method; 27 | import java.net.MalformedURLException; 28 | import java.net.URL; 29 | import java.nio.charset.Charset; 30 | 31 | import org.assertj.core.api.Assertions; 32 | import org.junit.ClassRule; 33 | import org.junit.Test; 34 | import org.junit.runner.RunWith; 35 | import org.junit.runners.Parameterized; 36 | import org.junit.runners.Parameterized.Parameters; 37 | import org.jvnet.hudson.test.Issue; 38 | import org.jvnet.hudson.test.JenkinsRule; 39 | 40 | import hudson.EnvVars; 41 | import hudson.ProxyConfiguration; 42 | import hudson.model.StreamBuildListener; 43 | import hudson.model.TaskListener; 44 | 45 | @RunWith(Parameterized.class) 46 | public class NodeJSInstallerProxyTest { 47 | 48 | @Parameters(name = "proxy url = {0}") 49 | public static String[][] data() throws MalformedURLException { 50 | return new String[][] { { "http://proxy.example.org:8080", "*.npm.org\n\nregistry.npm.org" }, 51 | { "http://user:password@proxy.example.org:8080", "*.npm.org\n\nregistry.npm.org" } 52 | }; 53 | } 54 | 55 | @ClassRule 56 | public static JenkinsRule r = new JenkinsRule(); 57 | 58 | private String host; 59 | private int port; 60 | private String username; 61 | private String password; 62 | private String expectedURL; 63 | private TaskListener log; 64 | private String noProxy; 65 | 66 | public NodeJSInstallerProxyTest(String url, String noProxy) throws Exception { 67 | URL proxyURL = new URL(url); 68 | 69 | this.log = new StreamBuildListener(System.out, Charset.defaultCharset()); 70 | this.expectedURL = url; 71 | this.noProxy = noProxy; 72 | this.host = proxyURL.getHost(); 73 | this.port = proxyURL.getPort(); 74 | if (proxyURL.getUserInfo() != null) { 75 | String[] userInfo = proxyURL.getUserInfo().split(":"); 76 | this.username = userInfo[0]; 77 | this.password = userInfo[1]; 78 | } 79 | } 80 | 81 | @Issue("JENKINS-29266") 82 | @Test 83 | public void test_proxy_settings() throws Exception { 84 | r.getInstance().proxy = new ProxyConfiguration(host, port, username, password); 85 | 86 | NodeJSInstaller installer = new NodeJSInstaller("test-id", "grunt", NodeJSInstaller.DEFAULT_NPM_PACKAGES_REFRESH_HOURS); 87 | EnvVars env = new EnvVars(); 88 | Method method = installer.getClass().getDeclaredMethod("buildProxyEnvVars", EnvVars.class, TaskListener.class); 89 | method.setAccessible(true); 90 | method.invoke(installer, env, log); 91 | 92 | Assertions.assertThat(env.keySet()).contains("HTTP_PROXY", "HTTPS_PROXY"); 93 | Assertions.assertThat(env.get("HTTP_PROXY")).isEqualTo(expectedURL); 94 | Assertions.assertThat(env.get("HTTPS_PROXY")).isEqualTo(expectedURL); 95 | Assertions.assertThat(env.keySet()).doesNotContain("NO_PROXY"); 96 | } 97 | 98 | @Test 99 | public void test_no_proxy_settings() throws Exception { 100 | r.getInstance().proxy = new ProxyConfiguration(host, port, username, password, noProxy); 101 | 102 | NodeJSInstaller installer = new NodeJSInstaller("test-id", "grunt", NodeJSInstaller.DEFAULT_NPM_PACKAGES_REFRESH_HOURS); 103 | EnvVars env = new EnvVars(); 104 | Method method = installer.getClass().getDeclaredMethod("buildProxyEnvVars", EnvVars.class, TaskListener.class); 105 | method.setAccessible(true); 106 | method.invoke(installer, env, log); 107 | 108 | Assertions.assertThat(env.keySet()).contains("HTTP_PROXY", "HTTPS_PROXY"); 109 | Assertions.assertThat(env.get("NO_PROXY")).isEqualTo("*.npm.org,registry.npm.org"); 110 | } 111 | 112 | } -------------------------------------------------------------------------------- /src/test/java/jenkins/plugins/nodejs/tools/ToolsUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2018, Nikolas Falco 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package jenkins.plugins.nodejs.tools; 25 | 26 | import static org.mockito.Mockito.mock; 27 | import static org.mockito.Mockito.mockStatic; 28 | import static org.mockito.Mockito.when; 29 | 30 | import hudson.model.Node; 31 | import org.assertj.core.api.Assertions; 32 | import org.junit.After; 33 | import org.junit.Before; 34 | import org.junit.Test; 35 | import org.mockito.MockedStatic; 36 | 37 | public class ToolsUtilsTest { 38 | 39 | private MockedStatic staticCpu; 40 | 41 | @Before 42 | public void setup() { 43 | CPU[] cpuValues = CPU.values(); 44 | staticCpu = mockStatic(CPU.class); 45 | staticCpu.when(CPU::values).thenReturn(cpuValues); 46 | } 47 | 48 | @After 49 | public void tearDown() { 50 | staticCpu.close(); 51 | } 52 | 53 | @Test 54 | public void nodejs_supports_32bit_64bit_on_windows_linux_mac() throws Exception { 55 | Node currentNode = mock(Node.class); 56 | 57 | when(CPU.of(currentNode)).thenReturn(CPU.amd64); 58 | CPU cpu = ToolsUtils.getCPU(currentNode, true); 59 | Assertions.assertThat(cpu).isEqualTo(CPU.i386); 60 | 61 | cpu = ToolsUtils.getCPU(currentNode); 62 | Assertions.assertThat(cpu).isEqualTo(CPU.amd64); 63 | } 64 | 65 | @Test(expected = DetectionFailedException.class) 66 | public void nodejs_doesn_t_supports_32bit_on_armv64() throws Exception { 67 | Node currentNode = mock(Node.class); 68 | 69 | when(CPU.of(currentNode)).thenReturn(CPU.arm64); 70 | ToolsUtils.getCPU(currentNode, true); 71 | } 72 | 73 | @Test 74 | public void nodejs_supports_32bit_on_armv6_armv7() throws Exception { 75 | Node currentNode = mock(Node.class); 76 | 77 | when(CPU.of(currentNode)).thenReturn(CPU.armv7l); 78 | CPU cpu = ToolsUtils.getCPU(currentNode, true); 79 | Assertions.assertThat(cpu).isEqualTo(CPU.armv7l); 80 | 81 | when(CPU.of(currentNode)).thenReturn(CPU.armv6l); 82 | cpu = ToolsUtils.getCPU(currentNode, true); 83 | Assertions.assertThat(cpu).isEqualTo(CPU.armv6l); 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/NodeJSSerialisationTest/test_reloading_job_configuration_contains_saved_cache_strategy_buildWrapper/jobs/test/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | 7 | 8 | true 9 | false 10 | false 11 | false 12 | 13 | false 14 | 15 | 16 | 17 | 18 | NodeJS test 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/NodeJSSerialisationTest/test_reloading_job_configuration_contains_saved_cache_strategy_interpreter/jobs/test/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | 7 | 8 | true 9 | false 10 | false 11 | false 12 | 13 | false 14 | 15 | 16 | 17 | 18 | 19 | NodeJS test 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/NodeJSSerialisationTest/test_serialisation_is_compatible_with_version_1_2_x_buildWrapper/jobs/test/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | 7 | 8 | true 9 | false 10 | false 11 | false 12 | 13 | false 14 | 15 | 16 | 17 | 18 | NodeJS test 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/NodeJSSerialisationTest/test_serialisation_is_compatible_with_version_1_2_x_interpreter/jobs/test/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | 7 | 8 | true 9 | false 10 | false 11 | false 12 | 13 | false 14 | 15 | 16 | 17 | 18 | 19 | NodeJS test 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/configfiles/npmrc.config: -------------------------------------------------------------------------------- 1 | ; cli configs 2 | global = true 3 | long = true 4 | user-agent = "npm/3.10.3 node/v0.10.42 linux x64" 5 | 6 | ; userconfig /var/lib/jenkins/.npmrc 7 | always-auth = true 8 | 9 | ; builtin config undefined 10 | prefix="/var/lib" 11 | 12 | ; globalconfig /var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/Node_6.x/etc/npmrc 13 | prefix = "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/Node_6.x" 14 | 15 | ; default values 16 | access = null 17 | also = null 18 | ; always-auth = false (overridden) 19 | bin-links = true 20 | ca = null 21 | cache = "/var/lib/jenkins/.npm" 22 | cache-lock-retries = 10 23 | cache-lock-stale = 60000 24 | 25 | ; parse error test 26 | browser -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/configuration-as-code.yaml: -------------------------------------------------------------------------------- 1 | unclassified: 2 | globalConfigFiles: 3 | configs: 4 | - npm: 5 | comment: "myComment" 6 | content: "myContent" 7 | id: "myconfigfile" 8 | name: "myConfig" 9 | providerId: "jenkins.plugins.nodejs.configfiles.NPMConfig" 10 | npm9Format: true 11 | registries: 12 | - hasScopes: true 13 | scopes: "myScope" 14 | url: "registryUrl" 15 | tool: 16 | nodejs: 17 | installations: 18 | - name: "myNode" 19 | properties: 20 | - installSource: 21 | installers: 22 | - nodeJSInstaller: 23 | force32Bit: true 24 | id: "14.4.0" 25 | npmPackages: "globalPackages" 26 | npmPackagesRefreshHours: 75 27 | - command: 28 | command: "install npm" 29 | label: "npm command" 30 | toolHome: "/my/path/1" 31 | - zip: 32 | label: "npm zip" 33 | subdir: "/my/path/2" 34 | url: "http://fake.com" 35 | - batchFile: 36 | command: "run batch command" 37 | label: "npm batch" 38 | toolHome: "/my/path/3" 39 | - home: "/onePath" 40 | name: "anotherNodeWithNoInstall" 41 | -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/dsl/NodeJSBuild.pipeline: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | stages { 5 | stage('Build') { 6 | steps { 7 | nodejs(nodeJSInstallationName: 'Node 6.x', configId: null) { 8 | sh 'npm config ls' 9 | } 10 | } 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/dsl/NodeJSInstallation.pipeline: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | tools { 5 | nodejs 'Node 6.x' 6 | } 7 | 8 | stages { 9 | stage('Build') { 10 | steps { 11 | sh 'npm -version' 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/tools/NodeJSInstallationTest/test_load_at_startup/jenkins.plugins.nodejs.tools.NodeJSInstallation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | myNode 6 | /tmp/foo 7 | 8 | 9 | 10 | 11 | 12 | 72 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/test/resources/jenkins/plugins/nodejs/tools/test.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/nodejs-plugin/2f4929d6ecfd4d09b947a50a0ca0095ed175d0e4/src/test/resources/jenkins/plugins/nodejs/tools/test.tar.gz --------------------------------------------------------------------------------