From 94ffdecd63528adcc5e5e2164f28b1fb76aaa7a0 Mon Sep 17 00:00:00 2001 From: Azure PowerShell <65331932+azure-powershell-bot@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:14:52 +0800 Subject: [PATCH] Sync tools folder from main branch to generation branch (#25871) Co-authored-by: azurepowershell --- .azure-pipelines/daily-build.yml | 2 +- tools/RunVersionController.ps1 | 27 ++-- tools/Tools.Common/Loaders/MetadataLoader.cs | 21 +-- tools/Tools.Common/Models/CmdletMetadata.cs | 5 + tools/Tools.Common/Models/CommonInfo.cs | 17 ++ tools/Tools.Common/Models/ModuleMetadata.cs | 7 +- .../Models/ParameterSetMetadata.cs | 21 ++- .../VersionController/Models/ModuleHelper.cs | 75 +++++++++ tools/VersionController/Models/ReleaseType.cs | 14 ++ .../Models/SyntaxChangelogGenerator.cs | 9 +- .../VersionController/Models/VersionBumper.cs | 152 ++++++------------ .../Models/VersionMetadataHelper.cs | 12 +- tools/VersionController/Program.cs | 90 +++++++---- 13 files changed, 286 insertions(+), 166 deletions(-) create mode 100644 tools/Tools.Common/Models/CommonInfo.cs create mode 100644 tools/VersionController/Models/ModuleHelper.cs create mode 100644 tools/VersionController/Models/ReleaseType.cs diff --git a/.azure-pipelines/daily-build.yml b/.azure-pipelines/daily-build.yml index 3019c0519f63..d180680dcd35 100644 --- a/.azure-pipelines/daily-build.yml +++ b/.azure-pipelines/daily-build.yml @@ -58,7 +58,7 @@ jobs: script: | $command = "`$PSVersionTable ` Get-PSRepository ` - ./tools/RunVersionController.ps1 -Release 'Daily Build $(today)' ` + ./tools/RunVersionController.ps1 -Release 'Daily Build $(today)' -ReleaseType $(ReleaseType)` Exit" dotnet tool run pwsh -c $command diff --git a/tools/RunVersionController.ps1 b/tools/RunVersionController.ps1 index a7d9642d585c..5f8fdc0a3ad9 100644 --- a/tools/RunVersionController.ps1 +++ b/tools/RunVersionController.ps1 @@ -21,7 +21,11 @@ Param( [string]$GalleryName = "PSGallery", [Parameter()] - [string]$ArtifactsOutputPath = "$PSScriptRoot/../artifacts/Release/" + [string]$ArtifactsOutputPath = "$PSScriptRoot/../artifacts/Release/", + + [Parameter()] + [ValidateSet("STS", "LTS")] + [string]$ReleaseType = "STS" ) enum PSVersion @@ -194,15 +198,18 @@ function Bump-AzVersion { Write-Host "Getting local Az information..." -ForegroundColor Yellow $localAz = Import-PowerShellDataFile -Path "$PSScriptRoot\Az\Az.psd1" - - Write-Host "Getting gallery Az information..." -ForegroundColor Yellow - $galleryAz = Find-Module -Name Az -Repository $GalleryName + Write-Host "Getting Az $ReleaseType information from gallery..." -ForegroundColor Yellow + if("LTS" -eq $ReleaseType){ + $galleryAz = (Find-Module -Name Az -Repository $GalleryName -AllVersions | Where-Object {([System.Version]($_.Version)).Major%2 -eq 0} | Sort-Object {[System.Version]$_.Version} -Descending)[0] + }else{ + $galleryAz = Find-Module -Name Az -Repository $GalleryName + } $versionBump = [PSVersion]::NONE $updatedModules = @() foreach ($localDependency in $localAz.RequiredModules) { - $galleryDependency = $galleryAz.Dependencies | where { $_.Name -eq $localDependency.ModuleName } + $galleryDependency = $galleryAz.Dependencies | Where-Object { $_.Name -eq $localDependency.ModuleName } if ($null -eq $galleryDependency) { $updatedModules += $localDependency.ModuleName @@ -313,7 +320,7 @@ function Update-AzPreview $Psd1Object = Import-PowerShellDataFile $Psd1FilePath $moduleName = [System.IO.Path]::GetFileName($Psd1FilePath) -replace ".psd1" $moduleVersion = $Psd1Object.ModuleVersion.ToString() - if('Az.Accounts' -eq $moduleName) + if('Az.Accounts' -eq $moduleName -and "STS" -eq $ReleaseType) { $requiredModulesString += "@{ModuleName = '$moduleName'; ModuleVersion = '$moduleVersion'; }, `n " } @@ -482,8 +489,8 @@ switch ($PSCmdlet.ParameterSetName) { "ReleaseSingleModule" { - Write-Host executing dotnet $PSScriptRoot/../artifacts/VersionController/VersionController.Netcore.dll $PSScriptRoot/../artifacts/VersionController/Exceptions $ModuleName - dotnet $PSScriptRoot/../artifacts/VersionController/VersionController.Netcore.dll $PSScriptRoot/../artifacts/VersionController/Exceptions $ModuleName + Write-Host executing dotnet $PSScriptRoot/../artifacts/VersionController/VersionController.Netcore.dll $PSScriptRoot/../artifacts/VersionController/Exceptions $ModuleName $ReleaseType + dotnet $PSScriptRoot/../artifacts/VersionController/VersionController.Netcore.dll $PSScriptRoot/../artifacts/VersionController/Exceptions $ModuleName $ReleaseType Update-AzPreview } @@ -521,8 +528,8 @@ switch ($PSCmdlet.ParameterSetName) } } - Write-Host executing dotnet $PSScriptRoot/../artifacts/VersionController/VersionController.Netcore.dll - dotnet $PSScriptRoot/../artifacts/VersionController/VersionController.Netcore.dll + Write-Host executing dotnet $PSScriptRoot/../artifacts/VersionController/VersionController.Netcore.dll $ReleaseType + dotnet $PSScriptRoot/../artifacts/VersionController/VersionController.Netcore.dll $ReleaseType $versionBump = Bump-AzVersion # Each release needs to update AzPreview.psd1 and dotnet csv diff --git a/tools/Tools.Common/Loaders/MetadataLoader.cs b/tools/Tools.Common/Loaders/MetadataLoader.cs index b79c1e0cf5a5..2e5adda0c2d5 100644 --- a/tools/Tools.Common/Loaders/MetadataLoader.cs +++ b/tools/Tools.Common/Loaders/MetadataLoader.cs @@ -30,17 +30,21 @@ namespace Tools.Common.Loaders { public class MetadataLoader { + private static string _rootPath = Path.GetFullPath(Path.Combine(Assembly.GetExecutingAssembly().Location, "..", "..", "..")); + public static ModuleMetadata GetModuleMetadata(string moduleName) { - string rootPath = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..")); - string modulePsd1Path = Directory.GetFiles(Path.Combine(rootPath, "artifacts"), $"{moduleName}.psd1", SearchOption.AllDirectories)[0]; + // bez: notice that this search way always find artifacts/Debug/{moduleName}/psd1 first, which may cause some issues + // to work around this issue, clear Debug folder if we are intended to bump version for Release + string modulePsd1Path = Directory.GetFiles(Path.Combine(_rootPath, "artifacts"), $"{moduleName}.psd1", SearchOption.AllDirectories)[0]; if (modulePsd1Path == null) { - Console.Error.WriteLine($"Cannot find {moduleName}.psd1 in {Path.Combine(rootPath, "artifacts")}!"); + Console.Error.WriteLine($"Cannot find {moduleName}.psd1 in {Path.Combine(_rootPath, "artifacts")}!"); } return GetModuleMetadata(moduleName, modulePsd1Path); } - public static ModuleMetadata GetModuleMetadata(string moduleName, string modulePsd1Path) + + private static ModuleMetadata GetModuleMetadata(string moduleName, string modulePsd1Path) { using (var powershell = PowerShell.Create(RunspaceMode.NewRunspace)) { @@ -49,15 +53,14 @@ public static ModuleMetadata GetModuleMetadata(string moduleName, string moduleP powershell.AddScript("Set-ExecutionPolicy Unrestricted -Scope Process -ErrorAction Ignore"); } powershell.AddScript("$error.clear()"); - powershell.AddScript($"Write-Debug \"current directory: { AppDomain.CurrentDomain.BaseDirectory }\""); - string rootPath = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..")); - string repoToolsPath = Path.Combine(rootPath, "tools"); + powershell.AddScript($"Write-Debug \"current directory: { Assembly.GetExecutingAssembly().Location}\""); + string repoToolsPath = Path.Combine(_rootPath, "tools"); powershell.AddScript($"cd {repoToolsPath}\\ModuleMetadata"); powershell.AddScript($"Import-Module {repoToolsPath}\\ModuleMetadata\\GetModuleMetadata.psm1"); - string accountsPsd1Path = Directory.GetFiles(Path.Combine(rootPath, "artifacts"), "Az.Accounts.psd1", SearchOption.AllDirectories)[0]; + string accountsPsd1Path = Directory.GetFiles(Path.Combine(_rootPath, "artifacts"), "Az.Accounts.psd1", SearchOption.AllDirectories)[0]; if (accountsPsd1Path == null) { - Console.Error.WriteLine($"Cannot find Az.Accounts.psd1 in {Path.Combine(rootPath, "artifacts", "Accounts")}!"); + Console.Error.WriteLine($"Cannot find Az.Accounts.psd1 in {Path.Combine(_rootPath, "artifacts", "Accounts")}!"); } powershell.AddScript($"Import-Module {accountsPsd1Path}"); powershell.AddScript($"(Get-ModuleMetadata -Psd1Path {modulePsd1Path} -ModuleName {moduleName}).ToJsonString()"); diff --git a/tools/Tools.Common/Models/CmdletMetadata.cs b/tools/Tools.Common/Models/CmdletMetadata.cs index 19fbd5c4448b..150151d4d385 100644 --- a/tools/Tools.Common/Models/CmdletMetadata.cs +++ b/tools/Tools.Common/Models/CmdletMetadata.cs @@ -354,12 +354,17 @@ public override bool Equals(Object obj) var otherParameterSet = other.ParameterSets.Find(p => string.Equals(p.Name, thisParameterSet.Name, StringComparison.OrdinalIgnoreCase)); if (otherParameterSet == null) { + // Console.WriteLine($"Parameter set {thisParameterSet.Name} in cmdlet {this.Name} is not found in new module."); return false; } cmdletsEqual &= thisParameterSet.Equals(otherParameterSet); } + /*if (this.ParameterSets.Count != other.ParameterSets.Count) + { + Console.WriteLine($"The number of parameter sets in cmdlet {this.Name} is unmatched."); + }*/ cmdletsEqual &= this.ParameterSets.Count == other.ParameterSets.Count; return cmdletsEqual; } diff --git a/tools/Tools.Common/Models/CommonInfo.cs b/tools/Tools.Common/Models/CommonInfo.cs new file mode 100644 index 000000000000..b32ab1544b78 --- /dev/null +++ b/tools/Tools.Common/Models/CommonInfo.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace VersionController.Netcore.Models +{ + public class CommonInfo + { + public static List ExcludedParameters = new List{ + "AzureRMContext", "Break", "Debug", "DefaultProfile", "EnableTestCoverage", + "ErrorAction", "ErrorVariable", "HttpPipelineAppend", "HttpPipelinePrepend", "InformationAction", + "InformationVariable", "OutBuffer", "OutVariable", "PipelineVariable", "Proxy", + "ProxyCredential", "ProxyUseDefaultCredentials", "Verbose", "WarningAction", "WarningVariable", + "ProgressAction", + // excluded runtime dynamic parameters + // "EnableTestCoverage", "TestCoverageLocation", "TargetName" + }; + } +} diff --git a/tools/Tools.Common/Models/ModuleMetadata.cs b/tools/Tools.Common/Models/ModuleMetadata.cs index a068aa372705..d67f6996b04c 100644 --- a/tools/Tools.Common/Models/ModuleMetadata.cs +++ b/tools/Tools.Common/Models/ModuleMetadata.cs @@ -87,12 +87,15 @@ public override bool Equals(Object obj) var otherCmdlet = other.Cmdlets.Find(c => thisCmdletNames.ContainsKey(c.Name) || c.AliasList.Find(a => thisCmdletNames.ContainsKey(a)) != null); if (otherCmdlet == null) { + // Console.WriteLine($"Cannot find cmdlet {thisCmdletNames} in new version."); return false; } - modulesEqual &= thisCmdlet.Equals(otherCmdlet); } - + /*if(this.Cmdlets.Count != other.Cmdlets.Count) + { + Console.WriteLine($"The number of cmdlets is unmatched in old and new module"); + }*/ modulesEqual &= this.Cmdlets.Count == other.Cmdlets.Count; return modulesEqual; } diff --git a/tools/Tools.Common/Models/ParameterSetMetadata.cs b/tools/Tools.Common/Models/ParameterSetMetadata.cs index b8662fec2faa..24dad5435617 100644 --- a/tools/Tools.Common/Models/ParameterSetMetadata.cs +++ b/tools/Tools.Common/Models/ParameterSetMetadata.cs @@ -13,7 +13,11 @@ // ---------------------------------------------------------------------------------- using System; +using System.Collections; using System.Collections.Generic; +using System.Linq; + +using VersionController.Netcore.Models; namespace Tools.Common.Models { @@ -58,13 +62,24 @@ public override bool Equals(Object obj) var otherParameter = other.Parameters.Find(p => thisParameterNames.ContainsKey(p.ParameterMetadata.Name) || p.ParameterMetadata.AliasList.Find(a => thisParameterNames.ContainsKey(a)) != null); if (otherParameter == null) { + // Console.WriteLine($"Parameter {thisParameter.ParameterMetadata.Name} in parameter set {this.Name} is not found in new module."); return false; } - paramsSetEqual &= thisParameter.Equals(otherParameter); } - paramsSetEqual &= this.Parameters.Count == other.Parameters.Count; + var curParameters = this.Parameters.Where(p => !CommonInfo.ExcludedParameters.Contains(p.ParameterMetadata.Name)).ToList(); + var otherParameters = other.Parameters.Where(p => !CommonInfo.ExcludedParameters.Contains(p.ParameterMetadata.Name)).ToList(); + /*if (curParameters.Count != otherParameters.Count) + { + Console.WriteLine($"The number of parameters in parameter set {this.Name} is not same."); + Console.WriteLine("Parameters in old version: "); + this.Parameters.ForEach(p => Console.Write(p.ParameterMetadata.Name + " ")); + Console.WriteLine(Environment.NewLine + "Parameters in new version: "); + other.Parameters.ForEach(p => Console.Write(p.ParameterMetadata.Name + " ")); + Console.WriteLine(); + }*/ + paramsSetEqual &= curParameters.Count == otherParameters.Count; return paramsSetEqual; } @@ -232,13 +247,13 @@ public override bool Equals(Object obj) { return false; } - var paramsEqual = true; paramsEqual &= this.Mandatory == other.Mandatory && this.Position == other.Position && this.ValueFromPipeline == other.ValueFromPipeline && this.ValueFromPipelineByPropertyName == other.ValueFromPipelineByPropertyName && this.ParameterMetadata.Equals(other.ParameterMetadata); + // if (!paramsEqual) Console.WriteLine($"The attributes of {this.ParameterMetadata.Name} is different in new version"); return paramsEqual; } diff --git a/tools/VersionController/Models/ModuleHelper.cs b/tools/VersionController/Models/ModuleHelper.cs new file mode 100644 index 000000000000..2f8050b38d5f --- /dev/null +++ b/tools/VersionController/Models/ModuleHelper.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; +using System.Linq; +using System.Management.Automation; + +using Tools.Common.Models; + +namespace VersionController.Netcore.Models +{ + internal class ModuleHelper + { + /// + /// Get the version of latest Az.Accounts in LTS status from PSGallery + /// + /// + internal static string GetLatestVersionFromPSGallery(string moduleName, ReleaseType releaseType = ReleaseType.STS) + { + + string version = null; + string findModuleScript = releaseType == ReleaseType.STS ? $"Find-Module {moduleName} -Repository PSGallery -AllVersions" : "Find-Module Az -Repository PSGallery -AllVersions"; + string filterRequiredReleaseTypeScript = releaseType == ReleaseType.STS ? "" : "| Where-Object {([System.Version]($_.Version)).Major%2 -eq 0}"; + string sortModuleScript = "| Sort-Object {[System.Version]$_.Version} -Descending"; + string getLastModuleVersionScript = releaseType == ReleaseType.STS ? + $"({findModuleScript}{filterRequiredReleaseTypeScript}{sortModuleScript})[0].Version" : + $"(({findModuleScript}{filterRequiredReleaseTypeScript}{sortModuleScript})[0].Dependencies | Where-Object {{$_.Name -eq '{moduleName}'}})[1]"; + using (PowerShell powershell = PowerShell.Create()) + { + powershell.AddScript(getLastModuleVersionScript); + var cmdletResult = powershell.Invoke(); + version = cmdletResult[0]?.ToString(); + } + return version; + } + + /// + /// Get version from PSGallery and TestGallery and merge into one list. + /// + /// A list of version + internal static List GetAllVersionsFromGallery(string moduleName, string psRepository) + { + HashSet galleryVersion = new HashSet(); + using (PowerShell powershell = PowerShell.Create()) + { + powershell.AddScript($"Find-Module -Name {moduleName} -Repository {psRepository} -AllowPrerelease -AllVersions"); + var cmdletResult = powershell.Invoke(); + foreach (var versionInformation in cmdletResult) + { + if (versionInformation.Properties["Version"]?.Value != null) + { + galleryVersion.Add(new AzurePSVersion(versionInformation.Properties["Version"]?.Value?.ToString())); + } + } + } + return galleryVersion.ToList(); + } + + + /// + /// Under the same Major version, check if there exist preview version in gallery that has greater version. + /// + /// True if exist a version, false otherwise. + internal static AzurePSVersion GetLatestVersionFromGalleryUnderSameMajorVersion(AzurePSVersion bumpedVersion, List galleryVersion, bool IsPreview) + { + var maxVersionInGallery = new AzurePSVersion(0, 0, 0); + + foreach (var version in galleryVersion) + { + if (version.Major == bumpedVersion.Major && (version.IsPreview == IsPreview) && version > maxVersionInGallery) + { + maxVersionInGallery = version; + } + } + return maxVersionInGallery; + } + } +} diff --git a/tools/VersionController/Models/ReleaseType.cs b/tools/VersionController/Models/ReleaseType.cs new file mode 100644 index 000000000000..472ce6396a16 --- /dev/null +++ b/tools/VersionController/Models/ReleaseType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VersionController.Netcore.Models +{ + public enum ReleaseType + { + STS, + LTS + } +} diff --git a/tools/VersionController/Models/SyntaxChangelogGenerator.cs b/tools/VersionController/Models/SyntaxChangelogGenerator.cs index 9da7142aa547..96cf848e403c 100644 --- a/tools/VersionController/Models/SyntaxChangelogGenerator.cs +++ b/tools/VersionController/Models/SyntaxChangelogGenerator.cs @@ -16,18 +16,13 @@ public class SyntaxChangelogGenerator public AnalysisLogger Logger { get; set; } public string Name { get; set; } public string CmdletDiffIssueReportLoggerName { get; set; } - private List _ignoreParameters = new List - { - "AzureRMContext", "Break", "Debug", "DefaultProfile", "EnableTestCoverage", - "ErrorAction", "ErrorVariable", "HttpPipelineAppend", "HttpPipelinePrepend", "InformationAction", - "InformationVariable", "OutBuffer", "OutVariable", "PipelineVariable", "Proxy", - "ProxyCredential", "ProxyUseDefaultCredentials", "Verbose", "WarningAction", "WarningVariable" - }; + private List _ignoreParameters = CommonInfo.ExcludedParameters; private List diffInfo = new List(); public void Analyze(String rootDirectory) { var srcDirs = Path.Combine(rootDirectory, @"src\"); var toolsCommonDirs = Path.Combine(rootDirectory, @"tools\Tools.Common"); + // bez: Will include psd1 files under test proj var manifestFiles = Directory.EnumerateFiles(srcDirs, "*.psd1", SearchOption.AllDirectories) .Where(file => !Path.GetDirectoryName(file) diff --git a/tools/VersionController/Models/VersionBumper.cs b/tools/VersionController/Models/VersionBumper.cs index 96bb4409dee3..9195f3798231 100644 --- a/tools/VersionController/Models/VersionBumper.cs +++ b/tools/VersionController/Models/VersionBumper.cs @@ -22,6 +22,8 @@ using Tools.Common.Models; using Tools.Common.Utilities; +using VersionController.Netcore.Models; + namespace VersionController.Models { public class VersionBumper @@ -42,13 +44,16 @@ public class VersionBumper public AzurePSVersion MinimalVersion { get; set; } public string PSRepositories { get; set; } - public VersionBumper(VersionFileHelper fileHelper, IList changedModules) + private ReleaseType _releaseType { get; set; } + + public VersionBumper(VersionFileHelper fileHelper, IList changedModules, ReleaseType releaseType = ReleaseType.STS) { _fileHelper = fileHelper; _metadataHelper = new VersionMetadataHelper(_fileHelper); _loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddDebug()); _logger = _loggerFactory.CreateLogger(); _changedModules = changedModules; + _releaseType = releaseType; } /// @@ -88,14 +93,15 @@ public void BumpAllVersions() private string GetLatestAccountsVersion() { var localVersion = GetLocalAccountsVersion(); - var version = GetAccountsVersionFromPSGallery(); - if(!string.IsNullOrEmpty(localVersion) && !string.IsNullOrEmpty(version)) + + var version = ModuleHelper.GetLatestVersionFromPSGallery("Az.Accounts", _releaseType); + if (!string.IsNullOrEmpty(localVersion) && !string.IsNullOrEmpty(version)) { return new System.Version(localVersion).CompareTo(value: new System.Version(version)) > 0 ? localVersion : version; - }else if (string.IsNullOrEmpty(localVersion)) + } else if (string.IsNullOrEmpty(localVersion)) { return version; - }else if (string.IsNullOrEmpty(version)) + } else if (string.IsNullOrEmpty(version)) { return localVersion; } @@ -103,7 +109,6 @@ private string GetLatestAccountsVersion() { throw new Exception("Can not find the latest version for Az.Accounts."); } - } /// @@ -114,7 +119,7 @@ private string GetLocalAccountsVersion() { // Assume in outputModuleDirectory/../Az.Accounts/Az.Accounts.psd1 exists - var accountsOutputDirectory = Path.Combine(Directory.GetParent(_fileHelper.OutputModuleDirectory).FullName, "Az.Accounts"); + var accountsOutputDirectory = Path.Combine(Directory.GetParent(_fileHelper.OutputModuleDirectory).FullName, "Az.Accounts"); var accountsManifest = Directory.GetFiles(accountsOutputDirectory, "Az.Accounts.psd1", SearchOption.TopDirectoryOnly) .FirstOrDefault(); @@ -131,23 +136,6 @@ private string GetLocalAccountsVersion() return localPreview ? null : localVersion; } - /// - /// Get the latest version of Az.Accounts from PSGallery - /// - /// - private string GetAccountsVersionFromPSGallery() - { - string version = null; - using (PowerShell powershell = PowerShell.Create()) - { - powershell.AddScript("(Find-Module Az.Accounts -Repository PSGallery -AllVersions | Sort-Object {[System.Version]$_.Version} -Descending)[0].Version"); - var cmdletResult = powershell.Invoke(); - version = cmdletResult[0]?.ToString(); - } - // Console.WriteLine("The version of Az.Accounts in PSGallery is " + version ); - return version; - } - /// /// Get the local version of the module. /// @@ -161,7 +149,7 @@ public Tuple GetOldVersion() bool localPreview = false; // bool localPreview = false, psPreview = false, testPreview = false; var moduleName = _fileHelper.ModuleName; - + using (PowerShell powershell = PowerShell.Create()) { powershell.AddScript("$metadata = Test-ModuleManifest -Path " + _fileHelper.OutputModuleManifestPath + ";$metadata.Version;$metadata.PrivateData.PSData.Prerelease"); @@ -190,7 +178,7 @@ private string GetBumpedVersion() var versionBump = _metadataHelper.GetVersionBumpUsingSerialized(); if (string.Equals(moduleName, "Az.Accounts")) { - var commonCodeVersionBump = _metadataHelper.GetVersionBumpForCommonCode(); + var commonCodeVersionBump = _metadataHelper.GetVersionBumpForCommonCode(_releaseType); if (commonCodeVersionBump == Version.MAJOR) { throw new Exception("Breaking change detected in common code."); @@ -221,38 +209,26 @@ private string GetBumpedVersion() versionBump = Version.MINOR; } - var bumpedVersion = GetBumpedVersionByType(new AzurePSVersion(_oldVersion), versionBump); - - List galleryVersion = GetGalleryVersion(); + List galleryVersion = ModuleHelper.GetAllVersionsFromGallery(_fileHelper.ModuleName, PSRepositories); + AzurePSVersion bumpedVersion = galleryVersion.Count == 0 ? new AzurePSVersion(0, 1, 0) : GetBumpedVersionByType(new AzurePSVersion(_oldVersion), versionBump); + AzurePSVersion maxGAedVersionInGallery = ModuleHelper.GetLatestVersionFromGalleryUnderSameMajorVersion(bumpedVersion, galleryVersion, false); + AzurePSVersion maxPreGAedVersionInGallery = ModuleHelper.GetLatestVersionFromGalleryUnderSameMajorVersion(bumpedVersion, galleryVersion, true); - AzurePSVersion maxGalleryGAVersion = new AzurePSVersion("0.0.0"); - foreach(var version in galleryVersion) + // Continue bumping version until bumpedVersion is higher than maxGAedVersionInGallery in same major version + while (maxGAedVersionInGallery >= bumpedVersion) { - if (version.Major == bumpedVersion.Major && !version.IsPreview && version > maxGalleryGAVersion) - { - maxGalleryGAVersion = version; - } + string warningMsg = $"The GA version of {moduleName} in gallery ({maxGAedVersionInGallery}) is greater or equal to the bumped version({bumpedVersion}). Continue bumping version for {moduleName}."; + _logger.LogWarning(warningMsg); + bumpedVersion = GetBumpedVersionByType(bumpedVersion, versionBump); } - if (galleryVersion.Count == 0) - { - bumpedVersion = new AzurePSVersion(0, 1, 0); - } - else if (maxGalleryGAVersion >= bumpedVersion) + // Continue bumping version until bumpedVersion is higher than maxPreGAedVersionInGallery in same major version + while (maxPreGAedVersionInGallery >= bumpedVersion) { - string errorMsg = $"The GA version of {moduleName} in gallery ({maxGalleryGAVersion}) is greater or equal to the bumped version({bumpedVersion})."; - _logger.LogError(errorMsg); - throw new Exception(errorMsg); + _logger.LogWarning($"There is greater preview version in the gallery. Continue bumping version for ${moduleName}"); + bumpedVersion = GetBumpedVersionByType(bumpedVersion, Version.MINOR); } - else if (HasGreaterPreviewVersion(bumpedVersion, galleryVersion)) - { - while(HasGreaterPreviewVersion(bumpedVersion, galleryVersion)) - { - bumpedVersion = GetBumpedVersionByType(bumpedVersion, Version.MINOR); - } - _logger.LogWarning("There existed greater preview version in the gallery."); - } - + return bumpedVersion.ToString(); } @@ -280,45 +256,6 @@ private AzurePSVersion GetBumpedVersionByType(AzurePSVersion version, Version ty return bumpedVersion; } - /// - /// Get version from PSGallery and TestGallery and merge into one list. - /// - /// A list of version - private List GetGalleryVersion() - { - var moduleName = _fileHelper.ModuleName; - HashSet galleryVersion = new HashSet(); - using (PowerShell powershell = PowerShell.Create()) - { - powershell.AddScript($"Find-Module -Name {moduleName} -Repository {PSRepositories} -AllowPrerelease -AllVersions"); - var cmdletResult = powershell.Invoke(); - foreach (var versionInformation in cmdletResult) - { - if(versionInformation.Properties["Version"]?.Value != null) - { - galleryVersion.Add(new AzurePSVersion(versionInformation.Properties["Version"]?.Value?.ToString())); - } - } - } - return galleryVersion.ToList(); - } - - /// - /// Under the same Major version, check if there exist preview version in gallery that has greater version. - /// - /// True if exist a version, false otherwise. - private bool HasGreaterPreviewVersion(AzurePSVersion version, List galleryVersion) - { - foreach (var gaVersion in galleryVersion) - { - if (gaVersion.Major == version.Major && gaVersion >= version) - { - return true; - } - } - return false; - } - /// /// Bumps the version of the nested module in the serialized module metadata JSON file. /// @@ -369,7 +306,8 @@ private void UpdateRollupModuleManifest() var pattern = @"ModuleName(\s*)=(\s*)(['\""])" + moduleName + @"(['\""])(\s*);(\s*)RequiredVersion(\s*)=(\s*)(['\""])" + _oldVersion + @"(['\""])"; var updatedFile = file.Select(l => Regex.Replace(l, pattern, "ModuleName = '" + moduleName + "'; RequiredVersion = '" + _newVersion + "'")); var pattern2 = @"ModuleName(\s*)=(\s*)(['\""])" + moduleName + @"(['\""])(\s*);(\s*)ModuleVersion(\s*)=(\s*)(['\""])" + _oldVersion + @"(['\""])"; - var updatedFile2 = updatedFile.Select(l => Regex.Replace(l, pattern2, "ModuleName = '" + moduleName + "'; ModuleVersion = '" + _newVersion + "'")); + var updatedFile2 = _releaseType == ReleaseType.STS ? updatedFile.Select(l => Regex.Replace(l, pattern2, "ModuleName = '" + moduleName + "'; ModuleVersion = '" + _newVersion + "'")) : + updatedFile.Select(l => Regex.Replace(l, pattern2, "ModuleName = '" + moduleName + "'; RequiredVersion = '" + _newVersion + "'")); File.WriteAllLines(rollupModuleManifestPath, updatedFile2); } @@ -448,14 +386,28 @@ private void UpdateOutputModuleManifest(List releaseNotes) // Get required module list and update Az,Accounts' version var getRequiredModulesScript = "Import-LocalizedData -BaseDirectory " + outputModuleDirectory + " -FileName " + Path.GetFileName(outputModuleManifestPath) + " -BindingVariable moduleInfo;"; getRequiredModulesScript += "$requiredModules = @();"; - getRequiredModulesScript += "$moduleInfo.RequiredModules.ForEach({ " + - "if ($_.ModuleName -eq \"Az.Accounts\"){ " + - " $requiredModules += @{ModuleName = \"Az.Accounts\"; ModuleVersion = \"" + _accountsVersion + "\"} " + - "}else " + - "{ " + - " $requiredModules += $_ " + - "} " + - "});"; + if(_releaseType == ReleaseType.STS) + { + getRequiredModulesScript += "$moduleInfo.RequiredModules.ForEach({ " + + "if ($_.ModuleName -eq \"Az.Accounts\"){ " + + " $requiredModules += @{ModuleName = \"Az.Accounts\"; ModuleVersion = \"" + _accountsVersion + "\"} " + + "}else " + + "{ " + + " $requiredModules += $_ " + + "} " + + "});"; + } + else + { + getRequiredModulesScript += "$moduleInfo.RequiredModules.ForEach({ " + + "if ($_.ModuleName -eq \"Az.Accounts\"){ " + + " $requiredModules += @{ModuleName = \"Az.Accounts\"; RequiredVersion = \"" + _accountsVersion + "\"} " + + "}else " + + "{ " + + " $requiredModules += $_ " + + "} " + + "});"; + } // Update module manifest script += getRequiredModulesScript; diff --git a/tools/VersionController/Models/VersionMetadataHelper.cs b/tools/VersionController/Models/VersionMetadataHelper.cs index ef71fc468ad5..319b07372602 100644 --- a/tools/VersionController/Models/VersionMetadataHelper.cs +++ b/tools/VersionController/Models/VersionMetadataHelper.cs @@ -26,6 +26,8 @@ using Tools.Common.Loggers; using Tools.Common.Models; +using VersionController.Netcore.Models; + namespace VersionController.Models { public class VersionMetadataHelper @@ -136,17 +138,19 @@ private void CheckBreakingChangesInTypes( /// made to the common code to preserve backwards-compatibility. /// /// Version bump that should be applied to the common code library. - public Version GetVersionBumpForCommonCode() + internal Version GetVersionBumpForCommonCode(ReleaseType releaseType) { var outputModuleDirectory = _fileHelper.OutputModuleDirectory; var galleryModuleDirectory = _fileHelper.GalleryModuleDirectory; - Console.WriteLine("Saving Az.Accounts from the PowerShell Gallery to check common code changes. This will take a few seconds."); Version versionBump = Version.PATCH; var issueLogger = _logger.CreateLogger("BreakingChangeIssues.csv"); IEnumerable commonAssemblies = null; + + Console.WriteLine("Saving Az.Accounts from the PowerShell Gallery to check common code changes. This will take a few seconds."); using (PowerShell powershell = PowerShell.Create()) { - powershell.AddScript("Save-Module -Name Az.Accounts -Repository PSGallery -Path " + outputModuleDirectory ); + // for LTS, check latest LTS Accounts instead of STS Accounts. + powershell.AddScript($"Save-Module -Name Az.Accounts -Repository PSGallery -Path {outputModuleDirectory} -RequiredVersion {ModuleHelper.GetLatestVersionFromPSGallery("Az.Accounts", releaseType)}"); var cmdletResult = powershell.Invoke(); } @@ -155,7 +159,7 @@ public Version GetVersionBumpForCommonCode() { powershell.AddScript("$metadata = Test-ModuleManifest -Path " + Path.Combine(galleryModuleVersionDirectory, "Az.Accounts.psd1") + ";$metadata.RequiredAssemblies"); var cmdletResult = powershell.Invoke(); - commonAssemblies = cmdletResult.Select(c => c.ToString().Substring(2)).Where(s => Regex.IsMatch(s, "Microsoft.*.Commands.*")); + commonAssemblies = cmdletResult.Select(c => c.ToString()).Where(s => s.StartsWith("Microsoft.Azure.PowerShell")); } try diff --git a/tools/VersionController/Program.cs b/tools/VersionController/Program.cs index 1f9760ff4d1b..156dfe625ea7 100644 --- a/tools/VersionController/Program.cs +++ b/tools/VersionController/Program.cs @@ -32,7 +32,9 @@ public class Program private static SyntaxChangelogGenerator _syntaxChangelogGenerator = new SyntaxChangelogGenerator(); private static Dictionary _minimalVersion = new Dictionary(); private static List _projectDirectories, _outputDirectories; - private static string _rootDirectory, _moduleNameFilter; + private static string _rootDirectory, _moduleNameFilter, _exceptionsDirectory; + private static ReleaseType _releaseType = ReleaseType.STS; + private static bool _generateSyntaxChangelog = true; private const string Psd1NameExtension = ".psd1"; @@ -47,45 +49,73 @@ public class Program "ExampleIssues.csv" }; public static void Main(string[] args) + { + // bez: to do: change positional parameters to dictionary parameters + Initialize(args); + ConsolidateExceptionFiles(_exceptionsDirectory); + ValidateManifest(); + if (_generateSyntaxChangelog && _releaseType == ReleaseType.STS) { + GenerateSyntaxChangelog(_rootDirectory); + } + BumpVersions(); + } + + private static void Initialize(string[] args) { var executingAssemblyPath = Assembly.GetExecutingAssembly().Location; var versionControllerDirectory = Directory.GetParent(executingAssemblyPath).FullName; var artifactsDirectory = Directory.GetParent(versionControllerDirectory).FullName; - var syntaxChangelog = true; - _rootDirectory = Directory.GetParent(artifactsDirectory).FullName; - _projectDirectories = new List{ Path.Combine(_rootDirectory, @"src\") }.Where((d) => Directory.Exists(d)).ToList(); - _outputDirectories = new List{ Path.Combine(_rootDirectory, @"artifacts\Release\") }.Where((d) => Directory.Exists(d)).ToList(); - + _rootDirectory = Directory.GetParent(artifactsDirectory).FullName; + _projectDirectories = new List { Path.Combine(_rootDirectory, @"src\") }.Where((d) => Directory.Exists(d)).ToList(); + _outputDirectories = new List { Path.Combine(_rootDirectory, @"artifacts\Release\") }.Where((d) => Directory.Exists(d)).ToList(); + _moduleNameFilter = string.Empty; + _exceptionsDirectory = Path.Combine(versionControllerDirectory, "Exceptions"); SharedAssemblyLoader.Load(_outputDirectories.FirstOrDefault()); - var exceptionsDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Exceptions"); - if (args != null && args.Length > 0) - { - exceptionsDirectory = args[0]; - syntaxChangelog = false; - } - if (!Directory.Exists(exceptionsDirectory)) + if(null != args) { - throw new ArgumentException("Please provide a path to the Exceptions folder in the output directory (artifacts/Exceptions)."); - } + switch (args.Length) + { + case 0: + break; + case 1: + Enum.TryParse(args[0], out _releaseType); + break; + default: + if (args.Length > 0 && !string.IsNullOrEmpty(args[0])) + { + _exceptionsDirectory = args[0]; + _generateSyntaxChangelog = false; + } - _moduleNameFilter = string.Empty; - if (args != null && args.Length > 1) + if (!Directory.Exists(_exceptionsDirectory)) + { + throw new ArgumentException("Please provide a path to the Exceptions folder in the output directory (artifacts/Exceptions)."); + } + if (args.Length > 1 && !string.IsNullOrEmpty(args[1])) + { + _moduleNameFilter = args[1] + Psd1NameExtension; + } + if(args.Length > 2 && !string.IsNullOrEmpty(args[2])) + { + Enum.TryParse(args[2], out _releaseType); + } + break; + } + } + } + + private static void GenerateSyntaxChangelog(string projectDirectories) + { + try { - _moduleNameFilter = args[1] + Psd1NameExtension; + _syntaxChangelogGenerator.Analyze(projectDirectories); } - - ConsolidateExceptionFiles(exceptionsDirectory); - ValidateManifest(); - if (syntaxChangelog) { - GenerateSyntaxChangelog(_rootDirectory); + catch (Exception ex) { + Console.WriteLine($"Warning: Cannot generate syntax change log because {ex.Message}"); } - BumpVersions(); - } - private static void GenerateSyntaxChangelog(string _projectDirectories) - { - _syntaxChangelogGenerator.Analyze(_projectDirectories); } + private static void ValidateManifest() { foreach (var directory in _projectDirectories) @@ -209,7 +239,7 @@ private static void BumpVersions() } //Make Az.Accounts as the last module to calculate - changedModules = changedModules.OrderByDescending(c => c == "Az.Accounts" ? "" : c).ToList(); + changedModules = changedModules.OrderByDescending(c => c.Contains("Az.Accounts") ? "" : c).ToList(); foreach (var projectModuleManifestPath in changedModules) { var moduleFileName = Path.GetFileName(projectModuleManifestPath); @@ -230,7 +260,7 @@ private static void BumpVersions() var outputModuleManifestFile = outputModuleManifest.FirstOrDefault(); - _versionBumper = new VersionBumper(new VersionFileHelper(_rootDirectory, outputModuleManifestFile, projectModuleManifestPath), changedModules); + _versionBumper = new VersionBumper(new VersionFileHelper(_rootDirectory, outputModuleManifestFile, projectModuleManifestPath), changedModules, _releaseType); _versionBumper.PSRepositories = targetRepositories; if (_minimalVersion.ContainsKey(moduleName)) {