Skip to content

Commit

Permalink
Add node 20 support to task-lib for testing and pick highest node ver…
Browse files Browse the repository at this point in the history
…sion for tests (#1039)

* Add node 20 support to task-lib for testing and pick highest node version for tests

- Added node 20 support
- Changed the logic to pick highest handler instead of first one
- Added tests for node20
- Changed tests for node6, node10, node16 to use highest handler

* rename fake node20 task

* Add node 20 support to task-lib for testing and pick highest node version for tests

- Bumped node version

* Add node 20 support to task-lib for testing and pick highest node version for tests

- Fix test for node20

* Add node 20 support to task-lib for testing and pick highest node version for tests

- code review feedback
  • Loading branch information
DmitriiBobreshev committed May 27, 2024
1 parent 79bc298 commit 7c0de0d
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 35 deletions.
57 changes: 24 additions & 33 deletions node/mock-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,21 +165,17 @@ export class MockTestRunner {
// Returns a path to node.exe with the correct version for this task (based on if its node10 or node)
private async getNodePath(nodeVersion?: number): Promise<string> {
const version: number = nodeVersion || this.getNodeVersion();

let downloadVersion: string;
switch (version) {
case 6:
downloadVersion = 'v6.17.1';
break;
case 10:
downloadVersion = 'v10.21.0';
break;
case 16:
downloadVersion = 'v16.13.0';
break;
default:
throw new Error('Invalid node version, must be 6, 10, or 16 (received ' + version + ')');
}
const versions = {
20: 'v20.13.1',
16: 'v16.20.2',
10: 'v10.24.1',
6: 'v6.17.1',
};

const downloadVersion: string = versions[version];
if (!downloadVersion) {
throw new Error('Invalid node version, must be 6, 10, 16 or 20 (received ' + version + ')');
}

// Install node in home directory if it isn't already there.
const downloadDestination: string = path.join(downloadDirectory, 'node' + version);
Expand All @@ -203,31 +199,26 @@ export class MockTestRunner {
const taskJsonContents = fs.readFileSync(taskJsonPath, { encoding: 'utf-8' });
const taskJson: object = JSON.parse(taskJsonContents);

let nodeVersionFound = false;
const execution: object = (
taskJson['execution']
|| taskJson['prejobexecution']
|| taskJson['postjobexecution']
);
const keys = Object.keys(execution);
for (let i = 0; i < keys.length; i++) {
if (keys[i].toLowerCase() == 'node16') {
// Prefer node 16 and return immediately.
return 16;
} else if (keys[i].toLowerCase() == 'node10') {
// Prefer node 10 and return immediately.
return 10;
} else if (keys[i].toLowerCase() == 'node') {
nodeVersionFound = true;
let nodeVersion = 0;
const executors = ['execution', 'prejobexecution', 'postjobexecution'];
for (const executor of executors) {
if (!taskJson[executor]) continue;

for (const key of Object.keys(taskJson[executor])) {
const currExecutor = key.toLocaleLowerCase();
if (!currExecutor.startsWith('node')) continue;
const version = currExecutor.replace('node', '');
const intVersion = parseInt(version) || 6; // node handler is node v6 by default
nodeVersion = Math.max(intVersion, nodeVersion);
}
}

if (!nodeVersionFound) {
if (nodeVersion === 0) {
console.warn('Unable to determine execution type from task.json, defaulting to use Node 16');
return 16;
}

return 6;
return nodeVersion;
}

// Returns the path to the task.json for the task being tested. Returns null if unable to find it.
Expand Down
2 changes: 1 addition & 1 deletion node/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "azure-pipelines-task-lib",
"version": "4.12.1",
"version": "4.13.0",
"description": "Azure Pipelines Task SDK",
"main": "./task.js",
"typings": "./task.d.ts",
Expand Down
3 changes: 3 additions & 0 deletions node/test/fakeTasks/node10task/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"id": "id",
"name": "Node10Task",
"execution": {
"Node": {
"target": "usedotnet.js"
},
"Node10": {
"target": "usedotnet.js"
}
Expand Down
6 changes: 6 additions & 0 deletions node/test/fakeTasks/node16task/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
"id": "id",
"name": "Node16Task",
"execution": {
"Node": {
"target": "usedotnet.js"
},
"Node10": {
"target": "usedotnet.js"
},
"Node16": {
"target": "usedotnet.js"
}
Expand Down
18 changes: 18 additions & 0 deletions node/test/fakeTasks/node20task/task.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"id": "id",
"name": "Node20Task",
"execution": {
"Node": {
"target": "usedotnet.js"
},
"Node10": {
"target": "usedotnet.js"
},
"Node16": {
"target": "usedotnet.js"
},
"Node20": {
"target": "usedotnet.js"
}
}
}
10 changes: 10 additions & 0 deletions node/test/mocktests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,16 @@ describe('Mock Tests', function () {
await Promise.resolve()
})

it('MockTest handles node 20 tasks correctly', async function () {
this.timeout(30000);
const runner = await (new mtm.MockTestRunner).LoadAsync(path.join(__dirname, 'fakeTasks', 'node20task', 'entry.js'));
const nodePath = runner.nodePath;
assert(nodePath, 'node path should have been correctly set');
const version = ncp.execSync(nodePath + ' -v').toString().trim();
assert(semver.satisfies(version, '20.x'), 'Downloaded node version should be Node 20 instead of ' + version);
await Promise.resolve()
})

it('MockTest handles node tasks correctly by async call', async () => {
this.timeout(30000);
const runner = await (new mtm.MockTestRunner).LoadAsync(path.join(__dirname, 'fakeTasks', 'node16task', 'entry.js'));
Expand Down

0 comments on commit 7c0de0d

Please sign in to comment.