It is easy to create an Open Source Project and leave it to gather technical debt as the libraries it depends upon are updated.

I have tried to keep on top of updating all my Azure DevOps Pipeline Extensions, and I have to say Dependabot has certainly helped, but I have not been as diligent as I might have been.

So, as a Christmas project, I took the chance to start to do a major update of all my extensions. To make sure they used the newer Node16 execution runner (as per the document update process) and to update all the NPM packages used.

Steps (Part1)

  • In each task.json file
    • Update the minimum runner version
    • Add the Node16 based runner (assuming the task is Node based as most of mine are, I do have one or two PowerShell based ones)
  • Update all the NPM packages. I used npm-check-updates to do this.
  • I then checked that task still built locally (the TypeScript linting and transpilation)
  • I then ran my mocha/chai based test locally, and this is where I hit problems.

Problems with Mocha and TypeScript

The error I got was in the form

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension “.ts” for D:\a\1\s\Extensions\WikiPDFExport\WikiPDFExportTask\test\foldercreation.test.ts

Seems this is a known issue. As suggested, I tried swapping from the "require": "ts-node/register" to "loader": "ts-node/esm" in the .mocharc.json file, this caused the error to changed to

mocha ./test/.test.ts (node:31412) ExperimentalWarning: Custom ESM Loaders is an experimental feature. This feature could change at any time (Use node --trace-warnings ... to show where the warning was created) Warning: Cannot find any files matching pattern “extensions/**/test/.ts”

TSError: ⨯ Unable to compile TypeScript: test/foldercreation.test.ts:12:23 - error TS2695: Left side of comma operator is unused and has no side effects. 12 var actual = (0, GitWikiFunctions_1.GetWorkingFolder)(".\", “testdata\subfolder\1\”, agentSpecific_1.logInfo);

I battled with this for a while, but in the end gave up and just set my test macro to do the transpile first and then running mocha against the .js files, as opposed to letting mocha do all the steps itself.

So, swapping from

"test-no-logger": "mocha -r ts-node/register ./test/*.test.ts "


"transpile": "tsc -p ./",
"test-no-logger": "npm run transpile && mocha ./dist/test/*.test.js "

I could now run my tests locally, but some were failing. This turned out to be due to using the older del NPM module. I swapped to fs-extra and all was good.

Steps (Part2)

When it all builds and tests locally you can continue

  • As this is a major change and to give people the choice as to whether to update, I updated the Major version and zero’d the Minor version numbers in the CI/CD pipeline that publishes the task (for my extensions I chose to manually manage the major versions, increment the minor version for each public release, and use the patch as build number)
  • Create PR and let the CI/CD pipeline deploy a private version of the extension to the Azure DevOps Marketplace
  • I can then increment the task version number in the pipeline YAML files so the new version is tested (you can’t set this until you have deployed the incremented extension to the marketplace as the YAML validation will fail)

And that should be it…


This all seems a lot of work, but is essential if my OSS extensions are to trustworthy and usable. I have a few more to do, but I am hoping to get them all done before the end of the year.