Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add node20 to runner #2732

Merged
merged 27 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Misc/contentHash/externals/linux-arm
Original file line number Diff line number Diff line change
@@ -1 +1 @@
209a3b07522d883b745945ec8b1bfa57c0bce769573c3e79206b62959686c0d3
5bdddd32bab1e57af252b470579083049496e9e39b6e4f50de01232581f9a2d8
2 changes: 1 addition & 1 deletion src/Misc/contentHash/externals/linux-arm64
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1dd7654995ab54ce0d06519ad84c25029f0924f8313f0f5b7811c3631982a5e5
54b3b3a72da93db0fa38708c759fceadddb70cacdd3620a079084a242126dd78
2 changes: 1 addition & 1 deletion src/Misc/contentHash/externals/linux-x64
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9a06b2be3c18a06d2e676774d8b6d2869854f23f982433e9346bc7bdcb08f362
e7f2da271abb174285c3a757503538b3e9792e9d731b0382b6d1f21bb59a79ba
2 changes: 1 addition & 1 deletion src/Misc/contentHash/externals/osx-arm64
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4eb04e10e173b1f5d7cf8890878a3e178de162e5bf1a583067cf704b8162631a
2481c5b0d06b2b5621635f2568b86a43b0e5b259fed1298167ba4f33d4c464c7
2 changes: 1 addition & 1 deletion src/Misc/contentHash/externals/osx-x64
Original file line number Diff line number Diff line change
@@ -1 +1 @@
fc5efd1df9c75f01d7b6a43018ba49257bdc0d65e743ddd1ae753802a5ddb736
85de7677165e65ec69b8a9e344c0811efa51b7fe5376a1aa083505c560ea6f57
2 changes: 1 addition & 1 deletion src/Misc/contentHash/externals/win-arm64
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0064acac3fba3bd29851334c90f53adc13f88f2d23f5909f3bbec2b1c4ade9ef
763d18de11c11fd299c0e75e98fefc8a0e6605ae0ad6aba3bbc110db2262ab41
2 changes: 1 addition & 1 deletion src/Misc/contentHash/externals/win-x64
Original file line number Diff line number Diff line change
@@ -1 +1 @@
e2fa2229ed5bc8857acdd264c2f3964454fd710c776efdfb5dc0b40b7a75065a
16f3cc545dfe10e84df43746073fc64d3c44d1891782532805aeb2118869a55d
11 changes: 11 additions & 0 deletions src/Misc/externals.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ PRECACHE=$2
NODE_URL=https://nodejs.org/dist
UNOFFICIAL_NODE_URL=https://unofficial-builds.nodejs.org/download/release
NODE16_VERSION="16.20.1"
NODE20_VERSION="20.5.0"
# used only for win-arm64, remove node16 unofficial version when official version is available
NODE16_UNOFFICIAL_VERSION="16.20.0"

Expand Down Expand Up @@ -140,6 +141,8 @@ function acquireExternalTool() {
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
if [[ "$PRECACHE" != "" ]]; then
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
fi
Expand All @@ -150,6 +153,8 @@ if [[ "$PACKAGERUNTIME" == "win-arm64" ]]; then
# todo: replace these with official release when available
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin
acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_UNOFFICIAL_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
if [[ "$PRECACHE" != "" ]]; then
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
fi
Expand All @@ -158,23 +163,29 @@ fi
# Download the external tools only for OSX.
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-darwin-x64.tar.gz" node16 fix_nested_dir
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-darwin-x64.tar.gz" node20 fix_nested_dir

Choose a reason for hiding this comment

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

Mio

Choose a reason for hiding this comment

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

Vgf

fi

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

Choose a reason for hiding this comment

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

Pa

fi

# Download the external tools for Linux PACKAGERUNTIMEs.
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-x64.tar.gz" node16 fix_nested_dir
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE16_VERSION}/alpine/x64/node-v${NODE16_VERSION}-alpine-x64.tar.gz" node16_alpine
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-x64.tar.gz" node20 fix_nested_dir
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE20_VERSION}/alpine/x64/node-v${NODE20_VERSION}-alpine-x64.tar.gz" node20_alpine
fi

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

