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 agent support for the Node v10 runtime #1972

Merged
merged 5 commits into from
Nov 28, 2018
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
6 changes: 6 additions & 0 deletions src/Agent.Worker/Handlers/HandlerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public IHandler Create(
handler = HostContext.CreateService<INodeHandler>();
(handler as INodeHandler).Data = data as NodeHandlerData;
}
else if (data is Node10HandlerData)
{
// Node10.
handler = HostContext.CreateService<INodeHandler>();
(handler as INodeHandler).Data = data as Node10HandlerData;
}
else if (data is PowerShell3HandlerData)
{
// PowerShell3.
Expand Down
15 changes: 12 additions & 3 deletions src/Agent.Worker/Handlers/NodeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ namespace Microsoft.VisualStudio.Services.Agent.Worker.Handlers
[ServiceLocator(Default = typeof(NodeHandler))]
public interface INodeHandler : IHandler
{
NodeHandlerData Data { get; set; }
// Data can be of these two types: NodeHandlerData, and Node10HandlerData
BaseNodeHandlerData Data { get; set; }
}

public sealed class NodeHandler : Handler, INodeHandler
Expand All @@ -38,7 +39,7 @@ public sealed class NodeHandler : Handler, INodeHandler
"};"
};

public NodeHandlerData Data { get; set; }
public BaseNodeHandlerData Data { get; set; }

public async Task RunAsync()
{
Expand Down Expand Up @@ -107,8 +108,16 @@ public async Task RunAsync()
}
else
{
file = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), "node", "bin", $"node{IOUtil.ExeExtension}");
bool useNode10 = ExecutionContext.Variables.GetBoolean("AGENT_USE_NODE10") ??
StringUtil.ConvertToBoolean(System.Environment.GetEnvironmentVariable("AGENT_USE_NODE10"), false);
bool taskHasNode10Data = Data is Node10HandlerData;
string nodeFolder = (taskHasNode10Data || useNode10) ? "node10" : "node";

Trace.Info($"Task.json has node10 handler data: {taskHasNode10Data}, use node10 for node tasks: {useNode10}");

file = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Externals), nodeFolder, "bin", $"node{IOUtil.ExeExtension}");
}

// Format the arguments passed to node.
// 1) Wrap the script file path in double quotes.
// 2) Escape double quotes within the script file path. Double-quote is a valid
Expand Down
35 changes: 29 additions & 6 deletions src/Agent.Worker/TaskManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ public sealed class ExecutionData
private readonly List<HandlerData> _all = new List<HandlerData>();
private AzurePowerShellHandlerData _azurePowerShell;
private NodeHandlerData _node;
private Node10HandlerData _node10;
juliobbv marked this conversation as resolved.
Show resolved Hide resolved
private PowerShellHandlerData _powerShell;
private PowerShell3HandlerData _powerShell3;
private PowerShellExeHandlerData _powerShellExe;
Expand Down Expand Up @@ -313,6 +314,20 @@ public NodeHandlerData Node
}
}

public Node10HandlerData Node10
{
get
{
return _node10;
}

set
{
_node10 = value;
Add(value);
}
}

#if !OS_WINDOWS || X86
[JsonIgnore]
#endif
Expand Down Expand Up @@ -465,10 +480,8 @@ protected void SetInput(string name, string value)
}
}

public sealed class NodeHandlerData : HandlerData
public abstract class BaseNodeHandlerData : HandlerData
juliobbv marked this conversation as resolved.
Show resolved Hide resolved
{
public override int Priority => 1;

public string WorkingDirectory
{
get
Expand All @@ -483,11 +496,21 @@ public string WorkingDirectory
}
}

public sealed class PowerShell3HandlerData : HandlerData
public sealed class NodeHandlerData : BaseNodeHandlerData
{
public override int Priority => 2;
}

public sealed class Node10HandlerData : BaseNodeHandlerData
{
public override int Priority => 1;
juliobbv marked this conversation as resolved.
Show resolved Hide resolved
}

