Skip to content

Commit 7306e63

Browse files
bschnurrCopilot
andcommitted
Honor authenticated release registries in ci:msft
Preserve the release variable names and ci:msft command. Honor the effective npm registry for lockfile rewriting and installation while inheriting the template-authenticated npmrc. Resolve PIP_PROXY_INDEX_URL from PipAuthenticate output so per-step pip settings retain feed credentials. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent dd1243d commit 7306e63

4 files changed

Lines changed: 66 additions & 19 deletions

File tree

‎build/azure-devdiv-pipeline.pre-release.yml‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ variables:
3333
value: VSCode-python-debugger
3434
- name: VsixName
3535
value: python-debugger.vsix
36-
- name: AZURE_ARTIFACTS_FEED
36+
- name: NPM_CONFIG_REGISTRY
3737
value: 'https://devdiv.pkgs.visualstudio.com/DevDiv/_packaging/Pylance_PublicPackages/npm/registry/'
38+
- name: PIP_PROXY_INDEX_URL
39+
# PipAuthenticate supplies the internal index URL with credentials before buildSteps.
40+
value: '$(PIP_INDEX_URL)'
3841

3942
parameters:
4043
- name: publishExtension
@@ -72,20 +75,28 @@ parameters:
7275
- name: buildSteps
7376
type: stepList
7477
default:
75-
- script: npm ci
78+
- script: npm run ci:msft
7679
displayName: Install NPM dependencies
7780

7881
- script: python -m pip install -U pip
7982
displayName: Upgrade pip
83+
env:
84+
PIP_INDEX_URL: $(PIP_PROXY_INDEX_URL)
8085

8186
- script: python -m pip install wheel
8287
displayName: Install wheel
88+
env:
89+
PIP_INDEX_URL: $(PIP_PROXY_INDEX_URL)
8390

8491
- script: python -m pip install nox
8592
displayName: Install nox
93+
env:
94+
PIP_INDEX_URL: $(PIP_PROXY_INDEX_URL)
8695

8796
- script: python -m nox --session install_bundled_libs
8897
displayName: Install Python dependencies
98+
env:
99+
PIP_INDEX_URL: $(PIP_PROXY_INDEX_URL)
89100

90101
- script: python ./build/update_ext_version.py --for-publishing
91102
displayName: Update build number
@@ -102,7 +113,7 @@ extends:
102113
buildPlatforms: ${{ parameters.buildPlatforms }}
103114
buildSteps: ${{ parameters.buildSteps }}
104115
standardizedVersioning: true
105-
customNPMRegistry: $(AZURE_ARTIFACTS_FEED)
116+
customNPMRegistry: $(NPM_CONFIG_REGISTRY)
106117
publishExtension: ${{ parameters.publishExtension }}
107118
teamName: $(TeamName)
108119
ghCreateTag: true

‎build/azure-devdiv-pipeline.stable.yml‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ variables:
2828
value: VSCode-python-debugger
2929
- name: VsixName
3030
value: python-debugger.vsix
31-
- name: AZURE_ARTIFACTS_FEED
31+
- name: NPM_CONFIG_REGISTRY
3232
value: 'https://devdiv.pkgs.visualstudio.com/DevDiv/_packaging/Pylance_PublicPackages/npm/registry/'
33+
- name: PIP_PROXY_INDEX_URL
34+
# PipAuthenticate supplies the internal index URL with credentials before buildSteps.
35+
value: '$(PIP_INDEX_URL)'
3336

3437
parameters:
3538
- name: publishExtension
@@ -67,20 +70,28 @@ parameters:
6770
- name: buildSteps
6871
type: stepList
6972
default:
70-
- script: npm ci
73+
- script: npm run ci:msft
7174
displayName: Install NPM dependencies
7275

7376
- script: python -m pip install -U pip
7477
displayName: Upgrade pip
78+
env:
79+
PIP_INDEX_URL: $(PIP_PROXY_INDEX_URL)
7580

7681
- script: python -m pip install wheel
7782
displayName: Install wheel
83+
env:
84+
PIP_INDEX_URL: $(PIP_PROXY_INDEX_URL)
7885

7986
- script: python -m pip install nox
8087
displayName: Install nox
88+
env:
89+
PIP_INDEX_URL: $(PIP_PROXY_INDEX_URL)
8190

8291
- script: python -m nox --session install_bundled_libs
8392
displayName: Install Python dependencies
93+
env:
94+
PIP_INDEX_URL: $(PIP_PROXY_INDEX_URL)
8495

8596
- script: python ./build/update_ext_version.py --release --for-publishing
8697
displayName: Update build number
@@ -97,7 +108,7 @@ extends:
97108
buildPlatforms: ${{ parameters.buildPlatforms }}
98109
buildSteps: ${{ parameters.buildSteps }}
99110
standardizedVersioning: true
100-
customNPMRegistry: $(AZURE_ARTIFACTS_FEED)
111+
customNPMRegistry: $(NPM_CONFIG_REGISTRY)
101112
publishExtension: ${{ parameters.publishExtension }}
102113
teamName: $(TeamName)
103114
ghCreateTag: true

‎build/setup-npm-registry.js‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const { readFileSync, writeFileSync } = require('node:fs');
66
const path = require('node:path');
77
const { microsoft } = require('./package-feeds.json');
88

