diff --git a/Tasks/Npm/Tests/L0.ts b/Tasks/Npm/Tests/L0.ts index cd86ed7061a7..bff2dd410996 100644 --- a/Tasks/Npm/Tests/L0.ts +++ b/Tasks/Npm/Tests/L0.ts @@ -60,6 +60,20 @@ describe('Npm Task', function () { }); // custom + it('custom command succeeds with single service endpoint', (done: MochaDone) => { + this.timeout(1000); + let tp = path.join(__dirname, 'custom-singleEndpoint.js'); + let tr = new ttm.MockTestRunner(tp); + + tr.run(); + + assert(tr.stdOutContained('npm custom successful'), 'npm custom command should have run'); + assert(tr.stdOutContained('http://example.com/1/'), 'debug output should have contained endpoint'); + assert(tr.succeeded, 'task should have succeeded'); + + done(); + }); + it('custom command should return npm version', (done: MochaDone) => { this.timeout(1000); let tp = path.join(__dirname, 'custom-version.js'); @@ -132,6 +146,21 @@ describe('Npm Task', function () { done(); }); + it('install using multiple endpoints', (done: MochaDone) => { + this.timeout(1000); + let tp = path.join(__dirname, 'install-multipleEndpoints.js'); + let tr = new ttm.MockTestRunner(tp); + + tr.run(); + + assert(tr.stdOutContained('npm install successful'), 'npm should have installed the package'); + assert(tr.stdOutContained('http://example.com/1/'), 'debug output should have contained endpoint'); + assert(tr.stdOutContained('http://example.com/2/'), 'debug output should have contained endpoint'); + assert(tr.succeeded, 'task should have succeeded'); + + done(); + }); + // publish it ('publish using feed', (done: MochaDone) => { this.timeout(1000); diff --git a/Tasks/Npm/Tests/custom-singleEndpoint.ts b/Tasks/Npm/Tests/custom-singleEndpoint.ts new file mode 100644 index 000000000000..566a5299e478 --- /dev/null +++ b/Tasks/Npm/Tests/custom-singleEndpoint.ts @@ -0,0 +1,29 @@ +import * as path from 'path'; + +import { TaskLibAnswerExecResult } from 'vsts-task-lib/mock-answer'; +import * as tmrm from 'vsts-task-lib/mock-run'; + +import { NpmCommand, NpmTaskInput, RegistryLocation } from '../constants'; +import { NpmMockHelper } from './NpmMockHelper'; + +let taskPath = path.join(__dirname, '..', 'npm.js'); +let tmr = new NpmMockHelper(taskPath); + +tmr.setInput(NpmTaskInput.Command, NpmCommand.Custom); +tmr.setInput(NpmTaskInput.CustomCommand, 'mockcmd'); +tmr.setInput(NpmTaskInput.WorkingDir, ''); +tmr.setInput(NpmTaskInput.CustomRegistry, RegistryLocation.Npmrc); +tmr.setInput(NpmTaskInput.CustomEndpoint, '1'); +let auth = { + scheme: 'Token', + parameters: { + 'apitoken': 'AUTHTOKEN' + } +}; +tmr.mockServiceEndpoint('1', 'http://example.com/1/', auth); +tmr.mockNpmCommand('mockcmd', { + code: 0, + stdout: 'npm custom successful' +} as TaskLibAnswerExecResult); + +tmr.run(); diff --git a/Tasks/Npm/Tests/install-multipleEndpoints.ts b/Tasks/Npm/Tests/install-multipleEndpoints.ts new file mode 100644 index 000000000000..5facb8ff3787 --- /dev/null +++ b/Tasks/Npm/Tests/install-multipleEndpoints.ts @@ -0,0 +1,29 @@ +import * as path from 'path'; + +import { TaskLibAnswerExecResult } from 'vsts-task-lib/mock-answer'; +import * as tmrm from 'vsts-task-lib/mock-run'; + +import { NpmCommand, NpmTaskInput, RegistryLocation } from '../constants'; +import { NpmMockHelper } from './NpmMockHelper'; + +let taskPath = path.join(__dirname, '..', 'npm.js'); +let tmr = new NpmMockHelper(taskPath); + +tmr.setInput(NpmTaskInput.Command, NpmCommand.Install); +tmr.setInput(NpmTaskInput.WorkingDir, ''); +tmr.setInput(NpmTaskInput.CustomRegistry, RegistryLocation.Npmrc); +tmr.setInput(NpmTaskInput.CustomEndpoint, '1,2'); +let auth = { + scheme: 'Token', + parameters: { + 'apitoken': 'AUTHTOKEN' + } +}; +tmr.mockServiceEndpoint('1', 'http://example.com/1/', auth); +tmr.mockServiceEndpoint('2', 'http://example.com/2/', auth); +tmr.mockNpmCommand('install', { + code: 0, + stdout: 'npm install successful' +} as TaskLibAnswerExecResult); + +tmr.run(); diff --git a/Tasks/Npm/npmcustom.ts b/Tasks/Npm/npmcustom.ts index 6eccfdce01e3..d8b863a2fa20 100644 --- a/Tasks/Npm/npmcustom.ts +++ b/Tasks/Npm/npmcustom.ts @@ -21,9 +21,10 @@ export async function run(command?: string): Promise { break; case RegistryLocation.Npmrc: tl.debug(tl.loc('UseNpmrc')); - let endpointId = tl.getInput(NpmTaskInput.CustomEndpoint); - if (endpointId) { - npmRegistries.push(NpmRegistry.FromServiceEndpoint(endpointId, true)); + let endpointIds = tl.getDelimitedInput(NpmTaskInput.CustomEndpoint, ','); + if (endpointIds && endpointIds.length > 0) { + let endpointRegistries = endpointIds.map(e => NpmRegistry.FromServiceEndpoint(e, true)); + npmRegistries = npmRegistries.concat(endpointRegistries); } break; } diff --git a/Tasks/Npm/package.json b/Tasks/Npm/package.json index d9720ae6db6f..fbe52054dc29 100644 --- a/Tasks/Npm/package.json +++ b/Tasks/Npm/package.json @@ -1,6 +1,6 @@ { "name": "vsts-npm-task", - "version": "1.0.1", + "version": "1.0.2", "description": "VSTS NPM Task", "main": "npmtask.js", "scripts": { diff --git a/Tasks/Npm/task.json b/Tasks/Npm/task.json index eb60fe133e9a..88c9fe5ed592 100644 --- a/Tasks/Npm/task.json +++ b/Tasks/Npm/task.json @@ -9,7 +9,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 1 + "Patch": 2 }, "runsOn": [ "Agent", @@ -89,7 +89,10 @@ "label": "Credentials for registries outside this account/collection", "helpMarkDown": "Credentials to use for external registries located in the project's .npmrc. For registries in this account/collection, leave this blank; the build’s credentials are used automatically.", "type": "connectedService:externalnpmregistry", - "visibleRule": "customRegistry = useNpmrc" + "visibleRule": "customRegistry = useNpmrc", + "properties": { + "MultiSelectFlatList": "true" + } }, { "groupName": "publishRegistries", diff --git a/Tasks/Npm/task.loc.json b/Tasks/Npm/task.loc.json index 0d788e9636be..d5c770c0a477 100644 --- a/Tasks/Npm/task.loc.json +++ b/Tasks/Npm/task.loc.json @@ -9,7 +9,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 1 + "Patch": 2 }, "runsOn": [ "Agent", @@ -89,7 +89,10 @@ "label": "ms-resource:loc.input.label.customEndpoint", "helpMarkDown": "ms-resource:loc.input.help.customEndpoint", "type": "connectedService:externalnpmregistry", - "visibleRule": "customRegistry = useNpmrc" + "visibleRule": "customRegistry = useNpmrc", + "properties": { + "MultiSelectFlatList": "true" + } }, { "groupName": "publishRegistries", diff --git a/Tasks/Npm/util.ts b/Tasks/Npm/util.ts index 772d34735d42..0b7f4ed1d479 100644 --- a/Tasks/Npm/util.ts +++ b/Tasks/Npm/util.ts @@ -79,7 +79,8 @@ export async function getPackagingCollectionUrl(): Promise { } export function getTempNpmrcPath(): string { - let tempUserNpmrcPath: string = path.join(getTempPath(), `${tl.getVariable('Build.BuildId')}.npmrc`); + let id: string = tl.getVariable('Build.BuildId') || tl.getVariable('Release.ReleaseId'); + let tempUserNpmrcPath: string = path.join(getTempPath(), `${id}.npmrc`); return tempUserNpmrcPath; }