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:31 UTC

[maven] branch feature/MNG-7338-automatic-non-interactive-mode-in-ci created (now 2a87384e9)

This is an automated email from the ASF dual-hosted git repository.

martinkanters pushed a change to branch feature/MNG-7338-automatic-non-interactive-mode-in-ci
in repository https://gitbox.apache.org/repos/asf/maven.git


      at 2a87384e9 [MNG-7338] Automatically activate batch-mode and make output quiet when running in CI.

This branch includes the following new commits:

     new 2a87384e9 [MNG-7338] Automatically activate batch-mode and make output quiet when running in CI.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[maven] 01/01: [MNG-7338] Automatically activate batch-mode and make output quiet when running in CI.

Posted by ma...@apache.org.
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();