diff --git a/.azure-pipelines/PipelineSteps/analyze-steps.ps1 b/.azure-pipelines/PipelineSteps/analyze-steps.ps1 index a70cd22012ce..f557b90c6ffe 100644 --- a/.azure-pipelines/PipelineSteps/analyze-steps.ps1 +++ b/.azure-pipelines/PipelineSteps/analyze-steps.ps1 @@ -28,7 +28,7 @@ function Assert-ExitCodeSuccess { # Install PowerShell dependencies Write-Host -ForegroundColor Green "-------------------- Start installing PowerShell dependencies ... --------------------" -Install-Module "platyPS", "PSScriptAnalyzer" -Repository PSGallery -Force -Confirm:$false -Scope CurrentUser +Install-Module "Microsoft.PowerShell.PlatyPS", "PSScriptAnalyzer" -Repository PSGallery -Force -Confirm:$false -Scope CurrentUser Write-Host -ForegroundColor DarkGreen "-------------------- End installing PowerShell dependencies ... --------------------`n`n`n`n`n" # Install latest Az modules diff --git a/.azure-pipelines/security-tools.yml b/.azure-pipelines/security-tools.yml index 81cd5799e665..03540738dcab 100644 --- a/.azure-pipelines/security-tools.yml +++ b/.azure-pipelines/security-tools.yml @@ -70,10 +70,10 @@ jobs: & $buildStepsPath -RepoRoot "$(Build.SourcesDirectory)" -Configuration "Debug" -FilesChangedOutputPath $filesChangedOutputPath -IsSecurityCheck $true -BuildReason $(Build.Reason) -Trigger $trigger - task: PowerShell@2 - displayName: Install platyPS + displayName: Install Microsoft.PowerShell.PlatyPS inputs: targetType: inline - script: Install-Module platyPS -Force -Confirm:$false -Scope CurrentUser + script: Install-Module Microsoft.PowerShell.PlatyPS -Force -Confirm:$false -Scope CurrentUser pwsh: true - task: UseDotNet@2 displayName: 'Use .NET SDK 6.0 for CredScan' diff --git a/.azure-pipelines/util/analyze-steps.yml b/.azure-pipelines/util/analyze-steps.yml index e78beeaec072..929c0f926442 100644 --- a/.azure-pipelines/util/analyze-steps.yml +++ b/.azure-pipelines/util/analyze-steps.yml @@ -27,7 +27,7 @@ steps: packageType: sdk version: 8.x -- pwsh: 'Install-Module "platyPS", "PSScriptAnalyzer" -Force -Confirm:$false -Scope CurrentUser' +- pwsh: 'Install-Module "Microsoft.PowerShell.PlatyPS", "PSScriptAnalyzer" -Force -Confirm:$false -Scope CurrentUser' displayName: 'Install PowerShell Dependencies' - task: PowerShell@2 diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 964260ef1b8d..1ed4f3529b4c 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -25,7 +25,7 @@ First-time setup requires these exact steps: - **CRITICAL**: Ensure you have network connectivity to Azure DevOps package feeds. Build failures with "Name or service not known" errors indicate firewall/connectivity issues that must be resolved before building. - Install .NET SDK 8.0+ and .NET Framework Dev Pack 4.7.2+: `dotnet --version` should show 8.0+ - Install PowerShell 7+: `pwsh --version` should show 7.0+ -- Install platyPS module: `pwsh -c "Install-Module -Name platyPS -Force -Scope CurrentUser"` +- Install Microsoft.PowerShell.PlatyPS module: `pwsh -c "Install-Module -Name Microsoft.PowerShell.PlatyPS -Force -Scope CurrentUser"` - Install PSScriptAnalyzer: `pwsh -c "Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser"` - Set PowerShell execution policy: `pwsh -c "Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser"` @@ -110,7 +110,7 @@ If build appears to hang or shows no progress: - Builds may pause during package downloads or complex compilation steps ### Module-Specific Issues -- Help generation requires platyPS module to be installed and functioning +- Help generation requires Microsoft.PowerShell.PlatyPS module to be installed and functioning - Static analysis requires PSScriptAnalyzer module - Some projects depend on specific Azure SDK versions from Azure DevOps feeds - Missing ChangeLog.md updates will cause PR validation to fail diff --git a/documentation/development-docs/azure-powershell-developer-guide.md b/documentation/development-docs/azure-powershell-developer-guide.md index 10bb19bda0e3..209241f424d6 100644 --- a/documentation/development-docs/azure-powershell-developer-guide.md +++ b/documentation/development-docs/azure-powershell-developer-guide.md @@ -50,7 +50,7 @@ The following prerequisites should be completed before contributing to the Azure - Install [Visual Studio 2022 or above](https://www.visualstudio.com/downloads/) - Install the latest version of [Git](https://git-scm.com/downloads) -- Install the [`platyPS` module](help-generation.md#Installing-platyPS) +- Install the [`Microsoft.PowerShell.PlatyPS` module](help-generation.md#Installing-MicrosoftPowerShellPlatyPS) - Install [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer#installation) - Install [**.NET SDK 6, and .NET Framework Dev Pack 4.7.2**](https://dotnet.microsoft.com/en-us/download/dotnet) or greater - Install [PowerShell 7](https://github.com/PowerShell/PowerShell/releases/latest) @@ -89,7 +89,7 @@ git pull upstream main ### Building the Environment -_Note_: to build the environment locally, you need `platyPS` install on your machine. Please see the [Prerequisites](#prerequisites) section for details on how to install this module. +_Note_: to build the environment locally, you need `Microsoft.PowerShell.PlatyPS` install on your machine. Please see the [Prerequisites](#prerequisites) section for details on how to install this module. After cloning the repository to your local machine, you want to ensure that you can build the environment. To do so, launch `VS Developer Command Prompt` (which is installed with Visual Studio) and run the following command (from the root of the repository) to do a full build: @@ -105,7 +105,7 @@ PS C:\azure-powershell> dotnet msbuild build.proj ### Generating Help -We build the `dll-Help.xml` files (used to display the help content for cmdlets in PowerShell) from markdown using the `platyPS` module. Since this help generation step can take 10-15 minutes, it is a separate part of the command line build process. Run this to generate help: +We build the `dll-Help.xml` files (used to display the help content for cmdlets in PowerShell) from markdown using the `Microsoft.PowerShell.PlatyPS` module. Since this help generation step can take 10-15 minutes, it is a separate part of the command line build process. Run this to generate help: ``` msbuild build.proj /t:GenerateHelp @@ -153,7 +153,7 @@ Please submit a design review here: https://github.com/Azure/azure-powershell-cm _Note_: You will need to be part of the `GitHub Azure` org to see this repository. Please go to [this link](https://aka.ms/azuregithub) to become part of the `Azure` org. -We recommend using the `platyPS` module to easily generate markdown files that contains the above information and including the files in the design submission. +We recommend using the `Microsoft.PowerShell.PlatyPS` module to easily generate markdown files that contains the above information and including the files in the design submission. ### Point of Contact @@ -243,7 +243,7 @@ To import modules automatically when debug has started, follow the below steps: All cmdlets that are created must have accompanying help that is displayed when users execute the command `Get-Help `. -Each cmdlet has a markdown file that contains the help content that is displayed in PowerShell; these markdown files are created (and maintained) using the platyPS module. +Each cmdlet has a markdown file that contains the help content that is displayed in PowerShell; these markdown files are created (and maintained) using the Microsoft.PowerShell.PlatyPS module. For complete documentation, see [`help-generation.md`](help-generation.md) in the `documentation` folder. diff --git a/documentation/development-docs/help-generation.md b/documentation/development-docs/help-generation.md index cd1e10226997..911321b20845 100644 --- a/documentation/development-docs/help-generation.md +++ b/documentation/development-docs/help-generation.md @@ -2,16 +2,16 @@ ## Description -All MAML files containing the help content for cmdlets have been removed from the Azure PowerShell repository and replaced with markdown files, which are generated and maintained using the [`platyPS`](https://github.com/PowerShell/platyPS) module. Each module has a `help` folder (_e.g.,_ `src/Accounts/Accounts/help`) which contains a markdown file for each of the cmdlets found in that given module. When the help content for a cmdlet (or multiple cmdlets) needs to be updated, users will now only have to update the contents of the markdown file, _and not the MAML file as well_. +All MAML files containing the help content for cmdlets have been removed from the Azure PowerShell repository and replaced with markdown files, which are generated and maintained using the [`Microsoft.PowerShell.PlatyPS`](https://github.com/PowerShell/platyPS) module (v1.0+). Each module has a `help` folder (_e.g.,_ `src/Accounts/Accounts/help`) which contains a markdown file for each of the cmdlets found in that given module. When the help content for a cmdlet (or multiple cmdlets) needs to be updated, users will now only have to update the contents of the markdown file, _and not the MAML file as well_. -## Installing `platyPS` +## Installing `Microsoft.PowerShell.PlatyPS` -In order to use the cmdlets necessary to update the markdown help files (or generate MAML help locally from these markdown files), you must first install the `platyPS` module mentioned previously. You will need to install a minimum version of 0.11.0. +In order to use the cmdlets necessary to update the markdown help files (or generate MAML help locally from these markdown files), you must first install the `Microsoft.PowerShell.PlatyPS` module mentioned previously. You will need to install a minimum version of 1.0.0. -To do so, you can follow the below steps (which are outlined in the [**Quick start**](https://github.com/PowerShell/platyPS#quick-start) section of the `platyPS` README): +To do so, you can follow the below steps: ```powershell -Install-Module -Name platyPS -Scope CurrentUser +Install-Module -Name Microsoft.PowerShell.PlatyPS -Scope CurrentUser ``` **Note:** this module will need to be installed from the [PowerShell Gallery](http://www.powershellgallery.com/). If, for some reason, this isn't a registered repository when running the `Get-PSRepository` cmdlet, then you will need to register it by running the following command: @@ -20,11 +20,11 @@ Install-Module -Name platyPS -Scope CurrentUser Register-PSRepository -Default -InstallationPolicy Trusted ``` -## Using `platyPS` +## Using `Microsoft.PowerShell.PlatyPS` ### Importing your module -Before you run the `platyPS` cmdlets to update your markdown help files, you will need to first import the module containing the changes that you have made to your cmdlets into your current PowerShell session. Once you have built your project (either through Visual Studio or with `msbuild`), you can locate the module manifest that you will need to import in the `artifacts/Debug` folder of your local repository. +Before you run the `Microsoft.PowerShell.PlatyPS` cmdlets to update your markdown help files, you will need to first import the module containing the changes that you have made to your cmdlets into your current PowerShell session. Once you have built your project (either through Visual Studio or with `msbuild`), you can locate the module manifest that you will need to import in the `artifacts/Debug` folder of your local repository. For example, if you have made changes to the `Accounts` module, you will find the corresponding module manifest in `artifacts/Debug/Az.Accounts/Az.Accounts.psd1`. @@ -43,7 +43,7 @@ For new modules with no existing `help` folder containing the markdown help file ```powershell $PathToHelpFolder = "../../help" # Full path to help folder containing markdown files to be generated (e.g., src/Accounts/Accounts/help) -New-MarkdownHelp -Module {{moduleName}} -OutputFolder $PathToHelpFolder -AlphabeticParamsOrder -UseFullTypeName -WithModulePage +New-MarkdownCommandHelp -ModuleInfo (Get-Module {{moduleName}}) -OutputFolder $PathToHelpFolder -WithModulePage ``` Once this folder has been generated, follow the steps provided in the below section to update the files with any changes made to the public interface of the cmdlets. @@ -65,55 +65,59 @@ Whenever the public interface for a cmdlet has changed, the corresponding markdo #### Updating all markdown files in a module -To update all of the markdown files for a single module, use the [`Update-MarkdownHelpModule`](https://github.com/PowerShell/platyPS/blob/master/docs/Update-MarkdownHelpModule.md) cmdlet: +To update all of the markdown files for a single module, use the `Update-MarkdownCommandHelp` and `Update-MarkdownModuleFile` cmdlets: ```powershell $PathToModuleManifest = "../../.psd1" # Full path to the module manifest that you have updated Import-Module -Name $PathToModuleManifest $PathToHelpFolder = "../../help" # Full path to help folder containing markdown files to be updated -Update-MarkdownHelpModule -Path $PathToHelpFolder -RefreshModulePage -AlphabeticParamsOrder -UseFullTypeName -``` -If you would like to update the inputs/outputs for a markdown file, please run this cmdlet with the -UpdateInputOutput parameter. Keep in mind that this will overwrite any customized descriptions of inputs and outputs, so you will need to add these descriptions back if still relevant. +# Update individual command help markdown files +Update-MarkdownCommandHelp -Path "$PathToHelpFolder/*-*.md" + +# Refresh the module page with updated command list +$cmdHelp = Import-MarkdownCommandHelp -Path "$PathToHelpFolder/*-*.md" +$moduleFile = Get-ChildItem -Path $PathToHelpFolder -Filter "Az.*.md" | Where-Object { $_.Name -notlike "*-*" } | Select-Object -First 1 +if ($moduleFile) { Update-MarkdownModuleFile -Path $moduleFile.FullName -CommandHelp $cmdHelp } +``` -This will update all of the markdown files with public interface changes made to corresponding cmdlets, add markdown files for any new cmdlets, remove markdown files for any deleted cmdlets, and update the module page (_e.g.,_ `Az.Accounts.md`) with any added or removed cmdlets. +This will update all of the markdown files with public interface changes made to corresponding cmdlets and update the module page (_e.g.,_ `Az.Accounts.md`) with any added or removed cmdlets. _This seems to work better when run from within the `help` folder itself (For e.g. to generate the help files for the [`Network`](https://github.com/Azure/azure-powershell/tree/main/src/Network) module run the cmd from under [`Commands.Network/help`](https://github.com/Azure/azure-powershell/tree/main/src/Network/Network/help)). Also, you will have to import the profile module from under /artifacts/Debug/Az.Accounts/Az.Accounts.psd1_ #### Updating a single markdown file -To update a single markdown file with the changes made to the corresponding cmdlet, use the [`Update-MarkdownHelp`](https://github.com/PowerShell/platyPS/blob/master/docs/Update-MarkdownHelp.md) cmdlet: +To update a single markdown file with the changes made to the corresponding cmdlet, use the `Update-MarkdownCommandHelp` cmdlet: ```powershell $PathToModuleManifest = "../../.psd1" # Full path to the module manifest that you have updated Import-Module -Name $PathToModuleManifest $PathToMarkdownFile = "../../.md" # Full path to the markdown file to be updated -Update-MarkdownHelp -Path $PathToMarkdownFile -AlphabeticParamsOrder -UseFullTypeName +Update-MarkdownCommandHelp -Path $PathToMarkdownFile ``` -If you would like to update the inputs/outputs for a markdown file, please run this cmdlet with the -UpdateInputOutput parameter. Keep in mind that this will overwrite any customized descriptions of inputs and outputs, so you will need to add these descriptions back if still relevant. - #### Generating and viewing the MAML help During the build, the MAML help will be generated from the markdown files in the repository. If you would like to generate the MAML help and preview what the help content will look like for each of your cmdlets, you can do so with two more commands. -To generate the MAML help based on the contents of your markdown files, use the [`New-ExternalHelp`](https://github.com/PowerShell/platyPS/blob/master/docs/New-ExternalHelp.md) cmdlet: +To generate the MAML help based on the contents of your markdown files, use the `Import-MarkdownCommandHelp` and `Export-MamlCommandHelp` cmdlets: ```powershell $PathToHelpFolder = "../../help" # Full path to help folder containing markdown files to be updated $PathToOutputFolder = "../../.." # Full path to folder where you want the MAML file to be generated -New-ExternalHelp -Path $PathToHelpFolder -OutputPath $PathToOutputFolder +$cmdHelp = Import-MarkdownCommandHelp -Path "$PathToHelpFolder/*-*.md" +Export-MamlCommandHelp -CommandHelp $cmdHelp -OutputFolder $PathToOutputFolder ``` -To preview the help that you just generated, use the [`Get-HelpPreview`](https://github.com/PowerShell/platyPS/blob/master/docs/Get-HelpPreview.md) cmdlet: +To preview the help that you just generated, use the `Show-HelpPreview` cmdlet: ```powershell $PathToMAML = "../../.dll-Help.xml" # Full path to the MAML file that was generated # Save the help locally -$help = Get-HelpPreview -Path $PathToMAML +$help = Show-HelpPreview -Path $PathToMAML # Get the help for a specific cmdlet $help | where { $_.Name -eq "" } diff --git a/documentation/development-docs/sdkbased-vs-autogen.md b/documentation/development-docs/sdkbased-vs-autogen.md index f7717a0e8f05..0395944c4571 100644 --- a/documentation/development-docs/sdkbased-vs-autogen.md +++ b/documentation/development-docs/sdkbased-vs-autogen.md @@ -78,7 +78,7 @@ Generally speaking, hero scenarios are implemented through customization through ### SDK-based Module -Docs are generated through playPS, please see [platyPS](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/help-generation.md#Installing-platyPS) for details. And developers should populate generated docs with examples. +Docs are generated through Microsoft.PowerShell.PlatyPS, please see [Microsoft.PowerShell.PlatyPS](https://github.com/Azure/azure-powershell/blob/main/documentation/development-docs/help-generation.md#Installing-MicrosoftPowerShellPlatyPS) for details. And developers should populate generated docs with examples. ### Auto-gen Module diff --git a/documentation/tooling/static-analysis.md b/documentation/tooling/static-analysis.md index 155318c65027..e0e768643b63 100644 --- a/documentation/tooling/static-analysis.md +++ b/documentation/tooling/static-analysis.md @@ -93,7 +93,7 @@ The dependency analyzer can be found in the [`DependencyAnalyzer`](https://githu The help analyzer can be found in the [`HelpAnalyzer`](https://github.com/Azure/azure-powershell/tree/01a81fbb7ea6c086fff2bc137053168c0fc7728a/tools/StaticAnalysis/HelpAnalyzer) folder. In this folder, you will find the following classes: - `HelpAnalyzer` - - The implementation of the `IStaticAnalyzer` interface; determines which modules to analyze and checks to see which cmdlets within those modules don't have a corresponding markdown help file. It also checks the content structure of markdown help conforms to [PlatyPS Schema](https://github.com/PowerShell/platyPS/blob/master/platyPS.schema.md) + - The implementation of the `IStaticAnalyzer` interface; determines which modules to analyze and checks to see which cmdlets within those modules don't have a corresponding markdown help file. It also checks the content structure of markdown help conforms to [PlatyPS Schema](https://github.com/PowerShell/platyPS) using the `Microsoft.PowerShell.PlatyPS` module - `HelpIssues` - The implementation of the `IReportRecord` interface; defines what a help exception looks like when it's reported in the `HelpIssues.csv` file that is found in the build artifacts of a CI run, as well as how to compare a new record to a record found in the existing `HelpIssues.csv` file used for exception suppressions diff --git a/src/StorageSync/Tools/storageSyncDevops.psm1 b/src/StorageSync/Tools/storageSyncDevops.psm1 index fadbdb10af8b..7be9b75301ef 100644 --- a/src/StorageSync/Tools/storageSyncDevops.psm1 +++ b/src/StorageSync/Tools/storageSyncDevops.psm1 @@ -96,16 +96,19 @@ function Update-StorageSyncHelp $status = $null try { - Write-Verbose "Re-Loading module: platyPS" - if (Get-Module platyPS) + Write-Verbose "Re-Loading module: Microsoft.PowerShell.PlatyPS" + if (Get-Module Microsoft.PowerShell.PlatyPS) { - Remove-Module platyPS + Remove-Module Microsoft.PowerShell.PlatyPS } - Import-Module platyPS + Import-Module Microsoft.PowerShell.PlatyPS $PathToHelpFolder = Join-Path (Get-RepositoryRootDirectory) "src\StorageSync\StorageSync\help" Write-Verbose "Updating help: $PathToHelpFolder" - $status = Update-MarkdownHelpModule -Path $PathToHelpFolder -RefreshModulePage -AlphabeticParamsOrder -UseFullTypeName + Update-MarkdownCommandHelp -Path "$PathToHelpFolder\*-*.md" + $updatedHelp = Import-MarkdownCommandHelp -Path "$PathToHelpFolder\*-*.md" + $moduleFile = Get-ChildItem -Path $PathToHelpFolder -Filter "Az.StorageSync.md" | Select-Object -First 1 + if ($moduleFile) { $status = Update-MarkdownModuleFile -Path $moduleFile.FullName -CommandHelp $updatedHelp } } finally { diff --git a/tools/Az.Tools.Installer/GenerateHelp.ps1 b/tools/Az.Tools.Installer/GenerateHelp.ps1 index d36e418a3f31..ca56867c6a85 100644 --- a/tools/Az.Tools.Installer/GenerateHelp.ps1 +++ b/tools/Az.Tools.Installer/GenerateHelp.ps1 @@ -1,4 +1,4 @@ -#Requires -Modules platyPS +#Requires -Modules Microsoft.PowerShell.PlatyPS [CmdletBinding()] Param( [Parameter()] @@ -10,5 +10,6 @@ Param( $ModuleFolder = Join-Path -Path $ArtifactFolder -ChildPath $ModuleName $TempDocFolder = Join-Path -Path $ModuleFolder -ChildPath 'help' Import-Module $ModuleFolder -New-MarkdownHelp -Module $ModuleName -OutputFolder $TempDocFolder -Force -New-ExternalHelp –Path $TempDocFolder -OutputPath $ModuleFolder -Force \ No newline at end of file +New-MarkdownCommandHelp -ModuleInfo (Get-Module $ModuleName) -OutputFolder $TempDocFolder -Force +$cmdHelp = Import-MarkdownCommandHelp -Path (Join-Path $TempDocFolder '*-*.md') +Export-MamlCommandHelp -CommandHelp $cmdHelp -OutputFolder $ModuleFolder -Force \ No newline at end of file diff --git a/tools/Az.Tools.Predictor/GenerateHelp.ps1 b/tools/Az.Tools.Predictor/GenerateHelp.ps1 index 568ed53e7652..9c1f901c014b 100644 --- a/tools/Az.Tools.Predictor/GenerateHelp.ps1 +++ b/tools/Az.Tools.Predictor/GenerateHelp.ps1 @@ -1,4 +1,4 @@ -#Requires -Modules platyPS +#Requires -Modules Microsoft.PowerShell.PlatyPS [CmdletBinding()] Param( [Parameter()] @@ -11,4 +11,5 @@ Param( $ModuleFolder = Join-Path -Path $ArtifactFolder -ChildPath $ModuleName Import-Module $ModuleFolder -New-ExternalHelp –Path $HelpFolder -OutputPath $ModuleFolder -Force -Debug \ No newline at end of file +$cmdHelp = Import-MarkdownCommandHelp -Path (Join-Path $HelpFolder '*-*.md') +Export-MamlCommandHelp -CommandHelp $cmdHelp -OutputFolder $ModuleFolder -Force \ No newline at end of file diff --git a/tools/BuildScripts/AdaptAutorestModule.ps1 b/tools/BuildScripts/AdaptAutorestModule.ps1 index 1889a475204e..57a3305e339f 100644 --- a/tools/BuildScripts/AdaptAutorestModule.ps1 +++ b/tools/BuildScripts/AdaptAutorestModule.ps1 @@ -154,7 +154,7 @@ if (Test-Path $assemblyInfoPath) { <# - merge temporary sub module csproj to parent module sln (for platyPS help markdown generation) + merge temporary sub module csproj to parent module sln (for Microsoft.PowerShell.PlatyPS help markdown generation) 1. delete submodule csproj 2. create temporary submodule csproj pointing src/moduleroot/submodule 3. add temporary submodule csproj to src/moduleroot/sln @@ -184,7 +184,7 @@ try{ Write-Host "Building $slnPath ..." -ForegroundColor DarkGreen dotnet build $slnPath <# - generate help markdown by platyPS + generate help markdown by Microsoft.PowerShell.PlatyPS #> Write-Host "Refreshing help markdown ..." -ForegroundColor DarkGreen @@ -214,7 +214,7 @@ try{ } Import-Module $artifactPsd1Path - Import-Module platyPS + Import-Module Microsoft.PowerShell.PlatyPS $helpPath = Join-Path $parentModulePath 'help' $subModuleHelpPath = Join-Path $RepoRoot 'src' $ModuleRootName $SubModuleName 'docs' @@ -224,7 +224,7 @@ try{ if (-Not (Test-Path $helpPath)) { New-Item -Type Directory $helpPath -Force - New-MarkDownHelp -Module "Az.$ModuleRootName" -OutputFolder $helpPath -AlphabeticParamsOrder -UseFullTypeName -WithModulePage -ExcludeDontShow + New-MarkdownCommandHelp -ModuleInfo (Get-Module "Az.$ModuleRootName") -OutputFolder $helpPath -WithModulePage $indexPath = Join-Path $helpPath "Az.$ModuleRootName.md" $content = Get-Content -Path $indexPath $content = $content -replace '{{ Update Download Link }}', "https://learn.microsoft.com/powershell/module/az.$($ModuleRootName.ToLower())" @@ -234,7 +234,10 @@ try{ } Get-ChildItem $subModuleHelpPath -Filter *-*.md | Copy-Item -Destination (Join-Path $helpPath $_.Name) -Force Write-Host "Refreshing help markdown files under: $helpPath ..." - Update-MarkdownHelpModule -Path $helpPath -RefreshModulePage -AlphabeticParamsOrder -UseFullTypeName -ExcludeDontShow + Update-MarkdownCommandHelp -Path "$helpPath\*-*.md" + $updatedHelp = Import-MarkdownCommandHelp -Path "$helpPath\*-*.md" + $moduleFile = Get-ChildItem -Path $helpPath -Filter "Az.$ModuleRootName.md" | Select-Object -First 1 + if ($moduleFile) { Update-MarkdownModuleFile -Path $moduleFile.FullName -CommandHelp $updatedHelp } foreach ($helpFile in (Get-ChildItem $helpPath -Filter "*-*.md" -Recurse)) { $cmdeltName = $helpFile.Name.Replace(".md", "") if ($exportedCommands -notcontains $cmdeltName) diff --git a/tools/BuildScripts/HelpMarkDown.psm1 b/tools/BuildScripts/HelpMarkDown.psm1 index ba474917b3c5..c3ce133c2ca8 100644 --- a/tools/BuildScripts/HelpMarkDown.psm1 +++ b/tools/BuildScripts/HelpMarkDown.psm1 @@ -2,7 +2,7 @@ function Remove-CommonParameterFromMarkdown { <# .SYNOPSIS - Remove a PlatyPS generated parameter block. + Remove a Microsoft.PowerShell.PlatyPS generated parameter block. .DESCRIPTION Removes parameter block for the provided parameter name from the markdown file provided. #> diff --git a/tools/GenerateHelp.ps1 b/tools/GenerateHelp.ps1 index 77b825987847..d1ee46019f8b 100644 --- a/tools/GenerateHelp.ps1 +++ b/tools/GenerateHelp.ps1 @@ -1,4 +1,4 @@ -#Requires -Modules platyPS +#Requires -Modules Microsoft.PowerShell.PlatyPS [CmdletBinding()] Param( [Parameter()] @@ -18,14 +18,11 @@ Import-Module "$PSScriptRoot\HelpGeneration\HelpGeneration.psm1" $UnfilteredHelpFolders = Get-ChildItem -Include 'help' -Path "$PSScriptRoot\..\artifacts" -Recurse -Directory | where { $_.FullName -like "*$BuildConfig*" -and (-not [Tools.Common.Utilities.ModuleFilter]::IsAzureStackModule($_.FullName)) } $FilteredHelpFolders = $UnfilteredHelpFolders -if (![string]::IsNullOrEmpty($FilteredModules)) -{ +if (![string]::IsNullOrEmpty($FilteredModules)) { $FilteredModulesList = $FilteredModules -split ';' $FilteredHelpFolders = @() - foreach ($HelpFolder in $UnfilteredHelpFolders) - { - if (($FilteredModulesList | where { $HelpFolder -like "*\$($_)\*" }) -ne $null) - { + foreach ($HelpFolder in $UnfilteredHelpFolders) { + if (($FilteredModulesList | where { $HelpFolder -like "*\$($_)\*" }) -ne $null) { $FilteredHelpFolders += $HelpFolder } } @@ -33,48 +30,45 @@ if (![string]::IsNullOrEmpty($FilteredModules)) # --------------------------------------------------------------------------------------------- -if ($ValidateMarkdownHelp) -{ +if ($ValidateMarkdownHelp) { $SuppressedExceptionsPath = "$PSScriptRoot\StaticAnalysis\Exceptions" - if (!(Test-Path -Path $SuppressedExceptionsPath)) - { + if (!(Test-Path -Path $SuppressedExceptionsPath)) { New-Item -Path "$PSScriptRoot\..\artifacts" -Name "Exceptions" -ItemType Directory } $Exceptions = @() - foreach ($ServiceFolder in $ResourceManagerFolders) - { + foreach ($ServiceFolder in $ResourceManagerFolders) { $HelpFolder = (Get-ChildItem -Path $ServiceFolder.FullName -Filter "help" -Recurse -Directory) - if ($HelpFolder -eq $null) - { + if ($HelpFolder -eq $null) { $Exceptions += $ServiceFolder.Name } } - if ($Exceptions.Count -gt 0) - { + if ($Exceptions.Count -gt 0) { $Services = $Exceptions -Join ", " throw "No help folder found in the following services: $Services" } $NewExceptionsPath = "$PSScriptRoot\..\artifacts\StaticAnalysisResults" - if (!(Test-Path -Path $NewExceptionsPath)) - { + if (!(Test-Path -Path $NewExceptionsPath)) { New-Item -Path "$PSScriptRoot\..\artifacts" -Name "StaticAnalysisResults" -ItemType Directory } - + Copy-Item -Path "$PSScriptRoot\HelpGeneration\Exceptions\ValidateHelpIssues.csv" -Destination $SuppressedExceptionsPath New-Item -Path $NewExceptionsPath -Name ValidateHelpIssues.csv -ItemType File -Force | Out-Null Add-Content "$NewExceptionsPath\ValidateHelpIssues.csv" "Target,Description" $FilteredHelpFolders | foreach { Test-AzMarkdownHelp $_.FullName $SuppressedExceptionsPath $NewExceptionsPath } $Exceptions = Import-Csv "$NewExceptionsPath\ValidateHelpIssues.csv" - if (($Exceptions | Measure-Object).Count -gt 0) - { - $Exceptions | Format-List - throw "A markdown file containing the help for a cmdlet is incomplete. Please check the exceptions provided for more details." + if (($Exceptions | Measure-Object).Count -gt 0) { + Write-Host "##[error]============ Help Validation Errors ============" + $Exceptions | ForEach-Object { + Write-Host "##[error] [$($_.Target)] $($_.Description)" + } + Write-Host "##[error]================================================" + Write-Host "##[error]Total issues: $(($Exceptions | Measure-Object).Count). Please fix the above issues in the corresponding help markdown files." + exit 1 } - else - { + else { New-Item -Path $NewExceptionsPath -Name NoHelpIssues -ItemType File -Force | Out-Null Remove-Item -Path "$SuppressedExceptionsPath\ValidateHelpIssues.csv" -Force Remove-Item -Path "$NewExceptionsPath\ValidateHelpIssues.csv" -Force @@ -84,21 +78,16 @@ if ($ValidateMarkdownHelp) # We need to define new version of module instead of hardcode here $GeneratedModuleListPath = [System.IO.Path]::Combine($PSScriptRoot, "GeneratedModuleList.txt") $GeneratedModules = Get-Content $GeneratedModuleListPath -if ($GenerateMamlHelp) -{ - foreach ($HelpFolder in $FilteredHelpFolders) - { - $ModuleName = "" - if($HelpFolder -match "(?s)artifacts\\$BuildConfig\\(?.+)\\help") - { +if ($GenerateMamlHelp) { + foreach ($HelpFolder in $FilteredHelpFolders) { + $ModuleName = "" + if ($HelpFolder -match "(?s)artifacts\\$BuildConfig\\(?.+)\\help") { $ModuleName = $Matches["module"] } - if($HelpFolder -match "(?s)artifacts/$BuildConfig/(?.+)/help") - { + if ($HelpFolder -match "(?s)artifacts/$BuildConfig/(?.+)/help") { $ModuleName = $Matches["module"] } - if($GeneratedModules -notcontains $ModuleName) - { + if ($GeneratedModules -notcontains $ModuleName) { New-AzMamlHelp $HelpFolder.FullName } diff --git a/tools/HelpGeneration/Exceptions/ValidateHelpIssues.csv b/tools/HelpGeneration/Exceptions/ValidateHelpIssues.csv index 362c51723f39..77ee4886d4b3 100644 --- a/tools/HelpGeneration/Exceptions/ValidateHelpIssues.csv +++ b/tools/HelpGeneration/Exceptions/ValidateHelpIssues.csv @@ -1,142 +1,142 @@ Target,Description -Get-AzApiManagementProperty.md,No synopsis found -Get-AzApiManagementProperty.md,No description found -Remove-AzApiManagementAuthorizationServer.md,No examples found -Update-AzApiManagementRegion.md,No examples found -Remove-AzAutomationDscConfiguration.md,No examples found -Remove-AzAutomationDscNodeConfiguration.md,No examples found -Get-AzBatchAccountKeys.md,No examples found -Remove-AzBatchJobSchedule.md,No examples found -Set-AzBatchJobSchedule.md,No examples found -Get-AzCdnCustomDomain.md,No examples found -Get-AzCdnEdgeNode.md,No examples found -Get-AzCdnEndpoint.md,No examples found -Get-AzCdnEndpointNameAvailability.md,No examples found -Get-AzCdnEndpointResourceUsage.md,No examples found -Get-AzCdnOrigin.md,No examples found -Get-AzCdnProfile.md,No examples found -Get-AzCdnProfileResourceUsage.md,No examples found -Get-AzCdnProfileSsoUrl.md,No examples found -Get-AzCdnSubscriptionResourceUsage.md,No examples found -New-AzCdnCustomDomain.md,No examples found -New-AzCdnEndpoint.md,No examples found -New-AzCdnProfile.md,No examples found -Publish-AzCdnEndpointContent.md,No examples found -Remove-AzCdnCustomDomain.md,No examples found -Remove-AzCdnEndpoint.md,No examples found -Remove-AzCdnProfile.md,No examples found -Set-AzCdnEndpoint.md,No examples found -Set-AzCdnOrigin.md,No examples found -Set-AzCdnProfile.md,No examples found -Start-AzCdnEndpoint.md,No examples found -Stop-AzCdnEndpoint.md,No examples found -Test-AzCdnCustomDomain.md,No examples found -Unpublish-AzCdnEndpointContent.md,No examples found -Get-AzVMADDomainExtension.md,No examples found -Get-AzVMDscExtensionStatus.md,No examples found -New-AzVMSqlServerKeyVaultCredentialConfig.md,No description found -New-AzVMSqlServerKeyVaultCredentialConfig.md,No examples found -Remove-AzVMAccessExtension.md,No examples found -Remove-AzVMBackup.md,No description found -Remove-AzVMCustomScriptExtension.md,No examples found -Remove-AzVMNetworkInterface.md,No examples found -Set-AzVMADDomainExtension.md,No examples found -Set-AzVMBackupExtension.md,No description found -Set-AzVMPlan.md,No examples found -Set-AzVmssVM.md,No examples found -Get-AzDtlAllowedVMSizesPolicy.md,No examples found -Get-AzDtlAutoShutdownPolicy.md,No examples found -Get-AzDtlAutoStartPolicy.md,No examples found -Get-AzDtlVMsPerLabPolicy.md,No examples found -Get-AzDtlVMsPerUserPolicy.md,No examples found -Set-AzDtlAllowedVMSizesPolicy.md,No examples found -Set-AzDtlAutoShutdownPolicy.md,No examples found -Set-AzDtlAutoStartPolicy.md,No examples found -Set-AzDtlVMsPerLabPolicy.md,No examples found -Set-AzDtlVMsPerUserPolicy.md,No examples found -Get-AzLogProfile.md,No examples found -New-AzAutoscaleWebhook.md,No examples found -Remove-AzAutoscaleSetting.md,No examples found -Remove-AzLogProfile.md,No examples found -Add-AzApplicationGatewayAuthenticationCertificate.md,No examples found -Add-AzApplicationGatewayUrlPathMapConfig.md,No examples found -Add-AzLoadBalancerInboundNatPoolConfig.md,No synopsis found -Add-AzLoadBalancerInboundNatPoolConfig.md,No description found -Get-AzApplicationGatewayAuthenticationCertificate.md,No examples found -Get-AzApplicationGatewayBackendAddressPool.md,No description found -Get-AzLoadBalancerInboundNatPoolConfig.md,No synopsis found -Get-AzLoadBalancerInboundNatPoolConfig.md,No description found -Get-AzRouteFilter.md,No examples found -Get-AzRouteFilterRuleConfig.md,No examples found -New-AzApplicationGatewayAuthenticationCertificate.md,No examples found -New-AzLoadBalancerInboundNatPoolConfig.md,No synopsis found -New-AzLoadBalancerInboundNatPoolConfig.md,No description found -New-AzRouteFilter.md,No examples found -New-AzRouteFilterRuleConfig.md,No examples found -Remove-AzApplicationGatewayAuthenticationCertificate.md,No examples found -Remove-AzApplicationGatewayUrlPathMapConfig.md,No examples found -Remove-AzLoadBalancerInboundNatPoolConfig.md,No synopsis found -Remove-AzLoadBalancerInboundNatPoolConfig.md,No description found -Remove-AzRouteFilter.md,No examples found -Remove-AzRouteFilterRuleConfig.md,No examples found -Set-AzApplicationGatewayAuthenticationCertificate.md,No examples found -Set-AzApplicationGatewayUrlPathMapConfig.md,No examples found -Set-AzLoadBalancerInboundNatPoolConfig.md,No synopsis found -Set-AzLoadBalancerInboundNatPoolConfig.md,No description found -Set-AzRouteFilter.md,No examples found -Set-AzRouteFilterRuleConfig.md,No examples found -New-AzNotificationHubKey.md,No examples found -New-AzNotificationHubsNamespaceKey.md,No examples found -Disable-AzOperationalInsightsIISLogCollection.md,No examples found -Disable-AzOperationalInsightsLinuxCustomLogCollection.md,No examples found -Disable-AzOperationalInsightsLinuxPerformanceCollection.md,No examples found -Disable-AzOperationalInsightsLinuxSyslogCollection.md,No examples found -Enable-AzOperationalInsightsIISLogCollection.md,No examples found -Enable-AzOperationalInsightsLinuxCustomLogCollection.md,No examples found -Enable-AzOperationalInsightsLinuxPerformanceCollection.md,No examples found -Enable-AzOperationalInsightsLinuxSyslogCollection.md,No examples found -Get-AzOperationalInsightsDataSource.md,No examples found -New-AzOperationalInsightsAzureActivityLogDataSource.md,No examples found -New-AzOperationalInsightsComputerGroup.md,No examples found -New-AzOperationalInsightsCustomLogDataSource.md,No examples found -New-AzOperationalInsightsLinuxPerformanceObjectDataSource.md,No examples found -New-AzOperationalInsightsLinuxSyslogDataSource.md,No examples found -New-AzOperationalInsightsWindowsEventDataSource.md,No examples found -New-AzOperationalInsightsWindowsPerformanceCounterDataSource.md,No examples found -Remove-AzOperationalInsightsDataSource.md,No examples found -Set-AzOperationalInsightsDataSource.md,No examples found -Get-AzResourceProvider.md,No examples found -Invoke-AzResourceAction.md,No examples found -Remove-AzResourceGroupDeployment.md,No examples found -Test-AzResourceGroupDeployment.md,No examples found -Unregister-AzResourceProvider.md,No examples found -Get-AzSqlDatabaseGeoBackupPolicy.md,No examples found -Get-AzSqlDatabaseReplicationLink.md,No examples found -Get-AzSqlServerBackupLongTermRetentionVault.md,No examples found -Get-AzSqlServerDisasterRecoveryConfiguration.md,No examples found -Get-AzSqlServerDisasterRecoveryConfigurationActivity.md,No examples found -New-AzSqlDatabaseCopy.md,No examples found -New-AzSqlServerDisasterRecoveryConfiguration.md,No examples found -Remove-AzSqlDatabaseSecondary.md,No examples found -Remove-AzSqlServerDisasterRecoveryConfiguration.md,No examples found -Set-AzSqlDatabaseGeoBackupPolicy.md,No examples found -Set-AzSqlDatabaseSecondary.md,No examples found -Set-AzSqlServerBackupLongTermRetentionVault.md,No examples found -Set-AzSqlServerDisasterRecoveryConfiguration.md,No examples found -Edit-AzWebAppBackupConfiguration.md,No synopsis found -Edit-AzWebAppBackupConfiguration.md,No examples found -Get-AzAppServicePlanMetric.md,No synopsis found -Get-AzWebAppBackup.md,No synopsis found -Get-AzWebAppBackupConfiguration.md,No synopsis found -Get-AzWebAppBackupList.md,No synopsis found -New-AzWebAppBackup.md,No synopsis found -New-AzWebAppDatabaseBackupSetting.md,No synopsis found -Remove-AzWebAppBackup.md,No synopsis found -Remove-AzWebAppSlot.md,No synopsis found -Reset-AzWebAppPublishingProfile.md,No synopsis found -Reset-AzWebAppSlotPublishingProfile.md,No synopsis found -Restart-AzWebAppSlot.md,No synopsis found -Restore-AzWebAppBackup.md,No synopsis found -Add-AzHDInsightSecurityProfile.md,No examples found -Find-AzDataProtectionRestorableTimeRange.md,No synopsis found -Find-AzDataProtectionRestorableTimeRange.md,No description found \ No newline at end of file +Get-AzApiManagementProperty.md,Missing SYNOPSIS content +Get-AzApiManagementProperty.md,Missing DESCRIPTION content +Remove-AzApiManagementAuthorizationServer.md,Missing EXAMPLES section +Update-AzApiManagementRegion.md,Missing EXAMPLES section +Remove-AzAutomationDscConfiguration.md,Missing EXAMPLES section +Remove-AzAutomationDscNodeConfiguration.md,Missing EXAMPLES section +Get-AzBatchAccountKeys.md,Missing EXAMPLES section +Remove-AzBatchJobSchedule.md,Missing EXAMPLES section +Set-AzBatchJobSchedule.md,Missing EXAMPLES section +Get-AzCdnCustomDomain.md,Missing EXAMPLES section +Get-AzCdnEdgeNode.md,Missing EXAMPLES section +Get-AzCdnEndpoint.md,Missing EXAMPLES section +Get-AzCdnEndpointNameAvailability.md,Missing EXAMPLES section +Get-AzCdnEndpointResourceUsage.md,Missing EXAMPLES section +Get-AzCdnOrigin.md,Missing EXAMPLES section +Get-AzCdnProfile.md,Missing EXAMPLES section +Get-AzCdnProfileResourceUsage.md,Missing EXAMPLES section +Get-AzCdnProfileSsoUrl.md,Missing EXAMPLES section +Get-AzCdnSubscriptionResourceUsage.md,Missing EXAMPLES section +New-AzCdnCustomDomain.md,Missing EXAMPLES section +New-AzCdnEndpoint.md,Missing EXAMPLES section +New-AzCdnProfile.md,Missing EXAMPLES section +Publish-AzCdnEndpointContent.md,Missing EXAMPLES section +Remove-AzCdnCustomDomain.md,Missing EXAMPLES section +Remove-AzCdnEndpoint.md,Missing EXAMPLES section +Remove-AzCdnProfile.md,Missing EXAMPLES section +Set-AzCdnEndpoint.md,Missing EXAMPLES section +Set-AzCdnOrigin.md,Missing EXAMPLES section +Set-AzCdnProfile.md,Missing EXAMPLES section +Start-AzCdnEndpoint.md,Missing EXAMPLES section +Stop-AzCdnEndpoint.md,Missing EXAMPLES section +Test-AzCdnCustomDomain.md,Missing EXAMPLES section +Unpublish-AzCdnEndpointContent.md,Missing EXAMPLES section +Get-AzVMADDomainExtension.md,Missing EXAMPLES section +Get-AzVMDscExtensionStatus.md,Missing EXAMPLES section +New-AzVMSqlServerKeyVaultCredentialConfig.md,Missing DESCRIPTION content +New-AzVMSqlServerKeyVaultCredentialConfig.md,Missing EXAMPLES section +Remove-AzVMAccessExtension.md,Missing EXAMPLES section +Remove-AzVMBackup.md,Missing DESCRIPTION content +Remove-AzVMCustomScriptExtension.md,Missing EXAMPLES section +Remove-AzVMNetworkInterface.md,Missing EXAMPLES section +Set-AzVMADDomainExtension.md,Missing EXAMPLES section +Set-AzVMBackupExtension.md,Missing DESCRIPTION content +Set-AzVMPlan.md,Missing EXAMPLES section +Set-AzVmssVM.md,Missing EXAMPLES section +Get-AzDtlAllowedVMSizesPolicy.md,Missing EXAMPLES section +Get-AzDtlAutoShutdownPolicy.md,Missing EXAMPLES section +Get-AzDtlAutoStartPolicy.md,Missing EXAMPLES section +Get-AzDtlVMsPerLabPolicy.md,Missing EXAMPLES section +Get-AzDtlVMsPerUserPolicy.md,Missing EXAMPLES section +Set-AzDtlAllowedVMSizesPolicy.md,Missing EXAMPLES section +Set-AzDtlAutoShutdownPolicy.md,Missing EXAMPLES section +Set-AzDtlAutoStartPolicy.md,Missing EXAMPLES section +Set-AzDtlVMsPerLabPolicy.md,Missing EXAMPLES section +Set-AzDtlVMsPerUserPolicy.md,Missing EXAMPLES section +Get-AzLogProfile.md,Missing EXAMPLES section +New-AzAutoscaleWebhook.md,Missing EXAMPLES section +Remove-AzAutoscaleSetting.md,Missing EXAMPLES section +Remove-AzLogProfile.md,Missing EXAMPLES section +Add-AzApplicationGatewayAuthenticationCertificate.md,Missing EXAMPLES section +Add-AzApplicationGatewayUrlPathMapConfig.md,Missing EXAMPLES section +Add-AzLoadBalancerInboundNatPoolConfig.md,Missing SYNOPSIS content +Add-AzLoadBalancerInboundNatPoolConfig.md,Missing DESCRIPTION content +Get-AzApplicationGatewayAuthenticationCertificate.md,Missing EXAMPLES section +Get-AzApplicationGatewayBackendAddressPool.md,Missing DESCRIPTION content +Get-AzLoadBalancerInboundNatPoolConfig.md,Missing SYNOPSIS content +Get-AzLoadBalancerInboundNatPoolConfig.md,Missing DESCRIPTION content +Get-AzRouteFilter.md,Missing EXAMPLES section +Get-AzRouteFilterRuleConfig.md,Missing EXAMPLES section +New-AzApplicationGatewayAuthenticationCertificate.md,Missing EXAMPLES section +New-AzLoadBalancerInboundNatPoolConfig.md,Missing SYNOPSIS content +New-AzLoadBalancerInboundNatPoolConfig.md,Missing DESCRIPTION content +New-AzRouteFilter.md,Missing EXAMPLES section +New-AzRouteFilterRuleConfig.md,Missing EXAMPLES section +Remove-AzApplicationGatewayAuthenticationCertificate.md,Missing EXAMPLES section +Remove-AzApplicationGatewayUrlPathMapConfig.md,Missing EXAMPLES section +Remove-AzLoadBalancerInboundNatPoolConfig.md,Missing SYNOPSIS content +Remove-AzLoadBalancerInboundNatPoolConfig.md,Missing DESCRIPTION content +Remove-AzRouteFilter.md,Missing EXAMPLES section +Remove-AzRouteFilterRuleConfig.md,Missing EXAMPLES section +Set-AzApplicationGatewayAuthenticationCertificate.md,Missing EXAMPLES section +Set-AzApplicationGatewayUrlPathMapConfig.md,Missing EXAMPLES section +Set-AzLoadBalancerInboundNatPoolConfig.md,Missing SYNOPSIS content +Set-AzLoadBalancerInboundNatPoolConfig.md,Missing DESCRIPTION content +Set-AzRouteFilter.md,Missing EXAMPLES section +Set-AzRouteFilterRuleConfig.md,Missing EXAMPLES section +New-AzNotificationHubKey.md,Missing EXAMPLES section +New-AzNotificationHubsNamespaceKey.md,Missing EXAMPLES section +Disable-AzOperationalInsightsIISLogCollection.md,Missing EXAMPLES section +Disable-AzOperationalInsightsLinuxCustomLogCollection.md,Missing EXAMPLES section +Disable-AzOperationalInsightsLinuxPerformanceCollection.md,Missing EXAMPLES section +Disable-AzOperationalInsightsLinuxSyslogCollection.md,Missing EXAMPLES section +Enable-AzOperationalInsightsIISLogCollection.md,Missing EXAMPLES section +Enable-AzOperationalInsightsLinuxCustomLogCollection.md,Missing EXAMPLES section +Enable-AzOperationalInsightsLinuxPerformanceCollection.md,Missing EXAMPLES section +Enable-AzOperationalInsightsLinuxSyslogCollection.md,Missing EXAMPLES section +Get-AzOperationalInsightsDataSource.md,Missing EXAMPLES section +New-AzOperationalInsightsAzureActivityLogDataSource.md,Missing EXAMPLES section +New-AzOperationalInsightsComputerGroup.md,Missing EXAMPLES section +New-AzOperationalInsightsCustomLogDataSource.md,Missing EXAMPLES section +New-AzOperationalInsightsLinuxPerformanceObjectDataSource.md,Missing EXAMPLES section +New-AzOperationalInsightsLinuxSyslogDataSource.md,Missing EXAMPLES section +New-AzOperationalInsightsWindowsEventDataSource.md,Missing EXAMPLES section +New-AzOperationalInsightsWindowsPerformanceCounterDataSource.md,Missing EXAMPLES section +Remove-AzOperationalInsightsDataSource.md,Missing EXAMPLES section +Set-AzOperationalInsightsDataSource.md,Missing EXAMPLES section +Get-AzResourceProvider.md,Missing EXAMPLES section +Invoke-AzResourceAction.md,Missing EXAMPLES section +Remove-AzResourceGroupDeployment.md,Missing EXAMPLES section +Test-AzResourceGroupDeployment.md,Missing EXAMPLES section +Unregister-AzResourceProvider.md,Missing EXAMPLES section +Get-AzSqlDatabaseGeoBackupPolicy.md,Missing EXAMPLES section +Get-AzSqlDatabaseReplicationLink.md,Missing EXAMPLES section +Get-AzSqlServerBackupLongTermRetentionVault.md,Missing EXAMPLES section +Get-AzSqlServerDisasterRecoveryConfiguration.md,Missing EXAMPLES section +Get-AzSqlServerDisasterRecoveryConfigurationActivity.md,Missing EXAMPLES section +New-AzSqlDatabaseCopy.md,Missing EXAMPLES section +New-AzSqlServerDisasterRecoveryConfiguration.md,Missing EXAMPLES section +Remove-AzSqlDatabaseSecondary.md,Missing EXAMPLES section +Remove-AzSqlServerDisasterRecoveryConfiguration.md,Missing EXAMPLES section +Set-AzSqlDatabaseGeoBackupPolicy.md,Missing EXAMPLES section +Set-AzSqlDatabaseSecondary.md,Missing EXAMPLES section +Set-AzSqlServerBackupLongTermRetentionVault.md,Missing EXAMPLES section +Set-AzSqlServerDisasterRecoveryConfiguration.md,Missing EXAMPLES section +Edit-AzWebAppBackupConfiguration.md,Missing SYNOPSIS content +Edit-AzWebAppBackupConfiguration.md,Missing EXAMPLES section +Get-AzAppServicePlanMetric.md,Missing SYNOPSIS content +Get-AzWebAppBackup.md,Missing SYNOPSIS content +Get-AzWebAppBackupConfiguration.md,Missing SYNOPSIS content +Get-AzWebAppBackupList.md,Missing SYNOPSIS content +New-AzWebAppBackup.md,Missing SYNOPSIS content +New-AzWebAppDatabaseBackupSetting.md,Missing SYNOPSIS content +Remove-AzWebAppBackup.md,Missing SYNOPSIS content +Remove-AzWebAppSlot.md,Missing SYNOPSIS content +Reset-AzWebAppPublishingProfile.md,Missing SYNOPSIS content +Reset-AzWebAppSlotPublishingProfile.md,Missing SYNOPSIS content +Restart-AzWebAppSlot.md,Missing SYNOPSIS content +Restore-AzWebAppBackup.md,Missing SYNOPSIS content +Add-AzHDInsightSecurityProfile.md,Missing EXAMPLES section +Find-AzDataProtectionRestorableTimeRange.md,Missing SYNOPSIS content +Find-AzDataProtectionRestorableTimeRange.md,Missing DESCRIPTION content diff --git a/tools/HelpGeneration/HelpGeneration.psm1 b/tools/HelpGeneration/HelpGeneration.psm1 index a32d579ae204..d7b0068f0cb9 100644 --- a/tools/HelpGeneration/HelpGeneration.psm1 +++ b/tools/HelpGeneration/HelpGeneration.psm1 @@ -1,6 +1,6 @@ -#Requires -Modules platyPS -function New-AzMarkdownHelp -{ +#Requires -Modules Microsoft.PowerShell.PlatyPS + +function New-AzMarkdownHelp { [CmdletBinding()] Param ( @@ -11,8 +11,7 @@ function New-AzMarkdownHelp $HelpFolder = Get-Item $HelpFolderPath $ModuleFolder = $HelpFolder.Parent $ModuleFolderPath = $ModuleFolder.FullName - if ($ModuleFolder.Name -eq "Azure.AnalysisServices") - { + if ($ModuleFolder.Name -eq "Azure.AnalysisServices") { return } @@ -21,13 +20,17 @@ function New-AzMarkdownHelp Import-Module $psd1.FullName -Scope Global New-Item -Path $NewHelpFolderPath -ItemType Directory -Force | Out-Null Copy-Item -Path "$HelpFolderPath\*" -Destination $NewHelpFolderPath - Update-MarkdownHelpModule -Path $NewHelpFolderPath -RefreshModulePage -AlphabeticParamsOrder | Out-Null + Update-MarkdownCommandHelp -Path "$NewHelpFolderPath\*-*.md" | Out-Null + $updatedHelp = Import-MarkdownCommandHelp -Path "$NewHelpFolderPath\*-*.md" + $moduleFilePath = Get-ChildItem -Path $NewHelpFolderPath -Filter "Az.*.md" | Where-Object { $_.Name -notlike "*-*" } | Select-Object -First 1 + if ($moduleFilePath) { + Update-MarkdownModuleFile -Path $moduleFilePath.FullName -CommandHelp $updatedHelp | Out-Null + } $errors = Compare-AzMarkdownHelp $HelpFolderPath $NewHelpFolderPath - if ($errors.Length -gt 0) - { + if ($errors.Length -gt 0) { $errorMessage = @() $errorMessage += "ERROR: The following files have not been updated with the latest module changes.`n" - $errorMessage += "Please make sure to run Update-MarkdownHelpModule to update the markdown files.`n" + $errorMessage += "Please make sure to run Update-MarkdownCommandHelp to update the markdown files.`n" $errors | foreach { $errorMessage += "- $_`n" } throw $errorMessage } @@ -35,8 +38,7 @@ function New-AzMarkdownHelp Remove-Item $NewHelpFolderPath -Recurse } -function Compare-AzMarkdownHelp -{ +function Compare-AzMarkdownHelp { [CmdletBinding()] Param ( @@ -49,24 +51,19 @@ function Compare-AzMarkdownHelp $comparatorInstance = New-Object MarkdownComparator.Comparator $OldHelpFolder = Get-Item $OldHelpFolderPath $errors = @() - foreach ($oldFile in Get-ChildItem $OldHelpFolder) - { + foreach ($oldFile in Get-ChildItem $OldHelpFolder) { $newFilePath = "$NewHelpFolderPath\$($oldFile.Name)" - if ($oldFile.Name -notlike "*-*") - { - continue; + if ($oldFile.Name -notlike "*-*") { + continue } - try - { + try { $result = $comparatorInstance.Compare($oldFile.FullName, $newFilePath) - if ($result -ne 0) - { + if ($result -ne 0) { $errors += $oldFile.Name } } - catch - { + catch { $_.Exception.InnerException } } @@ -74,8 +71,7 @@ function Compare-AzMarkdownHelp return $errors } -function Test-AzMarkdownHelp -{ +function Test-AzMarkdownHelp { [CmdletBinding()] Param( [Parameter(Mandatory = $true, Position = 0)] @@ -86,26 +82,21 @@ function Test-AzMarkdownHelp [String]$NewExceptionsPath ) - PROCESS - { + PROCESS { $HelpFolder = Get-Item $HelpFolderPath $Exceptions = Import-Csv "$SuppressedExceptionsPath\ValidateHelpIssues.csv" [String[]]$errors = @() $MarkdownFiles = Get-ChildItem -Path $HelpFolder -Filter "*.md" $HelpFolderPath = $HelpFolder.FullName.Replace("\", "/") - if ($HelpFolderPath -match "/artifacts/") - { + if ($HelpFolderPath -match "/artifacts/") { $ModuleName = $HelpFolderPath.split('/artifacts/')[1].split('/')[1] } - else - { + else { $ModuleName = "Az." + $HelpFolderPath.split('src/')[1].split('/')[0] } - foreach ($file in $MarkdownFiles) - { + foreach ($file in $MarkdownFiles) { # Ignore the module page - if ($file.Name -notlike "*-*") - { + if ($file.Name -notlike "*-*") { continue } @@ -113,118 +104,138 @@ function Test-AzMarkdownHelp $fileErrors = @() $content = Get-Content $file.FullName - for ($idx = 0; $idx -lt $content.Length; $idx++) - { - switch -Regex ($content[$idx]) - { - "## SYNOPSIS" - { + + # Detect schema version: new schema uses "PlatyPS schema version:" in YAML front matter + $isNewSchema = ($content | Where-Object { $_ -match "PlatyPS schema version:" }) -ne $null + + for ($idx = 0; $idx -lt $content.Length; $idx++) { + switch -Regex ($content[$idx]) { + "## SYNOPSIS" { $foundSynopsis = $False $idx++ # Check each line between SYNOPSIS and SYNTAX for any text - for (;;) - { + for (; ; ) { $foundSynopsis = $foundSynopsis -or (!([string]::IsNullOrWhiteSpace("$($content[$idx])"))) - if ($content[$idx+1] -notcontains "## SYNTAX") - { + if ($content[$idx + 1] -notcontains "## SYNTAX") { $idx++ - if ($idx -ge $content.Length) - { - Write-Error "Could not find SYNTAX header in file $($file.Name)" - return + if ($idx -ge $content.Length) { + $errors += "$($file.Name),Missing SYNTAX section" + break } } - elseif ($content[$idx] -contains "{{Fill in the Synopsis}}") - { + elseif ($content[$idx] -match "\{\{\s*Fill in the Synopsis\s*\}\}") { $foundSynopsis = $false break } - else - { + else { break } } - if (!($foundSynopsis)) - { - $fileErrors += "No synopsis found" + if (!($foundSynopsis)) { + $fileErrors += "Missing SYNOPSIS content" } } - "## DESCRIPTION" - { + "## DESCRIPTION" { $foundDescription = $False $idx++ # Check each line between DESCRIPTION and EXAMPLES for any text - for (;;) - { + for (; ; ) { $foundDescription = $foundDescription -or (!([string]::IsNullOrWhiteSpace("$($content[$idx])"))) - if ($content[$idx+1] -notcontains "## EXAMPLES") - { + if ($content[$idx + 1] -notcontains "## EXAMPLES") { $idx++ - if ($idx -ge $content.Length) - { - Write-Error "Could not find EXAMPLES header in file $($file.Name)" - return + if ($idx -ge $content.Length) { + $errors += "$($file.Name),Missing EXAMPLES section" + break } } - elseif ($content[$idx] -contains "{{Fill in the Description}}") - { + elseif ($content[$idx] -match "\{\{\s*Fill in the Description\s*\}\}") { $foundDescription = $false break } - else - { + else { break } } - if (!($foundDescription)) - { - $fileErrors += "No description found" + if (!($foundDescription)) { + $fileErrors += "Missing DESCRIPTION content" } } - "@{Text=}" - { - # This case occurs when there is no description provided for a parameter - $parameter = $content[$idx-1].Substring(5) - $fileErrors += "No description found for parameter $parameter" + "@{Text=}" { + # Old schema: empty parameter description + $parameter = $content[$idx - 1].Substring(5) + $fileErrors += "Missing description for parameter '$parameter'" + } + "\{\{\s*Fill \w+ Description\s*\}\}" { + # New schema: empty parameter description placeholder like {{ Fill ParamName Description }} + if ($content[$idx - 1] -match "^### -(.+)") { + $parameter = $Matches[1] + } + else { + $parameter = "(unknown)" + } + $fileErrors += "Missing description for parameter '$parameter'" + } + ".``````yaml" { + $parameter = $content[$idx - 1].Substring(5) + $fileErrors += "Malformed YAML in description for parameter '$parameter'" + } + "\{\{\s*Add example description here\s*\}\}" { + # New schema: example placeholder not filled in + $fileErrors += "Example description contains placeholder text" } - ".``````yaml" - { - $parameter = $content[$idx-1].Substring(5) - $fileErrors += "Trailing yaml string found in description for parameter $parameter. Please move the trailing yaml string to a line by itself." + "\{\{\s*Fill in the Notes\s*\}\}" { + # New schema: notes placeholder not filled in + $fileErrors += "NOTES section contains placeholder text" } - "online version:" - { - $onlineString = "https://learn.microsoft.com/powershell/module/$($ModuleName.ToLower())/$($CmdletName.ToLower())" - $split = $content[$idx] -split "online version:" - if ([string]::IsNullOrWhiteSpace($split[1]) -or $split[1] -notlike "*$onlineString*") - { - $fileErrors += "Online version in the header of the file is incorrect. The corresponding URL should be the following: $onlineString" + "\{\{\s*Fill in the related links here\s*\}\}" { + # New schema: related links placeholder not filled in + $fileErrors += "RELATED LINKS section contains placeholder text" + } + "\{\{\s*Insert list of aliases\s*\}\}" { + # New schema: aliases placeholder not filled in + $fileErrors += "Aliases section contains placeholder text" + } + "online version:" { + # Old schema (schema: 2.0.0): online version in YAML front matter + if (-not $isNewSchema) { + $onlineString = "https://learn.microsoft.com/powershell/module/$($ModuleName.ToLower())/$($CmdletName.ToLower())" + $split = $content[$idx] -split "online version:" + if ([string]::IsNullOrWhiteSpace($split[1]) -or $split[1] -notlike "*$onlineString*") { + $fileErrors += "Invalid 'online version' URL, expected: $onlineString" + } + } + } + "^HelpUri:" { + # New schema (PlatyPS schema version: 2024-05-01): HelpUri in YAML front matter + if ($isNewSchema) { + $onlineString = "https://learn.microsoft.com/powershell/module/$($ModuleName.ToLower())/$($CmdletName.ToLower())" + $split = $content[$idx] -split "HelpUri:" + $helpUri = $split[1].Trim().Trim("'").Trim('"') + if ([string]::IsNullOrWhiteSpace($helpUri) -or $helpUri -notlike "*$onlineString*") { + $fileErrors += "Invalid 'HelpUri' URL, expected: $onlineString" + } } } - default - { + default { } } } # If the markdown file had any missing help, add them to the list to be printed later - if ($fileErrors.Count -gt 0) - { + if ($fileErrors.Count -gt 0) { $fileExceptions = $Exceptions | where { $_.Target -eq "$($file.Name)" } $fileErrors | foreach { $error = $_ - if (($fileExceptions | where { $_.Description -eq "$error" }) -ne $null) - { + if (($fileExceptions | where { $_.Description -eq "$error" }) -ne $null) { # "Caught error - $file,$error" } - else - { + else { $errors += "$($file.Name),$error" } } @@ -232,15 +243,13 @@ function Test-AzMarkdownHelp } # If there were any errors recorded, print them out and throw - if ($errors.Count -gt 0) - { + if ($errors.Count -gt 0) { $errors | foreach { Add-Content "$NewExceptionsPath\ValidateHelpIssues.csv" $_ } } } } -function New-AzMamlHelp -{ +function New-AzMamlHelp { [CmdletBinding()] Param ( @@ -249,70 +258,15 @@ function New-AzMamlHelp ) $HelpFolder = Get-Item $HelpFolderPath - $MarkdownFiles = Get-ChildItem $HelpFolderPath # Generate the MAML help from the markdown files - New-ExternalHelp -Path $HelpFolderPath -OutputPath $HelpFolder.Parent.FullName -Force - $dir = Get-ChildItem $HelpFolder.Parent.FullName - $MAML = $dir | Where { $_.FullName -like "*.dll-Help.xml*" } - - # Modify the MAML (add spaces between examples) - $MAML | foreach { Edit-AzMamlHelp $HelpFolder $_ } + $cmdHelp = Import-MarkdownCommandHelp -Path "$HelpFolderPath\*-*.md" + Export-MamlCommandHelp -CommandHelp $cmdHelp -OutputFolder $HelpFolder.Parent.FullName -Force } -function Edit-AzMamlHelp -{ - [CmdletBinding()] - Param - ( - [Parameter(Mandatory = $true, Position = 0)] - [System.IO.DirectoryInfo]$HelpFolder, - [Parameter(Mandatory = $true, Position = 1)] - [System.IO.FileInfo]$MAML - ) - - $content = Get-Content "$($HelpFolder.Parent.FullName)\$($MAML.Name)" - - # Keep track of the number of examples we find so we can add enough space in the new array - $exampleCount = 0 - for ($idx = 0; $idx -lt $content.Length; $idx++) - { - if ($content[$idx] -like "**") - { - $exampleCount++ - } - } - - # Since we will be adding two tags to the MAML, we need to adjust the size of the array - $newContentLength = $content.Length + (2 * $exampleCount) - $newContent = New-Object string[] $newContentLength - $buffer = 0 - for ($idx = 0; $idx -lt $content.Length; $idx++) - { - $newContent[$idx + $buffer] = $content[$idx] - - # If the next line is going to be the end of a remark in an example, add the two new lines for spacing - if ($content[$idx+1] -like "**") - { - $newContent[$idx + $buffer + 1] = "" - $newContent[$idx + $buffer + 2] = "" - - $buffer += 2 - } - } - - # Replace the contents of the current MAML with the new contents - $result = $newContent -join "`r`n" - $tempFile = Get-Item "$($HelpFolder.Parent.FullName)\$($MAML.Name)" - [System.IO.File]::WriteAllText($tempFile.FullName, $result) - - # Check to ensure that the MAML file is still valid XML - [Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") | Out-Null - [System.Xml.Linq.XDocument]::Load($tempFile.FullName) | Out-Null -} # ------------ # Start # ------------ -Import-Module -Name platyPS -Scope Global +Import-Module -Name Microsoft.PowerShell.PlatyPS -Scope Global diff --git a/tools/StaticAnalysis/HelpAnalyzer/HelpAnalyzer.cs b/tools/StaticAnalysis/HelpAnalyzer/HelpAnalyzer.cs index b9bac1924820..029a550eb1cd 100644 --- a/tools/StaticAnalysis/HelpAnalyzer/HelpAnalyzer.cs +++ b/tools/StaticAnalysis/HelpAnalyzer/HelpAnalyzer.cs @@ -12,8 +12,7 @@ // limitations under the License. // ---------------------------------------------------------------------------------- -using Markdown.MAML.Parser; -using Markdown.MAML.Transformer; +using Microsoft.PowerShell.PlatyPS; using System; using System.Collections.Generic; using System.IO; @@ -297,13 +296,23 @@ private void ValidateHelpMarkdown(string helpFolder, IList helpRecords, foreach (var helpMarkdown in helpRecords) { var file = Path.Combine(helpFolder, helpMarkdown + ".md"); - var content = File.ReadAllText(file); try { - var parser = new MarkdownParser(); - var transformer = new ModelTransformerVersion2(); - var markdownModel = parser.ParseString(new[] { content }); - var model = transformer.NodeModelToMamlModel(markdownModel).FirstOrDefault(); + var issues = new List(); + var isValid = MarkdownConverter.ValidateMarkdownFile(file, out issues); + if (!isValid) + { + HelpIssue issue = new HelpIssue + { + Target = helpMarkdown, + Severity = 1, + ProblemId = PlatyPSSchemaViolation, + Description = "Help content doesn't conform to PlatyPS Schema definition: " + string.Join("; ", issues), + Remediation = string.Format("No.") + }; + helpLogger.LogRecord(issue); + Console.Error.WriteLine($"Failed to validate {file} by PlatyPS: {string.Join("; ", issues)}"); + } } catch (Exception ex) { diff --git a/tools/StaticAnalysis/StaticAnalysis.Netcore.csproj b/tools/StaticAnalysis/StaticAnalysis.Netcore.csproj index 3bf5d33c1c57..9bfafafe868d 100644 --- a/tools/StaticAnalysis/StaticAnalysis.Netcore.csproj +++ b/tools/StaticAnalysis/StaticAnalysis.Netcore.csproj @@ -47,8 +47,14 @@ - - lib\Markdown.MAML.dll + + lib\Microsoft.PowerShell.PlatyPS.dll + + + lib\Markdig.Signed.dll + + + lib\YamlDotNet.dll diff --git a/tools/StaticAnalysis/lib/Markdig.Signed.dll b/tools/StaticAnalysis/lib/Markdig.Signed.dll new file mode 100644 index 000000000000..f6996cca8856 Binary files /dev/null and b/tools/StaticAnalysis/lib/Markdig.Signed.dll differ diff --git a/tools/StaticAnalysis/lib/Markdown.MAML.dll b/tools/StaticAnalysis/lib/Markdown.MAML.dll deleted file mode 100644 index bdb2d4964446..000000000000 Binary files a/tools/StaticAnalysis/lib/Markdown.MAML.dll and /dev/null differ diff --git a/tools/StaticAnalysis/lib/Microsoft.PowerShell.PlatyPS.dll b/tools/StaticAnalysis/lib/Microsoft.PowerShell.PlatyPS.dll new file mode 100644 index 000000000000..927a33284d14 Binary files /dev/null and b/tools/StaticAnalysis/lib/Microsoft.PowerShell.PlatyPS.dll differ diff --git a/tools/StaticAnalysis/lib/YamlDotNet.dll b/tools/StaticAnalysis/lib/YamlDotNet.dll new file mode 100644 index 000000000000..f731d810fcf9 Binary files /dev/null and b/tools/StaticAnalysis/lib/YamlDotNet.dll differ