Skip to content

Commit

Permalink
[MNG-7338] Automatically activate batch-mode and make output quiet wh…
Browse files Browse the repository at this point in the history
…en running in CI.
  • Loading branch information
MartinKanters committed Nov 11, 2022
1 parent fa15fcf commit 811592c
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 16 deletions.
5 changes: 5 additions & 0 deletions maven-embedder/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/**
Expand Down Expand Up @@ -138,7 +142,9 @@ public 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() );
Expand Down
68 changes: 53 additions & 15 deletions maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@
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;

Expand Down Expand Up @@ -504,10 +507,11 @@ private CommandLine cliMerge( CommandLine mavenArgs, CommandLine mavenConfig )
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 );
Expand All @@ -527,7 +531,7 @@ else if ( cliRequest.quiet )

// 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 );
Expand All @@ -541,16 +545,20 @@ else if ( !"auto".equals( styleColor ) && !"tty".equals( styleColor ) && !"if-tt
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
Expand All @@ -573,9 +581,9 @@ else if ( cliRequest.commandLine.hasOption( CLIManager.BATCH_MODE )
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 )
{
Expand All @@ -591,7 +599,7 @@ else if ( cliRequest.commandLine.hasOption( CLIManager.BATCH_MODE )
}
}

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." );
Expand Down Expand Up @@ -1374,7 +1382,7 @@ private MavenExecutionRequest populateRequest( CliRequest cliRequest, MavenExecu
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 ) );
Expand Down Expand Up @@ -1438,6 +1446,33 @@ private MavenExecutionRequest populateRequest( CliRequest cliRequest, MavenExecu
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( "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 static boolean isRunningOnCI( Properties systemProperties )
{
String ciEnv = systemProperties.getProperty( "env.CI" );
return ciEnv != null && !"false".equals( ciEnv );
}

private String determineLocalRepositoryPath( final MavenExecutionRequest request )
{
String userDefinedLocalRepo = request.getUserProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
Expand Down Expand Up @@ -1593,7 +1628,10 @@ private TransferListener determineTransferListener( final boolean quiet,
final CommandLine commandLine,
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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
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;
Expand All @@ -51,6 +52,9 @@
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;
Expand All @@ -61,9 +65,13 @@
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
Expand Down Expand Up @@ -359,6 +367,20 @@ public void testStyleColors()
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";
Expand Down Expand Up @@ -588,6 +610,65 @@ public void populatePropertiesOverwrite() throws Exception
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();
Expand Down

0 comments on commit 811592c

Please sign in to comment.