Skip to content

Commit 59ec9b4

Browse files
authored
Remove node16 from the runner. (#3503)
1 parent 4a99838 commit 59ec9b4

14 files changed

+47
-193
lines changed

docs/checks/nodejs.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
Make sure the built-in node.js has access to GitHub.com or GitHub Enterprise Server.
66

7-
The runner carries its own copy of node.js executable under `<runner_root>/externals/node16/`.
7+
The runner carries its own copy of node.js executable under `<runner_root>/externals/node20/`.
88

9-
All javascript base Actions will get executed by the built-in `node` at `<runner_root>/externals/node16/`.
9+
All javascript base Actions will get executed by the built-in `node` at `<runner_root>/externals/node20/`.
1010

1111
> Not the `node` from `$PATH`
1212

src/Misc/externals.sh

+1-14
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@ PACKAGERUNTIME=$1
33
PRECACHE=$2
44

55
NODE_URL=https://nodejs.org/dist
6-
UNOFFICIAL_NODE_URL=https://unofficial-builds.nodejs.org/download/release
76
NODE_ALPINE_URL=https://github.com/actions/alpine_nodejs/releases/download
87
# When you update Node versions you must also create a new release of alpine_nodejs at that updated version.
98
# Follow the instructions here: https://github.com/actions/alpine_nodejs?tab=readme-ov-file#getting-started
10-
NODE16_VERSION="16.20.2"
11-
NODE20_VERSION="20.13.1"
12-
NODE16_UNOFFICIAL_VERSION="16.20.0" # used only for win-arm64, remove node16 unofficial version when official version is available
9+
NODE20_VERSION="20.18.0"
1310

1411
get_abs_path() {
1512
# exploits the fact that pwd will print abs path when no args
@@ -140,8 +137,6 @@ function acquireExternalTool() {
140137

141138
# Download the external tools only for Windows.
142139
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
143-
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
144-
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
145140
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
146141
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
147142
if [[ "$PRECACHE" != "" ]]; then
@@ -152,8 +147,6 @@ fi
152147
# Download the external tools only for Windows.
153148
if [[ "$PACKAGERUNTIME" == "win-arm64" ]]; then
154149
# todo: replace these with official release when available
155-
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
156-
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
157150
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
158151
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
159152
if [[ "$PRECACHE" != "" ]]; then
@@ -163,30 +156,24 @@ fi
163156

164157
# Download the external tools only for OSX.
165158
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
166-
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-x64.tar.gz" node16 fix_nested_dir
167159
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-darwin-x64.tar.gz" node20 fix_nested_dir
168160
fi
169161

170162
if [[ "$PACKAGERUNTIME" == "osx-arm64" ]]; then
171163
# node.js v12 doesn't support macOS on arm64.
172-
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-arm64.tar.gz" node16 fix_nested_dir
173164
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-darwin-arm64.tar.gz" node20 fix_nested_dir
174165
fi
175166

176167
# Download the external tools for Linux PACKAGERUNTIMEs.
177168
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
178-
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-x64.tar.gz" node16 fix_nested_dir
179-
acquireExternalTool "$NODE_ALPINE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-alpine-x64.tar.gz" node16_alpine
180169
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-x64.tar.gz" node20 fix_nested_dir
181170
acquireExternalTool "$NODE_ALPINE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-alpine-x64.tar.gz" node20_alpine
182171
fi
183172

184173
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
185-
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-arm64.tar.gz" node16 fix_nested_dir
186174
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-arm64.tar.gz" node20 fix_nested_dir
187175
fi
188176

189177
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
190-
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-armv7l.tar.gz" node16 fix_nested_dir
191178
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-armv7l.tar.gz" node20 fix_nested_dir
192179
fi

src/Misc/layoutbin/runsvc.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ if [ -f ".path" ]; then
1010
echo ".path=${PATH}"
1111
fi
1212

13-
nodever=${GITHUB_ACTIONS_RUNNER_FORCED_NODE_VERSION:-node16}
13+
nodever="node20"
1414

1515
# insert anything to setup env when running as a service
1616
# run the host process which keep the listener alive

src/Misc/layoutbin/update.sh.template

+21-3
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,17 @@ if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then
135135
then
136136
# inspect the open file handles to find the node process
137137
# we can't actually inspect the process using ps because it uses relative paths and doesn't follow symlinks
138-
nodever="node16"
138+
nodever="node20"
139139
path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-)
140-
if [[ $? -ne 0 || -z "$path" ]] # Fallback if RunnerService.js was started with node12
140+
if [[ $? -ne 0 || -z "$path" ]] # Fallback if RunnerService.js was started with node16
141141
then
142-
nodever="node12"
142+
nodever="node16"
143143
path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-)
144+
if [[ $? -ne 0 || -z "$path" ]] # Fallback if RunnerService.js was started with node12
145+
then
146+
nodever="node12"
147+
path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-)
148+
fi
144149
fi
145150
if [[ $? -eq 0 && -n "$path" ]]
146151
then
@@ -178,6 +183,19 @@ if [[ "$currentplatform" == 'darwin' && restartinteractiverunner -eq 0 ]]; then
178183
fi
179184
fi
180185

