Skip to content

Node 24 enforcement + Linux ARM32 deprecation support#4303

Open
salmanmkc wants to merge 2 commits intomainfrom
salmanmkc/node24-enforcement-arm32-deprecation
Open

Node 24 enforcement + Linux ARM32 deprecation support#4303
salmanmkc wants to merge 2 commits intomainfrom
salmanmkc/node24-enforcement-arm32-deprecation

Conversation

@salmanmkc
Copy link
Contributor

When we flip UseNode24ByDefault, actions targeting node20 get forced to node24 and we show an annotation saying which ones were forced over. On linux-arm32 we can't do that since there's no node24 binary, so instead we show a deprecation warning and keep them on node20 for now.

Added two new feature flags for the arm32 side:

  • actions_runner_deprecate_linux_arm32 - warns that arm32 is going away, keeps running on node20
  • actions_runner_kill_linux_arm32 - for when we actually want to stop supporting it, fails the step

Also split the tracking so upgraded-to-node24 actions and still-on-node20 actions get separate annotations instead of lumping them together.

Date for arm32 EOL is TBD, placeholder is October 2026, need to align on this still

@salmanmkc salmanmkc requested a review from a team as a code owner March 16, 2026 14:01
Copilot AI review requested due to automatic review settings March 16, 2026 14:01
@salmanmkc salmanmkc force-pushed the salmanmkc/node24-enforcement-arm32-deprecation branch from ff34d03 to 4c5eac9 Compare March 16, 2026 14:03
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Node.js 24 enforcement/tracking for Node.js actions, with special handling for Linux ARM32 where Node 24 binaries are unavailable (deprecation/kill switch behavior and messaging).

Changes:

  • Track Node20-targeting actions separately as either still-on-node20 vs. forced-to-node24, and emit separate job-level annotations.
  • Add Linux ARM32 deprecation + kill-switch feature flags and plumb them into Node version selection.
  • Add/extend L0 tests covering upgraded vs. deprecated tracking and ARM32-related NodeUtil behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/Test/L0/Worker/StepHostNodeVersionL0.cs Adds L0 tests for ARM32 deprecate/kill behaviors in NodeUtil.
src/Test/L0/Worker/HandlerFactoryL0.cs Adds L0 tests for upgraded-to-node24 vs deprecated tracking behavior.
src/Runner.Worker/JobExtension.cs Splits job-finalization warnings for still-on-node20 vs upgraded-to-node24 actions.
src/Runner.Worker/Handlers/HandlerFactory.cs Implements per-action Node version enforcement, ARM32 deprecate/kill logic, and tracking into two sets.
src/Runner.Worker/GlobalContext.cs Adds a new global set for actions upgraded to node24.
src/Runner.Worker/ExecutionContext.cs Initializes the new upgraded-actions tracking set at job start.
src/Runner.Common/Util/NodeUtil.cs Extends ARM32 node version check to support deprecation and kill-switch phases.
src/Runner.Common/Constants.cs Adds ARM32 feature flag constants and ARM32 deprecation message/date constants.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +66 to +86
public void CheckNodeVersionForArm32_DeprecationFlagShowsWarning()
{
string preferredVersion = "node24";
var (nodeVersion, warningMessage) = Common.Util.NodeUtil.CheckNodeVersionForLinuxArm32(preferredVersion, deprecateArm32: true);

bool isArm32 = RuntimeInformation.ProcessArchitecture == Architecture.Arm ||
Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")?.Contains("ARM") == true;
bool isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);

if (isArm32 && isLinux)
{
Assert.Equal("node20", nodeVersion);
Assert.NotNull(warningMessage);
Assert.Contains("deprecated", warningMessage);
Assert.Contains("no longer be supported", warningMessage);
}
else
{
Assert.Equal("node24", nodeVersion);
Assert.Null(warningMessage);
}
Comment on lines +423 to +434
// On non-ARM32 platforms, action should be upgraded to node24
// and tracked in UpgradedToNode24Actions, NOT in DeprecatedNode20Actions
bool isArm32Linux = System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture == System.Runtime.InteropServices.Architecture.Arm &&
System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux);

if (!isArm32Linux)
{
Assert.Equal("node24", handler.Data.NodeVersion);
Assert.Contains("actions/checkout@v4", upgradedActions);
Assert.DoesNotContain("actions/checkout@v4", deprecatedActions);
}
}
Comment on lines 74 to +85
// Check if node20 was explicitly specified in the action
// We don't modify if node24 was explicitly specified
if (string.Equals(nodeData.NodeVersion, Constants.Runner.NodeMigration.Node20, StringComparison.InvariantCultureIgnoreCase))
{
bool useNode24ByDefault = executionContext.Global.Variables?.GetBoolean(Constants.Runner.NodeMigration.UseNode24ByDefaultFlag) ?? false;
bool requireNode24 = executionContext.Global.Variables?.GetBoolean(Constants.Runner.NodeMigration.RequireNode24Flag) ?? false;
bool deprecateArm32 = executionContext.Global.Variables?.GetBoolean(Constants.Runner.NodeMigration.DeprecateLinuxArm32Flag) ?? false;
bool killArm32 = executionContext.Global.Variables?.GetBoolean(Constants.Runner.NodeMigration.KillLinuxArm32Flag) ?? false;

var (nodeVersion, configWarningMessage) = NodeUtil.DetermineActionsNodeVersion(environment, useNode24ByDefault, requireNode24);
var (finalNodeVersion, platformWarningMessage) = NodeUtil.CheckNodeVersionForLinuxArm32(nodeVersion);
var (finalNodeVersion, platformWarningMessage) = NodeUtil.CheckNodeVersionForLinuxArm32(nodeVersion, deprecateArm32, killArm32);

Comment on lines +68 to +72
// Track Node.js 20 actions for deprecation annotation
if (string.Equals(nodeData.NodeVersion, Constants.Runner.NodeMigration.Node20, StringComparison.InvariantCultureIgnoreCase))
{
bool warnOnNode20 = executionContext.Global.Variables?.GetBoolean(Constants.Runner.NodeMigration.WarnOnNode20Flag) ?? false;
if (warnOnNode20)
{
string actionName = GetActionName(action);
if (!string.IsNullOrEmpty(actionName))
{
executionContext.Global.DeprecatedNode20Actions?.Add(actionName);
}
}
}
// Note: tracking happens before potential upgrade to node24
// Actions that get upgraded will be moved to UpgradedToNode24Actions below
bool warnOnNode20 = executionContext.Global.Variables?.GetBoolean(Constants.Runner.NodeMigration.WarnOnNode20Flag) ?? false;
string actionName = GetActionName(action);
{
var sortedActions = context.Global.DeprecatedNode20Actions.OrderBy(a => a, StringComparer.OrdinalIgnoreCase);
var actionsList = string.Join(", ", sortedActions);
var deprecationMessage = $"Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: {actionsList}. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: {Constants.Runner.NodeMigration.Node20DeprecationUrl}";
@salmanmkc salmanmkc force-pushed the salmanmkc/node24-enforcement-arm32-deprecation branch from a3c3706 to 3bd3bff Compare March 16, 2026 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants