Azure-pipelines-agent: Offer way to write tasks that depend on Node 10 LTS

Created on 27 Sep 2018  路  16Comments  路  Source: microsoft/azure-pipelines-agent

Why latest agent versions (I checked Windows version) still come bundled with such an ancient Node.js version (v6.10)?
Node v10.x is already out, this is a huge gap. Any chance for update?

Core enhancement no-stale

Most helpful comment

Each task has a "handler" in the agent which is defined in the execution section of the task.json. It's basically a plug-in in the agent that knows how to run that handler. The agent knows how to run "node" which equates to node6 and ps3 which equates to powershell3. In hindsight the handler should have been called node6.

A better sequence would be the npm task:

  1. The worker runs the npm task by looking in the task.json, see node handler
  2. The node handler runs agents node.exe (6) against the tasks js script
  3. The task script will which npm in the PATH and that will use node in the PATH. Let's say node 8 or 10.

So the internal node is nothing but a way to run the task script - it's an internal script interpreter. The user steps (npm / node) that's part of the users build steps use what's installed on the machine. Our hosted images for example have node 8 and npm 5 (LTS)

Since node 10 is becoming LTS we do have plans to add a node10 execution handler. That will allow task authors to write tasks, depend on node 10 and publish it to the market place.

that introduces one more problem - an older agent that only carries node 6 won't be able to run your task. The solution to that is demand a minimum agent version in the task.json (see our tasks). the agent will pull itself forward to the minimum needed. So that means if you want to depend on node10, you will need to add minimumagent version. We'll have a table. Confusing - yes, I know. I'm looking for another solution where simply using node10 will implicitly demand the minimum.

The agent carries the node script runner because we have disconnected internet scenarios and the agent has to work. That's different than the user explicitly adding the node installer task which clearly needs internet (it's explicit).

I hope all that makes sense. I will write it up when we support node10 (soon).

So the short answer to your question is yes, soon. But the distinction is important :)

All 16 comments

What problem are you having? The node tasks (npm etc...) and running npm uses the one in the path on the image and not this one. Run node --version on the hosted vs2017 image or your agent. What do you get?