186+
# update runsvc.sh
187+
if [ -f "$rootfolder/runsvc.sh" ]
188+
then
189+
date "+[%F %T-%4N] Update runsvc.sh" >> "$logfile" 2>&1
190+
cat "$rootfolder/bin/runsvc.sh" > "$rootfolder/runsvc.sh"
191+
if [ $? -ne 0 ]
192+
then
193+
date "+[%F %T-%4N] Can't update $rootfolder/runsvc.sh using $rootfolder/bin/runsvc.sh" >> "$logfile" 2>&1
194+
mv -fv "$logfile" "$logfile.failed"
195+
exit 1
196+
fi
197+
fi
198+
181199
date "+[%F %T-%4N] Update succeed" >> "$logfile"
182200

183201
touch update.finished

src/Runner.Common/Constants.cs

+1-13
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ public static class ReturnCode
159159
public static class Features
160160
{
161161
public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
162-
public static readonly string Node16Warning = "DistributedTask.AddWarningToNode16Action";
163162
public static readonly string LogTemplateErrorsAsDebugMessages = "DistributedTask.LogTemplateErrorsAsDebugMessages";
164163
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
165164
public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks";
@@ -176,14 +175,6 @@ public static class Features
176175
public static readonly string UnsupportedStopCommandTokenDisabled = "You cannot use a endToken that is an empty string, the string 'pause-logging', or another workflow command. For more information see: https://docs.github.com/actions/learn-github-actions/workflow-commands-for-github-actions#example-stopping-and-starting-workflow-commands or opt into insecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS` environment variable to `true`.";
177176
public static readonly string UnsupportedSummarySize = "$GITHUB_STEP_SUMMARY upload aborted, supports content up to a size of {0}k, got {1}k. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
178177
public static readonly string SummaryUploadError = "$GITHUB_STEP_SUMMARY upload aborted, an error occurred when uploading the summary. For more information see: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary";
179-
public static readonly string DetectedNodeAfterEndOfLifeMessage = "Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: {0}. For more information see: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/.";
180-
public static readonly string DeprecatedNodeDetectedAfterEndOfLifeActions = "DeprecatedNodeActionsMessageWarnings";
181-
public static readonly string DeprecatedNodeVersion = "node16";
182-
public static readonly string EnforcedNode12DetectedAfterEndOfLife = "The following actions uses node12 which is deprecated and will be forced to run on node16: {0}. For more info: https://github.blog/changelog/2023-06-13-github-actions-all-actions-will-run-on-node16-instead-of-node12-by-default/";
183-
public static readonly string EnforcedNode12DetectedAfterEndOfLifeEnvVariable = "Node16ForceActionsWarnings";
184-
public static readonly string EnforcedNode16DetectedAfterEndOfLife = "The following actions use a deprecated Node.js version and will be forced to run on node20: {0}. For more info: https://github.blog/changelog/2024-03-07-github-actions-all-actions-will-run-on-node20-instead-of-node16-by-default/";
185-
public static readonly string EnforcedNode16DetectedAfterEndOfLifeEnvVariable = "Node20ForceActionsWarnings";
186-
187178
}
188179

189180
public static class RunnerEvent
@@ -254,20 +245,17 @@ public static class Actions
254245
public static readonly string RequireJobContainer = "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER";
255246
public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG";
256247
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
257-
public static readonly string AllowActionsUseUnsecureNodeVersion = "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION";
258-
public static readonly string ManualForceActionsToNode20 = "FORCE_JAVASCRIPT_ACTIONS_TO_NODE20";
259248
}
260249

261250
public static class Agent
262251
{
263252
public static readonly string ToolsDirectory = "agent.ToolsDirectory";
264253

265-
// Set this env var to "node12" to downgrade the node version for internal functions (e.g hashfiles). This does NOT affect the version of node actions.
254+
// Set this env var to "nodeXY" to downgrade the node version for internal functions (e.g hashfiles). This does NOT affect the version of node actions.
266255
public static readonly string ForcedInternalNodeVersion = "ACTIONS_RUNNER_FORCED_INTERNAL_NODE_VERSION";
267256
public static readonly string ForcedActionsNodeVersion = "ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION";
268257
public static readonly string PrintLogToStdout = "ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT";
269258
public static readonly string ActionArchiveCacheDirectory = "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE";
270-
public static readonly string ManualForceActionsToNode20 = "FORCE_JAVASCRIPT_ACTIONS_TO_NODE20";
271259
}
272260

273261
public static class System