if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
acquireExternalTool "$NODE_URL/v${NODE16_VERSION}/node-v${NODE16_VERSION}-linux-armv7l.tar.gz" node16 fix_nested_dir
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-armv7l.tar.gz" node20 fix_nested_dir
fi
3 changes: 1 addition & 2 deletions src/Runner.Common/Util/NodeUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ namespace GitHub.Runner.Common.Util
public static class NodeUtil
{
private const string _defaultNodeVersion = "node16";
public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16" });

public static readonly ReadOnlyCollection<string> BuiltInNodeVersions = new(new[] { "node16", "node20" });
public static string GetInternalNodeVersion()
{
var forcedInternalNodeVersion = Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedInternalNodeVersion);
Expand Down
7 changes: 4 additions & 3 deletions src/Runner.Worker/ActionManifestManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,8 @@ private ActionExecutionData ConvertRuns(
}
}
else if (string.Equals(usingToken.Value, "node12", StringComparison.OrdinalIgnoreCase) ||
string.Equals(usingToken.Value, "node16", StringComparison.OrdinalIgnoreCase))
string.Equals(usingToken.Value, "node16", StringComparison.OrdinalIgnoreCase) ||
string.Equals(usingToken.Value, "node20", StringComparison.OrdinalIgnoreCase))
{
if (string.IsNullOrEmpty(mainToken?.Value))
{
Expand Down Expand Up @@ -489,7 +490,7 @@ private ActionExecutionData ConvertRuns(
}
else
{
throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker', 'node12' or 'node16' instead.");
throw new ArgumentOutOfRangeException($"'using: {usingToken.Value}' is not supported, use 'docker', 'node12', 'node16' or 'node20' instead.");
}
}
else if (pluginToken != null)
Expand All @@ -500,7 +501,7 @@ private ActionExecutionData ConvertRuns(
};
}

throw new NotSupportedException("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12' or 'node16'.");
throw new NotSupportedException("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12', 'node16' or 'node20'.");
}

private void ConvertInputs(
Expand Down
2 changes: 1 addition & 1 deletion src/Runner.Worker/Handlers/HandlerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public IHandler Create(
warningActions = StringUtil.ConvertFromJson<HashSet<string>>(node16ForceWarnings);
}

var repoActionFullName = "";
string repoActionFullName;
if (string.IsNullOrEmpty(repoAction.Name))
{
repoActionFullName = repoAction.Path; // local actions don't have a 'Name'
Expand Down
2 changes: 1 addition & 1 deletion src/Runner.Worker/Handlers/NodeScriptActionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ public async Task RunAsync(ActionRunStage stage)
ExecutionContext.Output($"The node12 is not supported. Use node16 instead.");
Data.NodeVersion = "node16";
}
string forcedNodeVersion = System.Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedActionsNodeVersion);

