From 02639a2092978e945611c8cc917d6c15a3866f53 Mon Sep 17 00:00:00 2001 From: eric sciple Date: Mon, 13 Jan 2020 15:24:57 -0500 Subject: [PATCH] translate problem matcher file to host path (#272) --- src/Runner.Worker/Container/ContainerInfo.cs | 3 +- .../Handlers/ContainerActionHandler.cs | 4 +- src/Runner.Worker/Handlers/OutputManager.cs | 14 +- src/Test/L0/Worker/OutputManagerL0.cs | 133 +++++++++++++++++- 4 files changed, 147 insertions(+), 7 deletions(-) diff --git a/src/Runner.Worker/Container/ContainerInfo.cs b/src/Runner.Worker/Container/ContainerInfo.cs index 86885dbc4..8d3292496 100644 --- a/src/Runner.Worker/Container/ContainerInfo.cs +++ b/src/Runner.Worker/Container/ContainerInfo.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.IO; using GitHub.Runner.Common.Util; -using Pipelines = GitHub.DistributedTask.Pipelines; using GitHub.Runner.Common; using GitHub.Runner.Sdk; +using Pipelines = GitHub.DistributedTask.Pipelines; namespace GitHub.Runner.Worker.Container { @@ -19,7 +19,6 @@ namespace GitHub.Runner.Worker.Container public ContainerInfo() { - } public ContainerInfo(IHostContext hostContext, Pipelines.JobContainer container, bool isJobContainer = true, string networkAlias = null) diff --git a/src/Runner.Worker/Handlers/ContainerActionHandler.cs b/src/Runner.Worker/Handlers/ContainerActionHandler.cs index 2a91a1a42..bcd539469 100644 --- a/src/Runner.Worker/Handlers/ContainerActionHandler.cs +++ b/src/Runner.Worker/Handlers/ContainerActionHandler.cs @@ -189,8 +189,8 @@ namespace GitHub.Runner.Worker.Handlers container.ContainerEnvironmentVariables[variable.Key] = container.TranslateToContainerPath(variable.Value); } - using (var stdoutManager = new OutputManager(ExecutionContext, ActionCommandManager)) - using (var stderrManager = new OutputManager(ExecutionContext, ActionCommandManager)) + using (var stdoutManager = new OutputManager(ExecutionContext, ActionCommandManager, container)) + using (var stderrManager = new OutputManager(ExecutionContext, ActionCommandManager, container)) { var runExitCode = await dockerManger.DockerRun(ExecutionContext, container, stdoutManager.OnDataReceived, stderrManager.OnDataReceived); if (runExitCode != 0) diff --git a/src/Runner.Worker/Handlers/OutputManager.cs b/src/Runner.Worker/Handlers/OutputManager.cs index 369042ddf..3e8215704 100644 --- a/src/Runner.Worker/Handlers/OutputManager.cs +++ b/src/Runner.Worker/Handlers/OutputManager.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text.RegularExpressions; using GitHub.Runner.Common; using GitHub.Runner.Sdk; +using GitHub.Runner.Worker.Container; using DTWebApi = GitHub.DistributedTask.WebApi; namespace GitHub.Runner.Worker.Handlers @@ -17,6 +18,7 @@ namespace GitHub.Runner.Worker.Handlers private const string _timeoutKey = "GITHUB_ACTIONS_RUNNER_ISSUE_MATCHER_TIMEOUT"; private static readonly Regex _colorCodeRegex = new Regex(@"\x0033\[[0-9;]*m?", RegexOptions.Compiled | RegexOptions.CultureInvariant); private readonly IActionCommandManager _commandManager; + private readonly ContainerInfo _container; private readonly IExecutionContext _executionContext; private readonly int _failsafe = 50; private readonly object _matchersLock = new object(); @@ -25,10 +27,11 @@ namespace GitHub.Runner.Worker.Handlers // Mapping that indicates whether a directory belongs to the workflow repository private readonly Dictionary _directoryMap = new Dictionary(); - public OutputManager(IExecutionContext executionContext, IActionCommandManager commandManager) + public OutputManager(IExecutionContext executionContext, IActionCommandManager commandManager, ContainerInfo container = null) { _executionContext = executionContext; _commandManager = commandManager; + _container = container ?? executionContext.Container; // Recursion failsafe (test override) var failsafeString = Environment.GetEnvironmentVariable("RUNNER_TEST_GET_REPOSITORY_PATH_FAILSAFE"); @@ -257,6 +260,7 @@ namespace GitHub.Runner.Worker.Handlers if (!string.IsNullOrWhiteSpace(match.File)) { var file = match.File; + var translate = _container != null; // Root using fromPath if (!string.IsNullOrWhiteSpace(match.FromPath) && !Path.IsPathFullyQualified(file)) @@ -275,11 +279,19 @@ namespace GitHub.Runner.Worker.Handlers ArgUtil.NotNullOrEmpty(workspace, "workspace"); file = Path.Combine(workspace, file); + translate = false; } // Remove relative pathing and normalize slashes file = Path.GetFullPath(file); + // Translate to host + if (translate) + { + file = _container.TranslateToHostPath(file); + file = Path.GetFullPath(file); + } + // Check whether the file exists if (File.Exists(file)) { diff --git a/src/Test/L0/Worker/OutputManagerL0.cs b/src/Test/L0/Worker/OutputManagerL0.cs index ff8b18704..78d342a31 100644 --- a/src/Test/L0/Worker/OutputManagerL0.cs +++ b/src/Test/L0/Worker/OutputManagerL0.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using System.Runtime.CompilerServices; using GitHub.Runner.Sdk; using GitHub.Runner.Worker; +using GitHub.Runner.Worker.Container; using GitHub.Runner.Worker.Handlers; using Moq; using Xunit; @@ -748,6 +749,130 @@ namespace GitHub.Runner.Common.Tests.Worker Environment.SetEnvironmentVariable("RUNNER_TEST_GET_REPOSITORY_PATH_FAILSAFE", ""); } +#if OS_LINUX + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public async void MatcherFile_JobContainer() + { + var matchers = new IssueMatchersConfig + { + Matchers = + { + new IssueMatcherConfig + { + Owner = "my-matcher-1", + Patterns = new[] + { + new IssuePatternConfig + { + Pattern = @"(.+): (.+)", + File = 1, + Message = 2, + }, + }, + }, + }, + }; + var container = new ContainerInfo(); + using (var hostContext = Setup(matchers: matchers, jobContainer: container)) + using (_outputManager) + { + // Setup github.workspace, github.repository + var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work); + ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory)); + Directory.CreateDirectory(workDirectory); + var workspaceDirectory = Path.Combine(workDirectory, "workspace"); + Directory.CreateDirectory(workspaceDirectory); + _executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory); + _executionContext.Setup(x => x.GetGitHubContext("repository")).Returns("my-org/workflow-repo"); + + // Setup a git repository + await CreateRepository(hostContext, workspaceDirectory, "https://github.com/my-org/workflow-repo"); + + // Create test files + var file = Path.Combine(workspaceDirectory, "some-file.txt"); + File.WriteAllText(file, ""); + + // Add translation path + container.AddPathTranslateMapping(workspaceDirectory, "/container/path/to/workspace"); + + // Process + Process($"/container/path/to/workspace/some-file.txt: some error 1"); + Process($"some-file.txt: some error 2"); + + Assert.Equal(2, _issues.Count); + + Assert.Equal("some error 1", _issues[0].Item1.Message); + Assert.Equal("some-file.txt", _issues[0].Item1.Data["file"]); + + Assert.Equal("some error 2", _issues[1].Item1.Message); + Assert.Equal("some-file.txt", _issues[1].Item1.Data["file"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public async void MatcherFile_StepContainer() + { + var matchers = new IssueMatchersConfig + { + Matchers = + { + new IssueMatcherConfig + { + Owner = "my-matcher-1", + Patterns = new[] + { + new IssuePatternConfig + { + Pattern = @"(.+): (.+)", + File = 1, + Message = 2, + }, + }, + }, + }, + }; + var container = new ContainerInfo(); + using (var hostContext = Setup(matchers: matchers, stepContainer: container)) + using (_outputManager) + { + // Setup github.workspace, github.repository + var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work); + ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory)); + Directory.CreateDirectory(workDirectory); + var workspaceDirectory = Path.Combine(workDirectory, "workspace"); + Directory.CreateDirectory(workspaceDirectory); + _executionContext.Setup(x => x.GetGitHubContext("workspace")).Returns(workspaceDirectory); + _executionContext.Setup(x => x.GetGitHubContext("repository")).Returns("my-org/workflow-repo"); + + // Setup a git repository + await CreateRepository(hostContext, workspaceDirectory, "https://github.com/my-org/workflow-repo"); + + // Create test files + var file = Path.Combine(workspaceDirectory, "some-file.txt"); + File.WriteAllText(file, ""); + + // Add translation path + container.AddPathTranslateMapping(workspaceDirectory, "/container/path/to/workspace"); + + // Process + Process($"/container/path/to/workspace/some-file.txt: some error 1"); + Process($"some-file.txt: some error 2"); + + Assert.Equal(2, _issues.Count); + + Assert.Equal("some error 1", _issues[0].Item1.Message); + Assert.Equal("some-file.txt", _issues[0].Item1.Data["file"]); + + Assert.Equal("some error 2", _issues[1].Item1.Message); + Assert.Equal("some-file.txt", _issues[1].Item1.Data["file"]); + } + } +#endif + [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] @@ -806,7 +931,9 @@ namespace GitHub.Runner.Common.Tests.Worker private TestHostContext Setup( [CallerMemberName] string name = "", - IssueMatchersConfig matchers = null) + IssueMatchersConfig matchers = null, + ContainerInfo jobContainer = null, + ContainerInfo stepContainer = null) { matchers?.Validate(); @@ -824,6 +951,8 @@ namespace GitHub.Runner.Common.Tests.Worker .Returns(true); _executionContext.Setup(x => x.Variables) .Returns(_variables); + _executionContext.Setup(x => x.Container) + .Returns(jobContainer); _executionContext.Setup(x => x.GetMatchers()) .Returns(matchers?.Matchers ?? new List()); _executionContext.Setup(x => x.Add(It.IsAny())) @@ -856,7 +985,7 @@ namespace GitHub.Runner.Common.Tests.Worker return false; }); - _outputManager = new OutputManager(_executionContext.Object, _commandManager.Object); + _outputManager = new OutputManager(_executionContext.Object, _commandManager.Object, stepContainer); return hostContext; }