Public/Update-AdoNpmToken.ps1
|
function Update-AdoNpmToken { <# .SYNOPSIS Updates ADO npm feed tokens using artifacts-npm-credprovider. .DESCRIPTION Runs the @microsoft/artifacts-npm-credprovider against a temporary .npmrc to authenticate with Azure DevOps and obtain fresh access tokens. The tokens are set as environment variables referenced by the user-level .npmrc. Use -Feed to select the feed and -Name to control the environment variable name. .PARAMETER Feed The ADO npm feed registry URL to authenticate against. .PARAMETER Name The environment variable name to set. Defaults to ADO_NPM_TOKEN. .PARAMETER Force Force credential refresh even if current authentication is valid. .EXAMPLE Update-AdoNpmToken -Feed "https://pkgs.dev.azure.com/myorg/_packaging/myfeed/npm/registry/" Refreshes a specific feed into ADO_NPM_TOKEN. .EXAMPLE Update-AdoNpmToken -Feed "https://pkgs.dev.azure.com/myorg/_packaging/myfeed/npm/registry/" -Name MY_TOKEN Refreshes a specific feed into a custom environment variable. .EXAMPLE Update-AdoNpmToken -Feed "https://pkgs.dev.azure.com/myorg/_packaging/myfeed/npm/registry/" -Force Forces a credential refresh for the selected feed. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Feed, [Parameter()] [ValidatePattern('^[A-Za-z_][A-Za-z0-9_]*$')] [string]$Name, [Parameter()] [switch]$Force ) $feedsToRefresh = @(@{ Feed = $Feed Name = if ($Name) { $Name } else { 'ADO_NPM_TOKEN' } }) $npmRoot = npm root -g 2>$null if (-not $npmRoot) { Write-Error "npm is not installed or not in PATH." return } $credProviderBin = Join-Path $npmRoot '@microsoft\artifacts-npm-credprovider\bin\index.js' if (-not (Test-Path $credProviderBin)) { Write-Error "artifacts-npm-credprovider is not installed globally. Install with: npm install -g @microsoft/artifacts-npm-credprovider" return } foreach ($entry in $feedsToRefresh) { if (-not $PSCmdlet.ShouldProcess($entry.Name, "Refresh token for feed $($entry.Feed)")) { continue } # Build a temporary .npmrc with the feed entry so the credprovider writes the token into it $tempDir = New-Item -ItemType Directory -Path (Join-Path ([System.IO.Path]::GetTempPath()) "ado-npm-$([System.IO.Path]::GetRandomFileName())") $tempNpmrc = Join-Path $tempDir '.npmrc' Set-Content -Path $tempNpmrc -Value "//$($entry.Feed -replace '^https?://', ''):_authToken=" try { Write-Verbose "Requesting token for feed: $($entry.Feed)" $arguments = @('-c', $tempNpmrc) if ($Force) { $arguments += '--force' } # Run from the temp directory so the credprovider doesn't walk up # to ~ and find the user-level .npmrc (which would conflict with -c) Push-Location $tempDir try { & node $credProviderBin @arguments 2>&1 | ForEach-Object { Write-Verbose $_ } } finally { Pop-Location } $npmrcContent = Get-Content $tempNpmrc -Raw if ($npmrcContent -match ':_authToken=(.+)') { [System.Environment]::SetEnvironmentVariable($entry.Name, $Matches[1].Trim(), 'Process') Write-Verbose "$($entry.Name) updated successfully." } else { Write-Error "Failed to obtain token for $($entry.Name) from artifacts-npm-credprovider." } } finally { Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } } |