4343
4444$ErrorActionPreference = " Stop"
4545
46- $Script :InstallerVersion = " 1.9.5 "
46+ $Script :InstallerVersion = " 1.9.6 "
4747
4848try {
4949 [Console ]::OutputEncoding = [System.Text.Encoding ]::UTF8
@@ -105,11 +105,19 @@ function Invoke-WithCleanPythonPath([scriptblock]$Script) {
105105 $previousPipProgressBar = $env: PIP_PROGRESS_BAR
106106 $previousPipNoInput = $env: PIP_NO_INPUT
107107 $previousPipVersionCheck = $env: PIP_DISABLE_PIP_VERSION_CHECK
108+ $previousPipKeyringProvider = $env: PIP_KEYRING_PROVIDER
108109 try {
109110 Remove-Item Env:\PYTHONPATH - ErrorAction SilentlyContinue
110111 $env: PIP_PROGRESS_BAR = " off"
111112 $env: PIP_NO_INPUT = " 1"
112113 $env: PIP_DISABLE_PIP_VERSION_CHECK = " 1"
114+ # PIP_NO_INPUT=1 makes pip skip its interactive keyring path, which the
115+ # Azure Artifacts credential provider (artifacts-keyring) depends on, so
116+ # private-feed requests would fail to authenticate. Forcing the "import"
117+ # keyring provider makes pip load keyring in-process (no prompt, MSAL
118+ # silent in practice), restoring feed auth for both version discovery and
119+ # the actual install while staying fully non-interactive.
120+ $env: PIP_KEYRING_PROVIDER = " import"
113121 & $Script
114122 }
115123 finally {
@@ -122,6 +130,8 @@ function Invoke-WithCleanPythonPath([scriptblock]$Script) {
122130 else { $env: PIP_NO_INPUT = $previousPipNoInput }
123131 if ($null -eq $previousPipVersionCheck ) { Remove-Item Env:\PIP_DISABLE_PIP_VERSION_CHECK - ErrorAction SilentlyContinue }
124132 else { $env: PIP_DISABLE_PIP_VERSION_CHECK = $previousPipVersionCheck }
133+ if ($null -eq $previousPipKeyringProvider ) { Remove-Item Env:\PIP_KEYRING_PROVIDER - ErrorAction SilentlyContinue }
134+ else { $env: PIP_KEYRING_PROVIDER = $previousPipKeyringProvider }
125135 }
126136}
127137
@@ -590,6 +600,31 @@ function New-ManagedVenv($PythonInfo) {
590600 return $venvPython
591601}
592602
603+ function Get-LatestXTesterVersionFromFeed ([string ]$VenvPython ) {
604+ # Ask the feed directly for the newest published version instead of trusting
605+ # pip's `-U` against a possibly stale cached/locally-known index. We then pin
606+ # the install to that exact version so the result is deterministic.
607+ #
608+ # `pip index versions` prints the latest as the first token, e.g.
609+ # xtester (0.0.23)
610+ # Available versions: 0.0.23, 0.0.22, ...
611+ # Feed auth works here because the surrounding Invoke-WithCleanPythonPath sets
612+ # PIP_KEYRING_PROVIDER=import (see that function for why).
613+ $raw = & $VenvPython @ (
614+ " -m" , " pip" , " index" , " versions" , " xtester" ,
615+ " --no-cache-dir" ,
616+ " --index-url" , $FeedUrl ,
617+ " --extra-index-url" , $ExtraIndexUrl
618+ ) 2>&1
619+ if ($LASTEXITCODE -ne 0 ) { return $null }
620+ $text = ($raw | Out-String )
621+ $match = [regex ]::Match($text , ' xtester\s*\(([^)]+)\)' )
622+ if ($match.Success ) { return $match.Groups [1 ].Value.Trim() }
623+ $match = [regex ]::Match($text , ' LATEST:\s*([^\s]+)' )
624+ if ($match.Success ) { return $match.Groups [1 ].Value.Trim() }
625+ return $null
626+ }
627+
593628function Install-XTesterIntoVenv ([string ]$VenvPython ) {
594629 Invoke-WithCleanPythonPath {
595630 Invoke-Step " Upgrading pip and installing private-feed auth helpers" {
@@ -605,10 +640,26 @@ function Install-XTesterIntoVenv([string]$VenvPython) {
605640 return
606641 }
607642
608- $packageSpec = " xtester"
609- $installLabel = " latest X-Tester from private feed"
610- if (-not [string ]::IsNullOrWhiteSpace($Version )) {
611- $packageSpec = " xtester==$Version "
643+ # Resolve the concrete version to install. Explicit -Version always wins;
644+ # otherwise discover the latest from the feed and pin to it. Pinning to a
645+ # discovered version avoids the failure mode where pip reports an older
646+ # release as "already satisfied" because its known index is stale.
647+ $targetVersion = $Version
648+ if ([string ]::IsNullOrWhiteSpace($targetVersion )) {
649+ Info " Resolving latest X-Tester version from private feed"
650+ $targetVersion = Get-LatestXTesterVersionFromFeed $VenvPython
651+ if ([string ]::IsNullOrWhiteSpace($targetVersion )) {
652+ Warn " Could not resolve latest version from feed; falling back to plain 'latest' install."
653+ } else {
654+ Success " Latest X-Tester on feed: $targetVersion "
655+ }
656+ }
657+
658+ if ([string ]::IsNullOrWhiteSpace($targetVersion )) {
659+ $packageSpec = " xtester"
660+ $installLabel = " latest X-Tester from private feed"
661+ } else {
662+ $packageSpec = " xtester==$targetVersion "
612663 $installLabel = " X-Tester $packageSpec from private feed"
613664 }
614665
0 commit comments