Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,9 @@ This is equivalent to deleting project.assets.json.</value>
<data name="CmdNoHttpCacheOptionDescription" xml:space="preserve">
<value>Disable Http Caching for packages.</value>
</data>
<data name="CmdNoArtifactPostProcessingDescription" xml:space="preserve">
<value>Do not merge compatible artifacts, such as TRX reports or code coverage files, produced by different test applications.</value>
</data>
<data name="CmdNoProgressDescription" xml:space="preserve">
<value>Disable progress reporting.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ public sealed partial class MicrosoftTestingPlatform : TestCommandDefinition, IC
Arity = ArgumentArity.Zero
};

public readonly Option<bool> NoArtifactPostProcessingOption = new("--no-artifact-post-processing")
{
Description = CommandDefinitionStrings.CmdNoArtifactPostProcessingDescription,
Arity = ArgumentArity.Zero
};

public readonly Option<OutputOptions> OutputOption = new("--output")
{
Description = CommandDefinitionStrings.CmdTestOutputDescription,
Expand Down Expand Up @@ -215,6 +221,7 @@ public MicrosoftTestingPlatform()
Options.Add(UseCurrentRuntimeOption);
Options.Add(NoAnsiOption);
Options.Add(NoProgressOption);
Options.Add(NoArtifactPostProcessingOption);
Options.Add(OutputOption);
Options.Add(ListTestsOption);
Options.Add(NoLaunchProfileOption);
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 27 additions & 10 deletions src/Cli/dotnet/Commands/Test/MTP/ArtifactPostProcessingManager.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.ComponentModel;
using System.Globalization;
using System.Text.Json;
using Microsoft.DotNet.Cli.Commands.Test.IPC.Models;
Expand Down Expand Up @@ -112,29 +111,29 @@ public async Task ExecuteAsync(

if (invocation.FailureMessage is { } failureMessage)
{
output.WriteWarningMessage(string.Format(
ReportFailureUnlessCancelled(output, ctrlC, string.Format(
CultureInfo.CurrentCulture,
CliCommandStrings.ArtifactPostProcessingFailed,
job.Application.Module.TargetPath,
failureMessage));
}
else if (exitCode != ExitCode.Success)
{
output.WriteWarningMessage(string.Format(
ReportFailureUnlessCancelled(output, ctrlC, string.Format(
CultureInfo.CurrentCulture,
CliCommandStrings.ArtifactPostProcessingProcessFailed,
job.Application.Module.TargetPath,
exitCode));
}
}
catch (Exception ex) when (ex is IOException
or UnauthorizedAccessException
or InvalidOperationException
or Win32Exception
or NotSupportedException
or TimeoutException)
catch (Exception ex)
{
output.WriteWarningMessage(string.Format(
// Post-processing is a best-effort convenience on top of a completed test run: the
// original artifacts are always still on disk and still reported, so no failure here
// may escape and turn a finished run into a CLI crash with a different exit code.
Logger.LogTrace($"Artifact post-processing with '{job.Application.Module.TargetPath}' failed: {ex}");

ReportFailureUnlessCancelled(output, ctrlC, string.Format(
CultureInfo.CurrentCulture,
CliCommandStrings.ArtifactPostProcessingFailed,
job.Application.Module.TargetPath,
Expand All @@ -157,6 +156,24 @@ or NotSupportedException
}
}

/// <summary>
/// Reports a post-processing failure, unless the user cancelled the run. Cancellation kills the
/// post-processing process the same way it kills a test application, so the resulting failure is
/// the cancellation the user asked for rather than a post-processing problem worth reporting.
/// </summary>
internal static void ReportFailureUnlessCancelled(
TerminalTestReporter output,
CtrlCCancellationManager ctrlC,
string message)
{
if (ctrlC.Token.IsCancellationRequested)
{
return;
}

output.WriteWarningMessage(message);
}

internal IReadOnlyList<ArtifactPostProcessingApplication> SnapshotApplications()
{
lock (_lock)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ public int Run(ParseResult parseResult, bool isHelp)
exitCode = ExitCode.TestSessionAborted;
}

if (!testOptions.IsHelp && !testOptions.IsDiscovery && !ctrlC.Token.IsCancellationRequested)
if (!testOptions.IsHelp
&& !testOptions.IsDiscovery
&& !parseResult.GetValue(definition.NoArtifactPostProcessingOption)
&& !ctrlC.Token.IsCancellationRequested)
{
artifactPostProcessingManager.ExecuteAsync(buildOptions, output, ctrlC).GetAwaiter().GetResult();
}
Expand Down
Loading
Loading