diff --git a/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.Linux.verified.txt b/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.Linux.verified.txt index 34432ae0de0..ca72cc765ec 100644 --- a/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.Linux.verified.txt +++ b/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.Linux.verified.txt @@ -1,8 +1,9 @@ The plugin credential provider could not acquire credentials.Authentication may require manual action. Consider re-running the command with --interactive for `dotnet`, /p:NuGetInteractive="true" for MSBuild or removing the -NonInteractive switch for `NuGet` -directory/file(1,2,3,4): warning AA0000: Warning! -directory/file(1,2,3,4): warning AA0000: - A - Multi - Line - Warning! -directory/file(1,2,3,4): error AA0000: Error! + project failed with 1 error(s) and 2 warning(s) (0.2s) + directory/file(1,2,3,4): warning AA0000: Warning! + directory/file(1,2,3,4): warning AA0000: + A + Multi + Line + Warning! + directory/file(1,2,3,4): error AA0000: Error! diff --git a/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.OSX.verified.txt b/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.OSX.verified.txt index 5037f4b16db..450eaea951f 100644 --- a/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.OSX.verified.txt +++ b/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.OSX.verified.txt @@ -1,8 +1,9 @@ The plugin credential provider could not acquire credentials.Authentication may require manual action. Consider re-running the command with --interactive for `dotnet`, /p:NuGetInteractive="true" for MSBuild or removing the -NonInteractive switch for `NuGet` -directory/file(1,2,3,4): warning AA0000: Warning! -directory/file(1,2,3,4): warning AA0000: - A - Multi - Line - Warning! -directory/file(1,2,3,4): error AA0000: Error! + project failed with 1 error(s) and 2 warning(s) (0.2s) + directory/file(1,2,3,4): warning AA0000: Warning! + directory/file(1,2,3,4): warning AA0000: + A + Multi + Line + Warning! + directory/file(1,2,3,4): error AA0000: Error! diff --git a/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.Windows.verified.txt b/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.Windows.verified.txt index 34432ae0de0..ca72cc765ec 100644 --- a/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.Windows.verified.txt +++ b/src/Build.UnitTests/Snapshots/TerminalLogger_Tests.PrintBuildSummaryQuietVerbosity_FailedWithErrors.Windows.verified.txt @@ -1,8 +1,9 @@ The plugin credential provider could not acquire credentials.Authentication may require manual action. Consider re-running the command with --interactive for `dotnet`, /p:NuGetInteractive="true" for MSBuild or removing the -NonInteractive switch for `NuGet` -directory/file(1,2,3,4): warning AA0000: Warning! -directory/file(1,2,3,4): warning AA0000: - A - Multi - Line - Warning! -directory/file(1,2,3,4): error AA0000: Error! + project failed with 1 error(s) and 2 warning(s) (0.2s) + directory/file(1,2,3,4): warning AA0000: Warning! + directory/file(1,2,3,4): warning AA0000: + A + Multi + Line + Warning! + directory/file(1,2,3,4): error AA0000: Error! diff --git a/src/Build/Logging/TerminalLogger/TerminalLogger.cs b/src/Build/Logging/TerminalLogger/TerminalLogger.cs index dffb6064a90..8965696dfa8 100644 --- a/src/Build/Logging/TerminalLogger/TerminalLogger.cs +++ b/src/Build/Logging/TerminalLogger/TerminalLogger.cs @@ -754,18 +754,23 @@ private void ProjectFinished(object sender, ProjectFinishedEventArgs e) UpdateNodeStatus(buildEventContext, null); } - // Continue execution and add project summary to the static part of the Console only if verbosity is higher than Quiet. - if (Verbosity <= LoggerVerbosity.Quiet) - { - return; - } - ProjectContext c = new(buildEventContext); if (_projects.TryGetValue(c, out TerminalProjectInfo? project)) { project.Succeeded = e.Succeeded; project.Stopwatch.Stop(); + + // In quiet mode, only show projects with errors or warnings. + // In higher verbosity modes, show projects based on other criteria. + if (Verbosity == LoggerVerbosity.Quiet && !project.HasErrorsOrWarnings) + { + // Still need to update counts even if not displaying + _buildErrorsCount += project.ErrorCount; + _buildWarningsCount += project.WarningCount; + return; + } + lock (_lock) { Terminal.BeginUpdate(); @@ -809,6 +814,7 @@ private void ProjectFinished(object sender, ProjectFinishedEventArgs e) // If this was a notable project build, we print it as completed only if it's produced an output or warnings/error. // If this is a test project, print it always, so user can see either a success or failure, otherwise success is hidden // and it is hard to see if project finished, or did not run at all. + // In quiet mode, we show the project header if there are errors/warnings (already checked above). else if (project.OutputPath is not null || project.BuildMessages is not null || project.IsTestProject) { // Show project build complete and its output @@ -839,7 +845,7 @@ private void ProjectFinished(object sender, ProjectFinishedEventArgs e) _buildErrorsCount += project.ErrorCount; _buildWarningsCount += project.WarningCount; - if (_showNodesDisplay) + if (_showNodesDisplay && Verbosity > LoggerVerbosity.Quiet) { DisplayNodes(); } @@ -1300,27 +1306,24 @@ private void WarningRaised(object sender, BuildWarningEventArgs e) } if (buildEventContext is not null - && _projects.TryGetValue(new ProjectContext(buildEventContext), out TerminalProjectInfo? project) - && Verbosity > LoggerVerbosity.Quiet) + && _projects.TryGetValue(new ProjectContext(buildEventContext), out TerminalProjectInfo? project)) { // If the warning is not a 'global' auth provider message, but is immediate, we render it immediately // but we don't early return so that the project also tracks it. - if (IsImmediateWarning(e.Code)) + if (IsImmediateWarning(e.Code) && Verbosity > LoggerVerbosity.Quiet) { RenderImmediateMessage(FormatWarningMessage(e, Indentation)); } // This is the general case - _most_ warnings are not immediate, so we add them to the project summary // and display them in the per-project and final summary. + // In quiet mode, we still accumulate so they can be shown in project-grouped form later. project.AddBuildMessage(TerminalMessageSeverity.Warning, FormatWarningMessage(e, TripleIndentation)); } else { // It is necessary to display warning messages reported by MSBuild, - // even if it's not tracked in _projects collection or the verbosity is Quiet. - // The idea here (similar to the implementation in ErrorRaised) is that - // even in Quiet scenarios we need to show warnings/errors, even if not in - // full project-tree view + // even if it's not tracked in _projects collection. RenderImmediateMessage(FormatWarningMessage(e, Indentation)); _buildWarningsCount++; } @@ -1385,14 +1388,15 @@ private void ErrorRaised(object sender, BuildErrorEventArgs e) BuildEventContext? buildEventContext = e.BuildEventContext; if (buildEventContext is not null - && _projects.TryGetValue(new ProjectContext(buildEventContext), out TerminalProjectInfo? project) - && Verbosity > LoggerVerbosity.Quiet) + && _projects.TryGetValue(new ProjectContext(buildEventContext), out TerminalProjectInfo? project)) { + // Always accumulate errors in the project, even in quiet mode, so they can be shown + // in project-grouped form later. project.AddBuildMessage(TerminalMessageSeverity.Error, FormatErrorMessage(e, TripleIndentation)); } else { - // It is necessary to display error messages reported by MSBuild, even if it's not tracked in _projects collection or the verbosity is Quiet. + // It is necessary to display error messages reported by MSBuild, even if it's not tracked in _projects collection. // For nicer formatting, any messages from the engine we strip the file portion from. bool hasMSBuildPlaceholderLocation = e.File.Equals("MSBUILD", StringComparison.Ordinal); RenderImmediateMessage(FormatErrorMessage(e, Indentation, requireFileAndLinePortion: !hasMSBuildPlaceholderLocation));