You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ma...@apache.org on 2022/11/10 15:47:32 UTC
[maven] 01/01: [MNG-7338] Automatically activate batch-mode and make output quiet when running in CI.
This is an automated email from the ASF dual-hosted git repository.
martinkanters pushed a commit to branch feature/MNG-7338-automatic-non-interactive-mode-in-ci
in repository https://gitbox.apache.org/repos/asf/maven.git
commit 2a87384e92aed08178aeda45796c72c1ce1d42d6
Author: Martin Kanters <ma...@apache.org>
AuthorDate: Thu Nov 10 16:47:16 2022 +0100
[MNG-7338] Automatically activate batch-mode and make output quiet when running in CI.
---
maven-embedder/pom.xml | 5 ++
.../main/java/org/apache/maven/cli/CLIManager.java | 8 ++-
.../main/java/org/apache/maven/cli/MavenCli.java | 62 +++++++++++++----
.../java/org/apache/maven/cli/MavenCliTest.java | 81 ++++++++++++++++++++++
4 files changed, 140 insertions(+), 16 deletions(-)
diff --git a/maven-embedder/pom.xml b/maven-embedder/pom.xml
index 1e6c98968..892adb1b7 100644
--- a/maven-embedder/pom.xml
+++ b/maven-embedder/pom.xml
@@ -156,6 +156,11 @@ under the License.
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
index b6005fddf..eaebd5a37 100644
--- a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
@@ -40,6 +40,10 @@ public class CLIManager
public static final char BATCH_MODE = 'B';
+ public static final String NON_INTERACTIVE = "ni";
+
+ public static final String FORCE_INTERACTIVE = "fi";
+
public static final char SET_USER_PROPERTY = 'D';
/**
@@ -138,7 +142,9 @@ public class CLIManager
options.addOption( Option.builder( Character.toString( NON_RECURSIVE ) ).longOpt( "non-recursive" ).desc( "Do not recurse into sub-projects. When used together with -pl, do not recurse into sub-projects of selected aggregators" ).build() );
options.addOption( Option.builder( Character.toString( UPDATE_SNAPSHOTS ) ).longOpt( "update-snapshots" ).desc( "Forces a check for missing releases and updated snapshots on remote repositories" ).build() );
options.addOption( Option.builder( Character.toString( ACTIVATE_PROFILES ) ).longOpt( "activate-profiles" ).desc( "Comma-delimited list of profiles to activate. Prefixing a profile with ! excludes it, and ? marks it as optional" ).hasArg().build() );
- options.addOption( Option.builder( Character.toString( BATCH_MODE ) ).longOpt( "batch-mode" ).desc( "Run in non-interactive (batch) mode (disables output color)" ).build() );
+ options.addOption( Option.builder( Character.toString( BATCH_MODE ) ).longOpt( "batch-mode" ).desc( "Run in non-interactive (batch) mode (disables output color) - alias for --non-interactive (kept for backwards compatability)" ).build() );
+ options.addOption( Option.builder( NON_INTERACTIVE ).longOpt( "non-interactive" ).desc( "Run in non-interactive (batch) mode (disables output color) - alias for --batch-mode" ).build() );
+ options.addOption( Option.builder( FORCE_INTERACTIVE ).longOpt( "force-interactive" ).desc( "Run in interactive mode - even when the environment variable CI is set to true and --non-interactive or --batch-mode are set" ).build() );
options.addOption( Option.builder( SUPPRESS_SNAPSHOT_UPDATES ).longOpt( "no-snapshot-updates" ).desc( "Suppress SNAPSHOT updates" ).build() );
options.addOption( Option.builder( Character.toString( CHECKSUM_FAILURE_POLICY ) ).longOpt( "strict-checksums" ).desc( "Fail the build if checksums don't match" ).build() );
options.addOption( Option.builder( Character.toString( CHECKSUM_WARNING_POLICY ) ).longOpt( "lax-checksums" ).desc( "Warn if checksums don't match" ).build() );
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
index ebfb0830b..2c9ae0ce3 100644
--- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
@@ -121,7 +121,10 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
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.FORCE_INTERACTIVE;
+import static org.apache.maven.cli.CLIManager.NON_INTERACTIVE;
import static org.apache.maven.cli.ResolveFile.resolveFile;
import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
@@ -504,10 +507,11 @@ public class MavenCli
void logging( CliRequest cliRequest )
{
// LOG LEVEL
- cliRequest.verbose = cliRequest.commandLine.hasOption( CLIManager.VERBOSE )
- || cliRequest.commandLine.hasOption( CLIManager.DEBUG );
- cliRequest.quiet = !cliRequest.verbose && cliRequest.commandLine.hasOption( CLIManager.QUIET );
- cliRequest.showErrors = cliRequest.verbose || cliRequest.commandLine.hasOption( CLIManager.ERRORS );
+ CommandLine commandLine = cliRequest.commandLine;
+ cliRequest.verbose = commandLine.hasOption( CLIManager.VERBOSE )
+ || commandLine.hasOption( CLIManager.DEBUG );
+ cliRequest.quiet = !cliRequest.verbose && commandLine.hasOption( CLIManager.QUIET );
+ cliRequest.showErrors = cliRequest.verbose || commandLine.hasOption( CLIManager.ERRORS );
slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
Slf4jConfiguration slf4jConfiguration = Slf4jConfigurationFactory.getConfiguration( slf4jLoggerFactory );
@@ -527,7 +531,7 @@ public class MavenCli
// LOG COLOR
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 ) )
{
MessageUtils.setColorEnabled( true );
@@ -541,16 +545,20 @@ public class MavenCli
throw new IllegalArgumentException( "Invalid color configuration value '" + styleColor
+ "'. Supported are 'auto', 'always', 'never'." );
}
- else if ( cliRequest.commandLine.hasOption( CLIManager.BATCH_MODE )
- || cliRequest.commandLine.hasOption( CLIManager.LOG_FILE ) )
+ else
{
- MessageUtils.setColorEnabled( false );
+ boolean isBatchMode = !commandLine.hasOption( FORCE_INTERACTIVE )
+ && ( commandLine.hasOption( BATCH_MODE ) || commandLine.hasOption( NON_INTERACTIVE ) );
+ if ( isBatchMode || commandLine.hasOption( CLIManager.LOG_FILE ) )
+ {
+ MessageUtils.setColorEnabled( false );
+ }
}
// 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 );
// redirect stdout and stderr to file
@@ -573,9 +581,9 @@ public class MavenCli
plexusLoggerManager = new Slf4jLoggerManager();
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 )
{
@@ -591,7 +599,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"
+ " in a future version. Use -X/--verbose instead." );
@@ -1374,7 +1382,7 @@ public class MavenCli
request.setShowErrors( cliRequest.showErrors ); // default: false
File baseDirectory = new File( workingDirectory, "" ).getAbsoluteFile();
- disableOnPresentOption( commandLine, CLIManager.BATCH_MODE, request::setInteractiveMode );
+ disableInteractiveModeIfNeeded( cliRequest, request );
enableOnPresentOption( commandLine, CLIManager.SUPPRESS_SNAPSHOT_UPDATES, request::setNoSnapshotUpdates );
request.setGoals( commandLine.getArgList() );
request.setReactorFailureBehavior( determineReactorFailureBehaviour ( commandLine ) );
@@ -1438,6 +1446,27 @@ public class MavenCli
return request;
}
+ private void disableInteractiveModeIfNeeded( final CliRequest cliRequest, final MavenExecutionRequest request )
+ {
+ CommandLine commandLine = cliRequest.getCommandLine();
+ if ( commandLine.hasOption( FORCE_INTERACTIVE ) )
+ {
+ return;
+ }
+
+ String ciEnv = cliRequest.getSystemProperties().getProperty( "env.CI" );
+ if ( "true".equals( ciEnv ) )
+ {
+ slf4jLogger.info( "Detected a CI build, 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 String determineLocalRepositoryPath( final MavenExecutionRequest request )
{
String userDefinedLocalRepo = request.getUserProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
@@ -1593,7 +1622,10 @@ public class MavenCli
final CommandLine commandLine,
final MavenExecutionRequest request )
{
- if ( quiet || commandLine.hasOption( CLIManager.NO_TRANSFER_PROGRESS ) )
+ String ciEnv = request.getSystemProperties().getProperty( "env.CI" );
+ boolean quietCI = "true".equals( ciEnv ) && !commandLine.hasOption( FORCE_INTERACTIVE );
+
+ if ( quiet || commandLine.hasOption( CLIManager.NO_TRANSFER_PROGRESS ) || quietCI )
{
return new QuietMavenTransferListener();
}
diff --git a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
index c4fb01a91..54637c3fa 100644
--- a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
+++ b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
@@ -43,6 +43,7 @@ import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Stream;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
@@ -51,6 +52,9 @@ import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
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.execution.MavenExecutionRequest;
import org.apache.maven.execution.ProfileActivation;
@@ -61,9 +65,13 @@ import org.apache.maven.toolchain.building.ToolchainsBuildingRequest;
import org.apache.maven.toolchain.building.ToolchainsBuildingResult;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusContainer;
+import org.eclipse.aether.transfer.TransferListener;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
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;
public class MavenCliTest
@@ -359,6 +367,20 @@ public class MavenCliTest
cli.logging( request );
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 );
request = new CliRequest( new String[] { "-l", "target/temp/mvn.log" }, null );
request.workingDirectory = "target/temp";
@@ -588,6 +610,65 @@ public class MavenCliTest
assertThat( request.getUserProperties().getProperty( "x" ), is( "false" ) );
}
+ @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 )
{
MavenProject project = new MavenProject();