Skip to content

Commit 095e62d

Browse files
authored
Adding support for views within npm registry values (#7541) (#7575)
* Adding support for views within npm registry values
1 parent 9580f85 commit 095e62d

File tree

7 files changed

+64
-28
lines changed

7 files changed

+64
-28
lines changed

Tasks/Common/npm-common/npmregistry.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ export class NpmRegistry implements INpmRegistry {
9797

9898
public static async FromFeedId(feedId: string, authOnly?: boolean): Promise<NpmRegistry> {
9999
let url = NormalizeRegistry(await util.getFeedRegistryUrl(feedId));
100+
return NpmRegistry.FromUrl(url, authOnly);
101+
}
102+
103+
public static FromUrl(url: string, authOnly?: boolean): NpmRegistry {
100104
let nerfed = util.toNerfDart(url);
101105
let auth = `${nerfed}:_authToken=${util.getSystemAccessToken()}`;
102106

Tasks/Common/npm-common/util.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,14 @@ export function appendToNpmrc(npmrc: string, data: string): void {
1616
}
1717

1818
export async function getLocalRegistries(npmrc: string): Promise<string[]> {
19-
let localRegistries: string[] = [];
20-
let registries = NpmrcParser.GetRegistries(npmrc);
21-
let collectionUrl = url.parse(await getPackagingCollectionUrl());
22-
23-
for (let registry of registries) {
24-
let registryUrl = url.parse(registry);
25-
if (registryUrl.host.toLowerCase() === collectionUrl.host.toLowerCase()) {
26-
localRegistries.push(registry);
27-
}
28-
}
19+
// Local registries are VSTS feeds from the SAME collection host
20+
const collectionHost = url.parse(await getPackagingCollectionUrl()).host;
21+
const registries = NpmrcParser.GetRegistries(npmrc);
22+
23+
const localRegistries = registries.filter(registry => {
24+
const registryHost = url.parse(registry).host;
25+
return registryHost.toLowerCase() === collectionHost.toLowerCase();
26+
});
2927

3028
tl.debug(tl.loc('FoundLocalRegistries', localRegistries.length));
3129
return localRegistries;
@@ -42,19 +40,14 @@ export function getFeedIdFromRegistry(registry: string) {
4240
}
4341

4442
export async function getLocalNpmRegistries(workingDir: string): Promise<INpmRegistry[]> {
45-
let localNpmRegistries: INpmRegistry[] = [];
4643
let npmrcPath = path.join(workingDir, '.npmrc');
4744

4845
if (tl.exist(npmrcPath)) {
49-
let npmRegistries: INpmRegistry[] = [];
50-
for (let registry of await getLocalRegistries(npmrcPath)) {
51-
npmRegistries.push(await NpmRegistry.FromFeedId(getFeedIdFromRegistry(registry), true));
52-
}
53-
54-
localNpmRegistries = localNpmRegistries.concat(npmRegistries);
46+
const localRegistries = await getLocalRegistries(npmrcPath);
47+
return localRegistries.map(registry => NpmRegistry.FromUrl(registry, true));
5548
}
5649

57-
return localNpmRegistries;
50+
return [];
5851
}
5952

6053
export async function getPackagingCollectionUrl(): Promise<string> {

Tasks/NpmV1/Tests/L0.ts

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import * as assert from 'assert';
2-
import * as fs from 'fs';
32
import * as path from 'path';
4-
import * as Q from 'q';
5-
63
import * as mockery from 'mockery';
74
import * as ttm from 'vsts-task-lib/mock-test';
85

96
import { NpmMockHelper } from './NpmMockHelper';
7+
import Lazy_NpmRegistry = require('npm-common/npmregistry');
108

119
const BASIC_AUTH_PAT_PASSWD_REGEX = /\/\/.*\/:_password=.*/g;
1210
const BEARER_AUTH_REGEX = /\/\/.*\/:_authToken=AUTHTOKEN.*/g;
@@ -16,6 +14,7 @@ const AWLAYS_AUTH_REGEX = /\/\/.*\/:always-auth=true.*/g;
1614

1715
describe('Npm Task', function () {
1816
before(() => {
17+
mockery.disable(); // needed to ensure that we can mock vsts-task-lib/task
1918
mockery.enable({
2019
useCleanCache: true,
2120
warnOnUnregistered: false
@@ -236,15 +235,21 @@ describe('Npm Task', function () {
236235
});
237236

238237
it('gets feed id from VSTS registry', (done: MochaDone) => {
239-
mockery.registerMock('vsts-task-lib/task', {});
238+
let mockTask = {
239+
debug: message => {}
240+
};
241+
mockery.registerMock('vsts-task-lib/task', mockTask);
240242
let util = require('npm-common/util');
241243

242244
assert.equal(util.getFeedIdFromRegistry(
243-
'http://account.visualstudio.com/_packaging/feedId/npm/registry'),
245+
'https://account.visualstudio.com/_packaging/feedId/npm/registry'),
244246
'feedId');
245247
assert.equal(util.getFeedIdFromRegistry(
246-
'http://account.visualstudio.com/_packaging/feedId/npm/registry/'),
248+
'https://account.visualstudio.com/_packaging/feedId/npm/registry/'),
247249
'feedId');
250+
assert.equal(util.getFeedIdFromRegistry(
251+
'https://account.visualstudio.com/_packaging/feedId@PreRelease/npm/registry/'),
252+
'feedId@PreRelease');
248253
assert.equal(util.getFeedIdFromRegistry(
249254
'http://TFSSERVER/_packaging/feedId/npm/registry'),
250255
'feedId');
@@ -515,4 +520,39 @@ describe('Npm Task', function () {
515520
done();
516521
});
517522

523+
it('handles views in registry URL', async (done: MochaDone) => {
524+
// Scenario: Includes view (e.g. @Release) within the registry entry
525+
const hostName = 'https://mytfsserver.visualstudio.com';
526+
const nerfedRegistry = "//mytfsserver.pkgs.visualstudio.com/npmRegistry@Release/npm/registry/";
527+
const registry = `https:${nerfedRegistry}`;
528+
const authToken = '**sometoken**';
529+
530+
const mockTask = {
531+
loc: key => "LocValue",
532+
debug: msg => null,
533+
exist: path => true,
534+
getVariable: v => {
535+
return (v === 'System.TeamFoundationCollectionUri') ? hostName : null;
536+
},
537+
getEndpointAuthorization: (id, optional) => {
538+
return { scheme: 'OAuth', parameters: { 'AccessToken': authToken } };
539+
}
540+
};
541+
const mockParser = {
542+
GetRegistries: (npmrc: string) => [registry]
543+
};
544+
mockery.registerMock('vsts-task-lib/task', mockTask);
545+
mockery.registerMock('./npmrcparser', mockParser);
546+
547+
const util = require('npm-common/util');
548+
const registries = await util.getLocalNpmRegistries("somePath");
549+
550+
assert.equal(registries.length, 1, "Expected one response");
551+
const npmRegistry: Lazy_NpmRegistry.INpmRegistry = registries[0];
552+
assert.equal(npmRegistry.url, registry, "Registry needs to match");
553+
assert.equal(npmRegistry.auth, `${nerfedRegistry}:_authToken=${authToken}`, "Auth needs to match");
554+
assert.equal(npmRegistry.authOnly, true, "Authonly needs to match");
555+
556+
done();
557+
});
518558
});

Tasks/NpmV1/npmcustom.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export async function run(command?: string): Promise<void> {
1111
let workingDir = tl.getInput(NpmTaskInput.WorkingDir) || process.cwd();
1212
let npmrc = util.getTempNpmrcPath();
1313
let npmRegistries: INpmRegistry[] = await getCustomRegistries();
14-
let registryLocation = tl.getInput(NpmTaskInput.CustomRegistry);
1514
let overrideNpmrc = (tl.getInput(NpmTaskInput.CustomRegistry) == RegistryLocation.Feed) ? true : false;
1615

1716
for (let registry of npmRegistries) {

Tasks/NpmV1/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vsts-npm-task",
3-
"version": "1.0.16",
3+
"version": "1.0.17",
44
"description": "VSTS NPM Task",
55
"main": "npmtask.js",
66
"scripts": {

Tasks/NpmV1/task.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"version": {
1010
"Major": 1,
1111
"Minor": 0,
12-
"Patch": 16
12+
"Patch": 17
1313
},
1414
"runsOn": [
1515
"Agent",

Tasks/NpmV1/task.loc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"version": {
1010
"Major": 1,
1111
"Minor": 0,
12-
"Patch": 16
12+
"Patch": 17
1313
},
1414
"runsOn": [
1515
"Agent",

0 commit comments

Comments
 (0)