From what I see, when developing VSS task extensions (using https://github.com/Microsoft/vsts-task-lib) these are being executed using the old Node.js. It significantly limits the range of third party packages that can be used as many packages on npm require new language features (e.g. async code).

@vgalka-sl our built-in task already use async code with the version of node we packaged. (v6.10)
https://github.com/Microsoft/vsts-tasks/blob/master/Tasks/ANTV1/anttask.ts#L88

for reference, { "engines" : { "node" : ">=0.10.3 <0.12" } } in npm package.json

@vgalka-sl our built-in task already use async code with the version of node we packaged. (v6.10)
https://github.com/Microsoft/vsts-tasks/blob/master/Tasks/ANTV1/anttask.ts#L88

@TingluoHuang it's TypeScript code, which is transpiled to JavaScript with no async code since you have "target": "ES6" in tsconfig.json. But when you use third-party npm packages you can't control how they transpile their code.

I too am seeing this issue come up. The private agents come with node 6.10.3.0 still. Despite using Note Tool Installer to demand v9.x, the root of my build starts with the node 6.10.3.

Is there no way to update the node.exe and node.lib files supplied to private agents?

the root of my build starts with the node 6.10.3

Your build should never run with the node internal to the agent. For example, the npm task uses what's in the path. If you can clarify what "my build" means in this case then that may help.

Task scripts should always run with the node version carried by the agent and that is never added to the path.

Market place tasks are released and tested with the execution handler of "node" equating to node 6 and that will never change so market place extensions are consistent. We will add a node10 handler and you can write tasks with the expectation of being run with node10. But once again, that is never the users build.

I think what you're saying holds true. Let me see if my understanding is correct so I can try to clarify:

For Agent X, AgentService spawns Agent.Listener
-> the build is kicked off using node.js
-> which spawns Agent.Worker
-> which spawns the node.exe versioned 6.10.3.0 from the node.exe included with the latest vsts agent (sourced from downloading on my vsts repo)
-> which spawns a command prompt to execute vsts steps
-> which spawns a node.exe versioned 9.x to run any npm step (npm install in this case)

Market place tasks are released and tested with the execution handler of "node" equating to node 6 and that will never change so market place extensions are consistent. We will add a node10 handler and you can write tasks with the expectation of being run with node10. But once again, that is never the users build.

With that in mind, can you confirm that as of VSTS Agent Version 2.140.*+, we should still expect the packaged node.exe to be versioned 6.10.3.0?

Each task has a "handler" in the agent which is defined in the execution section of the task.json. It's basically a plug-in in the agent that knows how to run that handler. The agent knows how to run "node" which equates to node6 and ps3 which equates to powershell3. In hindsight the handler should have been called node6.

A better sequence would be the npm task:

  1. The worker runs the npm task by looking in the task.json, see node handler
  2. The node handler runs agents node.exe (6) against the tasks js script
  3. The task script will which npm in the PATH and that will use node in the PATH. Let's say node 8 or 10.

So the internal node is nothing but a way to run the task script - it's an internal script interpreter. The user steps (npm / node) that's part of the users build steps use what's installed on the machine. Our hosted images for example have node 8 and npm 5 (LTS)

Since node 10 is becoming LTS we do have plans to add a node10 execution handler. That will allow task authors to write tasks, depend on node 10 and publish it to the market place.

that introduces one more problem - an older agent that only carries node 6 won't be able to run your task. The solution to that is demand a minimum agent version in the task.json (see our tasks). the agent will pull itself forward to the minimum needed. So that means if you want to depend on node10, you will need to add minimumagent version. We'll have a table. Confusing - yes, I know. I'm looking for another solution where simply using node10 will implicitly demand the minimum.

The agent carries the node script runner because we have disconnected internet scenarios and the agent has to work. That's different than the user explicitly adding the node installer task which clearly needs internet (it's explicit).

I hope all that makes sense. I will write it up when we support node10 (soon).

So the short answer to your question is yes, soon. But the distinction is important :)

I'm going to morph this issue into what we are going to do :)

@bryanmacfarlane is this done now? As this appears to be in 2.144?
https://github.com/Microsoft/azure-pipelines-agent/commit/6adebd8df2392147658096cb94c1a8526a5bbe48

Yes but we鈥檙e working on docs / short answer is use node10 handler with minagentversion of 2.144

It's not entirely clear to me from this thread if it is possible for a task author to create the task with code that requires something higher than Node 6.x. We've tried the steps outlined above, but even with our pipelines executing these custom tasks on Agents that are v2.153.2, agents that have Node 10.x available, etc., the custom tasks still seem to be running in a Node 6.x context.

This is rather frustrating, especially considering that Node 6.x has been end-of-life for a few months now. A lot of npm packages/libs unsurprsingly require Node 8.x or higher, which functionally makes them unusable for custom task authors.

Is it possible for task authors to demand a node10 (or anything newer than node6) handler to execute their task?

In addition to @calebcartwright comment, changing the execution configuration within task.json to Node10 did not change the symptom.

Please see https://github.com/microsoft/azure-pipelines-task-lib/blob/master/tasks.schema.json#L267

The symptom:
Error thrown - ##[error]Unhandled: Unexpected token function

Another problem is that the NuGet download task does not work when behind a corporate proxy, since Node.js 6 does not pick up the system certs. And the NuGet download task runs with the old node 6. And there seems to be no way of telling node 6 about the system certs via a cert file, either. Which leaves us with hacks such as disabling SSL/TSL altogether.

If someone knows about a better workaround, please let us know.

The Node10 handler shipped a while ago; sorry that we didn't get this issue resolved. You can use:

"execution": {
    "Node10": {
        "target": "myentrypoint.js"
    }
}

Also, we will magically take care of the minAgentVersion requirement for you.

Was this page helpful?
0 / 5 - 0 ratings