// Return code definition: (this will be used by service host to determine whether it will re-launch Runner.Listener) // 0: Runner exit // 1: Terminate failure // 2: Retriable failure // 3: Exit for self update private async static Task <int> MainAsync(IHostContext context, string[] args) { Tracing trace = context.GetTrace(nameof(GitHub.Runner.Listener)); trace.Info($"Runner is built for {Constants.Runner.Platform} ({Constants.Runner.PlatformArchitecture}) - {BuildConstants.RunnerPackage.PackageName}."); trace.Info($"RuntimeInformation: {RuntimeInformation.OSDescription}."); context.WritePerfCounter("RunnerProcessStarted"); var terminal = context.GetService <ITerminal>(); // Validate the binaries intended for one OS are not running on a different OS. switch (Constants.Runner.Platform) { case Constants.OSPlatform.Linux: if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { terminal.WriteLine("This runner version is built for Linux. Please install a correct build for your OS."); return(Constants.Runner.ReturnCode.TerminatedError); } break; case Constants.OSPlatform.OSX: if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { terminal.WriteLine("This runner version is built for OSX. Please install a correct build for your OS."); return(Constants.Runner.ReturnCode.TerminatedError); } break; case Constants.OSPlatform.Windows: if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { terminal.WriteLine("This runner version is built for Windows. Please install a correct build for your OS."); return(Constants.Runner.ReturnCode.TerminatedError); } break; default: terminal.WriteLine($"Running the runner on this platform is not supported. The current platform is {RuntimeInformation.OSDescription} and it was built for {Constants.Runner.Platform.ToString()}."); return(Constants.Runner.ReturnCode.TerminatedError); } 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}"); // Validate directory permissions. string runnerDirectory = context.GetDirectory(WellKnownDirectory.Root); trace.Info($"Validating directory permissions for: '{runnerDirectory}'"); try { IOUtil.ValidateExecutePermission(runnerDirectory); } catch (Exception e) { terminal.WriteError($"An error occurred: {e.Message}"); trace.Error(e); return(Constants.Runner.ReturnCode.TerminatedError); } // Parse the command line args. var command = new CommandSettings(context, args); trace.Info("Arguments parsed"); // Up front validation, warn for unrecognized commandline args. var unknownCommandlines = command.Validate(); if (unknownCommandlines.Count > 0) { terminal.WriteError($"Unrecognized command-line input arguments: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help"); } // Defer to the Runner class to execute the command. IRunner runner = context.GetService <IRunner>(); try { return(await runner.ExecuteCommand(command)); } catch (OperationCanceledException) when(context.RunnerShutdownToken.IsCancellationRequested) { trace.Info("Runner execution been cancelled."); return(Constants.Runner.ReturnCode.Success); } catch (NonRetryableException e) { terminal.WriteError($"An error occurred: {e.Message}"); trace.Error(e); return(Constants.Runner.ReturnCode.TerminatedError); } } catch (Exception e) { terminal.WriteError($"An error occurred: {e.Message}"); trace.Error(e); return(Constants.Runner.ReturnCode.RetryableError); } }