Skip to content

Commit 100c99f

Browse files
authored
Force JS Actions Node version to 16 if FF is on unless user opted out (#1716)
* Set GH actions Node version to 16 if FF is on unless user opted out * Add L0s (WIP) * Wrap tests into theory * Only check for node12 actions * Refactor node version picking
1 parent e8ccafe commit 100c99f

File tree

3 files changed

+118
-1
lines changed

3 files changed

+118
-1
lines changed

src/Runner.Common/Constants.cs

+1
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ public static class Actions
220220
public static readonly string AllowUnsupportedStopCommandTokens = "ACTIONS_ALLOW_UNSECURE_STOPCOMMAND_TOKENS";
221221
public static readonly string RunnerDebug = "ACTIONS_RUNNER_DEBUG";
222222
public static readonly string StepDebug = "ACTIONS_STEP_DEBUG";
223+
public static readonly string AllowActionsUseUnsecureNodeVersion = "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION";
223224
}
224225

225226
public static class Agent

src/Runner.Worker/Handlers/HandlerFactory.cs

+17-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,23 @@ public IHandler Create(
5555
else if (data.ExecutionType == ActionExecutionType.NodeJS)
5656
{
5757
handler = HostContext.CreateService<INodeScriptActionHandler>();
58-
(handler as INodeScriptActionHandler).Data = data as NodeJSActionExecutionData;
58+
var nodeData = data as NodeJSActionExecutionData;
59+
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) &&
62+
(executionContext.Global.Variables.GetBoolean("DistributedTask.ForceGithubJavascriptActionsToNode16") ?? false))
63+
{
64+
// The user can opt out of this behaviour by setting this variable to true, either setting 'env' in their workflow or as an environment variable on their machine
65+
executionContext.Global.EnvironmentVariables.TryGetValue(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion, out var workflowOptOut);
66+
var isWorkflowOptOutSet = !string.IsNullOrEmpty(workflowOptOut);
67+
var isLocalOptOut = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion));
68+
bool isOptOut = isWorkflowOptOutSet ? StringUtil.ConvertToBoolean(workflowOptOut) : isLocalOptOut;
69+
if (!isOptOut)
70+
{
71+
nodeData.NodeVersion = "node16";
72+
}
73+
}
74+
(handler as INodeScriptActionHandler).Data = nodeData;
5975
}
6076
else if (data.ExecutionType == ActionExecutionType.Script)
6177
{
+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.CompilerServices;
4+
using Moq;
5+
using Xunit;
6+
using GitHub.Runner.Worker;
7+
using GitHub.Runner.Worker.Handlers;
8+
using GitHub.DistributedTask.Pipelines;
9+
using GitHub.DistributedTask.WebApi;
10+
11+
namespace GitHub.Runner.Common.Tests.Worker
12+
{
13+
public sealed class HandlerFactoryL0
14+
{
15+
private Mock<IExecutionContext> _ec;
16+
private TestHostContext CreateTestContext([CallerMemberName] string testName = "")
17+
{
18+
var hostContext = new TestHostContext(this, testName);
19+
_ec = new Mock<IExecutionContext>();
20+
_ec.SetupAllProperties();
21+
_ec.Object.Initialize(hostContext);
22+
var handler = new Mock<INodeScriptActionHandler>();
23+
handler.SetupAllProperties();
24+
hostContext.EnqueueInstance(handler.Object);
25+
//hostContext.EnqueueInstance(new ActionCommandManager() as IActionCommandManager);
26+
27+
return hostContext;
28+
}
29+
30+
[Theory]
31+
[Trait("Level", "L0")]
32+
[Trait("Category", "Worker")]
33+
[InlineData("node12", "", "", "", "node12")]
34+
[InlineData("node12", "true", "", "", "node16")]
35+
[InlineData("node12", "true", "", "true", "node12")]
36+
[InlineData("node12", "true", "true", "", "node12")]
37+
[InlineData("node12", "true", "true", "true", "node12")]
38+
[InlineData("node12", "true", "false", "true", "node16")] // workflow overrides env
39+
[InlineData("node16", "", "", "", "node16")]
40+
[InlineData("node16", "true", "", "", "node16")]
41+
[InlineData("node16", "true", "", "true", "node16")]
42+
[InlineData("node16", "true", "true", "", "node16")]
43+
[InlineData("node16", "true", "true", "true", "node16")]
44+
[InlineData("node16", "true", "false", "true", "node16")]
45+
public void IsNodeVersionUpgraded(string inputVersion, string serverFeatureFlag, string workflowOptOut, string machineOptOut, string expectedVersion)
46+
{
47+
using (TestHostContext hc = CreateTestContext())
48+
{
49+
// Arrange.
50+
var hf = new HandlerFactory();
51+
hf.Initialize(hc);
52+
53+
// Server Feature Flag
54+
var variables = new Dictionary<string, VariableValue>();
55+
if (!string.IsNullOrEmpty(serverFeatureFlag))
56+
{
57+
variables["DistributedTask.ForceGithubJavascriptActionsToNode16"] = serverFeatureFlag;
58+
}
59+
Variables serverVariables = new Variables(hc, variables);
60+
61+
// Workflow opt-out
62+
var workflowVariables = new Dictionary<string, string>();
63+
if (!string.IsNullOrEmpty(workflowOptOut))
64+
{
65+
workflowVariables[Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion] = workflowOptOut;
66+
}
67+
68+
// Machine opt-out
69+
if (!string.IsNullOrEmpty(machineOptOut))
70+
{
71+
Environment.SetEnvironmentVariable(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion, machineOptOut);
72+
}
73+
74+
_ec.Setup(x => x.Global).Returns(new GlobalContext()
75+
{
76+
Variables = serverVariables,
77+
EnvironmentVariables = workflowVariables
78+
});
79+
80+
81+
// Act.
82+
var data = new NodeJSActionExecutionData();
83+
data.NodeVersion = inputVersion;
84+
var handler = hf.Create(
85+
_ec.Object,
86+
new ScriptReference(),
87+
new Mock<IStepHost>().Object,
88+
data,
89+
new Dictionary<string, string>(),
90+
new Dictionary<string, string>(),
91+
new Variables(hc, new Dictionary<string, VariableValue>()), "", new List<JobExtensionRunner>()
92+
) as INodeScriptActionHandler;
93+
94+
// Assert.
95+
Assert.Equal(expectedVersion, handler.Data.NodeVersion);
96+
Environment.SetEnvironmentVariable(Constants.Variables.Actions.AllowActionsUseUnsecureNodeVersion, null);
97+
}
98+
}
99+
}
100+
}

0 commit comments

Comments
 (0)