MegaBites-AI/Windows-powershell
0372
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3 4[CmdletBinding()]5param (6 [Parameter()]7 [string]$SDKVersionOverride,8 9 [Parameter()]10 [switch]$UseNuGetOrg,11 12 [Parameter()]13 [string]$RuntimeSourceFeed,14 15 [Parameter()]16 [string]$RuntimeSourceFeedKey,17 18 [Parameter()]19 [switch]$InteractiveAuth,20 21 [Parameter()]22 [switch]$UseInternalFeed23)24 25<#26 .DESCRIPTION Update the global.json with the new SDK version to be used.27#>28function Update-GlobalJson([string] $Version) {29 $psGlobalJsonPath = Resolve-Path "$PSScriptRoot/../global.json"30 $psGlobalJson = Get-Content -Path $psGlobalJsonPath -Raw | ConvertFrom-Json31 32 if ($psGlobalJson.sdk.version -eq $Version) {33 throw '.NET SDK version is not updated'34 }35 36 $psGlobalJson.sdk.version = $Version37 $psGlobalJson | ConvertTo-Json | Out-File -FilePath $psGlobalJsonPath -Force38}39 40<#41 .DESCRIPTION Iterate through all the csproj to find all the packages that need to be updated42#>43function Update-PackageVersion {44 45 class PkgVer {46 [string] $Name47 [string] $Version48 [string] $NewVersion49 [string] $Path50 51 PkgVer($n, $v, $nv, $p) {52 $this.Name = $n53 $this.Version = $v54 $this.NewVersion = $nv55 $this.Path = $p56 }57 }58 59 $skipModules = @(60 "NJsonSchema"61 "Markdig.Signed"62 "PowerShellHelpFiles"63 "Newtonsoft.Json"64 "Microsoft.ApplicationInsights"65 "Microsoft.Management.Infrastructure"66 "Microsoft.PowerShell.Native"67 "Microsoft.NETCore.Windows.ApiSets"68 "Microsoft.PowerShell.MarkdownRender"69 )70 71 $packages = [System.Collections.Generic.Dictionary[[string], [PkgVer[]] ]]::new()72 73 $paths = @(74 "$PSScriptRoot/packaging/projects/reference/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands.Utility.csproj"75 "$PSScriptRoot/packaging/projects/reference/System.Management.Automation/System.Management.Automation.csproj"76 "$PSScriptRoot/packaging/projects/reference/Microsoft.PowerShell.ConsoleHost/Microsoft.PowerShell.ConsoleHost.csproj"77 "$PSScriptRoot/../src/"78 "$PSScriptRoot/../test/tools/"79 "$PSScriptRoot/../test/perf/dotnet-tools/"80 )81 82 Get-ChildItem -Path $paths -Recurse -Filter "*.csproj" -Exclude 'PSGalleryModules.csproj', 'PSGalleryTestModules.csproj' | ForEach-Object {83 Write-Verbose -Message "Reading - $($_.FullName)" -Verbose84 $prj = [xml] (Get-Content $_.FullName -Raw)85 $pkgRef = $prj.Project.ItemGroup.PackageReference86 87 foreach ($p in $pkgRef) {88 if ($null -ne $p -and -not $skipModules.Contains($p.Include)) {89 if (-not $packages.ContainsKey($p.Include)) {90 $packages.Add($p.Include, @([PkgVer]::new($p.Include, $p.Version, $null, $_.FullName)))91 } else {92 $packages[$p.Include] += [PkgVer]::new($p.Include, $p.Version, $null, $_.FullName)93 }94 }95 }96 }97 98 $versionPattern = (Get-Content "$PSScriptRoot/../DotnetRuntimeMetadata.json" | ConvertFrom-Json).sdk.packageVersionPattern99 100 $source = if ($UseNuGetOrg) { 'nuget.org' } elseif ($UseInternalFeed) { 'dotnet-internal' } else { 'dotnet' }101 102 # Always add nuget.org as some packages are only found there.103 $source = if ($source -ne 'nuget.org') {104 @($source, "nuget.org")105 }106 107 $packages.GetEnumerator() | ForEach-Object {108 $pkgName = $_.Key109 110 $pkgs = [System.Collections.Generic.Dictionary[string, Microsoft.PackageManagement.Packaging.SoftwareIdentity]]::new()111 112 # We have to find packages for all sources separately as Find-Package does not return all packages when both sources are provided at the same time.113 # Since there will be a lot of duplicates we add the package to a dictionary so we only get a unique set by version.114 $source | ForEach-Object {115 Find-Package -Name $pkgName -AllVersions -AllowPrereleaseVersions -Source $_ -ErrorAction SilentlyContinue | ForEach-Object {116 if (-not $pkgs.ContainsKey($_.Version)) {117 $pkgs.Add($_.Version, $_)118 }119 }120 }121 122 foreach ($v in $_.Value) {123 $version = $v.Version124 125 foreach ($p in $pkgs.Values) {126 # some packages are directly updated on nuget.org so need to check that too.127 if ($p.Version -like "$versionPattern*" -or $p.Source -eq 'nuget.org') {128 try {129 if ([System.Management.Automation.SemanticVersion] ($version) -lt [System.Management.Automation.SemanticVersion] ($p.Version)) {130 $v.NewVersion = $p.Version131 break132 }133 } catch {134 if ($_.FullyQualifiedErrorId -ne 'InvalidCastParseTargetInvocation') {135 throw $_136 }137 }138 }139 }140 }141 }142 143 # we need a ForEach-Object below to unravel each of the items in 'Values' which is an array of PkgVer144 $pkgsByPath = $packages.Values | ForEach-Object { $_ } | Group-Object -Property Path145 146 $pkgsByPath | ForEach-Object {147 Update-CsprojFile -Path $_.Name -Values $_.Group148 }149}150 151<#152 .DESCRIPTION Update package versions to the latest as per the pattern mentioned in DotnetRuntimeMetadata.json153#>154function Update-CsprojFile([string] $path, $values) {155 $fileContent = Get-Content $path -Raw156 $updated = $false157 158 foreach ($v in $values) {159 if ($v.NewVersion) {160 $stringToReplace = "<PackageReference Include=`"$($v.Name)`" Version=`"$($v.Version)`" />"161 $newString = "<PackageReference Include=`"$($v.Name)`" Version=`"$($v.NewVersion)`" />"162 163 $fileContent = $fileContent -replace $stringToReplace, $newString164 $updated = $true165 }166 }167 168 if ($updated) {169 ($fileContent).TrimEnd() | Out-File -FilePath $path -Force170 }171}172 173function Get-DotnetUpdate {174 param (175 $channel,176 $quality,177 $qualityFallback,178 $feedUrl,179 $sdkImageVersion180 )181 182 if ($SDKVersionOverride) {183 return @{184 ShouldUpdate = $true185 NewVersion = $SDKVersionOverride186 Message = $null187 FeedUrl = $feedUrl188 Quality = $quality189 }190 }191 192 try {193 194 try {195 $URL = "http://aka.ms/dotnet/$channel/$quality/productVersion.txt"196 $latestSDKVersionString = Invoke-RestMethod -Uri $URL -ErrorAction Stop | ForEach-Object { $_.Trim() }197 $selectedQuality = $quality198 } catch {199 if ($_.exception.Response.StatusCode -eq 'NotFound') {200 Write-Verbose -Verbose -Message "No build at '$URL' found!"201 } else {202 throw $_203 }204 }205 $latestSDKversion = $latestSDKVersionString -as "System.Management.Automation.SemanticVersion"206 207 if (-not $latestSDKVersion) {208 # we did not get a version number so fall back to daily209 $URL = "http://aka.ms/dotnet/$channel/$qualityFallback/productVersion.txt"210 $latestSDKVersionString = Invoke-RestMethod -Uri $URL -ErrorAction Stop | ForEach-Object { $_.Trim() }211 $selectedQuality = $qualityFallback212 213 $latestSDKversion = $latestSDKVersionString -as "System.Management.Automation.SemanticVersion"214 if (-not $latestSDKVersion) {215 throw "No build at '$URL' found!"216 }217 }218 219 $currentVersion = [System.Management.Automation.SemanticVersion] (( Get-Content -Path "$PSScriptRoot/../global.json" -Raw | ConvertFrom-Json).sdk.version)220 221 if ($latestSDKversion -gt $currentVersion -and $null -ne $latestSDKversion.PreReleaseLabel) {222 $shouldUpdate = $true223 $newVersion = $latestSDKversion224 } else {225 $shouldUpdate = $false226 $newVersion = $latestSDKVersionString227 228 $Message = $null -eq $currentVersion.PreReleaseLabel ? "$latestSDKversion is not preview, update manually." : "No update needed."229 }230 } catch {231 Write-Verbose -Verbose "Error occurred: $_.message"232 $shouldUpdate = $false233 $newVersion = $null234 Write-Error "Error while checking .NET SDK update: $($_.message)"235 }236 237 return @{238 ShouldUpdate = $shouldUpdate239 NewVersion = $newVersion240 Message = $Message241 FeedUrl = $feedUrl242 Quality = $selectedQuality243 }244}245 246function Update-DevContainer {247 $dockerFilePath = "$PSScriptRoot/../.devcontainer/Dockerfile"248 $sdkImageVersion = (Get-Content -Raw "$PSScriptRoot/../DotnetRuntimeMetadata.json" | ConvertFrom-Json).sdk.sdkImageVersion249 250 $devContainerDocker = (Get-Content $dockerFilePath) -replace 'FROM mcr\.microsoft\.com/dotnet.*', "FROM mcr.microsoft.com/dotnet/nightly/sdk:$sdkImageVersion"251 252 $devContainerDocker | Out-File -FilePath $dockerFilePath -Force253}254 255<#256 .DESCRIPTION Update the DotnetMetadata.json file with the latest version of the SDK257 #>258function Update-DotnetRuntimeMetadata {259 param (260 [string] $newSdk261 )262 263 # -replace uses regex so in order to split on `.`, we need to use `\.` to escape the dot character.264 $sdkParts = $newSdk -split '\.'265 266 # Transform SDK Version '7.0.100-preview.5.22263.22' -> '7.0.1xx-preview5'267 $newChannel = $sdkParts[0] + "." + $sdkParts[1] + "." + ($sdkParts[2] -replace '0','x') + $sdkParts[3]268 Write-Verbose -Verbose -Message "Updating DotnetRuntimeMetadata.json with channel $newChannel"269 270 # Transform SDK Version '7.0.100-preview.5.22263.22' -> '7.0.100-preview.5'271 $newPackageVersionPattern = $sdkParts[0] + "." + $sdkParts[1] + "." + '0-' + ($sdkParts[2] -split '-')[-1] + "." + $sdkParts[3]272 Write-Verbose -Verbose -Message "Updating DotnetRuntimeMetadata.json with package filter $newPackageVersionPattern"273 274 $metadata = Get-Content -Raw "$PSScriptRoot/../DotnetRuntimeMetadata.json" | ConvertFrom-Json275 $metadata.sdk.channel = $newChannel276 $metadata.sdk.packageVersionPattern = $newPackageVersionPattern277 $metadata | ConvertTo-Json | Out-File -FilePath "$PSScriptRoot/../DotnetRuntimeMetadata.json" -Force278}279 280$dotnetMetadataPath = "$PSScriptRoot/../DotnetRuntimeMetadata.json"281$dotnetMetadataJson = Get-Content $dotnetMetadataPath -Raw | ConvertFrom-Json282$channel = $dotnetMetadataJson.sdk.channel283$nextChannel = $dotnetMetadataJson.sdk.nextChannel284$quality = $dotnetMetadataJson.sdk.quality285$qualityFallback = $dotnetMetadataJson.sdk.qualityFallback286$sdkImageVersion = $dotnetMetadataJson.sdk.sdkImageVersion287$internalfeed = $dotnetMetadataJson.internalfeed.url288 289$dotnetUpdate = Get-DotnetUpdate -channel $nextChannel -quality $quality -feedUrl $internalfeed -qualityFallback $qualityFallback -sdkImageVersion $sdkImageVersion290 291if ($dotnetUpdate.ShouldUpdate) {292 293 Import-Module "$PSScriptRoot/../build.psm1" -Force294 295 Find-Dotnet296 297 $feedname = if ($UseNuGetOrg) { 'nuget.org' } elseif ($UseInternalFeed) { 'dotnet-internal' } else { 'dotnet' }298 299 $addDotnetSource = (-not (Get-PackageSource -Name $feedname -ErrorAction SilentlyContinue))300 301 if (!$UseNuGetOrg -and $addDotnetSource) {302 $nugetFileContent = Get-Content "$PSScriptRoot/../nuget.config" -Raw303 $nugetFileSources = ([xml]($nugetFileContent)).Configuration.packagesources.add304 305 if ($feedname -ne 'dotnet-internal') {306 $dotnetFeed = $nugetFileSources | Where-Object { $_.Key -eq $feedname } | Select-Object -ExpandProperty Value307 Register-PackageSource -Name $feedname -Location $dotnetFeed -ProviderName NuGet308 Write-Verbose -Message "Register new package source $feedname" -verbose309 }310 311 if ($feedname -eq 'dotnet-internal') {312 # This NuGet feed is for internal to Microsoft use only.313 $dotnetInternalFeed = $dotnetMetadataJson.internalfeed.url314 315 $updatedNugetFile = if ($nugetFileContent.Contains('dotnet-internal')) {316 $nugetFileContent -replace ".<add key=`"dotnet-internal?.*', ' <add key=`"dotnet-internal`" value=`"$dotnetInternalFeed`" />`r`n </packageSources>"317 } else {318 $nugetFileContent -replace "</packageSources>", " <add key=`"dotnet-internal`" value=`"$dotnetInternalFeed`" />`r`n </packageSources>"319 }320 321 $updatedNugetFile | Out-File "$PSScriptRoot/../nuget.config" -Force322 323 Register-PackageSource -Name 'dotnet-internal' -Location $dotnetInternalFeed -ProviderName NuGet324 Write-Verbose -Message "Register new package source 'dotnet-internal'" -verbose325 }326 }327 328 ## Install latest version from the channel329 330 $sdkQuality = $dotnetUpdate.Quality331 $sdkVersion = if ($SDKVersionOverride) { $SDKVersionOverride } else { $dotnetUpdate.NewVersion }332 333 if (-not $RuntimeSourceFeed) {334 Install-Dotnet -Version $sdkVersion -Quality $sdkQuality -Channel $null335 }336 else {337 Install-Dotnet -Version $sdkVersion -Quality $sdkQuality -AzureFeed $RuntimeSourceFeed -FeedCredential $RuntimeSourceFeedKey -Channel $null338 }339 340 Write-Verbose -Message "Installing .NET SDK completed." -Verbose341 342 $environment = Get-EnvironmentInformation343 344 $dotnetPath = if ($environment.IsWindows) { "$env:LocalAppData\Microsoft\dotnet" } else { "$env:HOME/.dotnet" }345 346 $pathSep = [System.IO.Path]::PathSeparator347 348 if (-not (($ENV:PATH -split $pathSep) -contains "$dotnetPath")) {349 $env:PATH = "$dotnetPath" + $pathSep + "$ENV:PATH"350 }351 352 $latestSdkVersion = (dotnet --list-sdks | Select-Object -Last 1 ).Split() | Select-Object -First 1353 354 Write-Verbose -Message "Installing .NET SDK completed, version - $latestSdkVersion" -Verbose355 356 Update-GlobalJson -Version $latestSdkVersion357 358 Write-Verbose -Message "Updating global.json completed." -Verbose359 360 Update-DotnetRuntimeMetadata -newSdk $latestSdkVersion361 362 Update-PackageVersion363 364 Write-Verbose -Message "Updating project files completed." -Verbose365 366 Update-DevContainer367}368else {369 Write-Verbose -Verbose -Message $dotnetUpdate.Message370}371 