Support for Node.js 16 for Azure Pipelines custom pipelines task extensions has arrived. From a TypeScript perspective, this post documents how to migrate from a Node.js 10 custom task to one that runs on Node 16 using azure-pipelines-task-lib
.
The road to Node.js 16
Azure Pipelines custom pipelines task extensions have been around for a while. They're a great way to extend the functionality of Azure Pipelines. They're written in TypeScript and run on Node.js. You can learn how to write one here. However, until recently they were restricted to only be able to run on Node.js 6 or Node.js 10. This was a problem as support for Node 6 ended in 2018 and Node 10 ended in 2020.
A GitHub issue was opened to track support for different Node versions with custom tasks, but it remained unresolved for a long time. In October 2022 it was announced that Node.js 16 support was available.
Migrating a task to Node.js 16
There's an official migration guide to help you migrate your task from Node.js 6 or Node.js 10 to Node.js 16. It's available here. It gave me a couple of pointers but I wanted to document the process in a bit more detail. Also, I wanted to show how you can start to get some benefits from being on Node.js 16 with TypeScript.
The version of the azure-pipelines-task-lib
being used in the package.json
should be incremented to 4.0.0
or higher. If you haven't already, it's worth updating the @types/node
version to 16.0.0
or higher. This will give you access to the types of the Node 16 APIs.
The migration guide suggests updating the task.json
to have a Node16
property alongside the existing Node10
one:
"execution": {
"Node10": {
"target": "bash.js",
"argumentFormat": ""
},
+ "Node16": {
+ "target": "bash.js",
+ "argumentFormat": ""
+ }
}
I'm rather unclear as to the benefits of having a Node10
and a Node16
alongside each other; there's no useful reason to do so that I can come up with. I may be missing something.
Either way, in my own case I wanted to take advantage of the Node 16 environment and so I removed the Node10
property entirely. My task.json
now looks like this:
"execution": {
"Node16": {
"target": "index.js"
}
}
This was all I needed to do, to get to the point of having a Node 16 compatible task. But we want to go a little further.
Updating TypeScript to use Node 16
Now we have Node 16, we can now start using some of the APIs available there if we'd like, and we can stop transpiling to an older version of JavaScript. To do this we need to update our TypeScript configuration in our tsconfig.json
file:
- "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
- "lib": [] /* Specify library files to be included in the compilation. */,
+ "target": "es2021" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
+ "lib": ["ES2021"] /* Specify library files to be included in the compilation. */,
Here we're just changing the emitted JavaScript to be more modern. We're also updating the lib
property to include the ES2021
library. This will give us access to the types of the Node 16 APIs.
How do we know we're using Node 16?
Great question! I was suspicious that the task was still running on Node 10. I wanted to know for sure. I ran a migrated task with system diagnostics enabled:
As we can see, we're using Node 16. This is great news!
##[debug]Using node path: /home/vsts/agents/2.213.2/externals/node16/bin/node
Conclusion
That's it, we're now writing modern custom pipelines task extensions using Node.js 16 and TypeScript. Fingers crossed it won't be such a long wait for newer versions of Node.js to be supported! 🤞
Top comments (0)