mirror of https://github.com/apache/maven.git
[MNG-7338] Automatically activate batch-mode and make output quiet when running in CI. (#869)
This commit is contained in:
parent
8b652a8b3e
commit
ac0bc5541e
|
@ -146,6 +146,11 @@ under the License.
|
||||||
<groupId>commons-cli</groupId>
|
<groupId>commons-cli</groupId>
|
||||||
<artifactId>commons-cli</artifactId>
|
<artifactId>commons-cli</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-core</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
|
|
|
@ -38,6 +38,10 @@ public class CLIManager {
|
||||||
|
|
||||||
public static final char BATCH_MODE = 'B';
|
public static final char BATCH_MODE = 'B';
|
||||||
|
|
||||||
|
public static final String NON_INTERACTIVE = "non-interactive";
|
||||||
|
|
||||||
|
public static final String FORCE_INTERACTIVE = "force-interactive";
|
||||||
|
|
||||||
public static final char SET_USER_PROPERTY = 'D';
|
public static final char SET_USER_PROPERTY = 'D';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,7 +177,16 @@ public class CLIManager {
|
||||||
.build());
|
.build());
|
||||||
options.addOption(Option.builder(Character.toString(BATCH_MODE))
|
options.addOption(Option.builder(Character.toString(BATCH_MODE))
|
||||||
.longOpt("batch-mode")
|
.longOpt("batch-mode")
|
||||||
.desc("Run in non-interactive (batch) mode (disables output color)")
|
.desc("Run in non-interactive mode. Alias for --non-interactive (kept for backwards compatability)")
|
||||||
|
.build());
|
||||||
|
options.addOption(Option.builder()
|
||||||
|
.longOpt(NON_INTERACTIVE)
|
||||||
|
.desc("Run in non-interactive mode. Alias for --batch-mode")
|
||||||
|
.build());
|
||||||
|
options.addOption(Option.builder()
|
||||||
|
.longOpt(FORCE_INTERACTIVE)
|
||||||
|
.desc(
|
||||||
|
"Run in interactive mode. Overrides, if applicable, the CI environment variable and --non-interactive/--batch-mode options")
|
||||||
.build());
|
.build());
|
||||||
options.addOption(Option.builder(SUPPRESS_SNAPSHOT_UPDATES)
|
options.addOption(Option.builder(SUPPRESS_SNAPSHOT_UPDATES)
|
||||||
.longOpt("no-snapshot-updates")
|
.longOpt("no-snapshot-updates")
|
||||||
|
|
|
@ -119,7 +119,10 @@ import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
|
||||||
import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
|
import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
|
||||||
|
|
||||||
import static java.util.Comparator.comparing;
|
import static java.util.Comparator.comparing;
|
||||||
|
import static org.apache.maven.cli.CLIManager.BATCH_MODE;
|
||||||
import static org.apache.maven.cli.CLIManager.COLOR;
|
import static org.apache.maven.cli.CLIManager.COLOR;
|
||||||
|
import static org.apache.maven.cli.CLIManager.FORCE_INTERACTIVE;
|
||||||
|
import static org.apache.maven.cli.CLIManager.NON_INTERACTIVE;
|
||||||
import static org.apache.maven.cli.ResolveFile.resolveFile;
|
import static org.apache.maven.cli.ResolveFile.resolveFile;
|
||||||
import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
|
import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
|
||||||
|
|
||||||
|
@ -486,10 +489,10 @@ public class MavenCli {
|
||||||
*/
|
*/
|
||||||
void logging(CliRequest cliRequest) {
|
void logging(CliRequest cliRequest) {
|
||||||
// LOG LEVEL
|
// LOG LEVEL
|
||||||
cliRequest.verbose = cliRequest.commandLine.hasOption(CLIManager.VERBOSE)
|
CommandLine commandLine = cliRequest.commandLine;
|
||||||
|| cliRequest.commandLine.hasOption(CLIManager.DEBUG);
|
cliRequest.verbose = commandLine.hasOption(CLIManager.VERBOSE) || commandLine.hasOption(CLIManager.DEBUG);
|
||||||
cliRequest.quiet = !cliRequest.verbose && cliRequest.commandLine.hasOption(CLIManager.QUIET);
|
cliRequest.quiet = !cliRequest.verbose && commandLine.hasOption(CLIManager.QUIET);
|
||||||
cliRequest.showErrors = cliRequest.verbose || cliRequest.commandLine.hasOption(CLIManager.ERRORS);
|
cliRequest.showErrors = cliRequest.verbose || commandLine.hasOption(CLIManager.ERRORS);
|
||||||
|
|
||||||
slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
|
slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
|
||||||
Slf4jConfiguration slf4jConfiguration = Slf4jConfigurationFactory.getConfiguration(slf4jLoggerFactory);
|
Slf4jConfiguration slf4jConfiguration = Slf4jConfigurationFactory.getConfiguration(slf4jLoggerFactory);
|
||||||
|
@ -506,7 +509,7 @@ public class MavenCli {
|
||||||
|
|
||||||
// LOG COLOR
|
// LOG COLOR
|
||||||
String styleColor = cliRequest.getUserProperties().getProperty(STYLE_COLOR_PROPERTY, "auto");
|
String styleColor = cliRequest.getUserProperties().getProperty(STYLE_COLOR_PROPERTY, "auto");
|
||||||
styleColor = cliRequest.commandLine.getOptionValue(COLOR, styleColor);
|
styleColor = commandLine.getOptionValue(COLOR, styleColor);
|
||||||
if ("always".equals(styleColor) || "yes".equals(styleColor) || "force".equals(styleColor)) {
|
if ("always".equals(styleColor) || "yes".equals(styleColor) || "force".equals(styleColor)) {
|
||||||
MessageUtils.setColorEnabled(true);
|
MessageUtils.setColorEnabled(true);
|
||||||
} else if ("never".equals(styleColor) || "no".equals(styleColor) || "none".equals(styleColor)) {
|
} else if ("never".equals(styleColor) || "no".equals(styleColor) || "none".equals(styleColor)) {
|
||||||
|
@ -514,14 +517,17 @@ public class MavenCli {
|
||||||
} else if (!"auto".equals(styleColor) && !"tty".equals(styleColor) && !"if-tty".equals(styleColor)) {
|
} else if (!"auto".equals(styleColor) && !"tty".equals(styleColor) && !"if-tty".equals(styleColor)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Invalid color configuration value '" + styleColor + "'. Supported are 'auto', 'always', 'never'.");
|
"Invalid color configuration value '" + styleColor + "'. Supported are 'auto', 'always', 'never'.");
|
||||||
} else if (cliRequest.commandLine.hasOption(CLIManager.BATCH_MODE)
|
} else {
|
||||||
|| cliRequest.commandLine.hasOption(CLIManager.LOG_FILE)) {
|
boolean isBatchMode = !commandLine.hasOption(FORCE_INTERACTIVE)
|
||||||
MessageUtils.setColorEnabled(false);
|
&& (commandLine.hasOption(BATCH_MODE) || commandLine.hasOption(NON_INTERACTIVE));
|
||||||
|
if (isBatchMode || commandLine.hasOption(CLIManager.LOG_FILE)) {
|
||||||
|
MessageUtils.setColorEnabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LOG STREAMS
|
// LOG STREAMS
|
||||||
if (cliRequest.commandLine.hasOption(CLIManager.LOG_FILE)) {
|
if (commandLine.hasOption(CLIManager.LOG_FILE)) {
|
||||||
File logFile = new File(cliRequest.commandLine.getOptionValue(CLIManager.LOG_FILE));
|
File logFile = new File(commandLine.getOptionValue(CLIManager.LOG_FILE));
|
||||||
logFile = resolveFile(logFile, cliRequest.workingDirectory);
|
logFile = resolveFile(logFile, cliRequest.workingDirectory);
|
||||||
|
|
||||||
// redirect stdout and stderr to file
|
// redirect stdout and stderr to file
|
||||||
|
@ -541,8 +547,8 @@ public class MavenCli {
|
||||||
plexusLoggerManager = new Slf4jLoggerManager();
|
plexusLoggerManager = new Slf4jLoggerManager();
|
||||||
slf4jLogger = slf4jLoggerFactory.getLogger(this.getClass().getName());
|
slf4jLogger = slf4jLoggerFactory.getLogger(this.getClass().getName());
|
||||||
|
|
||||||
if (cliRequest.commandLine.hasOption(CLIManager.FAIL_ON_SEVERITY)) {
|
if (commandLine.hasOption(CLIManager.FAIL_ON_SEVERITY)) {
|
||||||
String logLevelThreshold = cliRequest.commandLine.getOptionValue(CLIManager.FAIL_ON_SEVERITY);
|
String logLevelThreshold = commandLine.getOptionValue(CLIManager.FAIL_ON_SEVERITY);
|
||||||
|
|
||||||
if (slf4jLoggerFactory instanceof MavenSlf4jWrapperFactory) {
|
if (slf4jLoggerFactory instanceof MavenSlf4jWrapperFactory) {
|
||||||
LogLevelRecorder logLevelRecorder = new LogLevelRecorder(logLevelThreshold);
|
LogLevelRecorder logLevelRecorder = new LogLevelRecorder(logLevelThreshold);
|
||||||
|
@ -557,7 +563,7 @@ public class MavenCli {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cliRequest.commandLine.hasOption(CLIManager.DEBUG)) {
|
if (commandLine.hasOption(CLIManager.DEBUG)) {
|
||||||
slf4jLogger.warn("The option '--debug' is deprecated and may be repurposed as Java debug"
|
slf4jLogger.warn("The option '--debug' is deprecated and may be repurposed as Java debug"
|
||||||
+ " in a future version. Use -X/--verbose instead.");
|
+ " in a future version. Use -X/--verbose instead.");
|
||||||
}
|
}
|
||||||
|
@ -1242,7 +1248,7 @@ public class MavenCli {
|
||||||
request.setShowErrors(cliRequest.showErrors); // default: false
|
request.setShowErrors(cliRequest.showErrors); // default: false
|
||||||
File baseDirectory = new File(workingDirectory, "").getAbsoluteFile();
|
File baseDirectory = new File(workingDirectory, "").getAbsoluteFile();
|
||||||
|
|
||||||
disableOnPresentOption(commandLine, CLIManager.BATCH_MODE, request::setInteractiveMode);
|
disableInteractiveModeIfNeeded(cliRequest, request);
|
||||||
enableOnPresentOption(commandLine, CLIManager.SUPPRESS_SNAPSHOT_UPDATES, request::setNoSnapshotUpdates);
|
enableOnPresentOption(commandLine, CLIManager.SUPPRESS_SNAPSHOT_UPDATES, request::setNoSnapshotUpdates);
|
||||||
request.setGoals(commandLine.getArgList());
|
request.setGoals(commandLine.getArgList());
|
||||||
request.setReactorFailureBehavior(determineReactorFailureBehaviour(commandLine));
|
request.setReactorFailureBehavior(determineReactorFailureBehaviour(commandLine));
|
||||||
|
@ -1304,6 +1310,27 @@ public class MavenCli {
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void disableInteractiveModeIfNeeded(final CliRequest cliRequest, final MavenExecutionRequest request) {
|
||||||
|
CommandLine commandLine = cliRequest.getCommandLine();
|
||||||
|
if (commandLine.hasOption(FORCE_INTERACTIVE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean runningOnCI = isRunningOnCI(cliRequest.getSystemProperties());
|
||||||
|
if (runningOnCI) {
|
||||||
|
slf4jLogger.info("Making this build non-interactive, because the environment variable CI equals \"true\"."
|
||||||
|
+ " Disable this detection by removing that variable or adding --force-interactive.");
|
||||||
|
request.setInteractiveMode(false);
|
||||||
|
} else if (commandLine.hasOption(BATCH_MODE) || commandLine.hasOption(NON_INTERACTIVE)) {
|
||||||
|
request.setInteractiveMode(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isRunningOnCI(Properties systemProperties) {
|
||||||
|
String ciEnv = systemProperties.getProperty("env.CI");
|
||||||
|
return ciEnv != null && !"false".equals(ciEnv);
|
||||||
|
}
|
||||||
|
|
||||||
private String determineLocalRepositoryPath(final MavenExecutionRequest request) {
|
private String determineLocalRepositoryPath(final MavenExecutionRequest request) {
|
||||||
String userDefinedLocalRepo = request.getUserProperties().getProperty(MavenCli.LOCAL_REPO_PROPERTY);
|
String userDefinedLocalRepo = request.getUserProperties().getProperty(MavenCli.LOCAL_REPO_PROPERTY);
|
||||||
if (userDefinedLocalRepo != null) {
|
if (userDefinedLocalRepo != null) {
|
||||||
|
@ -1424,7 +1451,10 @@ public class MavenCli {
|
||||||
final boolean verbose,
|
final boolean verbose,
|
||||||
final CommandLine commandLine,
|
final CommandLine commandLine,
|
||||||
final MavenExecutionRequest request) {
|
final MavenExecutionRequest request) {
|
||||||
if (quiet || commandLine.hasOption(CLIManager.NO_TRANSFER_PROGRESS)) {
|
boolean runningOnCI = isRunningOnCI(request.getSystemProperties());
|
||||||
|
boolean quietCI = runningOnCI && !commandLine.hasOption(FORCE_INTERACTIVE);
|
||||||
|
|
||||||
|
if (quiet || commandLine.hasOption(CLIManager.NO_TRANSFER_PROGRESS) || quietCI) {
|
||||||
return new QuietMavenTransferListener();
|
return new QuietMavenTransferListener();
|
||||||
} else if (request.isInteractiveMode() && !commandLine.hasOption(CLIManager.LOG_FILE)) {
|
} else if (request.isInteractiveMode() && !commandLine.hasOption(CLIManager.LOG_FILE)) {
|
||||||
//
|
//
|
||||||
|
|
|
@ -26,6 +26,7 @@ import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
import org.apache.commons.cli.CommandLineParser;
|
||||||
|
@ -34,6 +35,9 @@ import org.apache.commons.cli.Option;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.maven.Maven;
|
import org.apache.maven.Maven;
|
||||||
|
import org.apache.maven.cli.transfer.ConsoleMavenTransferListener;
|
||||||
|
import org.apache.maven.cli.transfer.QuietMavenTransferListener;
|
||||||
|
import org.apache.maven.cli.transfer.Slf4jMavenTransferListener;
|
||||||
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
|
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
|
||||||
import org.apache.maven.execution.MavenExecutionRequest;
|
import org.apache.maven.execution.MavenExecutionRequest;
|
||||||
import org.apache.maven.execution.ProfileActivation;
|
import org.apache.maven.execution.ProfileActivation;
|
||||||
|
@ -45,9 +49,13 @@ import org.apache.maven.toolchain.building.ToolchainsBuildingRequest;
|
||||||
import org.apache.maven.toolchain.building.ToolchainsBuildingResult;
|
import org.apache.maven.toolchain.building.ToolchainsBuildingResult;
|
||||||
import org.codehaus.plexus.DefaultPlexusContainer;
|
import org.codehaus.plexus.DefaultPlexusContainer;
|
||||||
import org.codehaus.plexus.PlexusContainer;
|
import org.codehaus.plexus.PlexusContainer;
|
||||||
|
import org.eclipse.aether.transfer.TransferListener;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
@ -333,6 +341,20 @@ class MavenCliTest {
|
||||||
cli.logging(request);
|
cli.logging(request);
|
||||||
assertFalse(MessageUtils.isColorEnabled());
|
assertFalse(MessageUtils.isColorEnabled());
|
||||||
|
|
||||||
|
MessageUtils.setColorEnabled(true);
|
||||||
|
request = new CliRequest(new String[] {"--non-interactive"}, null);
|
||||||
|
cli.cli(request);
|
||||||
|
cli.properties(request);
|
||||||
|
cli.logging(request);
|
||||||
|
assertFalse(MessageUtils.isColorEnabled());
|
||||||
|
|
||||||
|
MessageUtils.setColorEnabled(true);
|
||||||
|
request = new CliRequest(new String[] {"--force-interactive", "--non-interactive"}, null);
|
||||||
|
cli.cli(request);
|
||||||
|
cli.properties(request);
|
||||||
|
cli.logging(request);
|
||||||
|
assertTrue(MessageUtils.isColorEnabled());
|
||||||
|
|
||||||
MessageUtils.setColorEnabled(true);
|
MessageUtils.setColorEnabled(true);
|
||||||
request = new CliRequest(new String[] {"-l", "target/temp/mvn.log"}, null);
|
request = new CliRequest(new String[] {"-l", "target/temp/mvn.log"}, null);
|
||||||
request.workingDirectory = "target/temp";
|
request.workingDirectory = "target/temp";
|
||||||
|
@ -585,6 +607,68 @@ class MavenCliTest {
|
||||||
assertThat(request.getCommandLine().getArgs(), equalTo(new String[] {"prefix:3.0.0:bar", "validate"}));
|
assertThat(request.getCommandLine().getArgs(), equalTo(new String[] {"prefix:3.0.0:bar", "validate"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("activateBatchModeArguments")
|
||||||
|
public void activateBatchMode(boolean ciEnv, String[] cliArgs, boolean isBatchMode) throws Exception {
|
||||||
|
CliRequest request = new CliRequest(cliArgs, null);
|
||||||
|
if (ciEnv) request.getSystemProperties().put("env.CI", "true");
|
||||||
|
cli.cli(request);
|
||||||
|
|
||||||
|
boolean batchMode = !cli.populateRequest(request).isInteractiveMode();
|
||||||
|
|
||||||
|
assertThat(batchMode, is(isBatchMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<Arguments> activateBatchModeArguments() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of(false, new String[] {}, false),
|
||||||
|
Arguments.of(true, new String[] {}, true),
|
||||||
|
Arguments.of(true, new String[] {"--force-interactive"}, false),
|
||||||
|
Arguments.of(true, new String[] {"--force-interactive", "--non-interactive"}, false),
|
||||||
|
Arguments.of(true, new String[] {"--force-interactive", "--batch-mode"}, false),
|
||||||
|
Arguments.of(true, new String[] {"--force-interactive", "--non-interactive", "--batch-mode"}, false),
|
||||||
|
Arguments.of(false, new String[] {"--non-interactive"}, true),
|
||||||
|
Arguments.of(false, new String[] {"--batch-mode"}, true),
|
||||||
|
Arguments.of(false, new String[] {"--non-interactive", "--batch-mode"}, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("calculateTransferListenerArguments")
|
||||||
|
public void calculateTransferListener(boolean ciEnv, String[] cliArgs, Class<TransferListener> expectedSubClass)
|
||||||
|
throws Exception {
|
||||||
|
CliRequest request = new CliRequest(cliArgs, null);
|
||||||
|
if (ciEnv) request.getSystemProperties().put("env.CI", "true");
|
||||||
|
cli.cli(request);
|
||||||
|
cli.logging(request);
|
||||||
|
|
||||||
|
TransferListener transferListener = cli.populateRequest(request).getTransferListener();
|
||||||
|
|
||||||
|
assertThat(transferListener.getClass(), is(expectedSubClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream<Arguments> calculateTransferListenerArguments() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of(false, new String[] {}, ConsoleMavenTransferListener.class),
|
||||||
|
Arguments.of(true, new String[] {}, QuietMavenTransferListener.class),
|
||||||
|
Arguments.of(false, new String[] {"-ntp"}, QuietMavenTransferListener.class),
|
||||||
|
Arguments.of(false, new String[] {"--quiet"}, QuietMavenTransferListener.class),
|
||||||
|
Arguments.of(true, new String[] {"--force-interactive"}, ConsoleMavenTransferListener.class),
|
||||||
|
Arguments.of(
|
||||||
|
true,
|
||||||
|
new String[] {"--force-interactive", "--non-interactive"},
|
||||||
|
ConsoleMavenTransferListener.class),
|
||||||
|
Arguments.of(
|
||||||
|
true, new String[] {"--force-interactive", "--batch-mode"}, ConsoleMavenTransferListener.class),
|
||||||
|
Arguments.of(
|
||||||
|
true,
|
||||||
|
new String[] {"--force-interactive", "--non-interactive", "--batch-mode"},
|
||||||
|
ConsoleMavenTransferListener.class),
|
||||||
|
Arguments.of(false, new String[] {"--non-interactive"}, Slf4jMavenTransferListener.class),
|
||||||
|
Arguments.of(false, new String[] {"--batch-mode"}, Slf4jMavenTransferListener.class),
|
||||||
|
Arguments.of(
|
||||||
|
false, new String[] {"--non-interactive", "--batch-mode"}, Slf4jMavenTransferListener.class));
|
||||||
|
}
|
||||||
|
|
||||||
private MavenProject createMavenProject(String groupId, String artifactId) {
|
private MavenProject createMavenProject(String groupId, String artifactId) {
|
||||||
MavenProject project = new MavenProject();
|
MavenProject project = new MavenProject();
|
||||||
project.setGroupId(groupId);
|
project.setGroupId(groupId);
|
||||||
|
|
Loading…
Reference in New Issue