public sealed class PowerShell3HandlerData : HandlerData
{
public override int Priority => 3;
}

public sealed class PowerShellHandlerData : HandlerData
{
public string ArgumentFormat
Expand All @@ -503,7 +526,7 @@ public string ArgumentFormat
}
}

public override int Priority => 3;
public override int Priority => 4;

public string WorkingDirectory
{
Expand Down Expand Up @@ -534,7 +557,7 @@ public string ArgumentFormat
}
}

public override int Priority => 4;
public override int Priority => 5;

public string WorkingDirectory
{
Expand Down
4 changes: 2 additions & 2 deletions src/Agent.Worker/TaskRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ public async Task RunAsync()
runtimeVariables = new Variables(HostContext, variableCopy, out expansionWarnings);
expansionWarnings?.ForEach(x => ExecutionContext.Warning(x));
}
else if (handlerData is NodeHandlerData || handlerData is PowerShell3HandlerData)
else if (handlerData is NodeHandlerData || handlerData is Node10HandlerData || handlerData is PowerShell3HandlerData)
{
// Only node handler and powershell3 handler support running inside container.
// Only the node, node10, and powershell3 handlers support running inside container.
// Make sure required container is already created.
ArgUtil.NotNullOrEmpty(ExecutionContext.Container.ContainerId, nameof(ExecutionContext.Container.ContainerId));
var containerStepHost = HostContext.CreateService<IContainerStepHost>();
Expand Down
8 changes: 8 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
CONTAINER_URL=https://vstsagenttools.blob.core.windows.net/tools
NODE_URL=https://nodejs.org/dist
NODE_VERSION="6.10.3"
NODE10_VERSION="10.13.0"

get_abs_path() {
# exploits the fact that pwd will print abs path when no args
Expand Down Expand Up @@ -137,6 +138,8 @@ if [[ "$PACKAGERUNTIME" == "win-x64" ]]; then
acquireExternalTool "$CONTAINER_URL/vswhere/1_0_62/vswhere.zip" vswhere
acquireExternalTool "$NODE_URL/v${NODE_VERSION}/win-x64/node.exe" node/bin
acquireExternalTool "$NODE_URL/v${NODE_VERSION}/win-x64/node.lib" node/bin
acquireExternalTool "$NODE_URL/v${NODE10_VERSION}/win-x64/node.exe" node10/bin
acquireExternalTool "$NODE_URL/v${NODE10_VERSION}/win-x64/node.lib" node10/bin
acquireExternalTool "https://dist.nuget.org/win-x86-commandline/v3.3.0/nuget.exe" nuget
fi

Expand All @@ -148,12 +151,15 @@ if [[ "$PACKAGERUNTIME" == "win-x86" ]]; then
acquireExternalTool "$CONTAINER_URL/vswhere/1_0_62/vswhere.zip" vswhere
acquireExternalTool "$NODE_URL/v${NODE_VERSION}/win-x86/node.exe" node/bin
acquireExternalTool "$NODE_URL/v${NODE_VERSION}/win-x86/node.lib" node/bin
acquireExternalTool "$NODE_URL/v${NODE10_VERSION}/win-x86/node.exe" node10/bin
acquireExternalTool "$NODE_URL/v${NODE10_VERSION}/win-x86/node.lib" node10/bin
acquireExternalTool "https://dist.nuget.org/win-x86-commandline/v3.3.0/nuget.exe" nuget
fi

# Download the external tools only for OSX.
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
acquireExternalTool "$NODE_URL/v${NODE_VERSION}/node-v${NODE_VERSION}-darwin-x64.tar.gz" node fix_nested_dir
acquireExternalTool "$NODE_URL/v${NODE10_VERSION}/node-v${NODE10_VERSION}-darwin-x64.tar.gz" node10 fix_nested_dir
fi

# Download the external tools common across OSX and Linux PACKAGERUNTIMEs.
Expand All @@ -165,8 +171,10 @@ fi
# Download the external tools common across Linux PACKAGERUNTIMEs (excluding OSX).
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
acquireExternalTool "$NODE_URL/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz" node fix_nested_dir
acquireExternalTool "$NODE_URL/v${NODE10_VERSION}/node-v${NODE10_VERSION}-linux-x64.tar.gz" node10 fix_nested_dir
fi

if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
acquireExternalTool "$NODE_URL/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-armv7l.tar.gz" node fix_nested_dir
acquireExternalTool "$NODE_URL/v${NODE10_VERSION}/node-v${NODE10_VERSION}-linux-armv7l.tar.gz" node10 fix_nested_dir
fi
15 changes: 12 additions & 3 deletions src/Test/L0/ProcessInvokerL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,18 @@ public async Task TestCancel()
Assert.True(!execTask.IsFaulted);
Assert.True(execTask.IsCanceled);
watch.Stop();
var elapsedSeconds = watch.ElapsedMilliseconds / 1000;
//if cancellation fails, then execution time is more than 10 seconds
Assert.True(elapsedSeconds < SecondsToRun / 2, $"cancellation failed, because task took too long to run. {elapsedSeconds}");
long elapsedSeconds = watch.ElapsedMilliseconds / 1000;

#if ARM
// if cancellation fails, then execution time is more than 15 seconds
// longer time to compensate for a slower ARM environment (e.g. Raspberry Pi)
long expectedSeconds = (SecondsToRun * 3) / 4;
#else
// if cancellation fails, then execution time is more than 10 seconds
long expectedSeconds = SecondsToRun / 2;
#endif

Assert.True(elapsedSeconds <= expectedSeconds, $"cancellation failed, because task took too long to run. {elapsedSeconds}");
}
}
#endif
Expand Down
17 changes: 13 additions & 4 deletions src/Test/L0/Worker/TaskManagerL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,10 @@ public void LoadsDefinition()
""target"": ""Some Node target"",
""extraNodeArg"": ""Extra node arg value""
},
""Node10"": {
""target"": ""Some Node10 target"",
""extraNodeArg"": ""Extra node10 arg value""
},
""Process"": {
""target"": ""Some process target"",
""argumentFormat"": ""Some process argument format"",
Expand Down Expand Up @@ -432,21 +436,26 @@ public void LoadsDefinition()

#if OS_WINDOWS
// Process handler should only be deserialized on Windows.
Assert.Equal(2, definition.Data.Execution.All.Count);
Assert.Equal(3, definition.Data.Execution.All.Count);
#else
// Only Node handler should be deserialized on non-Windows.
Assert.Equal(1, definition.Data.Execution.All.Count);
// Only the Node and Node10 handlers should be deserialized on non-Windows.
Assert.Equal(2, definition.Data.Execution.All.Count);
#endif

// Node handler should always be deserialized.
Assert.NotNull(definition.Data.Execution.Node); // execution.Node
Assert.Equal(definition.Data.Execution.Node, definition.Data.Execution.All[0]);
Assert.Equal("Some Node target", definition.Data.Execution.Node.Target);

// Node10 handler should always be deserialized.
Assert.NotNull(definition.Data.Execution.Node10); // execution.Node10
Assert.Equal(definition.Data.Execution.Node10, definition.Data.Execution.All[1]);
Assert.Equal("Some Node10 target", definition.Data.Execution.Node10.Target);

#if OS_WINDOWS
// Process handler should only be deserialized on Windows.
Assert.NotNull(definition.Data.Execution.Process); // execution.Process
Assert.Equal(definition.Data.Execution.Process, definition.Data.Execution.All[1]);
Assert.Equal(definition.Data.Execution.Process, definition.Data.Execution.All[2]);
Assert.Equal("Some process argument format", definition.Data.Execution.Process.ArgumentFormat);
Assert.NotNull(definition.Data.Execution.Process.Platforms);
Assert.Equal(1, definition.Data.Execution.Process.Platforms.Length);
Expand Down