@@ -766,6 +766,50 @@ if ($isRunningOnADO) {
766766[string []]$DominoArguments = @ ($DominoArguments | % { $_.Replace (" #singlequote#" , " '" ).Replace(" #openparens#" , " (" ).Replace(" #closeparens#" , " )" ); })
767767[string []]$DominoArguments = $AdditionalBuildXLArguments + $DominoArguments ;
768768
769+ function getTokenFromCredentialProvider () {
770+ [OutputType ([string ])]
771+ Param (
772+ [parameter (Mandatory = $true )]
773+ [string ]
774+ $credProvider ,
775+
776+ [parameter (Mandatory = $true )]
777+ [string ]
778+ $internalFeed ,
779+
780+ [parameter (Mandatory = $true )]
781+ [boolean ]
782+ $isRetry
783+ )
784+
785+ $processInfo = New-Object System.Diagnostics.ProcessStartInfo
786+ $processInfo.FileName = $credProvider
787+ $processInfo.RedirectStandardError = $true
788+ $processInfo.RedirectStandardOutput = $true
789+ $processInfo.UseShellExecute = $false
790+ $processInfo.CreateNoWindow = $true
791+ $processInfo.Arguments = " -U $internalFeed -V Information -C -F Json"
792+ if ($isRetry ) {
793+ $processInfo.Arguments += " -I"
794+ }
795+ # tells the artifacts cred provider to generate a PAT instead of a self-describing token
796+ if ($processInfo.EnvironmentVariables.ContainsKey (" NUGET_CREDENTIALPROVIDER_VSTS_TOKENTYPE" )) {
797+ $processInfo.EnvironmentVariables [" NUGET_CREDENTIALPROVIDER_VSTS_TOKENTYPE" ] = " Compact"
798+ }
799+ else {
800+ $processInfo.EnvironmentVariables.Add (" NUGET_CREDENTIALPROVIDER_VSTS_TOKENTYPE" , " Compact" )
801+ }
802+ $p = New-Object System.Diagnostics.Process
803+ $p.StartInfo = $processInfo
804+ $p.Start () | Out-Null
805+ $p.WaitForExit ()
806+ $stdout = $p.StandardOutput.ReadToEnd ()
807+
808+ # parse token from output
809+ $tokenMatches = $stdout | Select-String - Pattern ' .*\{"Username":"[a-zA-Z0-9]*","Password":"(.*)"\}.*'
810+ return $tokenMatches.Matches.Groups [1 ].Value
811+ }
812+
769813# The MS internal build needs authentication. When not running on ADO use the configured cred provider
770814# to prompt for credentials as a way to guarantee the auth token will be cached for the subsequent build.
771815# This may prompt an interactive pop-up/console. ADO pipelines already configure the corresponding env vars
@@ -810,26 +854,29 @@ if ($isMicrosoftInternal -and (-not $isRunningOnADO)) {
810854 # Set the cached credential into the user npmrc
811855 # we don't run vsts-npm-auth here because it requires us to have npm installed first
812856 # the code below will essentially duplicate what vsts-npm-auth performs
813- $processInfo = New-Object System.Diagnostics.ProcessStartInfo
814- $processInfo.FileName = $credProvider
815- $processInfo.RedirectStandardError = $true
816- $processInfo.RedirectStandardOutput = $true
817- $processInfo.UseShellExecute = $false
818- $processInfo.CreateNoWindow = $true
819- $processInfo.Arguments = " -U $internalFeed -V Information -C -F Json"
820- # tells the artifacts cred provider to generate a PAT instead of a self-describing token
821- if ($processInfo.EnvironmentVariables.ContainsKey (" NUGET_CREDENTIALPROVIDER_VSTS_TOKENTYPE" )) {
822- $processInfo.EnvironmentVariables [" NUGET_CREDENTIALPROVIDER_VSTS_TOKENTYPE" ] = " Compact"
857+ $token = getTokenFromCredentialProvider $credProvider $internalFeed $false ;
858+
859+ # verify whether the provided PAT is valid
860+ $auth = " username" + ' :' + $token
861+ $encoded = [System.Text.Encoding ]::UTF8.GetBytes($auth )
862+ $authorizationInfo = [System.Convert ]::ToBase64String($encoded )
863+ $headers = @ {" Authorization" = " Basic $ ( $authorizationInfo ) " }
864+ $statusCode = 0 ;
865+
866+ try {
867+ $response = Invoke-WebRequest - Uri " https://feeds.dev.azure.com/cloudbuild/CloudBuild/_apis/packaging/feeds?api-version=7.1-preview.1" - Method GET - Headers $headers
868+ $statusCode = $response.StatusCode
823869 }
824- else {
825- $processInfo .EnvironmentVariables.Add ( " NUGET_CREDENTIALPROVIDER_VSTS_TOKENTYPE " , " Compact " )
870+ catch {
871+ $statusCode = 401
826872 }
827- $p = New-Object System.Diagnostics.Process
828- $p.StartInfo = $processInfo
829- $p.Start () | Out-Null
830- $p.WaitForExit ()
831- $stdout = $p.StandardOutput.ReadToEnd ()
832-
873+
874+ # a 200 response indicates that the PAT is valid
875+ # if we didn't get this, we need to re-run the credential provider with the -I arg
876+ if ($statusCode -ne 200 ) {
877+ $token = getTokenFromCredentialProvider $credProvider $internalFeed $true ;
878+ }
879+
833880 # npmrc files can contain multiple sources, so we'll create a buildxl specific one here
834881 if (! [System.IO.File ]::Exists(" $env: USERPROFILE /.npmrc" )) {
835882 New-Item - Path " $env: USERPROFILE /.npmrc" - ItemType File
@@ -838,9 +885,7 @@ if ($isMicrosoftInternal -and (-not $isRunningOnADO)) {
838885 Set-Content - Path " $env: USERPROFILE /.npmrc" - Value (Get-Content " $env: USERPROFILE /.npmrc" | Select-String - Pattern ' .*\/\/cloudbuild\.pkgs\.visualstudio\.com\/_packaging\/BuildXL\.Selfhost\/npm\/registry.*' -NotMatch )
839886 }
840887
841- # parse token from output and base64 encode
842- $tokenMatches = $stdout | Select-String - Pattern ' .*\{"Username":"[a-zA-Z0-9]*","Password":"(.*)"\}.*'
843- $token = $tokenMatches.Matches.Groups [1 ].Value
888+ # base64 encode the token
844889 $b64token = [Convert ]::ToBase64String([System.Text.Encoding ]::UTF8.GetBytes($token ))
845890
846891 # add new lines with token to npmrc
0 commit comments