diff --git a/.azure-pipelines/live-test.yml b/.azure-pipelines/live-test.yml index 0fe1f8b2c6eb..5fd7947d39b6 100644 --- a/.azure-pipelines/live-test.yml +++ b/.azure-pipelines/live-test.yml @@ -180,37 +180,37 @@ stages: psVersion: ${{ parameters.ps_latest }} dotnetVersion: ${{ parameters.dotnet_sdk_8 }} - - template: util/live-test-steps.yml - parameters: - name: 'ps_7_2_x_macOS' - vmImage: ${{ parameters.os_macos }} - osType: 'MacOS' - psVersion: ${{ parameters.ps_7_2_x }} - dotnetVersion: ${{ parameters.dotnet_sdk_6 }} - - - template: util/live-test-steps.yml - parameters: - name: 'ps_7_3_x_macOS' - vmImage: ${{ parameters.os_macos }} - osType: 'MacOS' - psVersion: ${{ parameters.ps_7_3_x }} - dotnetVersion: ${{ parameters.dotnet_sdk_7 }} - - - template: util/live-test-steps.yml - parameters: - name: 'ps_7_4_x_macOS' - vmImage: ${{ parameters.os_macos }} - osType: 'MacOS' - psVersion: ${{ parameters.ps_7_4_x }} - dotnetVersion: ${{ parameters.dotnet_sdk_8 }} - - - template: util/live-test-steps.yml - parameters: - name: 'ps_latest_macOS' - vmImage: ${{ parameters.os_macos }} - osType: 'MacOS' - psVersion: ${{ parameters.ps_latest }} - dotnetVersion: ${{ parameters.dotnet_sdk_8 }} + # - template: util/live-test-steps.yml + # parameters: + # name: 'ps_7_2_x_macOS' + # vmImage: ${{ parameters.os_macos }} + # osType: 'MacOS' + # psVersion: ${{ parameters.ps_7_2_x }} + # dotnetVersion: ${{ parameters.dotnet_sdk_6 }} + + # - template: util/live-test-steps.yml + # parameters: + # name: 'ps_7_3_x_macOS' + # vmImage: ${{ parameters.os_macos }} + # osType: 'MacOS' + # psVersion: ${{ parameters.ps_7_3_x }} + # dotnetVersion: ${{ parameters.dotnet_sdk_7 }} + + # - template: util/live-test-steps.yml + # parameters: + # name: 'ps_7_4_x_macOS' + # vmImage: ${{ parameters.os_macos }} + # osType: 'MacOS' + # psVersion: ${{ parameters.ps_7_4_x }} + # dotnetVersion: ${{ parameters.dotnet_sdk_8 }} + + # - template: util/live-test-steps.yml + # parameters: + # name: 'ps_latest_macOS' + # vmImage: ${{ parameters.os_macos }} + # osType: 'MacOS' + # psVersion: ${{ parameters.ps_latest }} + # dotnetVersion: ${{ parameters.dotnet_sdk_8 }} - stage: Report displayName: Send Report diff --git a/.azure-pipelines/release-test.yml b/.azure-pipelines/release-test.yml index bb2146f52401..8a6ed3e73e3d 100644 --- a/.azure-pipelines/release-test.yml +++ b/.azure-pipelines/release-test.yml @@ -136,42 +136,42 @@ jobs: psVersion: ${{ parameters.preview_ps }} netCoreVersion: ${{ parameters.netCoreVersion_8 }} -- template: util/smoke-test-steps.yml - parameters: - name: 'MacOS_PS7_2_X_SmokeTest' - agentPoolName: ${{ variables.macOsAgentPoolName }} - agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} - psVersion: ${{ parameters.ps7_2 }} - netCoreVersion: ${{ parameters.netCoreVersion }} - -- template: util/smoke-test-steps.yml - parameters: - name: 'MacOS_PS7_3_X_SmokeTest' - agentPoolName: ${{ variables.macOsAgentPoolName }} - agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} - psVersion: ${{ parameters.ps7_3 }} - netCoreVersion: ${{ parameters.netCoreVersion_7 }} - -- template: util/smoke-test-steps.yml - parameters: - name: 'MacOS_PS7_4_X_SmokeTest' - agentPoolName: ${{ variables.macOsAgentPoolName }} - agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} - psVersion: ${{ parameters.ps7_4 }} - netCoreVersion: ${{ parameters.netCoreVersion_8 }} - -- template: util/smoke-test-steps.yml - parameters: - name: 'MacOS_Latest_PS_SmokeTest' - agentPoolName: ${{ variables.macOsAgentPoolName }} - agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} - psVersion: ${{ parameters.latest_ps }} - netCoreVersion: ${{ parameters.netCoreVersion_8 }} - -- template: util/smoke-test-steps.yml - parameters: - name: 'MacOS_Preview_PS_SmokeTest' - agentPoolName: ${{ variables.macOsAgentPoolName }} - agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} - psVersion: ${{ parameters.preview_ps }} - netCoreVersion: ${{ parameters.netCoreVersion_8 }} +# - template: util/smoke-test-steps.yml +# parameters: +# name: 'MacOS_PS7_2_X_SmokeTest' +# agentPoolName: ${{ variables.macOsAgentPoolName }} +# agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} +# psVersion: ${{ parameters.ps7_2 }} +# netCoreVersion: ${{ parameters.netCoreVersion }} + +# - template: util/smoke-test-steps.yml +# parameters: +# name: 'MacOS_PS7_3_X_SmokeTest' +# agentPoolName: ${{ variables.macOsAgentPoolName }} +# agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} +# psVersion: ${{ parameters.ps7_3 }} +# netCoreVersion: ${{ parameters.netCoreVersion_7 }} + +# - template: util/smoke-test-steps.yml +# parameters: +# name: 'MacOS_PS7_4_X_SmokeTest' +# agentPoolName: ${{ variables.macOsAgentPoolName }} +# agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} +# psVersion: ${{ parameters.ps7_4 }} +# netCoreVersion: ${{ parameters.netCoreVersion_8 }} + +# - template: util/smoke-test-steps.yml +# parameters: +# name: 'MacOS_Latest_PS_SmokeTest' +# agentPoolName: ${{ variables.macOsAgentPoolName }} +# agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} +# psVersion: ${{ parameters.latest_ps }} +# netCoreVersion: ${{ parameters.netCoreVersion_8 }} + +# - template: util/smoke-test-steps.yml +# parameters: +# name: 'MacOS_Preview_PS_SmokeTest' +# agentPoolName: ${{ variables.macOsAgentPoolName }} +# agentPoolVMImage: ${{ variables.macOsAgentPoolVMImage }} +# psVersion: ${{ parameters.preview_ps }} +# netCoreVersion: ${{ parameters.netCoreVersion_8 }} diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index c7b5a2658657..d639c4da0c84 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,12 +6,12 @@ ## Mandatory Checklist -- Please choose the target release of Azure PowerShell +- Please choose the target release of Azure PowerShell. (⚠️**Target release** is a different concept from **API readiness**. Please click below links for details.) - [ ] [General release](../blob/main/CONTRIBUTING.md#target-release-types) - [ ] [Public preview](../blob/main/CONTRIBUTING.md#target-release-types) - [ ] [Private preview](../blob/main/CONTRIBUTING.md#target-release-types) - [ ] [Engineering build](../blob/main/CONTRIBUTING.md#target-release-types) - - [ ] N/A + - [ ] No need for a release - [ ] Check this box to confirm: **I have read the [_Submitting Changes_](../blob/main/CONTRIBUTING.md#submitting-changes) section of [`CONTRIBUTING.md`](../blob/main/CONTRIBUTING.md) and reviewed the following information:** diff --git a/tools/BreakingChanges/GenerateMigrationExcel.ps1 b/tools/BreakingChanges/GenerateMigrationExcel.ps1 index e95a80dd87f3..1697aa6d2883 100644 --- a/tools/BreakingChanges/GenerateMigrationExcel.ps1 +++ b/tools/BreakingChanges/GenerateMigrationExcel.ps1 @@ -12,51 +12,55 @@ # limitations under the License. # ---------------------------------------------------------------------------------- +# The generated excel will contains one sheet. The title is: +# ModuleName, CmdletName, Description, Before, After, TeamMember, PR + +# .\tools\BreakingChanges\GenerateMigrationExcel.ps1 -ExcelPath (Join-Path $env:USERPROFILE "Documents" "2024-05-21-Az-12.0-Breaking-Change-Migration-Guide.xlsx") + #Requires -Modules PSExcel [CmdletBinding()] Param( [Parameter()] [string]$ExcelPath ) -$ExcelPath = Resolve-Path -Path $ExcelPath If (Test-Path $ExcelPath) { Remove-Item $ExcelPath } $Path = [System.IO.Path]::Combine($PSScriptRoot, '..', '..') Set-Location -Path $Path -Get-ChildItem -Path .\tools\StaticAnalysis\Exceptions\ -Filter BreakingChangeIssues.csv -Recurse -dotnet msbuild /t:Clean -dotnet msbuild /t:Build -dotnet msbuild /t:StaticAnalysis -$BreakingChangeItems = Import-Csv .\artifacts\StaticAnalysisResults\BreakingChangeIssues.csv -$TotalTable = @{} -foreach ($BreakingChangeItem in $BreakingChangeItems) { - $ModuleName = 'Az' + $BreakingChangeItem.AssemblyFileName.Replace("Microsoft.Azure.PowerShell.Cmdlets", "").Replace('.dll', '') - $CmdletName = $BreakingChangeItem.Target - $Description = $BreakingChangeItem.Description - if (-not $TotalTable.ContainsKey($ModuleName)) { - $TotalTable.Add($ModuleName, @{}) - } - if (-not $TotalTable[$ModuleName].ContainsKey($CmdletName)) { - $TotalTable[$ModuleName].Add($CmdletName, "") - } - $TotalTable[$ModuleName][$CmdletName] = $TotalTable[$ModuleName][$CmdletName] + "$Description`n" -} +# dotnet msbuild /t:Clean +# dotnet msbuild /t:Build +# dotnet msbuild /t:StaticAnalysis +Import-Module (Join-Path $PSScriptRoot "Get-BreakingChangeMetadata.ps1") -Force +$ArtifactsPath = [System.IO.Path]::Combine($Path, "artifacts", "Debug") + +$AllModuleList = Get-ChildItem -Path $ArtifactsPath -Filter Az.* | ForEach-Object { $_.Name } $Data = New-Object System.Collections.ArrayList -foreach ($ModuleName in $TotalTable.Keys) { - foreach ($CmdletName in $TotalTable[$ModuleName].Keys) { - $Tmp = New-Object -TypeName PSObject -Property @{ +ForEach ($ModuleName In $AllModuleList) +{ + Write-Host "Processing Module: $ModuleName" + $ModuleBreakingChangeInfo = Get-BreakingChangeMetadata -ArtifactsPath $ArtifactsPath -ModuleName $ModuleName + If ($ModuleBreakingChangeInfo.Count -eq 0) + { + Continue + } + + ForEach ($CmdletName In ($ModuleBreakingChangeInfo.Keys | Sort-Object)) + { + Write-Host "Processing Cmdlet: $ModuleName - $CmdletName" + $NewRow = New-Object -TypeName PSObject -Property @{ ModuleName = $ModuleName CmdletName = $CmdletName - Description = $TotalTable[$ModuleName][$CmdletName] + Description = Export-BreakingChangeMessageOfCmdlet $ModuleBreakingChangeInfo[$CmdletName] Before = $Null After = $Null TeamMember = $Null PR = $Null - } | Select ModuleName, CmdletName, Description, Before, After, TeamMember, PR - $Null = $Data.Add($Tmp) + } | Select-Object ModuleName, CmdletName, Description, Before, After, TeamMember, PR + $Null = $Data.Add($NewRow) } } + $Data | Export-XLSX -Path $ExcelPath Write-Host "Excel is generated at $ExcelPath. Please goto edit it." \ No newline at end of file diff --git a/tools/BreakingChanges/Get-BreakingChangeMetadata.ps1 b/tools/BreakingChanges/Get-BreakingChangeMetadata.ps1 new file mode 100644 index 000000000000..f997757889c0 --- /dev/null +++ b/tools/BreakingChanges/Get-BreakingChangeMetadata.ps1 @@ -0,0 +1,616 @@ + +$AllParameterSetsName = "AllParameterSets" + +Function Test-TypeIsGenericBreakingChangeAttribute +{ + [CmdletBinding()] + Param( + [Parameter()] + [System.Reflection.TypeInfo[]] + $type + ) + ForEach ($loopType in $type) + { + While ($loopType.Name -ne "Object") + { + If ($loopType.Name -eq "GenericBreakingChangeAttribute") + { + Return $True + } + $loopType = $loopType.BaseType + } + } + Return $False +} + +Function Test-TypeIsGenericBreakingChangeWithVersionAttribute +{ + [CmdletBinding()] + Param( + [Parameter()] + [System.Reflection.TypeInfo[]] + $type + ) + ForEach ($loopType in $type) + { + While ($loopType.Name -ne "Object") + { + If ($loopType.Name -eq "GenericBreakingChangeWithVersionAttribute") + { + Return $True + } + $loopType = $loopType.BaseType + } + } + Return $False +} + +Function Get-AttributeSpecificMessage +{ + [CmdletBinding()] + Param ( + [Parameter()] + [string] + $ModuleName, + + [Parameter()] + [System.Object] + $attribute + ) + If ($Null -ne $attribute.ChangeDescription) + { + $Message = $attribute.ChangeDescription + } + Else + { + # GenericBreakingChangeAttribute is the base class of the BreakingChangeAttribute classes and have a protected method named as Get-AttributeSpecIficMessage. + # We can use this to get the specIfic message to show on document. + $Method = $attribute.GetType().GetMethod('GetAttributeSpecificMessage', [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance) + + $Message = $Method.Invoke($attribute, @()).Trim() + } + If (-Not ($Message.StartsWith("-"))) + { + $Message = "- $Message" + } + $Message += "`n- This change is expected to take effect from $ModuleName version: $($attribute.DeprecateByVersion) and Az version: $($attribute.DeprecateByAzVersion)" + Return $Message +} + +# Get the breaking change info of the cmdlet Parameter. +Function Find-ParameterBreakingChange +{ + [CmdletBinding()] + Param ( + [Parameter()] + [string] + $ModuleName, + + [Parameter()] + [System.Management.Automation.ParameterMetadata] + $ParameterInfo + ) + + ForEach ($attribute In $ParameterInfo.Attributes) + { + If (Test-TypeIsGenericBreakingChangeWithVersionAttribute $attribute.TypeId) + { + Return Get-AttributeSpecIficMessage -ModuleName $ModuleName -attribute $attribute + } + } + + Return $Null +} + +# Get the breaking change info of the cmdlet. +Function Find-CmdletBreakingChange +{ + [CmdletBinding()] + Param ( + [Parameter()] + [string] + $ModuleName, + + [Parameter()] + [System.Management.Automation.CommandInfo] + $CmdletInfo + ) + $Result = @{} + Write-Debug "Find-CmdletBreakingChange: $ModuleName $($CmdletInfo.Name)" + #Region get breaking change info of cmdlet + $customAttributes = $CmdletInfo.ImplementingType.GetTypeInfo().GetCustomAttributes([System.object], $true) + ForEach ($customAttribute In $customAttributes) + { + If (Test-TypeIsGenericBreakingChangeWithVersionAttribute $customAttribute.TypeId) + { + $tmp = Get-AttributeSpecIficMessage -ModuleName $ModuleName -attribute $customAttribute + If (-not $Result.ContainsKey($AllParameterSetsName)) + { + $Null = $Result.Add($AllParameterSetsName, @{ + CmdletBreakingChange = [System.Collections.ArrayList]::New(@($tmp)) + }) + } + ElseIf (-not $Result[$AllParameterSetsName].ContainsKey("CmdletBreakingChange")) + { + $Result[$AllParameterSetsName]["CmdletBreakingChange"] = [System.Collections.ArrayList]::New(@(tmp)) + } + Else + { + $Null = $Result[$AllParameterSetsName]["CmdletBreakingChange"].Add($tmp) + } + } + } + #EndRegion + + #Region get breaking change info of parameters + $ParameterBreakingChanges = @{} + ForEach ($ParameterInfo In $CmdletInfo.Parameters.values) + { + Write-Debug "Find-CmdletBreakingChange -> Find-ParameterBreakingChange $ModuleName $($ModuleName.GetType())" + $ParameterBreakingChange = Find-ParameterBreakingChange -ModuleName $ModuleName -ParameterInfo $ParameterInfo + If ($Null -ne $ParameterBreakingChange) + { + $Null = $ParameterBreakingChanges.Add($ParameterInfo.Name, $ParameterBreakingChange) + } + } + If ($ParameterBreakingChanges.Count -ne 0) + { + If (-not $Result.ContainsKey($AllParameterSetsName)) + { + $Null = $Result.Add($AllParameterSetsName, @{ + ParameterBreakingChange = $ParameterBreakingChanges + }) + } + Else + { + $Result[$AllParameterSetsName].Add("ParameterBreakingChange", $ParameterBreakingChanges) + } + } + #EndRegion + + Return $Result +} + +Function Get-BreakingChangeInfoOfModule +{ + [CmdletBinding()] + Param ( + [Parameter()] + [String] + $ArtifactsPath, + [Parameter()] + [String] + $ModuleName + ) + $BreakingChangeMessages = @{} + $ModuleRoot = [System.IO.Path]::Combine($ArtifactsPath, $ModuleName) + + #Region Generated modules + $Dlls = Get-ChildItem -Path $ModuleRoot -Filter *.private.dll -Recurse + ForEach ($Dll In $Dlls) + { + $CustomRoot = [System.IO.Path]::Combine($Dll, '..', '..', 'custom') + $Psm1Path = Get-ChildItem -Path $CustomRoot -Filter *.psm1 + $BreakingChangeMessage = Get-BreakingChangeOfGeneratedModule -DllPath $Dll -Psm1Path $Psm1Path + $BreakingChangeMessages += $BreakingChangeMessage + } + #EndRegion + + #Region SDK based modules + If (-Not (Test-Path -Path ([System.IO.Path]::Combine($ModuleRoot, "generated")))) + { + $psd1Path = [System.IO.Path]::Combine($ModuleRoot, "$ModuleName.psd1") + Import-Module $psd1Path + $ModuleInfo = Get-Module $ModuleName + ForEach ($cmdletInfo In $ModuleInfo.ExportedCmdlets.Values) + { + $cmdletBreakingChangeInfo = Find-CmdletBreakingChange -ModuleName $ModuleName -CmdletInfo $cmdletInfo + If ($cmdletBreakingChangeInfo.Count -ne 0) + { + $BreakingChangeMessages.Add($cmdletInfo.Name, $cmdletBreakingChangeInfo) + } + } + } + #EndRegion + + Return $BreakingChangeMessages +} + +Function Get-BreakingChangeMessageFromGeneratedAttribute +{ + [CmdletBinding()] + Param ( + [Parameter()] + [Object] + $Attribute, + [Parameter()] + [Object] + $AttributeType + ) + $StringBuilder = [System.Text.StringBuilder]::New() + + # $GetAttributeSpecificMessageMethod = $AttributeType.GetMethod('GetAttributeSpecificMessage', [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance) + # $BreakingChangeMessage = $GetAttributeSpecificMessageMethod.Invoke($Attribute, @()) + # $Null = $StringBuilder.Append($BreakingChangeMessage) + + $PrintCustomAttributeInfo = [System.Action[System.String]]{ + Param([System.String] $s) + $StringBuilder.Append($s) + } + $PrintCustomAttributeInfoMethod = $AttributeType.GetMethod('PrintCustomAttributeInfo', [System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Instance) + $Null = $PrintCustomAttributeInfoMethod.Invoke($Attribute, @($PrintCustomAttributeInfo)) + + Return $StringBuilder.ToString().Trim() +} + +Function Get-BreakingChangeOfGeneratedModule +{ + [CmdletBinding()] + Param ( + [Parameter()] + [String] + $DllPath, + [Parameter()] + [String] + $Psm1Path + ) + $AllBreakingChangeMessages = @{} + + #Region Dll + $Dll = [Reflection.Assembly]::LoadFrom($DllPath) + $Cmdlets = $Dll.ExportedTypes | Where-Object { $_.CustomAttributes.Attributetype.name -contains "GeneratedAttribute" -and ($_.CustomAttributes.Attributetype.name -notcontains "InternalExportAttribute") } + + $BreakingChangeCmdlets = $Cmdlets | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.CustomAttributes.Attributetype } + ForEach ($BreakingChangeCmdlet in $BreakingChangeCmdlets) + { + $ParameterSetName = $BreakingChangeCmdlet.Name + $CmdletAttribute = $BreakingChangeCmdlet.CustomAttributes | Where-Object { $_.AttributeType.Name -eq 'CmdletAttribute' } + $Verb = $CmdletAttribute.ConstructorArguments[0].Value + $Noun = $CmdletAttribute.ConstructorArguments[1].Value.Split('_')[0] + $CmdletName = "$Verb-$Noun" + + $BreakingChangeAttributes = $BreakingChangeCmdlet.CustomAttributes | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.Attributetype } + $AttributeTypeList = $BreakingChangeAttributes | Select-Object -ExpandProperty AttributeType -Unique + ForEach ($AttributeType In $AttributeTypeList) + { + $AttributeList = $BreakingChangeCmdlet.GetCustomAttributes($AttributeType, $true) + ForEach ($Attribute In $AttributeList) + { + $BreakingChangeMessage = Get-BreakingChangeMessageFromGeneratedAttribute -Attribute $Attribute -AttributeType $AttributeType + + If (-not $AllBreakingChangeMessages.ContainsKey($CmdletName)) + { + $AllBreakingChangeMessages.Add($CmdletName, @{}) + } + If (-not $AllBreakingChangeMessages[$CmdletName].ContainsKey($ParameterSetName)) + { + $AllBreakingChangeMessages[$CmdletName].Add($ParameterSetName, @{ + "CmdletBreakingChange" = [System.Collections.ArrayList]::New(@($BreakingChangeMessage)) + }) + } + Else { + $AllBreakingChangeMessages[$CmdletName][$ParameterSetName].Add($BreakingChangeMessage) + } + } + } + } + + ForEach ($Cmdlet in $Cmdlets) + { + $ParameterBreakingChangeMessage = @{} + $ParameterSetName = $Cmdlet.Name + $CmdletAttribute = $Cmdlet.CustomAttributes | Where-Object { $_.AttributeType.Name -eq 'CmdletAttribute' } + $Verb = $CmdletAttribute.ConstructorArguments[0].Value + $Noun = $CmdletAttribute.ConstructorArguments[1].Value.Split('_')[0] + $CmdletName = "$Verb-$Noun" + + $Parameters = $Cmdlet.DeclaredMembers | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.CustomAttributes.Attributetype } + ForEach ($Parameter In $Parameters) + { + $ParameterName = $Parameter.Name + $ParameterAttribute = $Parameter.CustomAttributes | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.AttributeType } + $AttributeTypeList = $ParameterAttribute | Select-Object -ExpandProperty AttributeType -Unique + ForEach ($AttributeType In $AttributeTypeList) + { + $AttributeList = $Parameter.GetCustomAttributes($AttributeType, $true) + ForEach ($Attribute In $AttributeList) + { + $BreakingChangeMessage = Get-BreakingChangeMessageFromGeneratedAttribute -Attribute $Attribute -AttributeType $AttributeType + $ParameterBreakingChangeMessage.Add($ParameterName, $BreakingChangeMessage) + } + } + + } + If ($ParameterBreakingChangeMessage.Count -ne 0) + { + If (-not $AllBreakingChangeMessages.ContainsKey($CmdletName)) + { + $AllBreakingChangeMessages.Add($CmdletName, @{}) + } + If (-not $AllBreakingChangeMessages[$CmdletName].ContainsKey($ParameterSetName)) + { + $AllBreakingChangeMessages[$CmdletName].Add($ParameterSetName, @{ + "ParameterBreakingChange" = $ParameterBreakingChangeMessage + }) + } + Else { + $AllBreakingChangeMessages[$CmdletName][$ParameterSetName].Add('ParameterBreakingChange', $ParameterBreakingChangeMessage) + } + } + } + #EndRegion + + #Region psm1 + Import-Module $Psm1Path -Force + $ModuleName = (Get-Item $Psm1Path).BaseName + $ModuleInfo = Get-Module $ModuleName + $BreakingChangeCmdlets = $ModuleInfo.ExportedCommands.Values | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.ScriptBlock.Attributes.TypeId } + ForEach ($BreakingChangeCmdlet In $BreakingChangeCmdlets) + { + $CmdletName = $BreakingChangeCmdlet.Name + $BreakingChangeAttributes = $BreakingChangeCmdlet.ScriptBlock.Attributes | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.TypeId } + ForEach ($BreakingChangeAttribute In $BreakingChangeAttributes) + { + $BreakingChangeMessage = Get-BreakingChangeMessageFromGeneratedAttribute -Attribute $BreakingChangeAttribute -AttributeType $BreakingChangeAttribute.TypeId + If (-not $AllBreakingChangeMessages.ContainsKey($CmdletName)) + { + $AllBreakingChangeMessages.Add($CmdletName, @{}) + } + If (-not $AllBreakingChangeMessages[$CmdletName].ContainsKey($AllParameterSetsName)) + { + $AllBreakingChangeMessages[$CmdletName].Add($AllParameterSetsName, @{ + "CmdletBreakingChange" = [System.Collections.ArrayList]::New(@($BreakingChangeMessage)) + }) + } + Else { + $AllBreakingChangeMessages[$CmdletName][$AllParameterSetsName].Add($BreakingChangeMessage) + } + } + } + + $Cmdlets = $ModuleInfo.ExportedCommands.Values + ForEach ($Cmdlet In $Cmdlets) + { + $CmdletName = $Cmdlet.Name + $ParameterBreakingChangeMessage = @{} + $Parameters = $Cmdlet.Parameters.Values | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.Attributes.TypeId } + ForEach ($Parameter In $Parameters) + { + $ParameterName = $Parameter.Name + $ParameterAttribute = $Parameter.Attributes | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.TypeId } + $BreakingChangeMessage = Get-BreakingChangeMessageFromGeneratedAttribute -Attribute $ParameterAttribute -AttributeType $ParameterAttribute.TypeId + $ParameterBreakingChangeMessage.Add($ParameterName, $BreakingChangeMessage) + } + If ($ParameterBreakingChangeMessage.Count -ne 0) + { + If (-not $AllBreakingChangeMessages.ContainsKey($CmdletName)) + { + $AllBreakingChangeMessages.Add($CmdletName, @{}) + } + If (-not $AllBreakingChangeMessages[$CmdletName].ContainsKey($AllParameterSetsName)) + { + $AllBreakingChangeMessages[$CmdletName].Add($AllParameterSetsName, @{ + "ParameterBreakingChange" = $ParameterBreakingChangeMessage + }) + } + Else { + $AllBreakingChangeMessages[$CmdletName][$AllParameterSetsName].Add('ParameterBreakingChange', $ParameterBreakingChangeMessage) + } + } + } + #EndRegion + + Return $AllBreakingChangeMessages +} + +Function Merge-BreakingChangeInfoOfModule +{ + [CmdletBinding()] + Param ( + [Parameter()] + [HashTable] + $ModuleBreakingChangeInfo + ) + $Result = @{} + ForEach ($CmdletName In $ModuleBreakingChangeInfo.Keys) + { + $Result[$CmdletName] = Merge-BreakingChangeInfoOfCmdlet $ModuleBreakingChangeInfo[$CmdletName] + } + + Return $Result +} + +# This function use to merge the breaking changes in all the parameter sets into key $AllParameterSetsName +# and remove them from their parameter set. Also remove the empty properties after this. +Function Merge-BreakingChangeInfoOfCmdlet +{ + [CmdletBinding()] + Param ( + [Parameter()] + [HashTable] + $CmdletBreakingChangeInfo + ) + If ($CmdletBreakingChangeInfo.ContainsKey($AllParameterSetsName)) + { + $AllParameterSets = $CmdletBreakingChangeInfo[$AllParameterSetsName] + $CmdletBreakingChangeInfo.Remove($AllParameterSetsName) + } + Else + { + $AllParameterSets = @{ + CmdletBreakingChange = [System.Collections.ArrayList]::New(); + ParameterBreakingChange = @{} + } + } + $ParameterSets = [System.Collections.ArrayList]::New($CmdletBreakingChangeInfo.Keys) + ForEach ($ParameterSetName In $ParameterSets) + { + $ParameterSetBreakingChange = $CmdletBreakingChangeInfo[$ParameterSetName] + #Region Move the CmdletBreakingChange contains in all parameter sets to AllParameterSets + If ($ParameterSetBreakingChange.ContainsKey("CmdletBreakingChange")) + { + $CmdletBreakingChanges = [System.Collections.ArrayList]::New($ParameterSetBreakingChange["CmdletBreakingChange"]) + ForEach ($CmdletBreakingChange In $CmdletBreakingChanges) + { + $ContainsInAllParameterSets = $True + ForEach ($PSN In $CmdletBreakingChangeInfo.Keys) + { + If ($CmdletBreakingChangeInfo[$PSN].ContainsKey("CmdletBreakingChange")) + { + If (-not $CmdletBreakingChangeInfo[$PSN]["CmdletBreakingChange"].Contains($CmdletBreakingChange)) + { + $ContainsInAllParameterSets = $False + } + } + Else + { + $ContainsInAllParameterSets = $False + } + } + If ($ContainsInAllParameterSets) + { + $Null = $AllParameterSets['CmdletBreakingChange'].Add($CmdletBreakingChange) + ForEach ($PSN In $CmdletBreakingChangeInfo.Keys) + { + $Null = $CmdletBreakingChangeInfo[$PSN]["CmdletBreakingChange"].Remove($CmdletBreakingChange) + } + } + } + } + #EndRegion + + #Region Move the ParameterBreakingChange contains in all parameter sets to AllParameterSets + If ($ParameterSetBreakingChange.ContainsKey("ParameterBreakingChange")) + { + $ParameterBreakingChange = $ParameterSetBreakingChange["ParameterBreakingChange"] + $Parameters = [System.Collections.ArrayList]::New($ParameterBreakingChange.Keys) + ForEach ($ParameterName In $Parameters) + { + $ContainsInAllParameterSets = $True + ForEach ($PSN In $CmdletBreakingChangeInfo.Keys) + { + If ($CmdletBreakingChangeInfo[$PSN].ContainsKey("ParameterBreakingChange")) + { + If (-Not $CmdletBreakingChangeInfo[$PSN]["ParameterBreakingChange"].Contains($ParameterName)) + { + $ContainsInAllParameterSets = $False + } + ElseIf ($CmdletBreakingChangeInfo[$PSN]["ParameterBreakingChange"][$ParameterName] -Ne $ParameterBreakingChange[$ParameterName]) + { + $ContainsInAllParameterSets = $False + } + } + Else + { + $ContainsInAllParameterSets = $False + } + } + If ($ContainsInAllParameterSets) + { + $Null = $AllParameterSets["ParameterBreakingChange"].Add($ParameterName, $ParameterBreakingChange[$ParameterName]) + ForEach ($PSN In $CmdletBreakingChangeInfo.Keys) + { + $CmdletBreakingChangeInfo[$PSN]["ParameterBreakingChange"].Remove($ParameterName) + } + } + } + } + #EndRegion + + #Region Clear the empty properties + If ($ParameterSetBreakingChange.ContainsKey("CmdletBreakingChange") -and + $ParameterSetBreakingChange["CmdletBreakingChange"].Count -eq 0) + { + $Null = $ParameterSetBreakingChange.Remove("CmdletBreakingChange") + } + If ($ParameterSetBreakingChange.ContainsKey("ParameterBreakingChange") -and + $ParameterSetBreakingChange["ParameterBreakingChange"].Count -eq 0) + { + $Null = $ParameterSetBreakingChange.Remove("ParameterBreakingChange") + } + If ($ParameterSetBreakingChange.Count -eq 0) + { + $Null = $CmdletBreakingChangeInfo.Remove($ParameterSetName) + } + #EndRegion + } + + #Region Add AllParameterSets to result + If ($AllParameterSets['CmdletBreakingChange'].Count -eq 0) + { + $Null = $AllParameterSets.Remove("CmdletBreakingChange") + } + If ($AllParameterSets['ParameterBreakingChange'].Count -eq 0) + { + $Null = $AllParameterSets.Remove("ParameterBreakingChange") + } + $CmdletBreakingChangeInfo[$AllParameterSetsName] = $AllParameterSets + #EndRegion + + Return $CmdletBreakingChangeInfo +} + + + +Function Export-BreakingChangeMessageOfCmdlet +{ + [CmdletBinding()] + Param ( + [Parameter()] + [HashTable] + $CmdletBreakingChangeInfo + ) + $Result = '' + ForEach ($ParameterSetName In ($CmdletBreakingChangeInfo.Keys | Sort-Object)) + { + If ($CmdletBreakingChangeInfo[$ParameterSetName].ContainsKey('CmdletBreakingChange')) + { + If ($ParameterSetName -ne $AllParameterSetsName) + { + $Result += "`n- Cmdlet breaking-change will happen to parameter set ``$ParameterSetName```n" + } + Else + { + $Result += "`n- Cmdlet breaking-change will happen to all parameter sets`n" + } + ForEach ($breakingChangeMsg In $CmdletBreakingChangeInfo[$ParameterSetName]['CmdletBreakingChange']) + { + $Result += (("$breakingChangeMsg" -Split "`n" | ForEach-Object { Return " $_" }) -Join "`n") + $Result += "`n" + } + } + If ($CmdletBreakingChangeInfo[$ParameterSetName].ContainsKey('ParameterBreakingChange')) + { + If ($ParameterSetName -eq $AllParameterSetsName) + { + $Result += "`n- Parameter breaking-change will happen to all parameter sets`n" + } + Else + { + $Result += "`n- Parameter breaking-change will happen to parameter set ``$ParameterSetName```n" + } + ForEach ($parameterName In ($CmdletBreakingChangeInfo[$ParameterSetName]['ParameterBreakingChange'].Keys | Sort-Object)) + { + $Result += " - ``-$parameterName```n" + $Result += ((($CmdletBreakingChangeInfo[$ParameterSetName]['ParameterBreakingChange'][$parameterName] -Split "`n" | ForEach-Object { Return " $_" }) -Join "`n") + "`n") + } + } + } + + Return $Result +} + +Function Get-BreakingChangeMetadata +{ + [CmdletBinding()] + Param ( + [Parameter()] + [String] + $ArtifactsPath, + [Parameter()] + [String] + $ModuleName + ) + $ModuleBreakingChangeInfo = Get-BreakingChangeInfoOfModule -ModuleName $ModuleName -ArtifactsPath $ArtifactsPath + return Merge-BreakingChangeInfoOfModule -ModuleBreakingChangeInfo $ModuleBreakingChangeInfo +} \ No newline at end of file diff --git a/tools/BreakingChanges/GetUpcomingBreakingChange.ps1 b/tools/BreakingChanges/GetUpcomingBreakingChange.ps1 index f53ada55344a..f9bb83cc1e67 100644 --- a/tools/BreakingChanges/GetUpcomingBreakingChange.ps1 +++ b/tools/BreakingChanges/GetUpcomingBreakingChange.ps1 @@ -19,604 +19,7 @@ # Export-AllBreakingChangeMessageUnderArtifacts -ArtifactsPath ./artifacts/Debug/ -MarkdownPath ./documentation/breaking-changes/upcoming-breaking-changes.md # ``` -$AllParameterSetsName = "AllParameterSets" - -Function Test-TypeIsGenericBreakingChangeAttribute -{ - [CmdletBinding()] - Param( - [Parameter()] - [System.Reflection.TypeInfo[]] - $type - ) - ForEach ($loopType in $type) - { - While ($loopType.Name -ne "Object") - { - If ($loopType.Name -eq "GenericBreakingChangeAttribute") - { - Return $True - } - $loopType = $loopType.BaseType - } - } - Return $False -} - -Function Test-TypeIsGenericBreakingChangeWithVersionAttribute -{ - [CmdletBinding()] - Param( - [Parameter()] - [System.Reflection.TypeInfo[]] - $type - ) - ForEach ($loopType in $type) - { - While ($loopType.Name -ne "Object") - { - If ($loopType.Name -eq "GenericBreakingChangeWithVersionAttribute") - { - Return $True - } - $loopType = $loopType.BaseType - } - } - Return $False -} - -Function Get-AttributeSpecificMessage -{ - [CmdletBinding()] - Param ( - [Parameter()] - [string] - $ModuleName, - - [Parameter()] - [System.Object] - $attribute - ) - If ($Null -ne $attribute.ChangeDescription) - { - $Message = $attribute.ChangeDescription - } - Else - { - # GenericBreakingChangeAttribute is the base class of the BreakingChangeAttribute classes and have a protected method named as Get-AttributeSpecIficMessage. - # We can use this to get the specIfic message to show on document. - $Method = $attribute.GetType().GetMethod('GetAttributeSpecificMessage', [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance) - - $Message = $Method.Invoke($attribute, @()).Trim() - } - If (-Not ($Message.StartsWith("-"))) - { - $Message = "- $Message" - } - $Message += "`n- This change is expected to take effect from $ModuleName version: $($attribute.DeprecateByVersion) and Az version: $($attribute.DeprecateByAzVersion)" - Return $Message -} - -# Get the breaking change info of the cmdlet Parameter. -Function Find-ParameterBreakingChange -{ - [CmdletBinding()] - Param ( - [Parameter()] - [string] - $ModuleName, - - [Parameter()] - [System.Management.Automation.ParameterMetadata] - $ParameterInfo - ) - - ForEach ($attribute In $ParameterInfo.Attributes) - { - If (Test-TypeIsGenericBreakingChangeWithVersionAttribute $attribute.TypeId) - { - Return Get-AttributeSpecIficMessage -ModuleName $ModuleName -attribute $attribute - } - } - - Return $Null -} - -# Get the breaking change info of the cmdlet. -Function Find-CmdletBreakingChange -{ - [CmdletBinding()] - Param ( - [Parameter()] - [string] - $ModuleName, - - [Parameter()] - [System.Management.Automation.CommandInfo] - $CmdletInfo - ) - $Result = @{} - Write-Debug "Find-CmdletBreakingChange: $ModuleName $($CmdletInfo.Name)" - #Region get breaking change info of cmdlet - $customAttributes = $CmdletInfo.ImplementingType.GetTypeInfo().GetCustomAttributes([System.object], $true) - ForEach ($customAttribute In $customAttributes) - { - If (Test-TypeIsGenericBreakingChangeWithVersionAttribute $customAttribute.TypeId) - { - $tmp = Get-AttributeSpecIficMessage -ModuleName $ModuleName -attribute $customAttribute - If (-not $Result.ContainsKey($AllParameterSetsName)) - { - $Null = $Result.Add($AllParameterSetsName, @{ - CmdletBreakingChange = [System.Collections.ArrayList]::New(@($tmp)) - }) - } - ElseIf (-not $Result[$AllParameterSetsName].ContainsKey("CmdletBreakingChange")) - { - $Result[$AllParameterSetsName]["CmdletBreakingChange"] = [System.Collections.ArrayList]::New(@(tmp)) - } - Else - { - $Null = $Result[$AllParameterSetsName]["CmdletBreakingChange"].Add($tmp) - } - } - } - #EndRegion - - #Region get breaking change info of parameters - $ParameterBreakingChanges = @{} - ForEach ($ParameterInfo In $CmdletInfo.Parameters.values) - { - Write-Debug "Find-CmdletBreakingChange -> Find-ParameterBreakingChange $ModuleName $($ModuleName.GetType())" - $ParameterBreakingChange = Find-ParameterBreakingChange -ModuleName $ModuleName -ParameterInfo $ParameterInfo - If ($Null -ne $ParameterBreakingChange) - { - $Null = $ParameterBreakingChanges.Add($ParameterInfo.Name, $ParameterBreakingChange) - } - } - If ($ParameterBreakingChanges.Count -ne 0) - { - If (-not $Result.ContainsKey($AllParameterSetsName)) - { - $Null = $Result.Add($AllParameterSetsName, @{ - ParameterBreakingChange = $ParameterBreakingChanges - }) - } - Else - { - $Result[$AllParameterSetsName].Add("ParameterBreakingChange", $ParameterBreakingChanges) - } - } - #EndRegion - - Return $Result -} - -Function Get-BreakingChangeInfoOfModule -{ - [CmdletBinding()] - Param ( - [Parameter()] - [String] - $ArtifactsPath, - [Parameter()] - [String] - $ModuleName - ) - $BreakingChangeMessages = @{} - $ModuleRoot = [System.IO.Path]::Combine($ArtifactsPath, $ModuleName) - - #Region Generated modules - $Dlls = Get-ChildItem -Path $ModuleRoot -Filter *.private.dll -Recurse - ForEach ($Dll In $Dlls) - { - $CustomRoot = [System.IO.Path]::Combine($Dll, '..', '..', 'custom') - $Psm1Path = Get-ChildItem -Path $CustomRoot -Filter *.psm1 - $BreakingChangeMessage = Get-BreakingChangeOfGeneratedModule -DllPath $Dll -Psm1Path $Psm1Path - $BreakingChangeMessages += $BreakingChangeMessage - } - #EndRegion - - #Region SDK based modules - If (-Not (Test-Path -Path ([System.IO.Path]::Combine($ModuleRoot, "generated")))) - { - $psd1Path = [System.IO.Path]::Combine($ModuleRoot, "$ModuleName.psd1") - Import-Module $psd1Path - $ModuleInfo = Get-Module $ModuleName - ForEach ($cmdletInfo In $ModuleInfo.ExportedCmdlets.Values) - { - $cmdletBreakingChangeInfo = Find-CmdletBreakingChange -ModuleName $ModuleName -CmdletInfo $cmdletInfo - If ($cmdletBreakingChangeInfo.Count -ne 0) - { - $BreakingChangeMessages.Add($cmdletInfo.Name, $cmdletBreakingChangeInfo) - } - } - } - #EndRegion - - Return $BreakingChangeMessages -} - -Function Get-BreakingChangeMessageFromGeneratedAttribute -{ - [CmdletBinding()] - Param ( - [Parameter()] - [Object] - $Attribute, - [Parameter()] - [Object] - $AttributeType - ) - $StringBuilder = [System.Text.StringBuilder]::New() - - # $GetAttributeSpecificMessageMethod = $AttributeType.GetMethod('GetAttributeSpecificMessage', [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance) - # $BreakingChangeMessage = $GetAttributeSpecificMessageMethod.Invoke($Attribute, @()) - # $Null = $StringBuilder.Append($BreakingChangeMessage) - - $PrintCustomAttributeInfo = [System.Action[System.String]]{ - Param([System.String] $s) - $StringBuilder.Append($s) - } - $PrintCustomAttributeInfoMethod = $AttributeType.GetMethod('PrintCustomAttributeInfo', [System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Instance) - $Null = $PrintCustomAttributeInfoMethod.Invoke($Attribute, @($PrintCustomAttributeInfo)) - - Return $StringBuilder.ToString().Trim() -} - -Function Get-BreakingChangeOfGeneratedModule -{ - [CmdletBinding()] - Param ( - [Parameter()] - [String] - $DllPath, - [Parameter()] - [String] - $Psm1Path - ) - $AllBreakingChangeMessages = @{} - - #Region Dll - $Dll = [Reflection.Assembly]::LoadFrom($DllPath) - $Cmdlets = $Dll.ExportedTypes | Where-Object { $_.CustomAttributes.Attributetype.name -contains "GeneratedAttribute" -and ($_.CustomAttributes.Attributetype.name -notcontains "InternalExportAttribute") } - - $BreakingChangeCmdlets = $Cmdlets | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.CustomAttributes.Attributetype } - ForEach ($BreakingChangeCmdlet in $BreakingChangeCmdlets) - { - $ParameterSetName = $BreakingChangeCmdlet.Name - $CmdletAttribute = $BreakingChangeCmdlet.CustomAttributes | Where-Object { $_.AttributeType.Name -eq 'CmdletAttribute' } - $Verb = $CmdletAttribute.ConstructorArguments[0].Value - $Noun = $CmdletAttribute.ConstructorArguments[1].Value.Split('_')[0] - $CmdletName = "$Verb-$Noun" - - $BreakingChangeAttributes = $BreakingChangeCmdlet.CustomAttributes | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.Attributetype } - $AttributeTypeList = $BreakingChangeAttributes | Select-Object -ExpandProperty AttributeType -Unique - ForEach ($AttributeType In $AttributeTypeList) - { - $AttributeList = $BreakingChangeCmdlet.GetCustomAttributes($AttributeType, $true) - ForEach ($Attribute In $AttributeList) - { - $BreakingChangeMessage = Get-BreakingChangeMessageFromGeneratedAttribute -Attribute $Attribute -AttributeType $AttributeType - - If (-not $AllBreakingChangeMessages.ContainsKey($CmdletName)) - { - $AllBreakingChangeMessages.Add($CmdletName, @{}) - } - If (-not $AllBreakingChangeMessages[$CmdletName].ContainsKey($ParameterSetName)) - { - $AllBreakingChangeMessages[$CmdletName].Add($ParameterSetName, @{ - "CmdletBreakingChange" = [System.Collections.ArrayList]::New(@($BreakingChangeMessage)) - }) - } - Else { - $AllBreakingChangeMessages[$CmdletName][$ParameterSetName].Add($BreakingChangeMessage) - } - } - } - } - - ForEach ($Cmdlet in $Cmdlets) - { - $ParameterBreakingChangeMessage = @{} - $ParameterSetName = $Cmdlet.Name - $CmdletAttribute = $Cmdlet.CustomAttributes | Where-Object { $_.AttributeType.Name -eq 'CmdletAttribute' } - $Verb = $CmdletAttribute.ConstructorArguments[0].Value - $Noun = $CmdletAttribute.ConstructorArguments[1].Value.Split('_')[0] - $CmdletName = "$Verb-$Noun" - - $Parameters = $Cmdlet.DeclaredMembers | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.CustomAttributes.Attributetype } - ForEach ($Parameter In $Parameters) - { - $ParameterName = $Parameter.Name - $ParameterAttribute = $Parameter.CustomAttributes | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.AttributeType } - $AttributeTypeList = $ParameterAttribute | Select-Object -ExpandProperty AttributeType -Unique - ForEach ($AttributeType In $AttributeTypeList) - { - $AttributeList = $Parameter.GetCustomAttributes($AttributeType, $true) - ForEach ($Attribute In $AttributeList) - { - $BreakingChangeMessage = Get-BreakingChangeMessageFromGeneratedAttribute -Attribute $Attribute -AttributeType $AttributeType - $ParameterBreakingChangeMessage.Add($ParameterName, $BreakingChangeMessage) - } - } - - } - If ($ParameterBreakingChangeMessage.Count -ne 0) - { - If (-not $AllBreakingChangeMessages.ContainsKey($CmdletName)) - { - $AllBreakingChangeMessages.Add($CmdletName, @{}) - } - If (-not $AllBreakingChangeMessages[$CmdletName].ContainsKey($ParameterSetName)) - { - $AllBreakingChangeMessages[$CmdletName].Add($ParameterSetName, @{ - "ParameterBreakingChange" = $ParameterBreakingChangeMessage - }) - } - Else { - $AllBreakingChangeMessages[$CmdletName][$ParameterSetName].Add('ParameterBreakingChange', $ParameterBreakingChangeMessage) - } - } - } - #EndRegion - - #Region psm1 - Import-Module $Psm1Path -Force - $ModuleName = (Get-Item $Psm1Path).BaseName - $ModuleInfo = Get-Module $ModuleName - $BreakingChangeCmdlets = $ModuleInfo.ExportedCommands.Values | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.ScriptBlock.Attributes.TypeId } - ForEach ($BreakingChangeCmdlet In $BreakingChangeCmdlets) - { - $CmdletName = $BreakingChangeCmdlet.Name - $BreakingChangeAttributes = $BreakingChangeCmdlet.ScriptBlock.Attributes | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.TypeId } - ForEach ($BreakingChangeAttribute In $BreakingChangeAttributes) - { - $BreakingChangeMessage = Get-BreakingChangeMessageFromGeneratedAttribute -Attribute $BreakingChangeAttribute -AttributeType $BreakingChangeAttribute.TypeId - If (-not $AllBreakingChangeMessages.ContainsKey($CmdletName)) - { - $AllBreakingChangeMessages.Add($CmdletName, @{}) - } - If (-not $AllBreakingChangeMessages[$CmdletName].ContainsKey($AllParameterSetsName)) - { - $AllBreakingChangeMessages[$CmdletName].Add($AllParameterSetsName, @{ - "CmdletBreakingChange" = [System.Collections.ArrayList]::New(@($BreakingChangeMessage)) - }) - } - Else { - $AllBreakingChangeMessages[$CmdletName][$AllParameterSetsName].Add($BreakingChangeMessage) - } - } - } - - $Cmdlets = $ModuleInfo.ExportedCommands.Values - ForEach ($Cmdlet In $Cmdlets) - { - $CmdletName = $Cmdlet.Name - $ParameterBreakingChangeMessage = @{} - $Parameters = $Cmdlet.Parameters.Values | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.Attributes.TypeId } - ForEach ($Parameter In $Parameters) - { - $ParameterName = $Parameter.Name - $ParameterAttribute = $Parameter.Attributes | Where-Object { Test-TypeIsGenericBreakingChangeAttribute $_.TypeId } - $BreakingChangeMessage = Get-BreakingChangeMessageFromGeneratedAttribute -Attribute $ParameterAttribute -AttributeType $ParameterAttribute.TypeId - $ParameterBreakingChangeMessage.Add($ParameterName, $BreakingChangeMessage) - } - If ($ParameterBreakingChangeMessage.Count -ne 0) - { - If (-not $AllBreakingChangeMessages.ContainsKey($CmdletName)) - { - $AllBreakingChangeMessages.Add($CmdletName, @{}) - } - If (-not $AllBreakingChangeMessages[$CmdletName].ContainsKey($AllParameterSetsName)) - { - $AllBreakingChangeMessages[$CmdletName].Add($AllParameterSetsName, @{ - "ParameterBreakingChange" = $ParameterBreakingChangeMessage - }) - } - Else { - $AllBreakingChangeMessages[$CmdletName][$AllParameterSetsName].Add('ParameterBreakingChange', $ParameterBreakingChangeMessage) - } - } - } - #EndRegion - - Return $AllBreakingChangeMessages -} - -Function Merge-BreakingChangeInfoOfModule -{ - [CmdletBinding()] - Param ( - [Parameter()] - [HashTable] - $ModuleBreakingChangeInfo - ) - $Result = @{} - ForEach ($CmdletName In $ModuleBreakingChangeInfo.Keys) - { - $Result[$CmdletName] = Merge-BreakingChangeInfoOfCmdlet $ModuleBreakingChangeInfo[$CmdletName] - } - - Return $Result -} - -# This function use to merge the breaking changes in all the parameter sets into key $AllParameterSetsName -# and remove them from their parameter set. Also remove the empty properties after this. -Function Merge-BreakingChangeInfoOfCmdlet -{ - [CmdletBinding()] - Param ( - [Parameter()] - [HashTable] - $CmdletBreakingChangeInfo - ) - If ($CmdletBreakingChangeInfo.ContainsKey($AllParameterSetsName)) - { - $AllParameterSets = $CmdletBreakingChangeInfo[$AllParameterSetsName] - $CmdletBreakingChangeInfo.Remove($AllParameterSetsName) - } - Else - { - $AllParameterSets = @{ - CmdletBreakingChange = [System.Collections.ArrayList]::New(); - ParameterBreakingChange = @{} - } - } - $ParameterSets = [System.Collections.ArrayList]::New($CmdletBreakingChangeInfo.Keys) - ForEach ($ParameterSetName In $ParameterSets) - { - $ParameterSetBreakingChange = $CmdletBreakingChangeInfo[$ParameterSetName] - #Region Move the CmdletBreakingChange contains in all parameter sets to AllParameterSets - If ($ParameterSetBreakingChange.ContainsKey("CmdletBreakingChange")) - { - $CmdletBreakingChanges = [System.Collections.ArrayList]::New($ParameterSetBreakingChange["CmdletBreakingChange"]) - ForEach ($CmdletBreakingChange In $CmdletBreakingChanges) - { - $ContainsInAllParameterSets = $True - ForEach ($PSN In $CmdletBreakingChangeInfo.Keys) - { - If ($CmdletBreakingChangeInfo[$PSN].ContainsKey("CmdletBreakingChange")) - { - If (-not $CmdletBreakingChangeInfo[$PSN]["CmdletBreakingChange"].Contains($CmdletBreakingChange)) - { - $ContainsInAllParameterSets = $False - } - } - Else - { - $ContainsInAllParameterSets = $False - } - } - If ($ContainsInAllParameterSets) - { - $Null = $AllParameterSets['CmdletBreakingChange'].Add($CmdletBreakingChange) - ForEach ($PSN In $CmdletBreakingChangeInfo.Keys) - { - $Null = $CmdletBreakingChangeInfo[$PSN]["CmdletBreakingChange"].Remove($CmdletBreakingChange) - } - } - } - } - #EndRegion - - #Region Move the ParameterBreakingChange contains in all parameter sets to AllParameterSets - If ($ParameterSetBreakingChange.ContainsKey("ParameterBreakingChange")) - { - $ParameterBreakingChange = $ParameterSetBreakingChange["ParameterBreakingChange"] - $Parameters = [System.Collections.ArrayList]::New($ParameterBreakingChange.Keys) - ForEach ($ParameterName In $Parameters) - { - $ContainsInAllParameterSets = $True - ForEach ($PSN In $CmdletBreakingChangeInfo.Keys) - { - If ($CmdletBreakingChangeInfo[$PSN].ContainsKey("ParameterBreakingChange")) - { - If (-Not $CmdletBreakingChangeInfo[$PSN]["ParameterBreakingChange"].Contains($ParameterName)) - { - $ContainsInAllParameterSets = $False - } - ElseIf ($CmdletBreakingChangeInfo[$PSN]["ParameterBreakingChange"][$ParameterName] -Ne $ParameterBreakingChange[$ParameterName]) - { - $ContainsInAllParameterSets = $False - } - } - Else - { - $ContainsInAllParameterSets = $False - } - } - If ($ContainsInAllParameterSets) - { - $Null = $AllParameterSets["ParameterBreakingChange"].Add($ParameterName, $ParameterBreakingChange[$ParameterName]) - ForEach ($PSN In $CmdletBreakingChangeInfo.Keys) - { - $CmdletBreakingChangeInfo[$PSN]["ParameterBreakingChange"].Remove($ParameterName) - } - } - } - } - #EndRegion - - #Region Clear the empty properties - If ($ParameterSetBreakingChange.ContainsKey("CmdletBreakingChange") -and - $ParameterSetBreakingChange["CmdletBreakingChange"].Count -eq 0) - { - $Null = $ParameterSetBreakingChange.Remove("CmdletBreakingChange") - } - If ($ParameterSetBreakingChange.ContainsKey("ParameterBreakingChange") -and - $ParameterSetBreakingChange["ParameterBreakingChange"].Count -eq 0) - { - $Null = $ParameterSetBreakingChange.Remove("ParameterBreakingChange") - } - If ($ParameterSetBreakingChange.Count -eq 0) - { - $Null = $CmdletBreakingChangeInfo.Remove($ParameterSetName) - } - #EndRegion - } - - #Region Add AllParameterSets to result - If ($AllParameterSets['CmdletBreakingChange'].Count -eq 0) - { - $Null = $AllParameterSets.Remove("CmdletBreakingChange") - } - If ($AllParameterSets['ParameterBreakingChange'].Count -eq 0) - { - $Null = $AllParameterSets.Remove("ParameterBreakingChange") - } - $CmdletBreakingChangeInfo[$AllParameterSetsName] = $AllParameterSets - #EndRegion - - Return $CmdletBreakingChangeInfo -} - -Function Export-BreakingChangeMessageOfCmdlet -{ - [CmdletBinding()] - Param ( - [Parameter()] - [HashTable] - $CmdletBreakingChangeInfo - ) - $Result = '' - ForEach ($ParameterSetName In ($CmdletBreakingChangeInfo.Keys | Sort-Object)) - { - If ($CmdletBreakingChangeInfo[$ParameterSetName].ContainsKey('CmdletBreakingChange')) - { - If ($ParameterSetName -ne $AllParameterSetsName) - { - $Result += "`n- Cmdlet breaking-change will happen to parameter set ``$ParameterSetName```n" - } - Else - { - $Result += "`n- Cmdlet breaking-change will happen to all parameter sets`n" - } - ForEach ($breakingChangeMsg In $CmdletBreakingChangeInfo[$ParameterSetName]['CmdletBreakingChange']) - { - $Result += (("$breakingChangeMsg" -Split "`n" | ForEach-Object { Return " $_" }) -Join "`n") - $Result += "`n" - } - } - If ($CmdletBreakingChangeInfo[$ParameterSetName].ContainsKey('ParameterBreakingChange')) - { - If ($ParameterSetName -eq $AllParameterSetsName) - { - $Result += "`n- Parameter breaking-change will happen to all parameter sets`n" - } - Else - { - $Result += "`n- Parameter breaking-change will happen to parameter set ``$ParameterSetName```n" - } - ForEach ($parameterName In ($CmdletBreakingChangeInfo[$ParameterSetName]['ParameterBreakingChange'].Keys | Sort-Object)) - { - $Result += " - ``-$parameterName```n" - $Result += ((($CmdletBreakingChangeInfo[$ParameterSetName]['ParameterBreakingChange'][$parameterName] -Split "`n" | ForEach-Object { Return " $_" }) -Join "`n") + "`n") - } - } - } - - Return $Result -} +Import-Module (Join-Path $PSScriptRoot "Get-BreakingChangeMetadata.ps1") -Force Function Export-BreakingChangeMessageOfModule { @@ -629,8 +32,7 @@ Function Export-BreakingChangeMessageOfModule [String] $ModuleName ) - $ModuleBreakingChangeInfo = Get-BreakingChangeInfoOfModule -ModuleName $ModuleName -ArtifactsPath $ArtifactsPath - $ModuleBreakingChangeInfo = Merge-BreakingChangeInfoOfModule -ModuleBreakingChangeInfo $ModuleBreakingChangeInfo + $ModuleBreakingChangeInfo = Get-BreakingChangeMetadata -ArtifactsPath $ArtifactsPath -ModuleName $ModuleName If ($ModuleBreakingChangeInfo.Count -eq 0) { Return "" diff --git a/tools/ResolveTools/Resolve-ModulesDoc.ps1 b/tools/ResolveTools/Resolve-ModulesDoc.ps1 new file mode 100644 index 000000000000..46d623ecc95d --- /dev/null +++ b/tools/ResolveTools/Resolve-ModulesDoc.ps1 @@ -0,0 +1,74 @@ +$ProjectRoot = "$PSScriptRoot/../.." + +$Modules = Get-ChildItem -Recurse -Depth 2 -Path "$ProjectRoot/src" -File -Filter *.sln | ForEach-Object {$_.BaseName} + +$Content = @" +# Azure PowerShell Modules + +## Rollup Module + +| Description | Module Name | PowerShell Gallery Link | +| ------------------------------------- | ----------- | -------------------------------- | +| Azure PowerShell | ``Az`` | [![Az]][AzGallery] | +| Azure PowerShell with preview Modules | ``AzPreview`` | [![AzPreview]][AzPreviewGallery] | + +## Service Modules + +| Azure Service | Module Name | PowerShell Gallery Link | Changelog | +| ------------------------------ | ------------------------------- | ------------------------------------------------------------------ | -------------------------------------------------- | + +"@ + +# Table +foreach ($Module in $Modules) +{ + $ServiceName = $Module + $ModuleName = "``Az.$Module``" + $PSGalleryLink = "[![$Module]][${Module}Gallery]" + $ChangeLogLink = "[Changelog][${Module}ChangeLog]" + $Content += "| {0,-30} | {1,-31} | {2,-66} | {3,-48} |`n" -f $ServiceName, $ModuleName, $PSGalleryLink, $ChangeLogLink +} + +# Shields +$Content += @" + + + + +[Az]: https://img.shields.io/powershellgallery/v/Az.svg?style=flat-square&label=Az +[AzPreview]: https://img.shields.io/powershellgallery/v/AzPreview.svg?style=flat-square&label=AzPreview + +"@ +foreach ($Module in $Modules) +{ + $ShieldsLink = "[${Module}]:" + $Content += "{0,-29} https://img.shields.io/powershellgallery/v/Az.$Module.svg?style=flat-square&label=Az.$Module`n" -f $ShieldsLink +} + +# PowerShell Gallery +$Content += @" + + +[AzGallery]: https://www.powershellgallery.com/packages/Az/ +[AzPreviewGallery]: https://www.powershellgallery.com/packages/AzPreview/ + +"@ +foreach ($Module in $Modules) +{ + $PSGalleryLink = "[${Module}Gallery]:" + $Content += "{0,-36} https://www.powershellgallery.com/packages/Az.$Module/`n" -f $PSGalleryLink +} + +# ChangeLog +$Content += @" + + + +"@ +foreach ($Module in $Modules) +{ + $ChangeLogLink = "[${Module}ChangeLog]:" + $Content += "{0,-38} ../src/$Module/$Module/ChangeLog.md`n" -f $ChangeLogLink +} + +$Content | Out-File -FilePath "$ProjectRoot/documentation/azure-powershell-Modules.md" -Encoding utf8 \ No newline at end of file diff --git a/tools/Resolve-SolutionFile.ps1 b/tools/ResolveTools/Resolve-SolutionFile.ps1 similarity index 97% rename from tools/Resolve-SolutionFile.ps1 rename to tools/ResolveTools/Resolve-SolutionFile.ps1 index 2e231d660147..1f6f63fa77af 100644 --- a/tools/Resolve-SolutionFile.ps1 +++ b/tools/ResolveTools/Resolve-SolutionFile.ps1 @@ -14,7 +14,7 @@ # This will resolve all the solution files under the src folder # ```powershell -# ./tools/Resolve-SolutionFile.ps1 +# ./tools/ResolveTools/Resolve-SolutionFile.ps1 # ``` function Resolve($solutionFilePath) { @@ -84,5 +84,5 @@ function Resolve($solutionFilePath) { Set-Location $saveLocation } -$srcFolder = "$PSScriptRoot/../src" +$srcFolder = "$PSScriptRoot/../../src" Get-ChildItem -Recurse -Filter *.sln -Path $srcFolder -Exclude Accounts.sln -Depth 2 | Foreach-Object { Resolve $_.FullName } \ No newline at end of file diff --git a/tools/StaticAnalysis/Exceptions/Az.ADDomainServices/ExampleIssues.csv b/tools/StaticAnalysis/Exceptions/Az.ADDomainServices/ExampleIssues.csv new file mode 100644 index 000000000000..08b372548231 --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.ADDomainServices/ExampleIssues.csv @@ -0,0 +1,5 @@ +"Module","Cmdlet","Example","Line","RuleName","ProblemId","Severity","Description","Extent","Remediation" +"Az.ADDomainServices","New-AzADDomainService","2","2","Invalid_Cmdlet","5000","1","New-AzADDomainServiceReplicaSet is not a valid command name.","New-AzADDomainServiceReplicaSet -Location westus -SubnetId /subscriptions/********-****-****-****-**********/resourceGroups/yishitest/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/default\","Check the spell of New-AzADDomainServiceReplicaSet." +"Az.ADDomainServices","New-AzADDomainService","2","7","Invalid_Parameter_Name","5011","1","New-AzADDomainService -LdapSettingPfxCertificate is not a valid parameter name.","-LdapSettingPfxCertificate","Check validity of the parameter -LdapSettingPfxCertificate." +"Az.ADDomainServices","New-AzADDomainService","2","2","Invalid_Cmdlet","5000","1","New-AzADDomainServiceReplicaSet is not a valid command name.","New-AzADDomainServiceReplicaSet -Location westus -SubnetId /subscriptions/********-****-****-****-**********/resourceGroups/yishitest/providers/Microsoft.Network/virtualNetworks/aadds-vnet/subnets/default\","Check the spell of New-AzADDomainServiceReplicaSet." +"Az.ADDomainServices","New-AzADDomainService","2","7","Invalid_Parameter_Name","5011","1","New-AzADDomainService -LdapSettingPfxCertificate is not a valid parameter name.","-LdapSettingPfxCertificate","Check validity of the parameter -LdapSettingPfxCertificate." diff --git a/tools/StaticAnalysis/Exceptions/Az.Aks/ExampleIssues.csv b/tools/StaticAnalysis/Exceptions/Az.Aks/ExampleIssues.csv new file mode 100644 index 000000000000..2f910d9b2db6 --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.Aks/ExampleIssues.csv @@ -0,0 +1,3 @@ +"Module","Cmdlet","Example","Line","RuleName","ProblemId","Severity","Description","Extent","Remediation" +"Az.Aks","Disable-AzAksAddOn","1","1","Capitalization_Conventions_Violated","5101","1","Disable-AzAksAddon doesn't follow the Capitalization Conventions.","Disable-AzAksAddon -Name HttpApplicationRouting,Monitoring,AzurePolicy,VirtualNode,KubeDashboard","Check the Capitalization Conventions. Suggest format: Disable-AzAksAddOn" +"Az.Aks","Enable-AzAksAddOn","1","1","Capitalization_Conventions_Violated","5101","1","Enable-AzAksAddon doesn't follow the Capitalization Conventions.","Enable-AzAksAddon -Name HttpApplicationRouting,Monitoring,AzurePolicy,VirtualNode,KubeDashboard -WorkspaceResourceId xxxxx/xxxx -SubnetName subnet","Check the Capitalization Conventions. Suggest format: Enable-AzAksAddOn" diff --git a/tools/StaticAnalysis/Exceptions/Az.KeyVault/BreakingChangeIssues.csv b/tools/StaticAnalysis/Exceptions/Az.KeyVault/BreakingChangeIssues.csv new file mode 100644 index 000000000000..a634d909ab6c --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.KeyVault/BreakingChangeIssues.csv @@ -0,0 +1,14 @@ +"Module","ClassName","Target","Severity","ProblemId","Description","Remediation" +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.Commands.Key.InvokeAzureKeyVaultKeyOperation","Invoke-AzKeyVaultKeyOperation","0","3010","The property 'Result' of type 'Microsoft.Azure.Commands.KeyVault.Models.PSKeyOperationResult' has been removed.","Add the property 'Result' back to type 'Microsoft.Azure.Commands.KeyVault.Models.PSKeyOperationResult'." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.Commands.Key.InvokeAzureKeyVaultKeyOperation","Invoke-AzKeyVaultKeyOperation","0","2000","The cmdlet 'Invoke-AzKeyVaultKeyOperation' no longer supports the parameter 'Value' and no alias was found for the original parameter name.","Add the parameter 'Value' back to the cmdlet 'Invoke-AzKeyVaultKeyOperation', or add an alias to the original parameter name." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.Commands.Key.InvokeAzureKeyVaultKeyOperation","Invoke-AzKeyVaultKeyOperation","0","1050","The parameter set '__AllParameterSets' for cmdlet 'Invoke-AzKeyVaultKeyOperation' has been removed.","Add parameter set '__AllParameterSets' back to cmdlet 'Invoke-AzKeyVaultKeyOperation'." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.Commands.Key.InvokeAzureKeyVaultKeyOperation","Invoke-AzKeyVaultKeyOperation","0","1050","The parameter set 'ByHsmName' for cmdlet 'Invoke-AzKeyVaultKeyOperation' has been removed.","Add parameter set 'ByHsmName' back to cmdlet 'Invoke-AzKeyVaultKeyOperation'." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.Commands.Key.InvokeAzureKeyVaultKeyOperation","Invoke-AzKeyVaultKeyOperation","0","1050","The parameter set 'ByVaultName' for cmdlet 'Invoke-AzKeyVaultKeyOperation' has been removed.","Add parameter set 'ByVaultName' back to cmdlet 'Invoke-AzKeyVaultKeyOperation'." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.Commands.Key.InvokeAzureKeyVaultKeyOperation","Invoke-AzKeyVaultKeyOperation","0","1050","The parameter set 'ByKeyInputObject' for cmdlet 'Invoke-AzKeyVaultKeyOperation' has been removed.","Add parameter set 'ByKeyInputObject' back to cmdlet 'Invoke-AzKeyVaultKeyOperation'." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.NewAzureKeyVault","New-AzKeyVault","0","2000","The cmdlet 'New-AzKeyVault' no longer supports the parameter 'EnableRbacAuthorization' and no alias was found for the original parameter name.","Add the parameter 'EnableRbacAuthorization' back to the cmdlet 'New-AzKeyVault', or add an alias to the original parameter name." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.NewAzureKeyVault","New-AzKeyVault","0","1050","The parameter set '__AllParameterSets' for cmdlet 'New-AzKeyVault' has been removed.","Add parameter set '__AllParameterSets' back to cmdlet 'New-AzKeyVault'." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.UpdateTopLevelResourceCommand","Update-AzKeyVault","0","2000","The cmdlet 'Update-AzKeyVault' no longer supports the parameter 'EnableRbacAuthorization' and no alias was found for the original parameter name.","Add the parameter 'EnableRbacAuthorization' back to the cmdlet 'Update-AzKeyVault', or add an alias to the original parameter name." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.UpdateTopLevelResourceCommand","Update-AzKeyVault","0","1050","The parameter set 'UpdateByNameParameterSet' for cmdlet 'Update-AzKeyVault' has been removed.","Add parameter set 'UpdateByNameParameterSet' back to cmdlet 'Update-AzKeyVault'." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.UpdateTopLevelResourceCommand","Update-AzKeyVault","0","1050","The parameter set 'UpdateByInputObjectParameterSet' for cmdlet 'Update-AzKeyVault' has been removed.","Add parameter set 'UpdateByInputObjectParameterSet' back to cmdlet 'Update-AzKeyVault'." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.UpdateTopLevelResourceCommand","Update-AzKeyVault","0","1050","The parameter set 'UpdateByResourceIdParameterSet' for cmdlet 'Update-AzKeyVault' has been removed.","Add parameter set 'UpdateByResourceIdParameterSet' back to cmdlet 'Update-AzKeyVault'." +"Az.KeyVault","Microsoft.Azure.Commands.KeyVault.UpdateTopLevelResourceCommand","Update-AzKeyVault","0","1050","The parameter set '__AllParameterSets' for cmdlet 'Update-AzKeyVault' has been removed.","Add parameter set '__AllParameterSets' back to cmdlet 'Update-AzKeyVault'." diff --git a/tools/StaticAnalysis/Exceptions/Az.Monitor/BreakingChangeIssues.csv b/tools/StaticAnalysis/Exceptions/Az.Monitor/BreakingChangeIssues.csv index 26360792b50a..30dbcdc7b03d 100644 --- a/tools/StaticAnalysis/Exceptions/Az.Monitor/BreakingChangeIssues.csv +++ b/tools/StaticAnalysis/Exceptions/Az.Monitor/BreakingChangeIssues.csv @@ -1,2 +1,10 @@ "Module","ClassName","Target","Severity","ProblemId","Description","Remediation" "Az.Monitor","Get-AzMetricsBatch","Get-AzMetricsBatch","0","2020","The cmdlet 'Get-AzMetricsBatch' no longer supports the type 'Microsoft.Azure.PowerShell.Cmdlets.Metric.Models.IMetricIdentity' for parameter 'InputObject'.","Change the type for parameter 'InputObject' back to 'Microsoft.Azure.PowerShell.Cmdlets.Metric.Models.IMetricIdentity'." +"Az.Monitor","Update-AzActionGroup","Update-AzActionGroup","0","2000","The cmdlet 'Update-AzActionGroup' no longer supports the parameter 'Location' and no alias was found for the original parameter name.","Add the parameter 'Location' back to the cmdlet 'Update-AzActionGroup', or add an alias to the original parameter name." +"Az.Monitor","Update-AzActionGroup","Update-AzActionGroup","0","1050","The parameter set 'UpdateExpanded' for cmdlet 'Update-AzActionGroup' has been removed.","Add parameter set 'UpdateExpanded' back to cmdlet 'Update-AzActionGroup'." +"Az.Monitor","Update-AzActionGroup","Update-AzActionGroup","0","1050","The parameter set 'UpdateViaIdentityExpanded' for cmdlet 'Update-AzActionGroup' has been removed.","Add parameter set 'UpdateViaIdentityExpanded' back to cmdlet 'Update-AzActionGroup'." +"Az.Monitor","Update-AzActionGroup","Update-AzActionGroup","0","1050","The parameter set '__AllParameterSets' for cmdlet 'Update-AzActionGroup' has been removed.","Add parameter set '__AllParameterSets' back to cmdlet 'Update-AzActionGroup'." +"Az.Monitor","Update-AzDataCollectionRule","Update-AzDataCollectionRule","0","2000","The cmdlet 'Update-AzDataCollectionRule' no longer supports the parameter 'Location' and no alias was found for the original parameter name.","Add the parameter 'Location' back to the cmdlet 'Update-AzDataCollectionRule', or add an alias to the original parameter name." +"Az.Monitor","Update-AzDataCollectionRule","Update-AzDataCollectionRule","0","1050","The parameter set 'UpdateExpanded' for cmdlet 'Update-AzDataCollectionRule' has been removed.","Add parameter set 'UpdateExpanded' back to cmdlet 'Update-AzDataCollectionRule'." +"Az.Monitor","Update-AzDataCollectionRule","Update-AzDataCollectionRule","0","1050","The parameter set 'UpdateViaIdentityExpanded' for cmdlet 'Update-AzDataCollectionRule' has been removed.","Add parameter set 'UpdateViaIdentityExpanded' back to cmdlet 'Update-AzDataCollectionRule'." +"Az.Monitor","Update-AzDataCollectionRule","Update-AzDataCollectionRule","0","1050","The parameter set '__AllParameterSets' for cmdlet 'Update-AzDataCollectionRule' has been removed.","Add parameter set '__AllParameterSets' back to cmdlet 'Update-AzDataCollectionRule'." \ No newline at end of file diff --git a/tools/StaticAnalysis/Exceptions/Az.MonitoringSolutions/ExampleIssues.csv b/tools/StaticAnalysis/Exceptions/Az.MonitoringSolutions/ExampleIssues.csv new file mode 100644 index 000000000000..05dea53a6ad5 --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.MonitoringSolutions/ExampleIssues.csv @@ -0,0 +1,9 @@ +"Module","Cmdlet","Example","Line","RuleName","ProblemId","Severity","Description","Extent","Remediation" +"Az.MonitoringSolutions","Get-AzMonitorLogAnalyticsSolution","1","1","Invalid_Parameter_Name","5011","1","Get-AzMonitorLogAnalyticsSolution -Type is not a valid parameter name.","-Type","Check validity of the parameter -Type." +"Az.MonitoringSolutions","Get-AzMonitorLogAnalyticsSolution","1","1","Invalid_Parameter_Name","5011","1","Get-AzMonitorLogAnalyticsSolution -Location is not a valid parameter name.","-Location","Check validity of the parameter -Location." +"Az.MonitoringSolutions","Get-AzMonitorLogAnalyticsSolution","1","1","Invalid_Parameter_Name","5011","1","Get-AzMonitorLogAnalyticsSolution -WorkspaceResourceId is not a valid parameter name.","-WorkspaceResourceId","Check validity of the parameter -WorkspaceResourceId." +"Az.MonitoringSolutions","Get-AzMonitorLogAnalyticsSolution","3","1","Invalid_Parameter_Name","5011","1","New-AzMonitorLogAnalyticsSolution -Name is not a valid parameter name.","-Name","Check validity of the parameter -Name." +"Az.MonitoringSolutions","Get-AzMonitorLogAnalyticsSolution","1","1","Invalid_Parameter_Name","5011","1","Get-AzMonitorLogAnalyticsSolution -Type is not a valid parameter name.","-Type","Check validity of the parameter -Type." +"Az.MonitoringSolutions","Get-AzMonitorLogAnalyticsSolution","1","1","Invalid_Parameter_Name","5011","1","Get-AzMonitorLogAnalyticsSolution -Location is not a valid parameter name.","-Location","Check validity of the parameter -Location." +"Az.MonitoringSolutions","Get-AzMonitorLogAnalyticsSolution","1","1","Invalid_Parameter_Name","5011","1","Get-AzMonitorLogAnalyticsSolution -WorkspaceResourceId is not a valid parameter name.","-WorkspaceResourceId","Check validity of the parameter -WorkspaceResourceId." +"Az.MonitoringSolutions","Get-AzMonitorLogAnalyticsSolution","3","1","Invalid_Parameter_Name","5011","1","New-AzMonitorLogAnalyticsSolution -Name is not a valid parameter name.","-Name","Check validity of the parameter -Name." diff --git a/tools/StaticAnalysis/Exceptions/Az.Purview/ExampleIssues.csv b/tools/StaticAnalysis/Exceptions/Az.Purview/ExampleIssues.csv new file mode 100644 index 000000000000..d06f44196368 --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.Purview/ExampleIssues.csv @@ -0,0 +1,3 @@ +"Module","Cmdlet","Example","Line","RuleName","ProblemId","Severity","Description","Extent","Remediation" +"Az.Purview","Get-AzPurviewAccount","4","2","Invalid_Cmdlet","5000","1","Get-AzADDomainService is not a valid command name.","Get-AzADDomainService -InputObject $got","Check the spell of Get-AzADDomainService." +"Az.Purview","Get-AzPurviewAccount","4","2","Invalid_Cmdlet","5000","1","Get-AzADDomainService is not a valid command name.","Get-AzADDomainService -InputObject $got","Check the spell of Get-AzADDomainService." diff --git a/tools/StaticAnalysis/Exceptions/Az.RecoveryServices/GeneratedSdkIssues.csv b/tools/StaticAnalysis/Exceptions/Az.RecoveryServices/GeneratedSdkIssues.csv index aecb85aea5d0..1d0b50480e54 100644 --- a/tools/StaticAnalysis/Exceptions/Az.RecoveryServices/GeneratedSdkIssues.csv +++ b/tools/StaticAnalysis/Exceptions/Az.RecoveryServices/GeneratedSdkIssues.csv @@ -1,2 +1,3 @@ "Module","Sdk","Severity","ProblemId","Description","Remediation" "Az.RecoveryServices","src/RecoveryServices/RecoveryServices.Backup.Management.Sdk","1","9090","Generated code for Az.RecoveryServices is not up to date or you have updated generated Sdk.","You may need to rebase on the latest main, regenerate code accroding to README.md file under src/RecoveryServices/RecoveryServices.Backup.Management.Sdk, and make sure no more updates based on generated files." + \ No newline at end of file diff --git a/tools/StaticAnalysis/Exceptions/Az.TimeSeriesInsights/ExampleIssues.csv b/tools/StaticAnalysis/Exceptions/Az.TimeSeriesInsights/ExampleIssues.csv new file mode 100644 index 000000000000..8efa6828417e --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.TimeSeriesInsights/ExampleIssues.csv @@ -0,0 +1,3 @@ +"Module","Cmdlet","Example","Line","RuleName","ProblemId","Severity","Description","Extent","Remediation" +"Az.TimeSeriesInsights","New-AzTimeSeriesInsightsEventSource","1","2","Invalid_Parameter_Name","5011","1","New-AzEventHub -MessageRetentionInDays is not a valid parameter name.","-MessageRetentionInDays","Check validity of the parameter -MessageRetentionInDays." +"Az.TimeSeriesInsights","New-AzTimeSeriesInsightsEventSource","1","2","Invalid_Parameter_Name","5011","1","New-AzEventHub -MessageRetentionInDays is not a valid parameter name.","-MessageRetentionInDays","Check validity of the parameter -MessageRetentionInDays." diff --git a/tools/StaticAnalysis/Exceptions/Az.Websites/ExampleIssues.csv b/tools/StaticAnalysis/Exceptions/Az.Websites/ExampleIssues.csv new file mode 100644 index 000000000000..f0ff99e59146 --- /dev/null +++ b/tools/StaticAnalysis/Exceptions/Az.Websites/ExampleIssues.csv @@ -0,0 +1,7 @@ +"Module","Cmdlet","Example","Line","RuleName","ProblemId","Severity","Description","Extent","Remediation" +"Az.Websites","Get-AzWebAppBackup","0","0","MissingSynopsis","5040","1","Synopsis is missing.","D:\a\_work\1\s\src\Websites\Websites\help\Get-AzWebAppBackup.md","Add Synopsis. Remove any placeholders." +"Az.Websites","Get-AzWebAppBackupConfiguration","0","0","MissingSynopsis","5040","1","Synopsis is missing.","D:\a\_work\1\s\src\Websites\Websites\help\Get-AzWebAppBackupConfiguration.md","Add Synopsis. Remove any placeholders." +"Az.Websites","Get-AzWebAppBackupList","0","0","MissingSynopsis","5040","1","Synopsis is missing.","D:\a\_work\1\s\src\Websites\Websites\help\Get-AzWebAppBackupList.md","Add Synopsis. Remove any placeholders." +"Az.Websites","Remove-AzWebAppBackup","0","0","MissingSynopsis","5040","1","Synopsis is missing.","D:\a\_work\1\s\src\Websites\Websites\help\Remove-AzWebAppBackup.md","Add Synopsis. Remove any placeholders." +"Az.Websites","Remove-AzWebAppSlot","0","0","MissingSynopsis","5040","1","Synopsis is missing.","D:\a\_work\1\s\src\Websites\Websites\help\Remove-AzWebAppSlot.md","Add Synopsis. Remove any placeholders." +"Az.Websites","Reset-AzWebAppSlotPublishingProfile","0","0","MissingSynopsis","5040","1","Synopsis is missing.","D:\a\_work\1\s\src\Websites\Websites\help\Reset-AzWebAppSlotPublishingProfile.md","Add Synopsis. Remove any placeholders."