diff --git a/docs/checks/nodejs.md b/docs/checks/nodejs.md index ee0a805e0..cbdd8659b 100644 --- a/docs/checks/nodejs.md +++ b/docs/checks/nodejs.md @@ -4,9 +4,9 @@ Make sure the built-in node.js has access to GitHub.com or GitHub Enterprise Server. -The runner carries it's own copy of node.js executable under `/externals/node12/`. +The runner carries its own copy of node.js executable under `/externals/node16/`. -All javascript base Actions will get executed by the built-in `node` at `/externals/node12/`. +All javascript base Actions will get executed by the built-in `node` at `/externals/node16/`. > Not the `node` from `$PATH` diff --git a/src/Misc/layoutbin/runsvc.sh b/src/Misc/layoutbin/runsvc.sh index 1919b9c21..c13564567 100755 --- a/src/Misc/layoutbin/runsvc.sh +++ b/src/Misc/layoutbin/runsvc.sh @@ -10,10 +10,11 @@ if [ -f ".path" ]; then echo ".path=${PATH}" fi -# insert anything to setup env when running as a service +nodever=${GITHUB_ACTIONS_RUNNER_FORCED_NODE_VERSION:-node16} +# insert anything to setup env when running as a service # run the host process which keep the listener alive -./externals/node12/bin/node ./bin/RunnerService.js & +./externals/$nodever/bin/node ./bin/RunnerService.js & PID=$! wait $PID trap - TERM INT diff --git a/src/Misc/layoutbin/update.sh.template b/src/Misc/layoutbin/update.sh.template index 42538cf24..2a6483ea0 100755 --- a/src/Misc/layoutbin/update.sh.template +++ b/src/Misc/layoutbin/update.sh.template @@ -125,7 +125,7 @@ attemptedtargetedfix=0 currentplatform=$(uname | awk '{print tolower($0)}') if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then # We needed a fix for https://github.com/actions/runner/issues/743 - # We will recreate the ./externals/node12/bin/node of the past runner version that launched the runnerlistener service + # We will recreate the ./externals/nodeXY/bin/node of the past runner version that launched the runnerlistener service # Otherwise mac gatekeeper kills the processes we spawn on creation as we are running a process with no backing file # We need the pid for the nodejs loop, get that here, its the parent of the runner C# pid @@ -135,7 +135,13 @@ if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then then # inspect the open file handles to find the node process # we can't actually inspect the process using ps because it uses relative paths and doesn't follow symlinks - path=$(lsof -a -g "$procgroup" -F n | grep node12/bin/node | grep externals | tail -1 | cut -c2-) + nodever="node16" + path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-) + if [[ $? -ne 0 || -z "$path" ]] # Fallback if RunnerService.js was started with node12 + then + nodever="node12" + path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-) + fi if [[ $? -eq 0 && -n "$path" ]] then # trim the last 5 characters of the path '/node' @@ -148,7 +154,7 @@ if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then then date "+[%F %T-%4N] Creating fallback node at path $path" >> "$logfile" 2>&1 mkdir -p "$trimmedpath" - cp "$rootfolder/externals/node12/bin/node" "$path" + cp "$rootfolder/externals/$nodever/bin/node" "$path" else date "+[%F %T-%4N] Path for fallback node exists, skipping creating $path" >> "$logfile" 2>&1 fi diff --git a/src/Runner.Common/Constants.cs b/src/Runner.Common/Constants.cs index 829c8223e..85b10e165 100644 --- a/src/Runner.Common/Constants.cs +++ b/src/Runner.Common/Constants.cs @@ -224,6 +224,9 @@ namespace GitHub.Runner.Common public static class Agent { public static readonly string ToolsDirectory = "agent.ToolsDirectory"; + + // Set this env var to force a node version for internal functions (e.g hashfiles). This does NOT affect the version of node actions. + public static readonly string ForcedNodeVersion = "GITHUB_ACTIONS_RUNNER_FORCED_NODE_VERSION"; } public static class System diff --git a/src/Runner.Common/Util/NodeUtil.cs b/src/Runner.Common/Util/NodeUtil.cs new file mode 100644 index 000000000..13a213256 --- /dev/null +++ b/src/Runner.Common/Util/NodeUtil.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.ObjectModel; + +namespace GitHub.Runner.Common.Util +{ + public static class NodeUtil + { + private const string _defaultNodeVersion = "node16"; + public static readonly ReadOnlyCollection BuiltInNodeVersions = new(new[] {"node12", "node16"}); + public static string GetNodeVersion() + { + var forcedNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedNodeVersion); + return !string.IsNullOrEmpty(forcedNodeVersion) && BuiltInNodeVersions.Contains(forcedNodeVersion) ? forcedNodeVersion : _defaultNodeVersion; + } + } +} diff --git a/src/Runner.Listener/Checks/CheckUtil.cs b/src/Runner.Listener/Checks/CheckUtil.cs index ee2e824f3..fd1461a6b 100644 --- a/src/Runner.Listener/Checks/CheckUtil.cs +++ b/src/Runner.Listener/Checks/CheckUtil.cs @@ -10,6 +10,7 @@ using System.Net.NetworkInformation; using System.Threading; using System.Threading.Tasks; using GitHub.Runner.Common; +using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using GitHub.Services.Common; @@ -314,12 +315,12 @@ namespace GitHub.Runner.Listener.Check }); var downloadCertScript = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Bin), "checkScripts", "downloadCert"); - var node12 = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}"); - result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Run '{node12} \"{downloadCertScript}\"' "); + var node = Path.Combine(hostContext.GetDirectory(WellKnownDirectory.Externals), NodeUtil.GetNodeVersion(), "bin", $"node{IOUtil.ExeExtension}"); + result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Run '{node} \"{downloadCertScript}\"' "); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} {StringUtil.ConvertToJson(env)}"); await processInvoker.ExecuteAsync( hostContext.GetDirectory(WellKnownDirectory.Root), - node12, + node, $"\"{downloadCertScript}\"", env, true, diff --git a/src/Runner.Listener/Checks/NodeJsCheck.cs b/src/Runner.Listener/Checks/NodeJsCheck.cs index 2b5586299..2ab61d7d6 100644 --- a/src/Runner.Listener/Checks/NodeJsCheck.cs +++ b/src/Runner.Listener/Checks/NodeJsCheck.cs @@ -6,6 +6,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; using GitHub.Runner.Common; +using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; namespace GitHub.Runner.Listener.Check @@ -144,12 +145,12 @@ namespace GitHub.Runner.Listener.Check }); var makeWebRequestScript = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Bin), "checkScripts", "makeWebRequest.js"); - var node12 = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}"); - result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Run '{node12} \"{makeWebRequestScript}\"' "); + var node = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), NodeUtil.GetNodeVersion(), "bin", $"node{IOUtil.ExeExtension}"); + result.Logs.Add($"{DateTime.UtcNow.ToString("O")} Run '{node} \"{makeWebRequestScript}\"' "); result.Logs.Add($"{DateTime.UtcNow.ToString("O")} {StringUtil.ConvertToJson(env)}"); await processInvoker.ExecuteAsync( HostContext.GetDirectory(WellKnownDirectory.Root), - node12, + node, $"\"{makeWebRequestScript}\"", env, true, diff --git a/src/Runner.Listener/SelfUpdater.cs b/src/Runner.Listener/SelfUpdater.cs index 776ab9689..13d0383fc 100644 --- a/src/Runner.Listener/SelfUpdater.cs +++ b/src/Runner.Listener/SelfUpdater.cs @@ -12,6 +12,7 @@ using System.Threading; using System.Threading.Tasks; using GitHub.DistributedTask.WebApi; using GitHub.Runner.Common; +using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using GitHub.Services.Common; using GitHub.Services.WebApi; @@ -804,7 +805,7 @@ namespace GitHub.Runner.Listener IOUtil.CopyDirectory(_externalsCloneDirectory, Path.Combine(downloadDirectory, Constants.Path.ExternalsDirectory), token); // try run node.js to see if current node.js works fine after copy over to new location. - var nodeVersions = new[] { "node12", "node16" }; + var nodeVersions = NodeUtil.BuiltInNodeVersions; foreach (var nodeVersion in nodeVersions) { var newNodeBinary = Path.Combine(downloadDirectory, Constants.Path.ExternalsDirectory, nodeVersion, "bin", $"node{IOUtil.ExeExtension}"); @@ -1069,7 +1070,7 @@ namespace GitHub.Runner.Listener var stopWatch = Stopwatch.StartNew(); string binDir = HostContext.GetDirectory(WellKnownDirectory.Bin); - string node = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}"); + string node = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), NodeUtil.GetNodeVersion(), "bin", $"node{IOUtil.ExeExtension}"); string hashFilesScript = Path.Combine(binDir, "hashFiles"); var hashResult = string.Empty; diff --git a/src/Runner.Worker/ExecutionContext.cs b/src/Runner.Worker/ExecutionContext.cs index d0028408e..b1ff5182b 100644 --- a/src/Runner.Worker/ExecutionContext.cs +++ b/src/Runner.Worker/ExecutionContext.cs @@ -668,6 +668,11 @@ namespace GitHub.Runner.Worker // Variables Global.Variables = new Variables(HostContext, message.Variables); + if (Global.Variables.GetBoolean("DistributedTask.ForceInternalNodeVersionOnRunnerTo12") ?? false) + { + Environment.SetEnvironmentVariable(Constants.Variables.Agent.ForcedNodeVersion, "node12"); + } + // Environment variables shared across all actions Global.EnvironmentVariables = new Dictionary(VarUtil.EnvironmentVariableKeyComparer); diff --git a/src/Runner.Worker/Expressions/HashFilesFunction.cs b/src/Runner.Worker/Expressions/HashFilesFunction.cs index a19f13e39..d07a1bc17 100644 --- a/src/Runner.Worker/Expressions/HashFilesFunction.cs +++ b/src/Runner.Worker/Expressions/HashFilesFunction.cs @@ -7,6 +7,7 @@ using GitHub.Runner.Sdk; using System.Reflection; using System.Threading; using System.Collections.Generic; +using GitHub.Runner.Common.Util; namespace GitHub.Runner.Worker.Expressions { @@ -62,7 +63,7 @@ namespace GitHub.Runner.Worker.Expressions string binDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); string runnerRoot = new DirectoryInfo(binDir).Parent.FullName; - string node = Path.Combine(runnerRoot, "externals", "node12", "bin", $"node{IOUtil.ExeExtension}"); + string node = Path.Combine(runnerRoot, "externals", NodeUtil.GetNodeVersion(), "bin", $"node{IOUtil.ExeExtension}"); string hashFilesScript = Path.Combine(binDir, "hashFiles"); var hashResult = string.Empty; var p = new ProcessInvoker(new HashFilesTrace(context.Trace)); diff --git a/src/Runner.Worker/Handlers/ScriptHandler.cs b/src/Runner.Worker/Handlers/ScriptHandler.cs index de7f1a931..f75a10ce5 100644 --- a/src/Runner.Worker/Handlers/ScriptHandler.cs +++ b/src/Runner.Worker/Handlers/ScriptHandler.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.WebApi; using GitHub.Runner.Common; +using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using Pipelines = GitHub.DistributedTask.Pipelines; @@ -267,10 +268,10 @@ namespace GitHub.Runner.Worker.Handlers if (Environment.ContainsKey("DYLD_INSERT_LIBRARIES")) // We don't check `isContainerStepHost` because we don't support container on macOS { // launch `node macOSRunInvoker.js shell args` instead of `shell args` to avoid macOS SIP remove `DYLD_INSERT_LIBRARIES` when launch process - string node12 = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node12", "bin", $"node{IOUtil.ExeExtension}"); + string node = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), NodeUtil.GetNodeVersion(), "bin", $"node{IOUtil.ExeExtension}"); string macOSRunInvoker = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Bin), "macos-run-invoker.js"); arguments = $"\"{macOSRunInvoker.Replace("\"", "\\\"")}\" \"{fileName.Replace("\"", "\\\"")}\" {arguments}"; - fileName = node12; + fileName = node; } #endif var systemConnection = ExecutionContext.Global.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));