GitHub Actions Runner

This commit is contained in:
Tingluo Huang
2019-10-10 00:52:42 -04:00
commit c8afc84840
1255 changed files with 198670 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
namespace GitHub.Runner.Common.Util
{
using System;
public static class EnumUtil
{
public static T? TryParse<T>(string value) where T: struct
{
T val;
if (Enum.TryParse(value ?? string.Empty, ignoreCase: true, result: out val))
{
return val;
}
return null;
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using GitHub.DistributedTask.WebApi;
using GitHub.Runner.Sdk;
namespace GitHub.Runner.Common.Util
{
public static class PlanUtil
{
public static PlanFeatures GetFeatures(TaskOrchestrationPlanReference plan)
{
ArgUtil.NotNull(plan, nameof(plan));
PlanFeatures features = PlanFeatures.None;
if (plan.Version >= 8)
{
features |= PlanFeatures.JobCompletedPlanEvent;
}
return features;
}
}
[Flags]
public enum PlanFeatures
{
None = 0,
JobCompletedPlanEvent = 1,
}
}

View File

@@ -0,0 +1,79 @@
using GitHub.DistributedTask.WebApi;
using System;
namespace GitHub.Runner.Common.Util
{
public static class TaskResultUtil
{
private static readonly int _returnCodeOffset = 100;
public static bool IsValidReturnCode(int returnCode)
{
int resultInt = returnCode - _returnCodeOffset;
return Enum.IsDefined(typeof(TaskResult), resultInt);
}
public static int TranslateToReturnCode(TaskResult result)
{
return _returnCodeOffset + (int)result;
}
public static TaskResult TranslateFromReturnCode(int returnCode)
{
int resultInt = returnCode - _returnCodeOffset;
if (Enum.IsDefined(typeof(TaskResult), resultInt))
{
return (TaskResult)resultInt;
}
else
{
return TaskResult.Failed;
}
}
// Merge 2 TaskResults get the worst result.
// Succeeded -> Failed/Canceled/Skipped/Abandoned
// Failed -> Failed/Canceled
// Canceled -> Canceled
// Skipped -> Skipped
// Abandoned -> Abandoned
public static TaskResult MergeTaskResults(TaskResult? currentResult, TaskResult comingResult)
{
if (currentResult == null)
{
return comingResult;
}
// current result is Canceled/Skip/Abandoned
if (currentResult > TaskResult.Failed)
{
return currentResult.Value;
}
// comming result is bad than current result
if (comingResult >= currentResult)
{
return comingResult;
}
return currentResult.Value;
}
public static ActionResult ToActionResult(this TaskResult result)
{
switch (result)
{
case TaskResult.Succeeded:
return ActionResult.Success;
case TaskResult.Failed:
return ActionResult.Failure;
case TaskResult.Canceled:
return ActionResult.Cancelled;
case TaskResult.Skipped:
return ActionResult.Skipped;
default:
throw new NotSupportedException(result.ToString());
}
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using GitHub.Runner.Sdk;
namespace GitHub.Runner.Common.Util
{
[ServiceLocator(Default = typeof(UnixUtil))]
public interface IUnixUtil : IRunnerService
{
Task ExecAsync(string workingDirectory, string toolName, string argLine);
Task ChmodAsync(string mode, string file);
Task ChownAsync(string owner, string group, string file);
}
public sealed class UnixUtil : RunnerService, IUnixUtil
{
private ITerminal _term;
public override void Initialize(IHostContext hostContext)
{
base.Initialize(hostContext);
_term = hostContext.GetService<ITerminal>();
}
public async Task ChmodAsync(string mode, string file)
{
Trace.Entering();
await ExecAsync(HostContext.GetDirectory(WellKnownDirectory.Root), "chmod", $"{mode} \"{file}\"");
}
public async Task ChownAsync(string owner, string group, string file)
{
Trace.Entering();
await ExecAsync(HostContext.GetDirectory(WellKnownDirectory.Root), "chown", $"{owner}:{group} \"{file}\"");
}
public async Task ExecAsync(string workingDirectory, string toolName, string argLine)
{
Trace.Entering();
string toolPath = WhichUtil.Which(toolName, trace: Trace);
Trace.Info($"Running {toolPath} {argLine}");
var processInvoker = HostContext.CreateService<IProcessInvoker>();
processInvoker.OutputDataReceived += OnOutputDataReceived;
processInvoker.ErrorDataReceived += OnErrorDataReceived;
try
{
using (var cs = new CancellationTokenSource(TimeSpan.FromSeconds(45)))
{
await processInvoker.ExecuteAsync(workingDirectory, toolPath, argLine, null, true, cs.Token);
}
}
finally
{
processInvoker.OutputDataReceived -= OnOutputDataReceived;
processInvoker.ErrorDataReceived -= OnErrorDataReceived;
}
}
private void OnOutputDataReceived(object sender, ProcessDataReceivedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Data))
{
_term.WriteLine(e.Data);
}
}
private void OnErrorDataReceived(object sender, ProcessDataReceivedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Data))
{
_term.WriteLine(e.Data);
}
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GitHub.Runner.Sdk;
namespace GitHub.Runner.Common.Util
{
public static class VarUtil
{
public static StringComparer EnvironmentVariableKeyComparer
{
get
{
switch (Constants.Runner.Platform)
{
case Constants.OSPlatform.Linux:
case Constants.OSPlatform.OSX:
return StringComparer.Ordinal;
case Constants.OSPlatform.Windows:
return StringComparer.OrdinalIgnoreCase;
default:
throw new NotSupportedException(); // Should never reach here.
}
}
}
public static string OS
{
get
{
switch (Constants.Runner.Platform)
{
case Constants.OSPlatform.Linux:
return "Linux";
case Constants.OSPlatform.OSX:
return "macOS";
case Constants.OSPlatform.Windows:
return "Windows";
default:
throw new NotSupportedException(); // Should never reach here.
}
}
}
public static string OSArchitecture
{
get
{
switch (Constants.Runner.PlatformArchitecture)
{
case Constants.Architecture.X86:
return "X86";
case Constants.Architecture.X64:
return "X64";
case Constants.Architecture.Arm:
return "ARM";
default:
throw new NotSupportedException(); // Should never reach here.
}
}
}
}
}