Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 0 additions & 49 deletions build/scripts/ensure-npm-userconfig.ps1

This file was deleted.

32 changes: 0 additions & 32 deletions build/scripts/finalize-npm-config.ps1

This file was deleted.

50 changes: 0 additions & 50 deletions build/scripts/setup-npm-and-yarn.ps1

This file was deleted.

70 changes: 0 additions & 70 deletions build/scripts/setup-npm-registry.js

This file was deleted.

34 changes: 0 additions & 34 deletions build/scripts/setup-npm-registry.ps1

This file was deleted.

109 changes: 92 additions & 17 deletions build/templates/setup.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# DevDiv pipeline setup steps
#
# Notes on custom registry support:
# - Custom npm registry setup is implemented inline below (no external scripts).
# - The template creates a temp .npmrc, sets NPM_CONFIG_USERCONFIG/REGISTRY, and
# rewrites lockfiles via a transient JS helper emitted into Agent.TempDirectory.
parameters:
- name: installNode
type: boolean
Expand Down Expand Up @@ -30,17 +35,47 @@ steps:
- ${{ if ne(parameters.customNPMRegistry, '') }}:
# When using a private/custom registry, configure npm to read auth/config from a temp user config
# instead of relying on a checked-in project .npmrc.
- pwsh: >
$(Build.SourcesDirectory)/build/scripts/ensure-npm-userconfig.ps1
-Path "${{ parameters.npmrcPath }}"
-Registry "${{ parameters.customNPMRegistry }}"
- pwsh: |
$path = "${{ parameters.npmrcPath }}"

if (Test-Path -LiteralPath $path -PathType Container) {
throw "npmrcPath points to a directory (expected a file): $path"
}

$parent = Split-Path -Parent $path
if ($parent -and -not (Test-Path -LiteralPath $parent)) {
New-Item -ItemType Directory -Path $parent -Force | Out-Null
}

if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
New-Item -ItemType File -Path $path -Force | Out-Null
}

Write-Host "##vso[task.setvariable variable=NPM_CONFIG_USERCONFIG]$path"
Write-Host "##vso[task.setvariable variable=NPM_CONFIG_REGISTRY]${{ parameters.customNPMRegistry }}"
displayName: 📦 Setup NPM User Config

# Configure npm/yarn to use the custom registry and ensure auth headers are sent.
- pwsh: >
$(Build.SourcesDirectory)/build/scripts/setup-npm-and-yarn.ps1
-NpmrcPath "${{ parameters.npmrcPath }}"
-Registry "${{ parameters.customNPMRegistry }}"
- pwsh: |
$path = "${{ parameters.npmrcPath }}"
$registry = "${{ parameters.customNPMRegistry }}"

$env:NPM_CONFIG_USERCONFIG = $path
$env:NPM_CONFIG_REGISTRY = $registry

npm config set registry "$registry"

# npm >v7 deprecated the `always-auth` config option, refs npm/cli@72a7eeb
# following is a workaround for yarn-like clients to send authorization header for GET
# requests to the registry.
"always-auth=true" | Out-File -FilePath $path -Append -Encoding utf8

$yarn = Get-Command yarn -ErrorAction SilentlyContinue
if ($null -ne $yarn) {
yarn config set registry "$registry"
} else {
Write-Host "yarn not found; skipping yarn registry configuration"
}
displayName: 📦 Setup NPM & Yarn

# Populate the temp .npmrc with auth for the configured registry.
Expand All @@ -49,17 +84,57 @@ steps:
workingFile: ${{ parameters.npmrcPath }}
displayName: 📦 Setup NPM Authentication

# Ensure the registry always sends auth headers (npmAuthenticate may overwrite the file).
- pwsh: >
$(Build.SourcesDirectory)/build/scripts/finalize-npm-config.ps1
-Path "${{ parameters.npmrcPath }}"
displayName: 📦 Finalize NPM config

# Some lockfiles contain hardcoded references to public registries. Rewrite them so installs
# and `npx` resolve from the custom registry consistently.
- pwsh: >
$(Build.SourcesDirectory)/build/scripts/setup-npm-registry.ps1
-Registry "${{ parameters.customNPMRegistry }}"
- pwsh: |
$registry = "${{ parameters.customNPMRegistry }}"
$env:NPM_CONFIG_REGISTRY = $registry
$scriptPath = Join-Path "$(Agent.TempDirectory)" 'setup-npm-registry.js'
$lines = @(
"const fs = require('fs').promises;",
"const path = require('path');",
"",
"async function* getLockFiles(dir) {",
" const files = await fs.readdir(dir);",
"",
" for (const file of files) {",
" const fullPath = path.join(dir, file);",
" const stat = await fs.stat(fullPath);",
"",
" if (stat.isDirectory()) {",
" if (file === 'node_modules' || file === '.git') {",
" continue;",
" }",
" yield* getLockFiles(fullPath);",
" } else if (file === 'yarn.lock' || file === 'package-lock.json') {",
" yield fullPath;",
" }",
" }",
"}",
"",
"async function rewrite(file, registry) {",
" let contents = await fs.readFile(file, 'utf8');",
" const re = new RegExp('https://registry\\.[^.]+\\.(com|org)/', 'g');",
" contents = contents.replace(re, registry);",
" await fs.writeFile(file, contents);",
"}",
"",
"async function main() {",
" const root = process.cwd();",
" const registry = process.env.NPM_CONFIG_REGISTRY;",
" if (!registry) { throw new Error('NPM_CONFIG_REGISTRY is not set'); }",
"",
" for await (const file of getLockFiles(root)) {",
" await rewrite(file, registry);",
" console.log('Updated node registry:', file);",
" }",
"}",
"",
"main();"
)

Set-Content -LiteralPath $scriptPath -Value ($lines -join "`n") -Encoding utf8
node $scriptPath
displayName: 📦 Setup NPM Registry

- script: npm config get registry
Expand Down
Loading