diff --git a/src/Platform/Microsoft.Testing.Extensions.Telemetry/AppInsightsProvider.cs b/src/Platform/Microsoft.Testing.Extensions.Telemetry/AppInsightsProvider.cs
index 647c516d13..edd545de3c 100644
--- a/src/Platform/Microsoft.Testing.Extensions.Telemetry/AppInsightsProvider.cs
+++ b/src/Platform/Microsoft.Testing.Extensions.Telemetry/AppInsightsProvider.cs
@@ -93,7 +93,7 @@ public AppInsightsProvider(
string sessionId)
{
_ = bool.TryParse(configuration[PlatformConfigurationConstants.PlatformTelemetryIsDevelopmentRepository], out _isDevelopmentRepository);
- _isCi = CIEnvironmentDetectorForTelemetry.IsCIEnvironment();
+ _isCi = new CIEnvironmentDetector(environment).IsCIEnvironment();
_environment = environment;
_currentSessionId = sessionId;
_testApplicationCancellationTokenSource = testApplicationCancellationTokenSource;
diff --git a/src/Platform/Microsoft.Testing.Extensions.Telemetry/Microsoft.Testing.Extensions.Telemetry.csproj b/src/Platform/Microsoft.Testing.Extensions.Telemetry/Microsoft.Testing.Extensions.Telemetry.csproj
index 9817dd8471..1c9ee840cf 100644
--- a/src/Platform/Microsoft.Testing.Extensions.Telemetry/Microsoft.Testing.Extensions.Telemetry.csproj
+++ b/src/Platform/Microsoft.Testing.Extensions.Telemetry/Microsoft.Testing.Extensions.Telemetry.csproj
@@ -7,6 +7,7 @@
+
diff --git a/src/Platform/Microsoft.Testing.Extensions.Telemetry/CIEnvironmentDetectorForTelemetry.cs b/src/Platform/Microsoft.Testing.Platform/Helpers/CIEnvironmentDetector.cs
similarity index 63%
rename from src/Platform/Microsoft.Testing.Extensions.Telemetry/CIEnvironmentDetectorForTelemetry.cs
rename to src/Platform/Microsoft.Testing.Platform/Helpers/CIEnvironmentDetector.cs
index 0ac25bde4a..f8f91094c9 100644
--- a/src/Platform/Microsoft.Testing.Extensions.Telemetry/CIEnvironmentDetectorForTelemetry.cs
+++ b/src/Platform/Microsoft.Testing.Platform/Helpers/CIEnvironmentDetector.cs
@@ -1,13 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-using Microsoft.Testing.Platform;
+using Microsoft.CodeAnalysis;
-namespace Microsoft.Testing.Extensions.Telemetry;
+namespace Microsoft.Testing.Platform.Helpers;
// Detection of CI: https://learn.microsoft.com/dotnet/core/tools/telemetry#continuous-integration-detection
-// From: https://github.com/dotnet/sdk/blob/main/src/Cli/dotnet/Telemetry/CIEnvironmentDetectorForTelemetry.cs
-internal sealed class CIEnvironmentDetectorForTelemetry
+// Based on: https://github.com/dotnet/sdk/blob/main/src/Cli/Microsoft.DotNet.Cli.Definitions/Telemetry/CIEnvironmentDetectorForTelemetry.cs
+[Embedded]
+[ExcludeFromCodeCoverage]
+internal sealed class CIEnvironmentDetector
{
// Systems that provide boolean values only, so we can simply parse and check for true
private static readonly string[] BooleanVariables =
@@ -22,14 +24,13 @@ internal sealed class CIEnvironmentDetectorForTelemetry
"APPVEYOR",
// A general-use flag - Many of the major players support this: AzDo, GitHub, GitLab, AppVeyor, Travis CI, CircleCI.
- // Given this, we could potentially remove all of these other options?
"CI",
// Travis CI - https://docs.travis-ci.com/user/environment-variables/#default-environment-variables
"TRAVIS",
// CircleCI - https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables
- "CIRCLECI"
+ "CIRCLECI",
];
// Systems where every variable must be present and not-null before returning true
@@ -52,14 +53,27 @@ internal sealed class CIEnvironmentDetectorForTelemetry
"TEAMCITY_VERSION",
// JetBrains Space - https://www.jetbrains.com/help/space/automation-environment-variables.html#general
- "JB_SPACE_API_URL"
+ "JB_SPACE_API_URL",
];
- public static bool IsCIEnvironment()
+ private readonly IEnvironment _environment;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The environment abstraction to use for reading environment variables.
+ public CIEnvironmentDetector(IEnvironment environment)
+ => _environment = environment;
+
+ ///
+ /// Detects if the current environment is a CI environment.
+ ///
+ /// true if running in a CI environment; otherwise, false.
+ public bool IsCIEnvironment()
{
foreach (string booleanVariable in BooleanVariables)
{
- if (bool.TryParse(Environment.GetEnvironmentVariable(booleanVariable), out bool envVar) && envVar)
+ if (bool.TryParse(_environment.GetEnvironmentVariable(booleanVariable), out bool envVar) && envVar)
{
return true;
}
@@ -67,7 +81,17 @@ public static bool IsCIEnvironment()
foreach (string[] variables in AllNotNullVariables)
{
- if (variables.All(variable => !RoslynString.IsNullOrEmpty(Environment.GetEnvironmentVariable(variable))))
+ bool allVariablesPresent = true;
+ foreach (string variable in variables)
+ {
+ if (global::Microsoft.Testing.Platform.RoslynString.IsNullOrEmpty(_environment.GetEnvironmentVariable(variable)))
+ {
+ allVariablesPresent = false;
+ break;
+ }
+ }
+
+ if (allVariablesPresent)
{
return true;
}
@@ -75,7 +99,7 @@ public static bool IsCIEnvironment()
foreach (string variable in IfNonNullVariables)
{
- if (!RoslynString.IsNullOrEmpty(Environment.GetEnvironmentVariable(variable)))
+ if (!global::Microsoft.Testing.Platform.RoslynString.IsNullOrEmpty(_environment.GetEnvironmentVariable(variable)))
{
return true;
}
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/SimpleAnsiTerminal.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/SimpleAnsiTerminal.cs
index 12b4f4eee0..84656db087 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/SimpleAnsiTerminal.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/SimpleAnsiTerminal.cs
@@ -6,8 +6,8 @@
namespace Microsoft.Testing.Platform.OutputDevice.Terminal;
///
-/// Simple terminal that uses 4-bit ANSI for colors but does not move cursor and does not do other fancy stuff to stay compatible with CI systems like AzDO.
-/// The colors are set on start of every line to properly color multiline strings in AzDO output.
+/// Simple terminal that uses 4-bit ANSI for colors but does not move cursor and does not do other fancy stuff to stay compatible with CI systems.
+/// The colors are set on start of every line to properly color multiline strings in CI log viewers that reset color state at each newline (e.g. Azure DevOps).
///
internal sealed class SimpleAnsiTerminal : SimpleTerminal
{
diff --git a/src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs b/src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs
index a3563ec9a2..623540dc95 100644
--- a/src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs
+++ b/src/Platform/Microsoft.Testing.Platform/OutputDevice/TerminalOutputDevice.cs
@@ -142,8 +142,7 @@ await _policiesService.RegisterOnAbortCallbackAsync(
_isServerMode = _commandLineOptions.IsOptionSet(PlatformCommandLineProvider.ServerOptionKey);
bool noAnsi = _commandLineOptions.IsOptionSet(TerminalTestReporterCommandLineOptionsProvider.NoAnsiOption);
- // TODO: Replace this with proper CI detection that we already have in telemetry. https://github.com/microsoft/testfx/issues/5533#issuecomment-2838893327
- bool inCI = string.Equals(_environment.GetEnvironmentVariable("TF_BUILD"), "true", StringComparison.OrdinalIgnoreCase) || string.Equals(_environment.GetEnvironmentVariable("GITHUB_ACTIONS"), "true", StringComparison.OrdinalIgnoreCase);
+ bool inCI = new CIEnvironmentDetector(_environment).IsCIEnvironment();
AnsiMode ansiMode = AnsiMode.AnsiIfPossible;
// In LLM environments, prefer simple text output so that LLM can parse it easily.