Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JENKINS-45840] Verify if the NodeJS executable exists before continu…
…e with the build step. This improves also the problem determination because avoid the emerge of strange issues.
  • Loading branch information
nfalco79 committed Jul 30, 2017
1 parent e82eece commit d2f7a53
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 7 deletions.
6 changes: 5 additions & 1 deletion src/main/java/jenkins/plugins/nodejs/NodeJSBuildWrapper.java
Expand Up @@ -123,6 +123,10 @@ public void setUp(final Context context, Run<?, ?> build, FilePath workspace, La
}
ni = ni.forNode(node, listener);
ni = ni.forEnvironment(initialEnvironment);
String exec = ni.getExecutable(launcher);
if (exec == null) {
throw new AbortException(Messages.NodeJSBuilders_noExecutableFound(ni.getHome()));
}
ni.buildEnvVars(new EnvVarsAdapter(context));

EnvVars env = initialEnvironment.overrideAll(context.getEnv());
Expand All @@ -131,7 +135,7 @@ public void setUp(final Context context, Run<?, ?> build, FilePath workspace, La
if (configId != null) {
ConfigFile cf = new ConfigFile(configId, null, true);
FilePath configFile = ConfigFileManager.provisionConfigFile(cf, env, build, workspace, listener, new ArrayList<String>());
context.env(NodeJSConstants.NPM_USERCONFIG, configFile.getRemote());
context.env(NodeJSConstants.NPM_USERCONFIG, configFile.getRemote());
build.addAction(new CleanTempFilesAction(configFile.getRemote()));
}
}
Expand Down
Expand Up @@ -115,6 +115,11 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, TaskListene

ni = ni.forNode(node, listener);
ni = ni.forEnvironment(env);
String exec = ni.getExecutable(launcher);
if (exec == null) {
listener.fatalError(Messages.NodeJSBuilders_noExecutableFound(ni.getHome()));
return false;
}
ni.buildEnvVars(newEnv);

// enhance env with installation environment because is passed to supplyConfig
Expand Down
Expand Up @@ -25,7 +25,7 @@ NodeJSInstaller.FailedToInstallNodeJS=Failed to install NodeJS. Exit code={0}
NodeJSInstallation.displayName=NodeJS
NodeJSBuildWrapper.displayName=Provide Node & npm bin/ folder to PATH
NodeJSCommandInterpreter.displayName=Execute NodeJS script
NodeJSBuilders.noExecutableFound=Cannot find executable from the chosen NodeJS installation "{0}"
NodeJSBuilders.noExecutableFound=Couldn\u2019t find any executable in "{0}"
NodeJSBuilders.noInstallationFound=No installation {0} found. Please define one in manager Jenkins.
NodeJSBuilders.nodeOffline=Cannot get installation for node, since it is not online
NPMConfig.displayName=Npm config file
Expand Down
37 changes: 32 additions & 5 deletions src/test/java/jenkins/plugins/nodejs/NodeJSBuildWrapperTest.java
Expand Up @@ -13,10 +13,12 @@
import org.jenkinsci.plugins.configfiles.GlobalConfigFiles;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.powermock.api.mockito.PowerMockito;

import hudson.EnvVars;
import hudson.Launcher;
import hudson.model.FreeStyleProject;
import hudson.model.Node;
import hudson.model.Result;
Expand All @@ -25,7 +27,9 @@
import jenkins.plugins.nodejs.configfiles.NPMConfig;
import jenkins.plugins.nodejs.configfiles.NPMConfig.NPMConfigProvider;
import jenkins.plugins.nodejs.configfiles.NPMRegistry;
import jenkins.plugins.nodejs.tools.DetectionFailedException;
import jenkins.plugins.nodejs.tools.NodeJSInstallation;
import jenkins.plugins.nodejs.tools.Platform;

