Files
runner/src/Runner.Worker/Handlers/ScriptHandlerHelpers.cs
Ferenc Hammerl 7d5e9cd70f Runner Job Started/Completed Hooks (#1737)
* Prototype for pre job hook

* Remove debug log

* Enable hooks again

* Initialize with hostContext

* Add event_path, fix no-path bug

* Allow script post steps

* Call script handler with correct pre post stage

* Add job completed hook

* Make filecommand work and hardcode shell

* Conditionally print step details and no telemetry for hooks

* Figure out whih script to use

* Only check path for managed scripts

* Resture win dependency

* Nits

* Remove unused, add named params

* Telemetry + refactoring

* add message to job

* rename hooks remove stale comment

* cleanup

* Use .CreateService to create step

* Add L0s

* pr feedback

* update tests

* add disclaimer, clean up code

* spacing fix

* little more cleanup

* pr fix

* pr feedback

* Refactor to use JobExtension

* fix tests

* fix typo

* cleanup code

* more cleanup

* little more cleanup

* last bit of cleanup

* fix tests

* nit fix

* Update src/Runner.Worker/JobHookProvider.cs

Co-authored-by: Edward Thomson <ethomson@github.com>

* don't override runner telemtry

* pr feedback

* pr feedback

* pr feedback

Co-authored-by: Thomas Boop <thboop@github.com>
Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>
Co-authored-by: Edward Thomson <ethomson@github.com>
2022-03-17 21:35:04 -04:00

103 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using GitHub.Runner.Sdk;
namespace GitHub.Runner.Worker.Handlers
{
internal class ScriptHandlerHelpers
{
private static readonly Dictionary<string, string> _defaultArguments = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["cmd"] = "/D /E:ON /V:OFF /S /C \"CALL \"{0}\"\"",
["pwsh"] = "-command \". '{0}'\"",
["powershell"] = "-command \". '{0}'\"",
["bash"] = "--noprofile --norc -e -o pipefail {0}",
["sh"] = "-e {0}",
["python"] = "{0}"
};
private static readonly Dictionary<string, string> _extensions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["cmd"] = ".cmd",
["pwsh"] = ".ps1",
["powershell"] = ".ps1",
["bash"] = ".sh",
["sh"] = ".sh",
["python"] = ".py"
};
internal static string GetScriptArgumentsFormat(string scriptType)
{
if (_defaultArguments.TryGetValue(scriptType, out var argFormat))
{
return argFormat;
}
return "";
}
internal static string GetScriptFileExtension(string scriptType)
{
if (_extensions.TryGetValue(scriptType, out var extension))
{
return extension;
}
return "";
}
internal static string FixUpScriptContents(string scriptType, string contents)
{
switch (scriptType)
{
case "cmd":
// Note, use @echo off instead of using the /Q command line switch.
// When /Q is used, echo can't be turned on.
contents = $"@echo off{Environment.NewLine}{contents}";
break;
case "powershell":
case "pwsh":
var prepend = "$ErrorActionPreference = 'stop'";
var append = @"if ((Test-Path -LiteralPath variable:\LASTEXITCODE)) { exit $LASTEXITCODE }";
contents = $"{prepend}{Environment.NewLine}{contents}{Environment.NewLine}{append}";
break;
}
return contents;
}
internal static (string shellCommand, string shellArgs) ParseShellOptionString(string shellOption)
{
var shellStringParts = shellOption.Split(" ", 2);
if (shellStringParts.Length == 2)
{
return (shellCommand: shellStringParts[0], shellArgs: shellStringParts[1]);
}
else if (shellStringParts.Length == 1)
{
return (shellCommand: shellStringParts[0], shellArgs: "");
}
else
{
throw new ArgumentException($"Failed to parse COMMAND [..ARGS] from {shellOption}");
}
}
internal static string GetDefaultShellForScript(string path, Common.Tracing trace, string prependPath)
{
var format = "{0} {1}";
switch (Path.GetExtension(path))
{
case ".sh":
// use 'sh' args but prefer bash
var pathToShell = WhichUtil.Which("bash", false, trace, prependPath) ?? WhichUtil.Which("sh", true, trace, prependPath);
return string.Format(format, pathToShell, _defaultArguments["sh"]);
case ".ps1":
var pathToPowershell = WhichUtil.Which("pwsh", false, trace, prependPath) ?? WhichUtil.Which("powershell", true, trace, prependPath);
return string.Format(format, pathToPowershell, _defaultArguments["powershell"]);
default:
throw new ArgumentException($"{path} is not a valid path to a script. Make sure it ends in '.sh' or '.ps1'.");
}
}
}
}