diff --git a/docs/start/envosx.md b/docs/start/envosx.md index 13969600a..d93f7a3eb 100644 --- a/docs/start/envosx.md +++ b/docs/start/envosx.md @@ -4,7 +4,7 @@ ## Supported Versions - - macOS Sierra (10.12) and later versions + - macOS High Sierra (10.13) and later versions -## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore2x) +## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30) diff --git a/docs/start/envwin.md b/docs/start/envwin.md index 4dd316990..fc3500a64 100644 --- a/docs/start/envwin.md +++ b/docs/start/envwin.md @@ -5,8 +5,8 @@ - Windows 7 64-bit - Windows 8.1 64-bit - Windows 10 64-bit - - Windows Server 2008 R2 SP1 64-bit - Windows Server 2012 R2 64-bit - Windows Server 2016 64-bit + - Windows Server 2019 64-bit -## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x) +## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore30) diff --git a/src/Runner.Service/Windows/FinalPublicKey.snk b/src/Runner.Service/Windows/FinalPublicKey.snk deleted file mode 100644 index 110b59c7b..000000000 Binary files a/src/Runner.Service/Windows/FinalPublicKey.snk and /dev/null differ diff --git a/src/Runner.Service/Windows/RunnerService.csproj b/src/Runner.Service/Windows/RunnerService.csproj index 8871f9a80..73fe4ecc6 100644 --- a/src/Runner.Service/Windows/RunnerService.csproj +++ b/src/Runner.Service/Windows/RunnerService.csproj @@ -9,9 +9,8 @@ Properties RunnerService RunnerService - true - FinalPublicKey.snk - true + false + false v4.5 512 true @@ -64,7 +63,6 @@ - diff --git a/src/Runner.Worker/ActionCommandManager.cs b/src/Runner.Worker/ActionCommandManager.cs index 2e2e6af1e..023e2f304 100644 --- a/src/Runner.Worker/ActionCommandManager.cs +++ b/src/Runner.Worker/ActionCommandManager.cs @@ -73,7 +73,7 @@ namespace GitHub.Runner.Worker return false; } - // process action command in serialize oreder. + // process action command in serialize order. lock (_commandSerializeLock) { if (_stopProcessCommand) @@ -107,32 +107,19 @@ namespace GitHub.Runner.Worker } else if (_commandExtensions.TryGetValue(actionCommand.Command, out IActionCommandExtension extension)) { - bool commandHasBeenOutput = false; + if (context.EchoOnActionCommand && !extension.OmitEcho) + { + context.Output(input); + } try { - if (context.EchoOnActionCommand) - { - context.Output(input); - context.Debug($"Processing command '{actionCommand.Command}'"); - commandHasBeenOutput = true; - } - extension.ProcessCommand(context, input, actionCommand); - - if (context.EchoOnActionCommand) - { - context.Debug($"Processed command '{actionCommand.Command}' successfully"); - } } catch (Exception ex) { - if (!commandHasBeenOutput) - { - context.Output(input); - } - - context.Error($"Unable to process command '{input}' successfully."); + var commandInformation = extension.OmitEcho ? extension.Command : input; + context.Error($"Unable to process command '{commandInformation}' successfully."); context.Error(ex); context.CommandResult = TaskResult.Failed; } @@ -151,6 +138,7 @@ namespace GitHub.Runner.Worker public interface IActionCommandExtension : IExtension { string Command { get; } + bool OmitEcho { get; } void ProcessCommand(IExecutionContext context, string line, ActionCommand command); } @@ -158,6 +146,7 @@ namespace GitHub.Runner.Worker public sealed class InternalPluginSetRepoPathCommandExtension : RunnerService, IActionCommandExtension { public string Command => "internal-set-repo-path"; + public bool OmitEcho => false; public Type ExtensionType => typeof(IActionCommandExtension); @@ -187,6 +176,7 @@ namespace GitHub.Runner.Worker public sealed class SetEnvCommandExtension : RunnerService, IActionCommandExtension { public string Command => "set-env"; + public bool OmitEcho => false; public Type ExtensionType => typeof(IActionCommandExtension); @@ -211,6 +201,7 @@ namespace GitHub.Runner.Worker public sealed class SetOutputCommandExtension : RunnerService, IActionCommandExtension { public string Command => "set-output"; + public bool OmitEcho => false; public Type ExtensionType => typeof(IActionCommandExtension); @@ -234,6 +225,7 @@ namespace GitHub.Runner.Worker public sealed class SaveStateCommandExtension : RunnerService, IActionCommandExtension { public string Command => "save-state"; + public bool OmitEcho => false; public Type ExtensionType => typeof(IActionCommandExtension); @@ -257,6 +249,7 @@ namespace GitHub.Runner.Worker public sealed class AddMaskCommandExtension : RunnerService, IActionCommandExtension { public string Command => "add-mask"; + public bool OmitEcho => true; public Type ExtensionType => typeof(IActionCommandExtension); @@ -268,6 +261,11 @@ namespace GitHub.Runner.Worker } else { + if (context.EchoOnActionCommand) + { + context.Output($"::{Command}::***"); + } + HostContext.SecretMasker.AddValue(command.Data); Trace.Info($"Add new secret mask with length of {command.Data.Length}"); } @@ -277,6 +275,7 @@ namespace GitHub.Runner.Worker public sealed class AddPathCommandExtension : RunnerService, IActionCommandExtension { public string Command => "add-path"; + public bool OmitEcho => false; public Type ExtensionType => typeof(IActionCommandExtension); @@ -291,6 +290,7 @@ namespace GitHub.Runner.Worker public sealed class AddMatcherCommandExtension : RunnerService, IActionCommandExtension { public string Command => "add-matcher"; + public bool OmitEcho => false; public Type ExtensionType => typeof(IActionCommandExtension); @@ -337,6 +337,7 @@ namespace GitHub.Runner.Worker public sealed class RemoveMatcherCommandExtension : RunnerService, IActionCommandExtension { public string Command => "remove-matcher"; + public bool OmitEcho => false; public Type ExtensionType => typeof(IActionCommandExtension); @@ -404,6 +405,7 @@ namespace GitHub.Runner.Worker public sealed class DebugCommandExtension : RunnerService, IActionCommandExtension { public string Command => "debug"; + public bool OmitEcho => true; public Type ExtensionType => typeof(IActionCommandExtension); @@ -431,6 +433,7 @@ namespace GitHub.Runner.Worker { public abstract IssueType Type { get; } public abstract string Command { get; } + public bool OmitEcho => true; public Type ExtensionType => typeof(IActionCommandExtension); @@ -510,6 +513,8 @@ namespace GitHub.Runner.Worker public abstract class GroupingCommandExtension : RunnerService, IActionCommandExtension { public abstract string Command { get; } + public bool OmitEcho => false; + public Type ExtensionType => typeof(IActionCommandExtension); public void ProcessCommand(IExecutionContext context, string line, ActionCommand command) @@ -522,6 +527,7 @@ namespace GitHub.Runner.Worker public sealed class EchoCommandExtension : RunnerService, IActionCommandExtension { public string Command => "echo"; + public bool OmitEcho => false; public Type ExtensionType => typeof(IActionCommandExtension); diff --git a/src/Runner.Worker/Handlers/OutputManager.cs b/src/Runner.Worker/Handlers/OutputManager.cs index 0a06bf956..a53a0436f 100644 --- a/src/Runner.Worker/Handlers/OutputManager.cs +++ b/src/Runner.Worker/Handlers/OutputManager.cs @@ -263,15 +263,17 @@ namespace GitHub.Runner.Worker.Handlers // Root using fromPath if (!string.IsNullOrWhiteSpace(match.FromPath) && !Path.IsPathRooted(file)) { - file = Path.Combine(match.FromPath, file); + var fromDirectory = Path.GetDirectoryName(match.FromPath); + if (!string.IsNullOrWhiteSpace(fromDirectory)) + { + file = Path.Combine(fromDirectory, file); + } } - // Root using system.defaultWorkingDirectory + // Root using workspace if (!Path.IsPathRooted(file)) { - var githubContext = _executionContext.ExpressionValues["github"] as GitHubContext; - ArgUtil.NotNull(githubContext, nameof(githubContext)); - var workspace = githubContext["workspace"].ToString(); + var workspace = _executionContext.GetGitHubContext("workspace"); ArgUtil.NotNullOrEmpty(workspace, "workspace"); file = Path.Combine(workspace, file); @@ -297,7 +299,7 @@ namespace GitHub.Runner.Worker.Handlers } else { - // prefer `/` on all platforms + // Prefer `/` on all platforms issue.Data["file"] = file.Substring(repositoryPath.Length).TrimStart(Path.DirectorySeparatorChar).Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); } } diff --git a/src/Test/L0/Worker/OutputManagerL0.cs b/src/Test/L0/Worker/OutputManagerL0.cs index 8e0680dda..cb0eefebd 100644 --- a/src/Test/L0/Worker/OutputManagerL0.cs +++ b/src/Test/L0/Worker/OutputManagerL0.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Runtime.CompilerServices; using GitHub.Runner.Sdk; @@ -158,7 +159,7 @@ namespace GitHub.Runner.Common.Tests.Worker [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] - public void Code() + public void MatcherCode() { var matchers = new IssueMatchersConfig { @@ -300,7 +301,7 @@ namespace GitHub.Runner.Common.Tests.Worker [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] - public void LineColumn() + public void MatcherLineColumn() { var matchers = new IssueMatchersConfig { @@ -348,7 +349,7 @@ namespace GitHub.Runner.Common.Tests.Worker [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] - public void ProcessCommand() + public void MatcherDoesNotReceiveCommand() { using (Setup()) using (_outputManager) @@ -382,7 +383,7 @@ namespace GitHub.Runner.Common.Tests.Worker [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] - public void RemoveColorCodes() + public void MatcherRemoveColorCodes() { using (Setup()) using (_outputManager) @@ -528,7 +529,7 @@ namespace GitHub.Runner.Common.Tests.Worker [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] - public void Severity() + public void MatcherSeverity() { var matchers = new IssueMatchersConfig { @@ -589,7 +590,7 @@ namespace GitHub.Runner.Common.Tests.Worker [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] - public void Timeout() + public void MatcherTimeout() { Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_ISSUE_MATCHER_TIMEOUT", "0:0:0.01"); var matchers = new IssueMatchersConfig @@ -640,10 +641,216 @@ namespace GitHub.Runner.Common.Tests.Worker } } - // todo: roots file against fromPath - // todo: roots file against system.defaultWorkingDirectory - // todo: matches repository - // todo: checks file exists + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void MatcherFile() + { + var matchers = new IssueMatchersConfig + { + Matchers = + { + new IssueMatcherConfig + { + Owner = "my-matcher-1", + Patterns = new[] + { + new IssuePatternConfig + { + Pattern = @"(.+): (.+)", + File = 1, + Message = 2, + }, + }, + }, + }, + }; + using (var hostContext = Setup(matchers: matchers)) + using (_outputManager) + { + // Setup github.workspace + 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); + + // Create a test file + Directory.CreateDirectory(Path.Combine(workspaceDirectory, "some-directory")); + var filePath = Path.Combine(workspaceDirectory, "some-directory", "some-file.txt"); + File.WriteAllText(filePath, ""); + + // Process + Process("some-directory/some-file.txt: some error"); + Assert.Equal(1, _issues.Count); + Assert.Equal("some error", _issues[0].Item1.Message); + Assert.Equal("some-directory/some-file.txt", _issues[0].Item1.Data["file"]); + Assert.Equal(0, _commands.Count); + Assert.Equal(0, _messages.Count); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void MatcherFileExists() + { + var matchers = new IssueMatchersConfig + { + Matchers = + { + new IssueMatcherConfig + { + Owner = "my-matcher-1", + Patterns = new[] + { + new IssuePatternConfig + { + Pattern = @"(.+): (.+)", + File = 1, + Message = 2, + }, + }, + }, + }, + }; + using (var hostContext = Setup(matchers: matchers)) + using (_outputManager) + { + // Setup github.workspace + 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); + + // Create a test file + File.WriteAllText(Path.Combine(workspaceDirectory, "some-file-1.txt"), ""); + + // Process + Process("some-file-1.txt: some error 1"); // file exists + Process("some-file-2.txt: some error 2"); // file does not exist + + Assert.Equal(2, _issues.Count); + Assert.Equal("some error 1", _issues[0].Item1.Message); + Assert.Equal("some-file-1.txt", _issues[0].Item1.Data["file"]); + Assert.Equal("some error 2", _issues[1].Item1.Message); + Assert.False(_issues[1].Item1.Data.ContainsKey("file")); // does not contain file key + Assert.Equal(0, _commands.Count); + Assert.Equal(0, _messages.Where(x => !x.StartsWith("##[debug]")).Count()); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void MatcherFileOutsideRepository() + { + var matchers = new IssueMatchersConfig + { + Matchers = + { + new IssueMatcherConfig + { + Owner = "my-matcher-1", + Patterns = new[] + { + new IssuePatternConfig + { + Pattern = @"(.+): (.+)", + File = 1, + Message = 2, + }, + }, + }, + }, + }; + using (var hostContext = Setup(matchers: matchers)) + using (_outputManager) + { + // Setup github.workspace + 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); + + // Create test files + var filePath1 = Path.Combine(workspaceDirectory, "some-file-1.txt"); + File.WriteAllText(filePath1, ""); + var workspaceSiblingDirectory = Path.Combine(Path.GetDirectoryName(workspaceDirectory), "workspace-sibling"); + Directory.CreateDirectory(workspaceSiblingDirectory); + var filePath2 = Path.Combine(workspaceSiblingDirectory, "some-file-2.txt"); + File.WriteAllText(filePath2, ""); + + // Process + Process($"{filePath1}: some error 1"); // file exists inside workspace + Process($"{filePath2}: some error 2"); // file exists outside workspace + + Assert.Equal(2, _issues.Count); + Assert.Equal("some error 1", _issues[0].Item1.Message); + Assert.Equal("some-file-1.txt", _issues[0].Item1.Data["file"]); + Assert.Equal("some error 2", _issues[1].Item1.Message); + Assert.False(_issues[1].Item1.Data.ContainsKey("file")); // does not contain file key + Assert.Equal(0, _commands.Count); + Assert.Equal(0, _messages.Where(x => !x.StartsWith("##[debug]")).Count()); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void MatcherFromPath() + { + var matchers = new IssueMatchersConfig + { + Matchers = + { + new IssueMatcherConfig + { + Owner = "my-matcher-1", + Patterns = new[] + { + new IssuePatternConfig + { + Pattern = @"(.+): (.+) \[(.+)\]", + File = 1, + Message = 2, + FromPath = 3, + }, + }, + }, + }, + }; + using (var hostContext = Setup(matchers: matchers)) + using (_outputManager) + { + // Setup github.workspace + 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); + + // Create a test file + Directory.CreateDirectory(Path.Combine(workspaceDirectory, "some-directory")); + Directory.CreateDirectory(Path.Combine(workspaceDirectory, "some-project", "some-directory")); + var filePath = Path.Combine(workspaceDirectory, "some-project", "some-directory", "some-file.txt"); + File.WriteAllText(filePath, ""); + + // Process + Process("some-directory/some-file.txt: some error [some-project/some-project.proj]"); + Assert.Equal(1, _issues.Count); + Assert.Equal("some error", _issues[0].Item1.Message); + Assert.Equal("some-project/some-directory/some-file.txt", _issues[0].Item1.Data["file"]); + Assert.Equal(0, _commands.Count); + Assert.Equal(0, _messages.Count); + } + } private TestHostContext Setup( [CallerMemberName] string name = "", diff --git a/src/runnerversion b/src/runnerversion index da0e9ef0d..68c57659e 100644 --- a/src/runnerversion +++ b/src/runnerversion @@ -1 +1 @@ -2.161.0 \ No newline at end of file +2.161.0