Skip to content

Commit

Permalink
[JENKINS-45840] Verify if the NodeJS executable exists before continu…
Browse files Browse the repository at this point in the history
…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.