Compare commits

..

9 Commits

Author SHA1 Message Date
Tingluo Huang
fcf795d86d release 2.165.2 runner 2020-02-12 14:45:31 -05:00
Tingluo Huang
5d95befb0b prepare 2.165.2 runner release. 2020-02-12 14:33:43 -05:00
Tingluo Huang
ba544a1d9f Revert "Update Base64 Encoders to deal with suffixes (#284)" (#330)
This reverts commit c45aebc9ab.
2020-02-12 14:30:48 -05:00
TingluoHuang
f1aa949184 release 2.165.1 runner. 2020-01-30 22:19:39 -05:00
Tingluo Huang
0d1d346078 setup/evaluate env context after setup steps context. 2020-01-30 22:14:57 -05:00
Tingluo Huang
2cf97ad42c Update releaseVersion 2020-01-27 22:39:31 -05:00
Tingluo Huang
2a3e64d335 Update releaseVersion 2020-01-27 22:39:19 -05:00
Tingluo Huang
004d2ececd Update release.yml 2020-01-27 22:38:49 -05:00
Tingluo Huang
659e8a3685 create 2.165.0 runner 2020-01-27 22:33:24 -05:00
11 changed files with 191 additions and 191 deletions

View File

@@ -43,6 +43,14 @@ jobs:
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
# Set Path workaround for https://github.com/actions/virtual-environments/issues/263
- run: |
echo "::add-path::C:\Program Files\Git\mingw64\bin"
echo "::add-path::C:\Program Files\Git\usr\bin"
echo "::add-path::C:\Program Files\Git\bin"
if: matrix.os == 'windows-latest'
name: "Temp step to Set Path for Windows"
# Build runner layout # Build runner layout
- name: Build & Layout Release - name: Build & Layout Release
run: | run: |

View File

@@ -70,7 +70,15 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v2
# Set Path workaround for https://github.com/actions/virtual-environments/issues/263
- run: |
echo "::add-path::C:\Program Files\Git\mingw64\bin"
echo "::add-path::C:\Program Files\Git\usr\bin"
echo "::add-path::C:\Program Files\Git\bin"
if: matrix.os == 'windows-latest'
name: "Temp step to Set Path for Windows"
# Build runner layout # Build runner layout
- name: Build & Layout Release - name: Build & Layout Release

View File

@@ -17,14 +17,13 @@
- Trace javascript action exit code to debug instead of user logs (#290) - Trace javascript action exit code to debug instead of user logs (#290)
- Change prompt message when removing a runner to lines up with GitHub.com UI (#303) - Change prompt message when removing a runner to lines up with GitHub.com UI (#303)
- Include step.env as part of env context. (#300) - Include step.env as part of env context. (#300)
- Update Base64 Encoders to deal with suffixes (#284)
## Misc ## Misc
- Move .sln file under ./src (#238) - Move .sln file under ./src (#238)
- Treat warnings as errors during compile (#249) - Treat warnings as errors during compile (#249)
## Windows x64 ## Windows x64
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows We recommend configuring the runner under "<DRIVE>:\actions-runner". This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows
``` ```
// Create a folder under the drive root // Create a folder under the drive root
mkdir \actions-runner ; cd \actions-runner mkdir \actions-runner ; cd \actions-runner
@@ -32,7 +31,7 @@ mkdir \actions-runner ; cd \actions-runner
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-x64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-x64-<RUNNER_VERSION>.zip Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-x64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-x64-<RUNNER_VERSION>.zip
// Extract the installer // Extract the installer
Add-Type -AssemblyName System.IO.Compression.FileSystem ; Add-Type -AssemblyName System.IO.Compression.FileSystem ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD") [System.IO.Compression.ZipFile]::ExtractToDirectory("$HOME\Downloads\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
``` ```
## OSX ## OSX

View File

@@ -1 +1 @@
2.164.0 2.165.2

View File

@@ -1,18 +1,19 @@
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common;
using GitHub.Runner.Common.Util; using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk;
using GitHub.Services.Common; using GitHub.Services.Common;
using GitHub.Services.OAuth; using GitHub.Services.OAuth;
using GitHub.Services.WebApi; using GitHub.Services.WebApi;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.InteropServices;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Runtime.InteropServices;
using GitHub.Runner.Common;
using GitHub.Runner.Sdk;
using System.Net.Http;
using System.Net.Http.Headers;
namespace GitHub.Runner.Listener.Configuration namespace GitHub.Runner.Listener.Configuration
{ {
@@ -276,15 +277,12 @@ namespace GitHub.Runner.Listener.Configuration
throw new NotSupportedException("Message queue listen OAuth token."); throw new NotSupportedException("Message queue listen OAuth token.");
} }
// Testing agent connection, detect any potential connection issue, like local clock skew that cause OAuth token expired. // Testing agent connection, detect any protential connection issue, like local clock skew that cause OAuth token expired.
var credMgr = HostContext.GetService<ICredentialManager>(); var credMgr = HostContext.GetService<ICredentialManager>();
VssCredentials credential = credMgr.LoadCredentials(); VssCredentials credential = credMgr.LoadCredentials();
try try
{ {
await _runnerServer.ConnectAsync(new Uri(runnerSettings.ServerUrl), credential); await _runnerServer.ConnectAsync(new Uri(runnerSettings.ServerUrl), credential);
// ConnectAsync() hits _apis/connectionData which is an anonymous endpoint
// Need to hit an authenticate endpoint to trigger OAuth token exchange.
await _runnerServer.GetAgentPoolsAsync();
_term.WriteSuccessMessage("Runner connection is good"); _term.WriteSuccessMessage("Runner connection is good");
} }
catch (VssOAuthTokenRequestException ex) when (ex.Message.Contains("Current server time is")) catch (VssOAuthTokenRequestException ex) when (ex.Message.Contains("Current server time is"))
@@ -521,20 +519,15 @@ namespace GitHub.Runner.Listener.Configuration
private async Task<GitHubAuthResult> GetTenantCredential(string githubUrl, string githubToken) private async Task<GitHubAuthResult> GetTenantCredential(string githubUrl, string githubToken)
{ {
var gitHubUrlBuilder = new UriBuilder(githubUrl); var gitHubUrl = new UriBuilder(githubUrl);
var githubApiUrl = $"{gitHubUrlBuilder.Scheme}://api.{gitHubUrlBuilder.Host}/actions/runner-registration"; var githubApiUrl = $"https://api.{gitHubUrl.Host}/repos/{gitHubUrl.Path.Trim('/')}/actions-runners/registration";
using (var httpClientHandler = HostContext.CreateHttpClientHandler()) using (var httpClientHandler = HostContext.CreateHttpClientHandler())
using (var httpClient = new HttpClient(httpClientHandler)) using (var httpClient = new HttpClient(httpClientHandler))
{ {
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("RemoteAuth", githubToken); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("RemoteAuth", githubToken);
httpClient.DefaultRequestHeaders.UserAgent.Add(HostContext.UserAgent); httpClient.DefaultRequestHeaders.UserAgent.Add(HostContext.UserAgent);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github.shuri-preview+json"));
var bodyObject = new Dictionary<string, string>() var response = await httpClient.PostAsync(githubApiUrl, new StringContent("", null, "application/json"));
{
{"url", githubUrl}
};
var response = await httpClient.PostAsync(githubApiUrl, new StringContent(StringUtil.ConvertToJson(bodyObject), null, "application/json"));
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {

View File

@@ -1,7 +1,6 @@
using GitHub.DistributedTask.Pipelines; using GitHub.DistributedTask.Pipelines;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Common.Util; using GitHub.Runner.Common.Util;
using GitHub.Runner.Worker.Container;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -16,14 +15,14 @@ namespace GitHub.Runner.Worker
{ {
void EnablePluginInternalCommand(); void EnablePluginInternalCommand();
void DisablePluginInternalCommand(); void DisablePluginInternalCommand();
bool TryProcessCommand(IExecutionContext context, string input, ContainerInfo container); bool TryProcessCommand(IExecutionContext context, string input);
} }
public sealed class ActionCommandManager : RunnerService, IActionCommandManager public sealed class ActionCommandManager : RunnerService, IActionCommandManager
{ {
private const string _stopCommand = "stop-commands"; private const string _stopCommand = "stop-commands";
private readonly Dictionary<string, IActionCommandExtension> _commandExtensions = new Dictionary<string, IActionCommandExtension>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, IActionCommandExtension> _commandExtensions = new Dictionary<string, IActionCommandExtension>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<string> _registeredCommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private HashSet<string> _registeredCommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private readonly object _commandSerializeLock = new object(); private readonly object _commandSerializeLock = new object();
private bool _stopProcessCommand = false; private bool _stopProcessCommand = false;
private string _stopToken = null; private string _stopToken = null;
@@ -59,7 +58,7 @@ namespace GitHub.Runner.Worker
_registeredCommands.Remove("internal-set-repo-path"); _registeredCommands.Remove("internal-set-repo-path");
} }
public bool TryProcessCommand(IExecutionContext context, string input, ContainerInfo container) public bool TryProcessCommand(IExecutionContext context, string input)
{ {
if (string.IsNullOrEmpty(input)) if (string.IsNullOrEmpty(input))
{ {
@@ -115,7 +114,7 @@ namespace GitHub.Runner.Worker
try try
{ {
extension.ProcessCommand(context, input, actionCommand, container); extension.ProcessCommand(context, input, actionCommand);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -141,7 +140,7 @@ namespace GitHub.Runner.Worker
string Command { get; } string Command { get; }
bool OmitEcho { get; } bool OmitEcho { get; }
void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container); void ProcessCommand(IExecutionContext context, string line, ActionCommand command);
} }
public sealed class InternalPluginSetRepoPathCommandExtension : RunnerService, IActionCommandExtension public sealed class InternalPluginSetRepoPathCommandExtension : RunnerService, IActionCommandExtension
@@ -151,7 +150,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
if (!command.Properties.TryGetValue(SetRepoPathCommandProperties.repoFullName, out string repoFullName) || string.IsNullOrEmpty(repoFullName)) if (!command.Properties.TryGetValue(SetRepoPathCommandProperties.repoFullName, out string repoFullName) || string.IsNullOrEmpty(repoFullName))
{ {
@@ -181,7 +180,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
if (!command.Properties.TryGetValue(SetEnvCommandProperties.Name, out string envName) || string.IsNullOrEmpty(envName)) if (!command.Properties.TryGetValue(SetEnvCommandProperties.Name, out string envName) || string.IsNullOrEmpty(envName))
{ {
@@ -206,7 +205,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName)) if (!command.Properties.TryGetValue(SetOutputCommandProperties.Name, out string outputName) || string.IsNullOrEmpty(outputName))
{ {
@@ -230,7 +229,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName)) if (!command.Properties.TryGetValue(SaveStateCommandProperties.Name, out string stateName) || string.IsNullOrEmpty(stateName))
{ {
@@ -254,7 +253,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
if (string.IsNullOrWhiteSpace(command.Data)) if (string.IsNullOrWhiteSpace(command.Data))
{ {
@@ -280,7 +279,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
ArgUtil.NotNullOrEmpty(command.Data, "path"); ArgUtil.NotNullOrEmpty(command.Data, "path");
context.PrependPath.RemoveAll(x => string.Equals(x, command.Data, StringComparison.CurrentCulture)); context.PrependPath.RemoveAll(x => string.Equals(x, command.Data, StringComparison.CurrentCulture));
@@ -295,7 +294,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
var file = command.Data; var file = command.Data;
@@ -307,9 +306,9 @@ namespace GitHub.Runner.Worker
} }
// Translate file path back from container path // Translate file path back from container path
if (container != null) if (context.Container != null)
{ {
file = container.TranslateToHostPath(file); file = context.Container.TranslateToHostPath(file);
} }
// Root the path // Root the path
@@ -342,7 +341,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
command.Properties.TryGetValue(RemoveMatcherCommandProperties.Owner, out string owner); command.Properties.TryGetValue(RemoveMatcherCommandProperties.Owner, out string owner);
var file = command.Data; var file = command.Data;
@@ -370,9 +369,9 @@ namespace GitHub.Runner.Worker
else else
{ {
// Translate file path back from container path // Translate file path back from container path
if (container != null) if (context.Container != null)
{ {
file = container.TranslateToHostPath(file); file = context.Container.TranslateToHostPath(file);
} }
// Root the path // Root the path
@@ -410,7 +409,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command)
{ {
context.Debug(command.Data); context.Debug(command.Data);
} }
@@ -438,7 +437,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command)
{ {
command.Properties.TryGetValue(IssueCommandProperties.File, out string file); command.Properties.TryGetValue(IssueCommandProperties.File, out string file);
command.Properties.TryGetValue(IssueCommandProperties.Line, out string line); command.Properties.TryGetValue(IssueCommandProperties.Line, out string line);
@@ -455,10 +454,10 @@ namespace GitHub.Runner.Worker
{ {
issue.Category = "Code"; issue.Category = "Code";
if (container != null) if (context.Container != null)
{ {
// Translate file path back from container path // Translate file path back from container path
file = container.TranslateToHostPath(file); file = context.Container.TranslateToHostPath(file);
command.Properties[IssueCommandProperties.File] = file; command.Properties[IssueCommandProperties.File] = file;
} }
@@ -518,7 +517,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
var data = this is GroupCommandExtension ? command.Data : string.Empty; var data = this is GroupCommandExtension ? command.Data : string.Empty;
context.Output($"##[{Command}]{data}"); context.Output($"##[{Command}]{data}");
@@ -532,7 +531,7 @@ namespace GitHub.Runner.Worker
public Type ExtensionType => typeof(IActionCommandExtension); public Type ExtensionType => typeof(IActionCommandExtension);
public void ProcessCommand(IExecutionContext context, string line, ActionCommand command, ContainerInfo container) public void ProcessCommand(IExecutionContext context, string line, ActionCommand command)
{ {
ArgUtil.NotNullOrEmpty(command.Data, "value"); ArgUtil.NotNullOrEmpty(command.Data, "value");

View File

@@ -84,7 +84,7 @@ namespace GitHub.Runner.Worker.Handlers
{ {
// This does not need to be inside of a critical section. // This does not need to be inside of a critical section.
// The logging queues and command handlers are thread-safe. // The logging queues and command handlers are thread-safe.
if (_commandManager.TryProcessCommand(_executionContext, line, _container)) if (_commandManager.TryProcessCommand(_executionContext, line))
{ {
return; return;
} }

View File

@@ -175,8 +175,8 @@ namespace GitHub.Runner.Common.Tests.Listener.Configuration
Assert.True(s.PoolId.Equals(_expectedPoolId)); Assert.True(s.PoolId.Equals(_expectedPoolId));
Assert.True(s.WorkFolder.Equals(_expectedWorkFolder)); Assert.True(s.WorkFolder.Equals(_expectedWorkFolder));
// validate GetAgentPoolsAsync gets called twice with automation pool type // validate GetAgentPoolsAsync gets called once with automation pool type
_runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Exactly(2)); _runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Once);
_runnerServer.Verify(x => x.AddAgentAsync(It.IsAny<int>(), It.Is<TaskAgent>(a => a.Labels.Contains("self-hosted") && a.Labels.Contains(VarUtil.OS) && a.Labels.Contains(VarUtil.OSArchitecture))), Times.Once); _runnerServer.Verify(x => x.AddAgentAsync(It.IsAny<int>(), It.Is<TaskAgent>(a => a.Labels.Contains("self-hosted") && a.Labels.Contains(VarUtil.OS) && a.Labels.Contains(VarUtil.OSArchitecture))), Times.Once);
} }

View File

@@ -1,10 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using GitHub.DistributedTask.WebApi; using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Worker; using GitHub.Runner.Worker;
using GitHub.Runner.Worker.Container;
using Moq; using Moq;
using Xunit; using Xunit;
using Pipelines = GitHub.DistributedTask.Pipelines; using Pipelines = GitHub.DistributedTask.Pipelines;
@@ -13,35 +11,47 @@ namespace GitHub.Runner.Common.Tests.Worker
{ {
public sealed class ActionCommandManagerL0 public sealed class ActionCommandManagerL0
{ {
private ActionCommandManager _commandManager;
private Mock<IExecutionContext> _ec;
private Mock<IExtensionManager> _extensionManager;
private Mock<IPipelineDirectoryManager> _pipelineDirectoryManager;
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void EnablePluginInternalCommand() public void EnablePluginInternalCommand()
{ {
using (TestHostContext hc = CreateTestContext()) using (TestHostContext _hc = new TestHostContext(this))
{ {
var extensionManger = new Mock<IExtensionManager>();
var directoryManager = new Mock<IPipelineDirectoryManager>();
var pluginCommand = new InternalPluginSetRepoPathCommandExtension();
pluginCommand.Initialize(_hc);
var envCommand = new SetEnvCommandExtension();
envCommand.Initialize(_hc);
extensionManger.Setup(x => x.GetExtensions<IActionCommandExtension>())
.Returns(new List<IActionCommandExtension>() { pluginCommand, envCommand });
_hc.SetSingleton<IExtensionManager>(extensionManger.Object);
_hc.SetSingleton<IPipelineDirectoryManager>(directoryManager.Object);
Mock<IExecutionContext> _ec = new Mock<IExecutionContext>();
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())) _ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string tag, string line) => .Returns((string tag, string line) =>
{ {
hc.GetTrace().Info($"{tag} {line}"); _hc.GetTrace().Info($"{tag} {line}");
return 1; return 1;
}); });
_ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>())) _ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>()))
.Callback((Issue issue, string message) => .Callback((Issue issue, string message) =>
{ {
hc.GetTrace().Info($"{issue.Type} {issue.Message} {message ?? string.Empty}"); _hc.GetTrace().Info($"{issue.Type} {issue.Message} {message ?? string.Empty}");
}); });
ActionCommandManager commandManager = new ActionCommandManager();
commandManager.Initialize(_hc);
_commandManager.EnablePluginInternalCommand(); commandManager.EnablePluginInternalCommand();
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[internal-set-repo-path repoFullName=actions/runner;workspaceRepo=true]somepath", null)); Assert.True(commandManager.TryProcessCommand(_ec.Object, "##[internal-set-repo-path repoFullName=actions/runner;workspaceRepo=true]somepath"));
_pipelineDirectoryManager.Verify(x => x.UpdateRepositoryDirectory(_ec.Object, "actions/runner", "somepath", true), Times.Once); directoryManager.Verify(x => x.UpdateRepositoryDirectory(_ec.Object, "actions/runner", "somepath", true), Times.Once);
} }
} }
@@ -50,29 +60,47 @@ namespace GitHub.Runner.Common.Tests.Worker
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void DisablePluginInternalCommand() public void DisablePluginInternalCommand()
{ {
using (TestHostContext hc = CreateTestContext()) using (TestHostContext _hc = new TestHostContext(this))
{ {
var extensionManger = new Mock<IExtensionManager>();
var directoryManager = new Mock<IPipelineDirectoryManager>();
var pluginCommand = new InternalPluginSetRepoPathCommandExtension();
pluginCommand.Initialize(_hc);
var envCommand = new SetEnvCommandExtension();
envCommand.Initialize(_hc);
extensionManger.Setup(x => x.GetExtensions<IActionCommandExtension>())
.Returns(new List<IActionCommandExtension>() { pluginCommand, envCommand });
_hc.SetSingleton<IExtensionManager>(extensionManger.Object);
_hc.SetSingleton<IPipelineDirectoryManager>(directoryManager.Object);
Mock<IExecutionContext> _ec = new Mock<IExecutionContext>();
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())) _ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string tag, string line) => .Returns((string tag, string line) =>
{ {
hc.GetTrace().Info($"{tag} {line}"); _hc.GetTrace().Info($"{tag} {line}");
return 1; return 1;
}); });
_ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>())) _ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>()))
.Callback((Issue issue, string message) => .Callback((Issue issue, string message) =>
{ {
hc.GetTrace().Info($"{issue.Type} {issue.Message} {message ?? string.Empty}"); _hc.GetTrace().Info($"{issue.Type} {issue.Message} {message ?? string.Empty}");
}); });
ActionCommandManager commandManager = new ActionCommandManager();
commandManager.Initialize(_hc);
_commandManager.EnablePluginInternalCommand(); commandManager.EnablePluginInternalCommand();
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[internal-set-repo-path repoFullName=actions/runner;workspaceRepo=true]somepath", null)); Assert.True(commandManager.TryProcessCommand(_ec.Object, "##[internal-set-repo-path repoFullName=actions/runner;workspaceRepo=true]somepath"));
_commandManager.DisablePluginInternalCommand(); commandManager.DisablePluginInternalCommand();
Assert.False(_commandManager.TryProcessCommand(_ec.Object, "##[internal-set-repo-path repoFullName=actions/runner;workspaceRepo=true]somepath", null)); Assert.False(commandManager.TryProcessCommand(_ec.Object, "##[internal-set-repo-path repoFullName=actions/runner;workspaceRepo=true]somepath"));
_pipelineDirectoryManager.Verify(x => x.UpdateRepositoryDirectory(_ec.Object, "actions/runner", "somepath", true), Times.Once); directoryManager.Verify(x => x.UpdateRepositoryDirectory(_ec.Object, "actions/runner", "somepath", true), Times.Once);
} }
} }
@@ -81,27 +109,42 @@ namespace GitHub.Runner.Common.Tests.Worker
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void StopProcessCommand() public void StopProcessCommand()
{ {
using (TestHostContext hc = CreateTestContext()) using (TestHostContext _hc = new TestHostContext(this))
{ {
var extensionManger = new Mock<IExtensionManager>();
var pluginCommand = new InternalPluginSetRepoPathCommandExtension();
pluginCommand.Initialize(_hc);
var envCommand = new SetEnvCommandExtension();
envCommand.Initialize(_hc);
extensionManger.Setup(x => x.GetExtensions<IActionCommandExtension>())
.Returns(new List<IActionCommandExtension>() { pluginCommand, envCommand });
_hc.SetSingleton<IExtensionManager>(extensionManger.Object);
Mock<IExecutionContext> _ec = new Mock<IExecutionContext>();
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())) _ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string tag, string line) => .Returns((string tag, string line) =>
{ {
hc.GetTrace().Info($"{tag} {line}"); _hc.GetTrace().Info($"{tag} {line}");
return 1; return 1;
}); });
_ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>())) _ec.Setup(x => x.AddIssue(It.IsAny<Issue>(), It.IsAny<string>()))
.Callback((Issue issue, string message) => .Callback((Issue issue, string message) =>
{ {
hc.GetTrace().Info($"{issue.Type} {issue.Message} {message ?? string.Empty}"); _hc.GetTrace().Info($"{issue.Type} {issue.Message} {message ?? string.Empty}");
}); });
_ec.Setup(x => x.EnvironmentVariables).Returns(new Dictionary<string, string>()); _ec.Setup(x => x.EnvironmentVariables).Returns(new Dictionary<string, string>());
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[stop-commands]stopToken", null)); ActionCommandManager commandManager = new ActionCommandManager();
Assert.False(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null)); commandManager.Initialize(_hc);
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[stopToken]", null));
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar", null)); Assert.True(commandManager.TryProcessCommand(_ec.Object, "##[stop-commands]stopToken"));
Assert.False(commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar"));
Assert.True(commandManager.TryProcessCommand(_ec.Object, "##[stopToken]"));
Assert.True(commandManager.TryProcessCommand(_ec.Object, "##[set-env name=foo]bar"));
} }
} }
@@ -110,29 +153,41 @@ namespace GitHub.Runner.Common.Tests.Worker
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void EchoProcessCommand() public void EchoProcessCommand()
{ {
using (TestHostContext hc = CreateTestContext()) using (TestHostContext _hc = new TestHostContext(this))
{ {
var extensionManager = new Mock<IExtensionManager>();
var echoCommand = new EchoCommandExtension();
echoCommand.Initialize(_hc);
extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
.Returns(new List<IActionCommandExtension>() { echoCommand });
_hc.SetSingleton<IExtensionManager>(extensionManager.Object);
Mock<IExecutionContext> _ec = new Mock<IExecutionContext>();
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())) _ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string tag, string line) => .Returns((string tag, string line) =>
{ {
hc.GetTrace().Info($"{tag} {line}"); _hc.GetTrace().Info($"{tag} {line}");
return 1; return 1;
}); });
_ec.SetupAllProperties(); _ec.SetupAllProperties();
ActionCommandManager commandManager = new ActionCommandManager();
commandManager.Initialize(_hc);
Assert.False(_ec.Object.EchoOnActionCommand); Assert.False(_ec.Object.EchoOnActionCommand);
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "::echo::on", null)); Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::on"));
Assert.True(_ec.Object.EchoOnActionCommand); Assert.True(_ec.Object.EchoOnActionCommand);
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "::echo::off", null)); Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::off"));
Assert.False(_ec.Object.EchoOnActionCommand); Assert.False(_ec.Object.EchoOnActionCommand);
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "::echo::ON", null)); Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::ON"));
Assert.True(_ec.Object.EchoOnActionCommand); Assert.True(_ec.Object.EchoOnActionCommand);
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "::echo::Off ", null)); Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::Off "));
Assert.False(_ec.Object.EchoOnActionCommand); Assert.False(_ec.Object.EchoOnActionCommand);
} }
} }
@@ -142,7 +197,7 @@ namespace GitHub.Runner.Common.Tests.Worker
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void EchoProcessCommandDebugOn() public void EchoProcessCommandDebugOn()
{ {
using (TestHostContext hc = CreateTestContext()) using (TestHostContext _hc = new TestHostContext(this))
{ {
// Set up a few things // Set up a few things
// 1. Job request message (with ACTIONS_STEP_DEBUG = true) // 1. Job request message (with ACTIONS_STEP_DEBUG = true)
@@ -164,135 +219,84 @@ namespace GitHub.Runner.Common.Tests.Worker
var jobServerQueue = new Mock<IJobServerQueue>(); var jobServerQueue = new Mock<IJobServerQueue>();
jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny<Guid>(), It.IsAny<TimelineRecord>())); jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny<Guid>(), It.IsAny<TimelineRecord>()));
hc.SetSingleton(jobServerQueue.Object); _hc.SetSingleton(jobServerQueue.Object);
var extensionManager = new Mock<IExtensionManager>();
var echoCommand = new EchoCommandExtension();
echoCommand.Initialize(_hc);
extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
.Returns(new List<IActionCommandExtension>() { echoCommand });
_hc.SetSingleton<IExtensionManager>(extensionManager.Object);
var configurationStore = new Mock<IConfigurationStore>(); var configurationStore = new Mock<IConfigurationStore>();
configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings()); configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings());
hc.SetSingleton(configurationStore.Object); _hc.SetSingleton(configurationStore.Object);
var pagingLogger = new Mock<IPagingLogger>(); var pagingLogger = new Mock<IPagingLogger>();
hc.EnqueueInstance(pagingLogger.Object); _hc.EnqueueInstance(pagingLogger.Object);
ActionCommandManager commandManager = new ActionCommandManager();
commandManager.Initialize(_hc);
var _ec = new Runner.Worker.ExecutionContext();
_ec.Initialize(_hc);
// Initialize the job (to exercise logic that sets EchoOnActionCommand) // Initialize the job (to exercise logic that sets EchoOnActionCommand)
var ec = new Runner.Worker.ExecutionContext(); _ec.InitializeJob(jobRequest, System.Threading.CancellationToken.None);
ec.Initialize(hc);
ec.InitializeJob(jobRequest, System.Threading.CancellationToken.None);
ec.Complete(); _ec.Complete();
Assert.True(ec.EchoOnActionCommand); Assert.True(_ec.EchoOnActionCommand);
Assert.True(_commandManager.TryProcessCommand(ec, "::echo::off", null)); Assert.True(commandManager.TryProcessCommand(_ec, "::echo::off"));
Assert.False(ec.EchoOnActionCommand); Assert.False(_ec.EchoOnActionCommand);
Assert.True(_commandManager.TryProcessCommand(ec, "::echo::on", null)); Assert.True(commandManager.TryProcessCommand(_ec, "::echo::on"));
Assert.True(ec.EchoOnActionCommand); Assert.True(_ec.EchoOnActionCommand);
} }
} }
[Fact] [Fact]
[Trait("Level", "L0")] [Trait("Level", "L0")]
[Trait("Category", "Worker")] [Trait("Category", "Worker")]
public void EchoProcessCommandInvalid() public void EchoProcessCommandInvalid()
{ {
using (TestHostContext hc = CreateTestContext()) using (TestHostContext _hc = new TestHostContext(this))
{ {
var extensionManager = new Mock<IExtensionManager>();
var echoCommand = new EchoCommandExtension();
echoCommand.Initialize(_hc);
extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
.Returns(new List<IActionCommandExtension>() { echoCommand });
_hc.SetSingleton<IExtensionManager>(extensionManager.Object);
Mock<IExecutionContext> _ec = new Mock<IExecutionContext>();
_ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())) _ec.Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>()))
.Returns((string tag, string line) => .Returns((string tag, string line) =>
{ {
hc.GetTrace().Info($"{tag} {line}"); _hc.GetTrace().Info($"{tag} {line}");
return 1; return 1;
}); });
_ec.SetupAllProperties(); _ec.SetupAllProperties();
ActionCommandManager commandManager = new ActionCommandManager();
commandManager.Initialize(_hc);
// Echo commands below are considered "processed", but are invalid // Echo commands below are considered "processed", but are invalid
// 1. Invalid echo value // 1. Invalid echo value
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "::echo::invalid", null)); Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::invalid"));
Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult); Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult);
Assert.False(_ec.Object.EchoOnActionCommand); Assert.False(_ec.Object.EchoOnActionCommand);
// 2. No value // 2. No value
Assert.True(_commandManager.TryProcessCommand(_ec.Object, "::echo::", null)); Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::"));
Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult); Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult);
Assert.False(_ec.Object.EchoOnActionCommand); Assert.False(_ec.Object.EchoOnActionCommand);
} }
} }
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void AddMatcherTranslatesFilePath()
{
using (TestHostContext hc = CreateTestContext())
{
// Create a problem matcher config file
var hostDirectory = hc.GetDirectory(WellKnownDirectory.Temp);
var hostFile = Path.Combine(hostDirectory, "my-matcher.json");
Directory.CreateDirectory(hostDirectory);
var content = @"
{
""problemMatcher"": [
{
""owner"": ""my-matcher"",
""pattern"": [
{
""regexp"": ""^ERROR: (.+)$"",
""message"": 1
}
]
}
]
}";
File.WriteAllText(hostFile, content);
// Setup translation info
var container = new ContainerInfo();
var containerDirectory = "/some-container-directory";
var containerFile = Path.Combine(containerDirectory, "my-matcher.json");
container.AddPathTranslateMapping(hostDirectory, containerDirectory);
// Act
_commandManager.TryProcessCommand(_ec.Object, $"::add-matcher::{containerFile}", container);
// Assert
_ec.Verify(x => x.AddMatchers(It.IsAny<IssueMatchersConfig>()), Times.Once);
}
}
private TestHostContext CreateTestContext([CallerMemberName] string testName = "")
{
var hostContext = new TestHostContext(this, testName);
// Mock extension manager
_extensionManager = new Mock<IExtensionManager>();
var commands = new IActionCommandExtension[]
{
new AddMatcherCommandExtension(),
new EchoCommandExtension(),
new InternalPluginSetRepoPathCommandExtension(),
new SetEnvCommandExtension(),
};
foreach (var command in commands)
{
command.Initialize(hostContext);
}
_extensionManager.Setup(x => x.GetExtensions<IActionCommandExtension>())
.Returns(new List<IActionCommandExtension>(commands));
hostContext.SetSingleton<IExtensionManager>(_extensionManager.Object);
// Mock pipeline directory manager
_pipelineDirectoryManager = new Mock<IPipelineDirectoryManager>();
hostContext.SetSingleton<IPipelineDirectoryManager>(_pipelineDirectoryManager.Object);
// Execution context
_ec = new Mock<IExecutionContext>();
// Command manager
_commandManager = new ActionCommandManager();
_commandManager.Initialize(hostContext);
return hostContext;
}
} }
} }

