Skip to content

Commit

Permalink
fix: allow online-npm-install if prefer-offline fails
Browse files Browse the repository at this point in the history
This resolves diffplug#1750
  • Loading branch information
simschla committed Jul 18, 2023
1 parent ca4136e commit 8187042
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 10 deletions.
29 changes: 28 additions & 1 deletion lib/src/main/java/com/diffplug/spotless/npm/NodeApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@
*/
package com.diffplug.spotless.npm;

import static com.diffplug.spotless.npm.NpmProcessFactory.OnlinePreferrence.PREFER_OFFLINE;
import static com.diffplug.spotless.npm.NpmProcessFactory.OnlinePreferrence.PREFER_ONLINE;

import java.util.Objects;

import javax.annotation.Nonnull;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.diffplug.spotless.ProcessRunner;

public class NodeApp {

private static final Logger logger = LoggerFactory.getLogger(NodeApp.class);
Expand Down Expand Up @@ -83,6 +88,28 @@ void prepareNodeAppLayout() {

void npmInstall() {
timedLogger.withInfo("Installing npm dependencies for {} with {}.", this.nodeServerLayout, this.npmProcessFactory.describe())
.run(() -> npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations).waitFor());
.run(this::optimizedNpmInstall);
}

private void optimizedNpmInstall() {
try {
npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations, PREFER_OFFLINE).waitFor();
} catch (NpmProcessException e) {
if (!offlineInstallFailed(e.getResult())) {
throw e; // pass through
}
// if the npm install fails with message "No matching version found for <package>@<version>", we try again without the offline flag
npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations, PREFER_ONLINE).waitFor();
}
}

private boolean offlineInstallFailed(ProcessRunner.Result result) {
if (result == null) {
return false; // no result, something else must have happened
}
if (result.exitCode() == 0) {
return false; // all is well
}
return result.stdOutUtf8().contains("code ETARGET") && result.stdOutUtf8().contains("No matching version found for"); // offline install failed, needs online install
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public static NodeModulesCachingNpmProcessFactory create(@Nonnull File cacheDir)
}

@Override
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations) {
NpmProcess actualNpmInstallProcess = StandardNpmProcessFactory.INSTANCE.createNpmInstallProcess(nodeServerLayout, formatterStepLocations);
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence) {
NpmProcess actualNpmInstallProcess = StandardNpmProcessFactory.INSTANCE.createNpmInstallProcess(nodeServerLayout, formatterStepLocations, onlinePreferrence);
return new CachingNmpInstall(actualNpmInstallProcess, nodeServerLayout);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,26 @@
*/
package com.diffplug.spotless.npm;

import javax.annotation.CheckForNull;

import com.diffplug.spotless.ProcessRunner;

public class NpmProcessException extends RuntimeException {
private static final long serialVersionUID = 6424331316676759525L;
private final ProcessRunner.Result result;

public NpmProcessException(String message) {
public NpmProcessException(String message, ProcessRunner.Result result) {
super(message);
this.result = result;
}

public NpmProcessException(String message, Throwable cause) {
super(message, cause);
this.result = null;
}

@CheckForNull
public ProcessRunner.Result getResult() {
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,22 @@
package com.diffplug.spotless.npm;

public interface NpmProcessFactory {
NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations);

enum OnlinePreferrence {
PREFER_OFFLINE("--prefer-offline"), PREFER_ONLINE("--prefer-online");

private final String option;

OnlinePreferrence(String option) {
this.option = option;
}

public String option() {
return option;
}
}

NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence);

NpmLongRunningProcess createNpmServeProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ private StandardNpmProcessFactory() {
}

@Override
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations) {
return new NpmInstall(nodeServerLayout.nodeModulesDir(), formatterStepLocations);
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence) {
return new NpmInstall(nodeServerLayout.nodeModulesDir(), formatterStepLocations, onlinePreferrence);
}

@Override
Expand Down Expand Up @@ -80,8 +80,11 @@ public String doDescribe() {

private static class NpmInstall extends AbstractStandardNpmProcess implements NpmProcess {

public NpmInstall(File workingDir, NpmFormatterStepLocations formatterStepLocations) {
private final OnlinePreferrence onlinePreferrence;

public NpmInstall(File workingDir, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence) {
super(workingDir, formatterStepLocations);
this.onlinePreferrence = onlinePreferrence;
}

@Override
Expand All @@ -91,7 +94,7 @@ protected List<String> commandLine() {
"install",
"--no-audit",
"--no-fund",
"--prefer-offline");
onlinePreferrence.option());
}

@Override
Expand All @@ -103,7 +106,7 @@ public String describe() {
public ProcessRunner.Result waitFor() {
try (ProcessRunner.LongRunningProcess npmProcess = doStart()) {
if (npmProcess.waitFor() != 0) {
throw new NpmProcessException("Running npm command '" + describe() + "' failed with exit code: " + npmProcess.exitValue() + "\n\n" + npmProcess.result());
throw new NpmProcessException("Running npm command '" + describe() + "' failed with exit code: " + npmProcess.exitValue() + "\n\n" + npmProcess.result(), npmProcess.result());
}
return npmProcess.result();
} catch (InterruptedException e) {
Expand Down

0 comments on commit 8187042

Please sign in to comment.