mirror of
https://github.com/actions/runner.git
synced 2025-12-10 20:36:49 +00:00
94 lines
3.7 KiB
C#
94 lines
3.7 KiB
C#
using System;
|
|
using System.Globalization;
|
|
using System.Threading.Tasks;
|
|
using GitHub.Runner.Common;
|
|
using GitHub.Runner.Sdk;
|
|
using System.Diagnostics;
|
|
|
|
namespace GitHub.Runner.Worker
|
|
{
|
|
public static class Program
|
|
{
|
|
public static int Main(string[] args)
|
|
{
|
|
using (HostContext context = new("Worker"))
|
|
{
|
|
return MainAsync(context, args).GetAwaiter().GetResult();
|
|
}
|
|
}
|
|
|
|
public static async Task<int> MainAsync(IHostContext context, string[] args)
|
|
{
|
|
Tracing trace = context.GetTrace(nameof(GitHub.Runner.Worker));
|
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_ATTACH_DEBUGGER")))
|
|
{
|
|
await WaitForDebugger(trace);
|
|
}
|
|
|
|
// We may want to consider registering this handler in Worker.cs, similiar to the unloading/SIGTERM handler
|
|
//ITerminal registers a CTRL-C handler, which keeps the Runner.Worker process running
|
|
//and lets the Runner.Listener handle gracefully the exit.
|
|
var term = context.GetService<ITerminal>();
|
|
try
|
|
{
|
|
trace.Info($"Version: {BuildConstants.RunnerPackage.Version}");
|
|
trace.Info($"Commit: {BuildConstants.Source.CommitHash}");
|
|
trace.Info($"Culture: {CultureInfo.CurrentCulture.Name}");
|
|
trace.Info($"UI Culture: {CultureInfo.CurrentUICulture.Name}");
|
|
context.WritePerfCounter("WorkerProcessStarted");
|
|
|
|
// Validate args.
|
|
ArgUtil.NotNull(args, nameof(args));
|
|
ArgUtil.Equal(3, args.Length, nameof(args.Length));
|
|
ArgUtil.NotNullOrEmpty(args[0], $"{nameof(args)}[0]");
|
|
ArgUtil.Equal("spawnclient", args[0].ToLowerInvariant(), $"{nameof(args)}[0]");
|
|
ArgUtil.NotNullOrEmpty(args[1], $"{nameof(args)}[1]");
|
|
ArgUtil.NotNullOrEmpty(args[2], $"{nameof(args)}[2]");
|
|
var worker = context.GetService<IWorker>();
|
|
|
|
// Run the worker.
|
|
return await worker.RunAsync(
|
|
pipeIn: args[1],
|
|
pipeOut: args[2]);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Populate any exception that cause worker failure back to runner.
|
|
Console.WriteLine(ex.ToString());
|
|
try
|
|
{
|
|
trace.Error(ex);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
// make sure we don't crash the app on trace error.
|
|
// since IOException will throw when we run out of disk space.
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Runner.Worker is started by Runner.Listener in a separate process,
|
|
/// so the two can't be debugged in the same session.
|
|
/// This method halts the Runner.Worker process until a debugger is attached,
|
|
/// allowing a developer to debug Runner.Worker from start to finish.
|
|
/// </summary>
|
|
private static async Task WaitForDebugger(Tracing trace)
|
|
{
|
|
trace.Info($"Waiting for a debugger to be attached. Edit the 'GITHUB_ACTIONS_RUNNER_ATTACH_DEBUGGER' environment variable to toggle this feature.");
|
|
int waitInSeconds = 20;
|
|
while (!Debugger.IsAttached && waitInSeconds-- > 0)
|
|
{
|
|
trace.Info($"Waiting for a debugger to be attached. {waitInSeconds} seconds left.");
|
|
await Task.Delay(1000);
|
|
}
|
|
Debugger.Break();
|
|
}
|
|
}
|
|
}
|