diff --git a/Tasks/NodeToolV0/Strings/resources.resjson/en-US/resources.resjson b/Tasks/NodeToolV0/Strings/resources.resjson/en-US/resources.resjson index af385bb523b1..fef772748fbb 100644 --- a/Tasks/NodeToolV0/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/NodeToolV0/Strings/resources.resjson/en-US/resources.resjson @@ -4,7 +4,7 @@ "loc.description": "Finds or downloads and caches the specified version spec of Node.js and adds it to the PATH", "loc.instanceNameFormat": "Use Node $(versionSpec)", "loc.input.label.versionSpec": "Version Spec", - "loc.input.help.versionSpec": "Version Spec of version to get. Examples: 6.x, 4.x, 6.10.0, >=6.10.0", + "loc.input.help.versionSpec": "Version Spec of version to get. Examples: 6.x, 4.x, 6.10.0, >=6.10.0. Also supports a path to a file. Examples: src/.nvmrc, .node-version", "loc.input.label.checkLatest": "Check for Latest Version", "loc.input.help.checkLatest": "Always checks online for the latest available version that satisfies the version spec. This is typically false unless you have a specific scenario to always get latest. This will cause it to incur download costs when potentially not necessary, especially with the hosted build pool.", "loc.input.label.force32bit": "Use 32 bit version on x64 agents", diff --git a/Tasks/NodeToolV0/Tests/L0.ts b/Tasks/NodeToolV0/Tests/L0.ts index 3eef5e2c10a4..22bb23185e45 100644 --- a/Tasks/NodeToolV0/Tests/L0.ts +++ b/Tasks/NodeToolV0/Tests/L0.ts @@ -73,4 +73,18 @@ describe('NodeTool Suite', function () { }, tr, done); }); + it('Reads node version from nvmrc', (done: Mocha.Done) => { + this.timeout(5000); + + let tp: string = path.join(__dirname, 'L0ReadsNvmrc.js'); + let tr: ttm.MockTestRunner = new ttm.MockTestRunner(tp); + + tr.run(); + + runValidations(() => { + assert(tr.succeeded, 'NodeTool should have succeeded.'); + assert(tr.stderr.length === 0, 'NodeTool should not have written to stderr'); + }, tr, done); + }); + }); \ No newline at end of file diff --git a/Tasks/NodeToolV0/Tests/L0ReadsNvmrc.ts b/Tasks/NodeToolV0/Tests/L0ReadsNvmrc.ts new file mode 100644 index 000000000000..d24eb9098419 --- /dev/null +++ b/Tasks/NodeToolV0/Tests/L0ReadsNvmrc.ts @@ -0,0 +1,100 @@ +import ma = require('azure-pipelines-task-lib/mock-answer'); +import tmrm = require('azure-pipelines-task-lib/mock-run'); +import os = require('os'); +import path = require('path'); +import semver = require('semver'); + +let taskPath = path.join(__dirname, '..', 'nodetool.js'); +let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); + +tmr.setInput('versionSpec', 'src/.nvmrc'); + +let a: ma.TaskLibAnswers = { + "assertAgent": { + "2.115.1": true + }, + "checkPath": { + ".nvmrc": true, + }, +}; +tmr.setAnswers(a); + + +//Create assertAgent and getVariable mocks +const tl = require('azure-pipelines-task-lib/mock-task'); +const tlClone = Object.assign({}, tl); +tlClone.getVariable = function (variable: string) { + if (variable.toLowerCase() == 'agent.tempdirectory') { + return 'temp'; + } + return null; +}; +tlClone.assertAgent = function (variable: string) { + return; +}; +tmr.registerMock('azure-pipelines-task-lib/mock-task', tlClone); + +tmr.registerMock('fs', { + readFileSync: function (path, options) { + if (path != 'src/.nvmrc') { + throw new Error(`reading wrong .nvmrc: '${[path]}'`); + } + + return '0.6.21'; + } +}); + +//Create tool-lib mock +tmr.registerMock('azure-pipelines-tool-lib/tool', { + isExplicitVersion: semver.valid, + findLocalTool: function (toolName, versionSpec) { + if (toolName != 'node') { + throw new Error('Searching for wrong tool'); + } + return false; + }, + evaluateVersions: function (versions, versionSpec) { + if (versionSpec !== 'v0.6.21') { + throw new Error(`Incorrect versionSpec: ${versionSpec}`); + } + return versionSpec; + }, + cleanVersion: semver.clean, + downloadTool(url) { + let err = new Error(); + err['httpStatusCode'] = '404'; + if (url === `https://nodejs.org/dist/v0.6.21/node-v0.6.21-win-${os.arch()}.7z` || + url === `https://nodejs.org/dist/v0.6.21/node-v0.6.21-${os.platform()}-${os.arch()}.tar.gz`) { + throw err; + } + else if (url === `https://nodejs.org/dist/v0.6.21/win-${os.arch()}/node.exe`) { + throw err; + } + else if (url === `https://nodejs.org/dist/v0.6.21/win-${os.arch()}/node.lib`) { + throw err; + } + else if (url === `https://nodejs.org/dist/v0.6.21/node.exe`) { + return 'exe_loc'; + } + else if (url === `https://nodejs.org/dist/v0.6.21/node.lib`) { + return 'exe_lib'; + } + else { + throw new Error(`Incorrect URL: ${url}`); + } + }, + extract7z(downloadPath, extPath, _7zPath) { + return 'extPath'; + }, + extractTar(downloadPath, extPath, _7zPath) { + return 'extPath'; + }, + cacheDir(dir, tool, version) { + return 'path to tool'; + }, + prependPath(toolPath) { + return; + } +}); + +tmr.run(); \ No newline at end of file diff --git a/Tasks/NodeToolV0/nodetool.ts b/Tasks/NodeToolV0/nodetool.ts index 09f84d0006c2..0c17fb7fc8c6 100644 --- a/Tasks/NodeToolV0/nodetool.ts +++ b/Tasks/NodeToolV0/nodetool.ts @@ -4,6 +4,7 @@ import * as restm from 'typed-rest-client/RestClient'; import * as telemetry from 'azure-pipelines-tasks-utility-common/telemetry'; import * as os from 'os'; import * as path from 'path'; +import * as fs from 'fs'; const force32bit: boolean = taskLib.getBoolInput('force32bit', false); let osPlat: string = os.platform(); @@ -11,7 +12,7 @@ let osArch: string = getArch(); async function run() { try { - let versionSpec = taskLib.getInput('versionSpec', true); + let versionSpec = getVersionSpec(); let checkLatest: boolean = taskLib.getBoolInput('checkLatest', false); await getNode(versionSpec, checkLatest); telemetry.emitTelemetry('TaskHub', 'NodeToolV0', { versionSpec, checkLatest, force32bit }); @@ -21,6 +22,20 @@ async function run() { } } +function getVersionSpec() { + const versionSpecInput = taskLib.getInput('versionSpec', true); + + const cleanVersion = toolLib.cleanVersion(versionSpecInput); + if (cleanVersion) { + taskLib.debug(`version spec '${cleanVersion}' from '${versionSpecInput}'`); + return versionSpecInput; + } + + const versionSpec = fs.readFileSync(versionSpecInput, { 'encoding': 'utf' }); + taskLib.debug(`Got node version spec '${versionSpec}' from file '${versionSpecInput}'`); + return versionSpec; +} + // // Node versions interface // see https://nodejs.org/dist/index.json diff --git a/Tasks/NodeToolV0/task.json b/Tasks/NodeToolV0/task.json index 286cf8c95049..ff795cdc7e4a 100644 --- a/Tasks/NodeToolV0/task.json +++ b/Tasks/NodeToolV0/task.json @@ -31,7 +31,7 @@ "label": "Version Spec", "defaultValue": "6.x", "required": true, - "helpMarkDown": "Version Spec of version to get. Examples: 6.x, 4.x, 6.10.0, >=6.10.0" + "helpMarkDown": "Version Spec of version to get. Examples: 6.x, 4.x, 6.10.0, >=6.10.0. Also supports a path to a file. Examples: src/.nvmrc, .node-version" }, { "name": "checkLatest",