src/Runner.Common/Util/NodeUtil.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ namespace GitHub.Runner.Common.Util
55
{
66
public static class NodeUtil
77
{
8-
private const string _defaultNodeVersion = "node16";
9-
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16", "node20" });
8+
private const string _defaultNodeVersion = "node20";
9+
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node20" });
1010
public static string GetInternalNodeVersion()
1111
{
1212
var forcedInternalNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion);

src/Runner.Worker/ExecutionContext.cs

-5
Original file line numberDiff line numberDiff line change
@@ -814,11 +814,6 @@ public void InitializeJob(Pipelines.AgentJobRequestMessage message, Cancellation
814814

815815
Global.Variables = new Variables(HostContext, variables);
816816

817-
if (Global.Variables.GetBoolean("DistributedTask.ForceInternalNodeVersionOnRunnerTo16") ?? false)
818-
{
819-
Environment.SetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion, "node16");
820-
}
821-
822817
// Environment variables shared across all actions
823818
Global.EnvironmentVariables = new Dictionary<string, string>(VarUtil.EnvironmentVariableKeyComparer);
824819

src/Runner.Worker/Handlers/HandlerFactory.cs

+4-63
Original file line numberDiff line numberDiff line change
@@ -57,72 +57,13 @@ public IHandler Create(
5757
handler = HostContext.CreateService<INodeScriptActionHandler>();
5858
var nodeData = data as NodeJSActionExecutionData;
5959

60-
// With node12 EoL in 04/2022, we want to be able to uniformly upgrade all JS actions to node16 from the server
61-
if (string.Equals(nodeData.NodeVersion, "node12", StringComparison.InvariantCultureIgnoreCase))
60+
// With node12 EoL in 04/2022 and node16 EoL in 09/23, we want to execute all JS actions using node20
61+
if (string.Equals(nodeData.NodeVersion, "node12", StringComparison.InvariantCultureIgnoreCase) ||
62+
string.Equals(nodeData.NodeVersion, "node16", StringComparison.InvariantCultureIgnoreCase))
6263
{
63-
var repoAction = action as Pipelines.RepositoryPathReference;
64-
if (repoAction != null)
65-
{
66-
var warningActions = new HashSet<string>();
67-
if (executionContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode12DetectedAfterEndOfLifeEnvVariable, out var node16ForceWarnings))
68-
{
69-
warningActions = StringUtil.ConvertFromJson<HashSet<string>>(node16ForceWarnings);
70-
}
71-
72-
string repoActionFullName;
73-
if (string.IsNullOrEmpty(repoAction.Name))
74-
{
75-
repoActionFullName = repoAction.Path; // local actions don't have a 'Name'
76-
}
77-
else
78-
{
79-
repoActionFullName = $"{repoAction.Name}/{repoAction.Path ?? string.Empty}".TrimEnd('/') + $"@{repoAction.Ref}";
80-
}
81-
82-
warningActions.Add(repoActionFullName);
83-
executionContext.Global.Variables.Set("Node16ForceActionsWarnings", StringUtil.ConvertToJson(warningActions));
84-
}
85-
nodeData.NodeVersion = "node16";
64+
nodeData.NodeVersion = "node20";
8665
}
8766

88-
var localForceActionsToNode20 = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Agent.ManualForceActionsToNode20));
89-
executionContext.Global.EnvironmentVariables.TryGetValue(Constants.Variables.Actions.ManualForceActionsToNode20, out var workflowForceActionsToNode20);
90-
var enforceNode20Locally = !string.IsNullOrWhiteSpace(workflowForceActionsToNode20) ? StringUtil.ConvertToBoolean(workflowForceActionsToNode20) : localForceActionsToNode20;
91-
if (string.Equals(nodeData.NodeVersion, "node16")
92-
&& ((executionContext.Global.Variables.GetBoolean("DistributedTask.ForceGithubJavascriptActionsToNode20") ?? false) || enforceNode20Locally))
93-
{
94-
executionContext.Global.EnvironmentVariables.TryGetValue(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion, out var workflowOptOut);
95-
var isWorkflowOptOutSet = !string.IsNullOrWhiteSpace(workflowOptOut);
96-
var isLocalOptOut = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion));
97-
bool isOptOut = isWorkflowOptOutSet ? StringUtil.ConvertToBoolean(workflowOptOut) : isLocalOptOut;
98-
99-
if (!isOptOut)
100-
{
101-
var repoAction = action as Pipelines.RepositoryPathReference;
102-
if (repoAction != null)
103-
{
104-
var warningActions = new HashSet<string>();
105-
if (executionContext.Global.Variables.TryGetValue(Constants.Runner.EnforcedNode16DetectedAfterEndOfLifeEnvVariable, out var node20ForceWarnings))
106-
{
107-
warningActions = StringUtil.ConvertFromJson<HashSet<string>>(node20ForceWarnings);
108-
}
109-
110-
string repoActionFullName;
111-
if (string.IsNullOrEmpty(repoAction.Name))
112-
{
113-
repoActionFullName = repoAction.Path; // local actions don't have a 'Name'
114-
}
115-
else
116-
{
117-
repoActionFullName = $"{repoAction.Name}/{repoAction.Path ?? string.Empty}".TrimEnd('/') + $"@{repoAction.Ref}";
118-
}
119-
120-
warningActions.Add(repoActionFullName);
121-
executionContext.Global.Variables.Set(Constants.Runner.EnforcedNode16DetectedAfterEndOfLifeEnvVariable, StringUtil.ConvertToJson(warningActions));
122-
}
123-
nodeData.NodeVersion = "node20";
124-
}
125-
}
12667
(handler as INodeScriptActionHandler).Data = nodeData;
12768
}
12869
else if (data.ExecutionType == ActionExecutionType.Script)

0 commit comments

Comments
 (0)