public class NodeJSBuildWrapperTest {

Expand All @@ -41,7 +45,7 @@ public void test_calls_sequence_of_installer() throws Exception {

job.getBuildWrappersList().add(bw);

j.assertBuildStatus(Result.SUCCESS, job.scheduleBuild2(0));
j.assertBuildStatusSuccess(job.scheduleBuild2(0));

verify(installation).forNode(any(Node.class), any(TaskListener.class));
verify(installation).forEnvironment(any(EnvVars.class));
Expand All @@ -61,7 +65,7 @@ public void test_creation_of_config() throws Exception {

job.getBuildersList().add(new FileVerifier());

j.assertBuildStatus(Result.SUCCESS, job.scheduleBuild2(0));
j.assertBuildStatusSuccess(job.scheduleBuild2(0));
}

@Test
Expand All @@ -70,16 +74,33 @@ public void test_inject_path_variable() throws Exception {

final Config config = createSetting("my-config-id", "", null);

NodeJSInstallation installation = new NodeJSInstallation("test", getTestHome(), null);
NodeJSInstallation installation = spy(new NodeJSInstallation("test", getTestHome(), null));
doReturn(getTestExecutable()).when(installation).getExecutable(any(Launcher.class));
doReturn(installation).when(installation).forNode(any(Node.class), any(TaskListener.class));
doReturn(installation).when(installation).forEnvironment(any(EnvVars.class));

NodeJSBuildWrapper spy = mockWrapper(installation, config);

job.getBuildWrappersList().add(spy);

job.getBuildersList().add(new PathVerifier(installation));

j.assertBuildStatus(Result.SUCCESS, job.scheduleBuild2(0));
j.assertBuildStatusSuccess(job.scheduleBuild2(0));
}

@Issue("JENKINS-45840")
@Test
public void test_check_no_executable_in_installation_folder() throws Exception {
FreeStyleProject job = j.createFreeStyleProject("free");

NodeJSInstallation installation = mockInstaller();
when(installation.getExecutable(any(Launcher.class))).thenReturn(null);
NodeJSBuildWrapper bw = mockWrapper(installation, mock(NPMConfig.class));

job.getBuildWrappersList().add(bw);

j.assertBuildStatus(Result.FAILURE, job.scheduleBuild2(0));
}

private Config createSetting(String id, String content, List<NPMRegistry> registries) {
String providerId = new NPMConfigProvider().getProviderId();
Expand All @@ -98,15 +119,21 @@ private NodeJSBuildWrapper mockWrapper(NodeJSInstallation installation, Config c
return wrapper;
}

private NodeJSInstallation mockInstaller() throws IOException, InterruptedException {
private NodeJSInstallation mockInstaller() throws Exception {
NodeJSInstallation mock = mock(NodeJSInstallation.class);
when(mock.forNode(any(Node.class), any(TaskListener.class))).then(RETURNS_SELF);
when(mock.forEnvironment(any(EnvVars.class))).then(RETURNS_SELF);
when(mock.getName()).thenReturn("mockNode");
when(mock.getHome()).thenReturn(getTestHome());
when(mock.getExecutable(any(Launcher.class))).thenReturn(getTestExecutable());
return mock;
}

private String getTestExecutable() throws Exception {
Platform currentPlatform = Platform.current();
return new File(new File(getTestHome(), currentPlatform.binFolder), currentPlatform.nodeFileName).getAbsolutePath();
}

private String getTestHome() {
return new File("/home", "nodejs").getAbsolutePath();
}
Expand Down
Expand Up @@ -23,6 +23,7 @@
import hudson.model.AbstractBuild;
import hudson.model.FreeStyleProject;
import hudson.model.Node;
import hudson.model.Result;
import hudson.model.TaskListener;
import jenkins.plugins.nodejs.CIBuilderHelper.Verifier;
import jenkins.plugins.nodejs.CIBuilderHelper;
Expand Down Expand Up @@ -112,6 +113,19 @@ public void test_calls_sequence_of_installer() throws Exception {
verify(installation).buildEnvVars(any(EnvVars.class));
}

@Issue("JENKINS-45840")
@Test
public void test_check_no_executable_in_installation_folder() throws Exception {
NodeJSInstallation installation = mockInstaller();
when(installation.getExecutable(any(Launcher.class))).thenReturn(null);

NodeJSCommandInterpreter builder = CIBuilderHelper.createMock("test_creation_of_config", installation, null);

FreeStyleProject job = j.createFreeStyleProject("free");
job.getBuildersList().add(builder);
j.assertBuildStatus(Result.FAILURE, job.scheduleBuild2(0));
}

private Config createSetting(String id, String content, List<NPMRegistry> registries) {
String providerId = new NPMConfigProvider().getProviderId();
Config config = new NPMConfig(id, null, null, content, providerId, registries);
Expand Down

0 comments on commit d2f7a53

Please sign in to comment.