From a17712d4d82cadc0ce2899e0c5e84924a2ab0dac Mon Sep 17 00:00:00 2001 From: NikolayPianikov Date: Wed, 17 Nov 2021 16:54:56 +0300 Subject: [PATCH] TW-73982 .NET runner and C# script runner do not propagate TEAMCITY_PROCESS_FLOW_ID environment variables to spawned processes --- .../TeamCity.MSBuild.Logger.Tests.csproj | 2 +- .../TeamCityHierarchicalMessageWriterTests.cs | 4 ++-- TeamCity.MSBuild.Logger/Composer.cs | 1 + TeamCity.MSBuild.Logger/Environment.cs | 19 +++++++++++++++++++ TeamCity.MSBuild.Logger/IEnvironment.cs | 2 ++ TeamCity.MSBuild.Logger/NodeLogger.cs | 4 +++- TeamCity.MSBuild.Logger/Parameters.cs | 9 ++++++++- .../TeamCity.MSBuild.Logger.csproj | 4 ++-- .../TeamCityHierarchicalMessageWriter.cs | 6 ++---- .../TeamCityMSBuildLogger.cs | 17 ++++------------- 10 files changed, 44 insertions(+), 24 deletions(-) diff --git a/TeamCity.MSBuild.Logger.Tests/TeamCity.MSBuild.Logger.Tests.csproj b/TeamCity.MSBuild.Logger.Tests/TeamCity.MSBuild.Logger.Tests.csproj index 06a31ee..9864aca 100644 --- a/TeamCity.MSBuild.Logger.Tests/TeamCity.MSBuild.Logger.Tests.csproj +++ b/TeamCity.MSBuild.Logger.Tests/TeamCity.MSBuild.Logger.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/TeamCity.MSBuild.Logger.Tests/TeamCityHierarchicalMessageWriterTests.cs b/TeamCity.MSBuild.Logger.Tests/TeamCityHierarchicalMessageWriterTests.cs index 6d84be9..73ded7b 100644 --- a/TeamCity.MSBuild.Logger.Tests/TeamCityHierarchicalMessageWriterTests.cs +++ b/TeamCity.MSBuild.Logger.Tests/TeamCityHierarchicalMessageWriterTests.cs @@ -68,7 +68,7 @@ public void ShouldSendMessageInDefaultFlow() public void ShouldNotCreateNestedServiceMessage(string serviceMessage) { // Given - var writer = CreateInstance(new Parameters {PlainServiceMessage = true}); + var writer = CreateInstance(new Parameters(Mock.Of()) {PlainServiceMessage = true}); var serviceMessage1 = new ServiceMessage("message"); var serviceMessage2 = new ServiceMessage("publishArtifacts"); _serviceMessageParser.Setup(i => i.ParseServiceMessages(serviceMessage.Trim())).Returns(new IServiceMessage[] { serviceMessage1, serviceMessage2 }); @@ -554,7 +554,7 @@ public void ShouldNotOpenFlowWhenNoBlocks() private TeamCityHierarchicalMessageWriter CreateInstance([CanBeNull] Parameters parameters = null) { var loggerContext = new Mock(); - loggerContext.SetupGet(i => i.Parameters).Returns(parameters ?? new Parameters()); + loggerContext.SetupGet(i => i.Parameters).Returns(parameters ?? new Parameters(Mock.Of())); return new TeamCityHierarchicalMessageWriter( loggerContext.Object, _colorTheme.Object, diff --git a/TeamCity.MSBuild.Logger/Composer.cs b/TeamCity.MSBuild.Logger/Composer.cs index fb83d1d..26e22ad 100644 --- a/TeamCity.MSBuild.Logger/Composer.cs +++ b/TeamCity.MSBuild.Logger/Composer.cs @@ -23,6 +23,7 @@ private static void Setup() => .Bind().Bind().To() .Bind().To() .Bind().To() + .Bind().To() .Bind().To() .Bind().To() .Bind().To() diff --git a/TeamCity.MSBuild.Logger/Environment.cs b/TeamCity.MSBuild.Logger/Environment.cs index 5116917..88ebfe4 100644 --- a/TeamCity.MSBuild.Logger/Environment.cs +++ b/TeamCity.MSBuild.Logger/Environment.cs @@ -1,8 +1,27 @@ namespace TeamCity.MSBuild.Logger { + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + // ReSharper disable once ClassNeverInstantiated.Global internal class Environment : IEnvironment { + private static readonly Dictionary Envs = new Dictionary(StringComparer.OrdinalIgnoreCase); + + static Environment() + { + foreach (var entry in System.Environment.GetEnvironmentVariables().OfType()) + { + var key = entry.Key?.ToString()?.Trim() ?? string.Empty; + var value = entry.Value?.ToString()?.Trim() ?? string.Empty; + Envs[key] = value; + } + } + + public string GetEnvironmentVariable(string name) => Envs.TryGetValue(name, out var val) ? val : string.Empty; + public string DiagnosticsFile => System.Environment.GetEnvironmentVariable("MSBUILDDIAGNOSTICSFILE") ?? string.Empty; public bool TargetOutputLogging => !string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("MSBUILDTARGETOUTPUTLOGGING")); diff --git a/TeamCity.MSBuild.Logger/IEnvironment.cs b/TeamCity.MSBuild.Logger/IEnvironment.cs index cfba470..00ba3c3 100644 --- a/TeamCity.MSBuild.Logger/IEnvironment.cs +++ b/TeamCity.MSBuild.Logger/IEnvironment.cs @@ -4,6 +4,8 @@ internal interface IEnvironment { + string GetEnvironmentVariable(string name); + bool TargetOutputLogging { get; } [NotNull] string DiagnosticsFile { get; } diff --git a/TeamCity.MSBuild.Logger/NodeLogger.cs b/TeamCity.MSBuild.Logger/NodeLogger.cs index cd74a4a..ae1c11a 100644 --- a/TeamCity.MSBuild.Logger/NodeLogger.cs +++ b/TeamCity.MSBuild.Logger/NodeLogger.cs @@ -11,6 +11,7 @@ // ReSharper disable once ClassWithVirtualMembersNeverInherited.Global internal class NodeLogger : INodeLogger { + [NotNull] private readonly Parameters _parameters; [NotNull] private readonly ILoggerContext _context; [NotNull] private readonly IEnvironment _environment; [NotNull] private readonly IDiagnostics _diagnostics; @@ -29,7 +30,6 @@ internal class NodeLogger : INodeLogger [NotNull] private readonly IBuildEventHandler _buildStartedEventHandler; [NotNull] private readonly IParametersParser _parametersParser; [NotNull] private readonly ILogWriter _logWriter; - [NotNull] private readonly Parameters _parameters = new Parameters(); [NotNull] private readonly object _lockObject = new object(); // ReSharper disable once IdentifierTypo private int _reentrancy; @@ -37,6 +37,7 @@ internal class NodeLogger : INodeLogger public NodeLogger( // ReSharper disable once UnusedParameter.Local // ReSharper disable once IdentifierTypo + [NotNull] Parameters parameters, [NotNull] IInitializable[] initializables, [NotNull] IParametersParser parametersParser, [NotNull] ILogWriter logWriter, @@ -57,6 +58,7 @@ public NodeLogger( [NotNull] IBuildEventHandler warningHandler, [NotNull] IBuildEventHandler customEventHandler) { + _parameters = parameters ?? throw new ArgumentNullException(nameof(parameters)); _context = context ?? throw new ArgumentNullException(nameof(context)); _environment = environment ?? throw new ArgumentNullException(nameof(environment)); _diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); diff --git a/TeamCity.MSBuild.Logger/Parameters.cs b/TeamCity.MSBuild.Logger/Parameters.cs index b63f89c..f11aae9 100644 --- a/TeamCity.MSBuild.Logger/Parameters.cs +++ b/TeamCity.MSBuild.Logger/Parameters.cs @@ -1,9 +1,16 @@ namespace TeamCity.MSBuild.Logger { + using System; + using JetBrains.Annotations; using Microsoft.Build.Framework; internal class Parameters { + private readonly IEnvironment _environment; + + public Parameters([NotNull] IEnvironment environment) => + _environment = environment ?? throw new ArgumentNullException(nameof(environment)); + public bool Debug { get; set; } public bool ShowOnlyWarnings { get; set; } @@ -47,7 +54,7 @@ internal class Parameters public bool PlainServiceMessage { get; set; } // ReSharper disable once MemberCanBeMadeStatic.Global - public string FlowId => System.Environment.GetEnvironmentVariable("TEAMCITY_PROCESS_FLOW_ID") ?? string.Empty; + public string FlowId => _environment.GetEnvironmentVariable("TEAMCITY_PROCESS_FLOW_ID") ?? string.Empty; public override string ToString() => $"{nameof(Debug)}: {Debug}, {nameof(ShowOnlyWarnings)}: {ShowOnlyWarnings}, {nameof(ShowEnvironment)}: {ShowEnvironment}, {nameof(Verbosity)}: {Verbosity}, {nameof(ShowPerfSummary)}: {ShowPerfSummary}, {nameof(ShowItemAndPropertyList)}: {ShowItemAndPropertyList}, {nameof(ShowSummary)}: {ShowSummary}, {nameof(ShowOnlyErrors)}: {ShowOnlyErrors}, {nameof(ShowProjectFile)}: {ShowProjectFile}, {nameof(ShowCommandLine)}: {ShowCommandLine}, {nameof(ShowTimeStamp)}: {ShowTimeStamp}, {nameof(ShowEventId)}: {ShowEventId}, {nameof(ForceNoAlign)}: {ForceNoAlign}, {nameof(AlignMessages)}: {AlignMessages}, {nameof(ShowTargetOutputs)}: {ShowTargetOutputs}, {nameof(BufferWidth)}: {BufferWidth}, {nameof(ColorMode)}: {ColorMode}, {nameof(TeamCityMode)}: {TeamCityMode}, {nameof(StatisticsMode)}: {StatisticsMode}, {nameof(ColorThemeMode)}: {ColorThemeMode}, {nameof(PlainServiceMessage)}: {PlainServiceMessage}"; } diff --git a/TeamCity.MSBuild.Logger/TeamCity.MSBuild.Logger.csproj b/TeamCity.MSBuild.Logger/TeamCity.MSBuild.Logger.csproj index 0173ef7..6d7bc2a 100644 --- a/TeamCity.MSBuild.Logger/TeamCity.MSBuild.Logger.csproj +++ b/TeamCity.MSBuild.Logger/TeamCity.MSBuild.Logger.csproj @@ -19,8 +19,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/TeamCity.MSBuild.Logger/TeamCityHierarchicalMessageWriter.cs b/TeamCity.MSBuild.Logger/TeamCityHierarchicalMessageWriter.cs index 37b94a6..58e6bc6 100644 --- a/TeamCity.MSBuild.Logger/TeamCityHierarchicalMessageWriter.cs +++ b/TeamCity.MSBuild.Logger/TeamCityHierarchicalMessageWriter.cs @@ -193,10 +193,8 @@ private void Write([NotNull] string message, [NotNull] Flow flow) } } - private string FormatMessage(MessageState messageState, MessageInfo messageInfo, string text) - { - return messageState == MessageState.Normal && messageInfo.Color.HasValue ? $"\x001B[{_colorTheme.GetAnsiColor(messageInfo.Color.Value)}m{text}" : text; - } + private string FormatMessage(MessageState messageState, MessageInfo messageInfo, string text) => + messageState == MessageState.Normal && !string.IsNullOrWhiteSpace(text) && messageInfo.Color.HasValue ? $"\x001B[{_colorTheme.GetAnsiColor(messageInfo.Color.Value)}m{text}" : text; private enum MessageState { diff --git a/TeamCity.MSBuild.Logger/TeamCityMSBuildLogger.cs b/TeamCity.MSBuild.Logger/TeamCityMSBuildLogger.cs index 7c731e3..8e62d46 100644 --- a/TeamCity.MSBuild.Logger/TeamCityMSBuildLogger.cs +++ b/TeamCity.MSBuild.Logger/TeamCityMSBuildLogger.cs @@ -6,7 +6,7 @@ namespace TeamCity.MSBuild.Logger // ReSharper disable once UnusedMember.Global public class TeamCityMsBuildLogger : INodeLogger { - private readonly INodeLogger _logger = Composer.Resolve(); + private readonly INodeLogger _logger = Composer.ResolveINodeLogger(); public string Parameters { @@ -20,19 +20,10 @@ public LoggerVerbosity Verbosity set => _logger.Verbosity = value; } - public void Initialize(IEventSource eventSource, int nodeCount) - { - _logger.Initialize(eventSource, nodeCount); - } + public void Initialize(IEventSource eventSource, int nodeCount) => _logger.Initialize(eventSource, nodeCount); - public void Initialize(IEventSource eventSource) - { - _logger.Initialize(eventSource); - } + public void Initialize(IEventSource eventSource) => _logger.Initialize(eventSource); - public void Shutdown() - { - _logger.Shutdown(); - } + public void Shutdown() => _logger.Shutdown(); } }