View File

@@ -973,8 +973,8 @@ namespace GitHub.Runner.Common.Tests.Worker
}); });
_commandManager = new Mock<IActionCommandManager>(); _commandManager = new Mock<IActionCommandManager>();
_commandManager.Setup(x => x.TryProcessCommand(It.IsAny<IExecutionContext>(), It.IsAny<string>(), It.IsAny<ContainerInfo>())) _commandManager.Setup(x => x.TryProcessCommand(It.IsAny<IExecutionContext>(), It.IsAny<string>()))
.Returns((IExecutionContext executionContext, string line, ContainerInfo container) => .Returns((IExecutionContext executionContext, string line) =>
{ {
if (line.IndexOf("##[some-command]") >= 0) if (line.IndexOf("##[some-command]") >= 0)
{ {

View File

@@ -1,16 +1,5 @@
@setlocal @setlocal
@echo off @echo off
rem add expected utils to path
IF EXIST C:\Program Files\Git\usr\bin (
SET PATH=C:\Program Files\Git\usr\bin;%PATH%
)
IF EXIST C:\Program Files\Git\mingw64\bin (
SET PATH=C:\Program Files\Git\mingw64\bin;%PATH%
)
IF EXIST C:\Program Files\Git\bin (
SET PATH=C:\Program Files\Git\bin;%PATH%
)
rem Check if SH_PATH is defined. rem Check if SH_PATH is defined.
if defined SH_PATH ( if defined SH_PATH (
goto run goto run