9-
function rewritePackageLock(source) {
9+
function rewritePackageLock(source, registry = microsoft.npm) {
1010
const lockfile = JSON.parse(source);
1111
if (
1212
![2, 3].includes(lockfile.lockfileVersion) ||
@@ -19,16 +19,16 @@ function rewritePackageLock(source) {
1919

2020
return source.replace(/("resolved"\s*:\s*)("(?:\\.|[^"\\])*")/g, (match, prefix, encodedUrl) => {
2121
const url = JSON.parse(encodedUrl);
22-
const rewritten = url.replace(/^https:\/\/registry\.(?:npmjs\.org|yarnpkg\.com)\//, microsoft.npm);
22+
const rewritten = url.replace(/^https:\/\/registry\.(?:npmjs\.org|yarnpkg\.com)\//, registry);
2323
return rewritten === url ? match : prefix + JSON.stringify(rewritten);
2424
});
2525
}
2626

27-
function rewritePackageLocks(root = path.resolve(__dirname, '..')) {
27+
function rewritePackageLocks(root = path.resolve(__dirname, '..'), registry = microsoft.npm) {
2828
const files = [path.join(root, 'package-lock.json')];
2929
const updates = files.map((file) => {
3030
const source = readFileSync(file, 'utf8');
31-
return { file, source, rewritten: rewritePackageLock(source) };
31+
return { file, source, rewritten: rewritePackageLock(source, registry) };
3232
});
3333
for (const { file, source, rewritten } of updates) {
3434
if (rewritten !== source) {
@@ -48,13 +48,13 @@ if (require.main === module) {
4848
if (install && !process.env.npm_execpath) {
4949
throw new Error('Run npm install using npm run ci:msft.');
5050
}
51-
rewritePackageLocks();
51+
const registry = process.env.npm_config_registry || process.env.NPM_CONFIG_REGISTRY || microsoft.npm;
52+
rewritePackageLocks(undefined, registry);
5253
if (install) {
53-
const result = spawnSync(
54-
process.execPath,
55-
[process.env.npm_execpath, 'ci', `--registry=${microsoft.npm}`],
56-
{ cwd: path.resolve(__dirname, '..'), stdio: 'inherit' },
57-
);
54+
const result = spawnSync(process.execPath, [process.env.npm_execpath, 'ci', `--registry=${registry}`], {
55+
cwd: path.resolve(__dirname, '..'),
56+
stdio: 'inherit',
57+
});
5858
if (result.error || result.signal || result.status !== 0) {
5959
const reason = result.error?.message || result.signal || `exit code ${result.status}`;
6060
const error = new Error(`npm ci failed: ${reason}`);

‎build/setup-npm-registry.test.js‎

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,20 +100,20 @@ test('missing or invalid root lockfile fails explicitly', (t) => {
100100
assert.throws(() => rewritePackageLocks(root), /Expected an npm lockfile/);
101101
});
102102

103-
function runCli({ args = ['--ci'], npmCli = 'npm-cli.js', result = { status: 0 } } = {}) {
103+
function runCli({ args = ['--ci'], npmCli = 'npm-cli.js', result = { status: 0 }, env = {} } = {}) {
104104
const calls = [];
105105
const errors = [];
106106
const process = {
107107
argv: ['node', 'setup-npm-registry.js', ...args],
108-
env: { npm_execpath: npmCli },
108+
env: { npm_execpath: npmCli, ...env },
109109
execPath: 'node',
110110
};
111111
const module = { exports: {} };
112112
const mockedRequire = (name) => {
113113
if (name === 'node:fs') {
114114
return {
115115
readFileSync: () => source,
116-
writeFileSync: (file) => calls.push({ file }),
116+
writeFileSync: (file, source) => calls.push({ file, source }),
117117
};
118118
}
119119
if (name === 'node:child_process') {
@@ -150,6 +150,31 @@ test('ci:msft rewrites the root lockfile before installing with the shared proxy
150150
assert.equal(scripts['ci:msft'], 'node ./build/setup-npm-registry.js --ci');
151151
});
152152

153+
test('ci:msft preserves template authentication for the configured internal registry', () => {
154+
const registry = 'https://devdiv.pkgs.visualstudio.com/DevDiv/_packaging/Pylance_PublicPackages/npm/registry/';
155+
for (const settings of [
156+
{ NPM_CONFIG_REGISTRY: registry },
157+
{ npm_config_registry: registry },
158+
{ NPM_CONFIG_REGISTRY: proxyRegistry, npm_config_registry: registry },
159+
]) {
160+
const env = {
161+
...settings,
162+
NPM_CONFIG_USERCONFIG: path.join(tmpdir(), 'authenticated.npmrc'),
163+
NODE_AUTH_TOKEN: 'test-token',
164+
};
165+
const context = runCli({ env });
166+
const install = context.calls.at(-1);
167+
assert.deepEqual(install.args, ['npm-cli.js', 'ci', `--registry=${registry}`]);
168+
assert.equal(install.env, undefined);
169+
assert.equal(context.process.env.NPM_CONFIG_USERCONFIG, env.NPM_CONFIG_USERCONFIG);
170+
assert.equal(context.process.env.NODE_AUTH_TOKEN, env.NODE_AUTH_TOKEN);
171+
for (const write of context.calls.slice(0, -1)) {
172+
assert.equal(write.source, rewritePackageLock(source, registry));
173+
}
174+
assert.equal(context.errors.length, 0);
175+
}
176+
});
177+
153178
for (const result of [{ status: 7 }, { status: null, signal: 'SIGTERM' }, { error: new Error('not found') }]) {
154179
test(`ci:msft reports npm failure: ${result.signal || result.error?.message || result.status}`, () => {
155180
const context = runCli({ result });

0 commit comments

Comments
 (0)