string forcedNodeVersion = System.Environment.GetEnvironmentVariable(Constants.Variables.Agent.ForcedActionsNodeVersion);
if (forcedNodeVersion == "node16" && Data.NodeVersion != "node16")
{
Data.NodeVersion = "node16";
Expand Down
68 changes: 68 additions & 0 deletions src/Test/L0/Worker/ActionManagerL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,74 @@ public void LoadsNode16ActionDefinition()
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void LoadsNode20ActionDefinition()
{
try
{
// Arrange.
Setup();
const string Content = @"
# Container action
name: 'Hello World'
description: 'Greet the world and record the time'
author: 'GitHub'
inputs:
greeting: # id of input
description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout'
required: true
default: 'Hello'
entryPoint: # id of input
description: 'optional docker entrypoint overwrite.'
required: false
outputs:
time: # id of output
description: 'The time we did the greeting'
icon: 'hello.svg' # vector art to display in the GitHub Marketplace
color: 'green' # optional, decorates the entry in the GitHub Marketplace
runs:
using: 'node20'
main: 'task.js'
";
Pipelines.ActionStep instance;
string directory;
CreateAction(yamlContent: Content, instance: out instance, directory: out directory);

// Act.
Definition definition = _actionManager.LoadAction(_ec.Object, instance);

// Assert.
Assert.NotNull(definition);
Assert.Equal(directory, definition.Directory);
Assert.NotNull(definition.Data);
Assert.NotNull(definition.Data.Inputs); // inputs
Dictionary<string, string> inputDefaults = new(StringComparer.OrdinalIgnoreCase);
foreach (var input in definition.Data.Inputs)
{
var name = input.Key.AssertString("key").Value;
var value = input.Value.AssertScalar("value").ToString();

_hc.GetTrace().Info($"Default: {name} = {value}");
inputDefaults[name] = value;
}

Assert.Equal(2, inputDefaults.Count);
Assert.True(inputDefaults.ContainsKey("greeting"));
Assert.Equal("Hello", inputDefaults["greeting"]);
Assert.True(string.IsNullOrEmpty(inputDefaults["entryPoint"]));
Assert.NotNull(definition.Data.Execution); // execution

Assert.NotNull(definition.Data.Execution as NodeJSActionExecutionData);
Assert.Equal("task.js", (definition.Data.Execution as NodeJSActionExecutionData).Script);
Assert.Equal("node20", (definition.Data.Execution as NodeJSActionExecutionData).NodeVersion);
}
finally
{
Teardown();
}
}
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
Expand Down
45 changes: 44 additions & 1 deletion src/Test/L0/Worker/ActionManifestManagerL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,49 @@ public void Load_Node16Action()
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void Load_Node20Action()
{
try
{
//Arrange
Setup();

var actionManifest = new ActionManifestManager();
actionManifest.Initialize(_hc);

//Act
var result = actionManifest.Load(_ec.Object, Path.Combine(TestUtil.GetTestDataPath(), "node20action.yml"));

//Assert
Assert.Equal("Hello World", result.Name);
Assert.Equal("Greet the world and record the time", result.Description);
Assert.Equal(2, result.Inputs.Count);
Assert.Equal("greeting", result.Inputs[0].Key.AssertString("key").Value);
Assert.Equal("Hello", result.Inputs[0].Value.AssertString("value").Value);
Assert.Equal("entryPoint", result.Inputs[1].Key.AssertString("key").Value);
Assert.Equal("", result.Inputs[1].Value.AssertString("value").Value);
Assert.Equal(1, result.Deprecated.Count);

Assert.True(result.Deprecated.ContainsKey("greeting"));
result.Deprecated.TryGetValue("greeting", out string value);
Assert.Equal("This property has been deprecated", value);

Assert.Equal(ActionExecutionType.NodeJS, result.Execution.ExecutionType);

var nodeAction = result.Execution as NodeJSActionExecutionData;

Assert.Equal("main.js", nodeAction.Script);
Assert.Equal("node20", nodeAction.NodeVersion);
}
finally
{
Teardown();
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
Expand Down Expand Up @@ -715,7 +758,7 @@ public void Load_CompositeActionNoUsing()
//Assert
var err = Assert.Throws<ArgumentException>(() => actionManifest.Load(_ec.Object, action_path));
Assert.Contains($"Fail to load {action_path}", err.Message);
_ec.Verify(x => x.AddIssue(It.Is<Issue>(s => s.Message.Contains("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12' or 'node16'.")), It.IsAny<ExecutionContextLogOptions>()), Times.Once);
_ec.Verify(x => x.AddIssue(It.Is<Issue>(s => s.Message.Contains("Missing 'using' value. 'using' requires 'composite', 'docker', 'node12', 'node16' or 'node20'.")), It.IsAny<ExecutionContextLogOptions>()), Times.Once);
}
finally
{
Expand Down
1 change: 1 addition & 0 deletions src/Test/L0/Worker/HandlerFactoryL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ private TestHostContext CreateTestContext([CallerMemberName] string testName = "
[Trait("Category", "Worker")]
[InlineData("node12", "node16")]
[InlineData("node16", "node16")]
[InlineData("node20", "node20")]
public void IsNodeVersionUpgraded(string inputVersion, string expectedVersion)
{
using (TestHostContext hc = CreateTestContext())
Expand Down
54 changes: 54 additions & 0 deletions src/Test/L0/Worker/StepHostL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,33 @@ public async Task DetermineNodeRuntimeVersionInAlpineContainerAsync()
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public async Task DetermineNode20RuntimeVersionInAlpineContainerAsync()
{
using (TestHostContext hc = CreateTestContext())
{
// Arrange.
var sh = new ContainerStepHost();
sh.Initialize(hc);
sh.Container = new ContainerInfo() { ContainerId = "1234abcd" };

_dc.Setup(d => d.DockerExec(_ec.Object, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<List<string>>()))
.Callback((IExecutionContext ec, string id, string options, string command, List<string> output) =>
{
output.Add("alpine");
})
.ReturnsAsync(0);

// Act.
var nodeVersion = await sh.DetermineNodeRuntimeVersion(_ec.Object, "node20");

// Assert.
Assert.Equal("node20_alpine", nodeVersion);
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
Expand All @@ -108,6 +135,33 @@ public async Task DetermineNodeRuntimeVersionInUnknowContainerAsync()
Assert.Equal("node16", nodeVersion);
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public async Task DetermineNode20RuntimeVersionInUnknowContainerAsync()
{
using (TestHostContext hc = CreateTestContext())
{
// Arrange.
var sh = new ContainerStepHost();
sh.Initialize(hc);
sh.Container = new ContainerInfo() { ContainerId = "1234abcd" };

_dc.Setup(d => d.DockerExec(_ec.Object, It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<List<string>>()))
.Callback((IExecutionContext ec, string id, string options, string command, List<string> output) =>
{
output.Add("github");
})
.ReturnsAsync(0);

// Act.
var nodeVersion = await sh.DetermineNodeRuntimeVersion(_ec.Object, "node20");

// Assert.
Assert.Equal("node20", nodeVersion);
}
}
#endif
}
}
20 changes: 20 additions & 0 deletions src/Test/TestData/node20action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: 'Hello World'
description: 'Greet the world and record the time'
author: 'Test Corporation'
inputs:
greeting: # id of input
description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout'
required: true
default: 'Hello'
deprecationMessage: 'This property has been deprecated'
entryPoint: # id of input
description: 'optional docker entrypoint overwrite.'
required: false
outputs:
time: # id of output
description: 'The time we did the greeting'
icon: 'hello.svg' # vector art to display in the GitHub Marketplace
color: 'green' # optional, decorates the entry in the GitHub Marketplace
runs:
using: 'node20'
main: 'main.js'