Improve error message for missing build script
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package org.springframework.ide.eclipse.boot.dash.docker.runtarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springsource.ide.eclipse.commons.core.util.OsUtils;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class BuildScriptLocator {
|
||||
|
||||
public static enum BuildKind {
|
||||
MAVEN,
|
||||
GRADLE,
|
||||
SHELL
|
||||
};
|
||||
|
||||
public final File directory;
|
||||
public final List<String> command = new ArrayList<>();
|
||||
public final List<File> checkedLocations = new ArrayList<>();
|
||||
private BuildKind buildKind;
|
||||
|
||||
/**
|
||||
* Tries to find build script in given directory. Various bits of information
|
||||
* such as the type of script found, the build command to run etc. can
|
||||
* be accessed via the public fields and accessors of the created object.
|
||||
*/
|
||||
public BuildScriptLocator(File directory) {
|
||||
this.directory = directory;
|
||||
findBuildScript();
|
||||
}
|
||||
|
||||
private void findBuildScript() {
|
||||
String buildShellScript;
|
||||
this.buildKind = null;
|
||||
if (OsUtils.isWindows()) {
|
||||
buildShellScript = "sts-docker-build.bat";
|
||||
if (exists(directory.toPath().resolve(buildShellScript))) {
|
||||
buildKind = BuildKind.SHELL;
|
||||
command.addAll(ImmutableList.of("CMD", "/C", buildShellScript));
|
||||
} else if (exists(directory.toPath().resolve("mvnw.cmd"))) {
|
||||
buildKind = BuildKind.MAVEN;
|
||||
command.addAll(ImmutableList.of("CMD", "/C", "mvnw.cmd", "spring-boot:build-image", "-DskipTests"));
|
||||
//, "-Dspring-boot.repackage.excludeDevtools=false" };
|
||||
} else if (exists(directory.toPath().resolve("gradlew.bat"))) {
|
||||
buildKind = BuildKind.GRADLE;
|
||||
command.addAll(ImmutableList.of("CMD", "/C", "gradlew.bat", "bootBuildImage", "-x", "test"));
|
||||
}
|
||||
} else {
|
||||
buildShellScript = "sts-docker-build.sh";
|
||||
if (exists(directory.toPath().resolve(buildShellScript))) {
|
||||
buildKind = BuildKind.SHELL;
|
||||
command.addAll(ImmutableList.of("./sts-docker-build.sh"));
|
||||
} else if (exists(directory.toPath().resolve("mvnw"))) {
|
||||
buildKind = BuildKind.MAVEN;
|
||||
command.addAll(ImmutableList.of("./mvnw", "spring-boot:build-image", "-DskipTests"));
|
||||
} else if (exists(directory.toPath().resolve("gradlew"))) {
|
||||
buildKind = BuildKind.GRADLE;
|
||||
command.addAll(ImmutableList.of("./gradlew", "--stacktrace", "bootBuildImage", "-x", "test" ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean exists(Path resolved) {
|
||||
checkedLocations.add(resolved.toFile());
|
||||
return Files.exists(resolved);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The type of build script that was found. Returns null to indicate no build script was found.
|
||||
*/
|
||||
public BuildKind getBuildKind() {
|
||||
return this.buildKind;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ package org.springframework.ide.eclipse.boot.dash.docker.runtarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -51,6 +50,7 @@ import org.springframework.ide.eclipse.boot.dash.api.TemporalBoolean;
|
||||
import org.springframework.ide.eclipse.boot.dash.console.LogType;
|
||||
import org.springframework.ide.eclipse.boot.dash.devtools.DevtoolsUtil;
|
||||
import org.springframework.ide.eclipse.boot.dash.docker.jmx.JmxSupport;
|
||||
import org.springframework.ide.eclipse.boot.dash.docker.runtarget.BuildScriptLocator.BuildKind;
|
||||
import org.springframework.ide.eclipse.boot.dash.labels.BootDashLabels;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.RunState;
|
||||
import org.springframework.ide.eclipse.boot.dash.model.remote.ChildBearing;
|
||||
@@ -59,10 +59,10 @@ import org.springframework.ide.eclipse.boot.dash.util.LineBasedStreamGobler;
|
||||
import org.springframework.ide.eclipse.boot.launch.util.PortFinder;
|
||||
import org.springframework.ide.eclipse.boot.util.JavaProjectUtil;
|
||||
import org.springsource.ide.eclipse.commons.core.pstore.PropertyStoreApi;
|
||||
import org.springsource.ide.eclipse.commons.core.util.OsUtils;
|
||||
import org.springsource.ide.eclipse.commons.frameworks.core.util.JobUtil;
|
||||
import org.springsource.ide.eclipse.commons.frameworks.core.util.StringUtils;
|
||||
import org.springsource.ide.eclipse.commons.livexp.core.AbstractDisposable;
|
||||
import org.springsource.ide.eclipse.commons.livexp.util.ExceptionUtil;
|
||||
import org.springsource.ide.eclipse.commons.livexp.util.Log;
|
||||
import org.springsource.ide.eclipse.commons.livexp.util.OldValueDisposer;
|
||||
|
||||
@@ -244,7 +244,19 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing,
|
||||
throw new IllegalStateException("The project '"+project.getName()+"' is not accessible");
|
||||
}
|
||||
console.write("Deploying Docker app " + getName() + BootDashLabels.ELLIPSIS, LogType.STDOUT);
|
||||
return build(console);
|
||||
try {
|
||||
return build(console);
|
||||
} catch (Exception e) {
|
||||
console.write(ExceptionUtil.getMessage(e), LogType.STDERROR);
|
||||
if (e instanceof MissingBuildScriptException) {
|
||||
console.write("Places we looked for build script: ", LogType.STDERROR);
|
||||
for (File loc : ((MissingBuildScriptException) e).locationsChecked) {
|
||||
console.write(" - "+loc, LogType.STDERROR);
|
||||
}
|
||||
showBuildScriptHelp(console, (MissingBuildScriptException) e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
refreshTracker.run("Starting container '" + image + "'" + + BootDashLabels.ELLIPSIS, () -> {
|
||||
@@ -253,6 +265,30 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing,
|
||||
});
|
||||
}
|
||||
|
||||
private void showBuildScriptHelp(AppConsole console, MissingBuildScriptException e) {
|
||||
String[] help = {
|
||||
"To build a docker image, Boot Dash needs to run a build script from your project.",
|
||||
"Three different types are supported and checked for in this order:",
|
||||
"",
|
||||
"1. "+e.locationsChecked.get(0).getAbsoluteFile().getName(),
|
||||
" A custom script placed by you at the project root.",
|
||||
" Typically this runs a custom maven or gradle command on your project.",
|
||||
"",
|
||||
"2. maven",
|
||||
" If your project has a mvnw, we will use that to execute the `spring-boot:build-image` task",
|
||||
"",
|
||||
"3. gradle",
|
||||
" If your project has a gradlew, we will use that to execute the `bootBuildImage` task",
|
||||
};
|
||||
try {
|
||||
for (String line : help) {
|
||||
console.write(line, LogType.STDERROR);
|
||||
}
|
||||
} catch (Exception e1) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
private void run(AppConsole console, String image, DockerDeployment deployment) throws Exception {
|
||||
if (client==null) {
|
||||
console.write("Cannot start container... Docker client is disconnected!", LogType.STDERROR);
|
||||
@@ -409,36 +445,19 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing,
|
||||
IVMInstall jvm = JavaRuntime.getVMInstall(JavaCore.create(project));
|
||||
return jvm.getInstallLocation().toString();
|
||||
}
|
||||
|
||||
private String[] getBuildCommand(File directory) {
|
||||
boolean isMaven = true;
|
||||
List<String> command = new ArrayList<>();
|
||||
if (OsUtils.isWindows()) {
|
||||
if (Files.exists(directory.toPath().resolve("mvnw.cmd"))) {
|
||||
command.addAll(ImmutableList.of("CMD", "/C", "mvnw.cmd", "spring-boot:build-image", "-DskipTests"));
|
||||
//, "-Dspring-boot.repackage.excludeDevtools=false" };
|
||||
} else if (Files.exists(directory.toPath().resolve("gradlew.bat"))) {
|
||||
isMaven = false;
|
||||
command.addAll(ImmutableList.of("CMD", "/C", "gradlew.bat", "bootBuildImage", "-x", "test"));
|
||||
}
|
||||
} else {
|
||||
if (Files.exists(directory.toPath().resolve("sts-docker-build.sh"))) {
|
||||
command.addAll(ImmutableList.of("./sts-docker-build.sh"));
|
||||
} else if (Files.exists(directory.toPath().resolve("mvnw"))) {
|
||||
command.addAll(ImmutableList.of("./mvnw", "spring-boot:build-image", "-DskipTests"));
|
||||
} else if (Files.exists(directory.toPath().resolve("gradlew"))) {
|
||||
isMaven = false;
|
||||
command.addAll(ImmutableList.of("./gradlew", "--stacktrace", "bootBuildImage", "-x", "test" ));
|
||||
}
|
||||
}
|
||||
if (command.isEmpty()) {
|
||||
throw new IllegalStateException("Neither sts-docker-build.sh nor Gradle/Maven wrapper was found!");
|
||||
|
||||
private String[] getBuildCommand(File directory) throws MissingBuildScriptException {
|
||||
BuildScriptLocator buildScriptLocator = new BuildScriptLocator(directory);
|
||||
BuildKind buildKind = buildScriptLocator.getBuildKind();
|
||||
if (buildKind==null) {
|
||||
throw new MissingBuildScriptException(buildScriptLocator.checkedLocations);
|
||||
}
|
||||
boolean wantsDevtools = deployment().getSystemProperties().getOrDefault(DevtoolsUtil.REMOTE_SECRET_PROP, null)!=null;
|
||||
List<String> command = buildScriptLocator.command;
|
||||
if (wantsDevtools) {
|
||||
if (isMaven) {
|
||||
if (buildKind==BuildKind.MAVEN) {
|
||||
command.add("-Dspring-boot.repackage.excludeDevtools=false");
|
||||
} else {
|
||||
} else if (buildKind==BuildKind.GRADLE) {
|
||||
try {
|
||||
command.addAll(gradle_initScript(
|
||||
"allprojects {\n" +
|
||||
@@ -458,7 +477,6 @@ public class DockerApp extends AbstractDisposable implements App, ChildBearing,
|
||||
}
|
||||
|
||||
private synchronized static List<String> gradle_initScript(String script) throws IOException {
|
||||
System.out.println(script);
|
||||
if (initFile==null) {
|
||||
initFile = File.createTempFile("init-script", ".gradle");
|
||||
FileUtils.writeStringToFile(initFile, script, "UTF8");
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2020 Pivotal, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.eclipse.boot.dash.docker.runtarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Exception raised when BootDash wants to build a docker image but can not
|
||||
* find / determine how to build it. I.e. we are looking for a number of
|
||||
* different build scripts in project-relative locations. If none of
|
||||
* them are found then this exception is raised.
|
||||
*/
|
||||
public class MissingBuildScriptException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public final List<File> locationsChecked;
|
||||
|
||||
public MissingBuildScriptException(List<File> locationsChecked) {
|
||||
super("Niether maven wraper, gradle wrapper or custom build script found.");
|
||||
this.locationsChecked = locationsChecked;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user