Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SqlServerDsc: Add markdown creation for public commands #1986

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- SqlServerDsc
- Added build tasks to generate Wiki documentation for public commands.

### Fixed

- SqlServerDsc
Expand Down Expand Up @@ -35,6 +40,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Update markdown highlights with newly supported keywords.
- Bump GitHub Action _Stale_ to v9.
- Bump GitHub Action _CodeQL-Action_ to v3.
- Documentation is now built using a separate meta task `docs`.
It is run with the meta task `pack` which is run by the pipeline.
To run the meta task `docs` the SMO assemblies must be loaded into the
session, either by importing SqlServer module or loading SMO stubs.
- QA test improved to speed up quality testing.
- SqlSetup
- Updated integration tests to use PSResourceGet to download required modules.

Expand Down
13 changes: 11 additions & 2 deletions RequiredModules.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
MarkdownLinkCheck = 'latest'
'DscResource.Test' = 'latest'
xDscResourceDesigner = 'latest'
'DscResource.DocGenerator' = 'latest'

# Build dependencies needed for using the module
'DscResource.Base' = 'latest'
Expand All @@ -46,9 +45,19 @@
# Need to pin this to 3.7.2 because 4.0.0 made the integration tests fail.
PSPKI = '3.7.2'

# Prerequisites modules needed for examples or integration tests
# Prerequisite modules needed for examples or integration tests
xPSDesiredStateConfiguration = '9.1.0'
StorageDsc = '5.1.0'
NetworkingDsc = '9.0.0'
WSManDsc = '3.1.1'

# Prerequisite modules for documentation.
#'DscResource.DocGenerator' = 'latest'
'DscResource.DocGenerator' = @{
Version = 'latest'
Parameters = @{
AllowPrerelease = $true
}
}
PlatyPS = 'latest'
}
15 changes: 15 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ stages:
}
Write-Host -Object "##vso[build.updatebuildnumber]$($gitVersionObject.FullSemVer)"
displayName: Calculate ModuleVersion (GitVersion)
- pwsh: |
<#
This is intentionally not saved to RequiredModules. It is only
used for creating documentation and should not be part of the
build artifact.
#>
Write-Information -MessageData 'Removing SqlServer and SQLPS from the CI worker.' -InformationAction Continue
Import-Module -Name ./tests/TestHelpers/CommonTestHelper.psm1
Remove-PowerShellModuleFromCI -Name @('SqlServer', 'SQLPS')
Remove-Module -Name CommonTestHelper
Write-Information -MessageData 'Installing latest SqlServer on the CI worker' -InformationAction Continue
Install-Module -Name SqlServer -Force -Confirm:$false -Verbose
Get-Module -Name SqlServer -ListAvailable |
Select-Object -Property Name,Version,@{Name='Prerelease'; Expression={$_.PrivateData.PSData.Prerelease}}, Path
displayName: Install SqlServer module
- task: PowerShell@2
name: package
displayName: 'Build & Package Module'
Expand Down
50 changes: 38 additions & 12 deletions build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,21 @@ BuildWorkflow:
- Build_Module_ModuleBuilder
- Build_NestedModules_ModuleBuilder
- Create_Changelog_Release_Output

docs:
- Check_SqlServer_Availability
- Generate_Conceptual_Help
- Generate_Wiki_Content
- Generate_Markdown_For_Public_Commands
- Generate_External_Help_File_For_Public_Commands
- Clean_Markdown_Of_Public_Commands
- Generate_Wiki_Sidebar
- Clean_Markdown_Metadata
- Package_WikContent

fastbuild:
- Clean
- Build_Module_ModuleBuilder
- Build_NestedModules_ModuleBuilder

pack:
- build
- docs
- package_module_nupkg # cSpell: disable-line

hqrmtest: # cSpell: disable-line
Expand All @@ -38,15 +42,22 @@ BuildWorkflow:
- Publish_Module_To_gallery
- Publish_GitHub_Wiki_Content

Check_SqlServer_Availability: |
{
Import-Module -Name SqlServer -ErrorAction 'SilentlyContinue'

try
{
[Microsoft.SqlServer.Management.Smo.Server] -as [Type] | Out-Null
}
catch
{
throw 'The SqlServer types are not available. Please install the SqlServer module or load SMO stubs types and try again.'
}
}

Package_WikContent: |
{
<#
This is quick fix for issue https://github.com/PoshCode/ModuleBuilder/issues/103.
Aliases need to be added to module manifest, and we can only use
New-Alias or Set-Alias together with build tasks. This module
already automatically exports aliases using [Alias()] so this quick
fix is meant as a workaround until the above issue is resolved.
#>
param
(
$OutputDirectory = (property OutputDirectory (Join-Path $BuildRoot 'output')),
Expand Down Expand Up @@ -207,3 +218,18 @@ DscResource.DocGenerator:
- '_(.+?)_' # Match Italic (underscore)
- '\*\*(.+?)\*\*' # Match bold
- '\*(.+?)\*' # Match Italic (asterisk)
Publish_GitHub_Wiki_Content:
Debug: false
Generate_Wiki_Content:
MofResourceMetadata:
Type: MofResource
Category: Resources
ClassResourceMetadata:
Type: ClassResource
Category: Resources
CompositeResourceMetadata:
Type: CompositeResource
Category: Resources
Generate_Wiki_Sidebar:
Debug: false
AlwaysOverwrite: true
121 changes: 45 additions & 76 deletions tests/QA/module.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Describe 'Changelog Management' -Tag 'Changelog' {
}

It 'Changelog should have an Unreleased header' -Skip:$skipTest {
(Get-ChangelogData -Path (Join-Path -Path $ProjectPath -ChildPath 'CHANGELOG.md') -ErrorAction Stop).Unreleased | Should -Not -BeNullOrEmpty
(Get-ChangelogData -Path (Join-Path -Path $ProjectPath -ChildPath 'CHANGELOG.md') -ErrorAction Stop).Unreleased | Should -Not -BeNullOrEmpty
}
}

Expand All @@ -125,14 +125,25 @@ BeforeDiscovery {
$allModuleFunctions = & $mut { Get-Command -Module $args[0] -CommandType Function } $script:moduleName

# Build test cases.
$testCases = @()
$testCasesAllModuleFunction = @()

foreach ($function in $allModuleFunctions)
{
$testCases += @{
$testCasesAllModuleFunction += @{
Name = $function.Name
}
}

$allPublicCommand = (Get-Command -Module $script:moduleName).Name

$testCasesPublicCommand = @()

foreach ($command in $allPublicCommand)
{
$testCasesPublicCommand += @{
Name = $command
}
}
}

Describe 'Quality for module' -Tags 'TestQuality' {
Expand All @@ -154,11 +165,11 @@ Describe 'Quality for module' -Tags 'TestQuality' {
}
}

It 'Should have a unit test for <Name>' -ForEach $testCases {
It 'Should have a unit test for <Name>' -ForEach $testCasesAllModuleFunction {
Get-ChildItem -Path 'tests\' -Recurse -Include "$Name.Tests.ps1" | Should -Not -BeNullOrEmpty
}

It 'Should pass Script Analyzer for <Name>' -ForEach $testCases -Skip:(-not $scriptAnalyzerRules) {
It 'Should pass Script Analyzer for <Name>' -ForEach $testCasesAllModuleFunction -Skip:(-not $scriptAnalyzerRules) {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$pssaResult = (Invoke-ScriptAnalyzer -Path $functionFile.FullName)
Expand All @@ -169,88 +180,46 @@ Describe 'Quality for module' -Tags 'TestQuality' {
}

Describe 'Help for module' -Tags 'helpQuality' {
It 'Should have .SYNOPSIS for <Name>' -ForEach $testCases {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName

$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)
Context 'Validating help for <Name>' -ForEach $testCasesAllModuleFunction -Tag 'helpQuality' {
BeforeAll {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }
$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName

$parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) |
Where-Object -FilterScript {
$_.Name -eq $Name
}
$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)

$functionHelp = $parsedFunction.GetHelpContent()
$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }

$functionHelp.Synopsis | Should -Not -BeNullOrEmpty
}

It 'Should have a .DESCRIPTION with length greater than 40 characters for <Name>' -ForEach $testCases {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName

$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)

$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }

$parsedFunction = $abstractSyntaxTree.FindAll($astSearchDelegate, $true) |
Where-Object -FilterScript {
$_.Name -eq $Name
}

$functionHelp = $parsedFunction.GetHelpContent()

$functionHelp.Description.Length | Should -BeGreaterThan 40
}
$parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) |
Where-Object -FilterScript {
$_.Name -eq $Name
}

It 'Should have at least one (1) example for <Name>' -ForEach $testCases {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"

$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName

$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)

$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }

$parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) |
Where-Object -FilterScript {
$_.Name -eq $Name
}

$functionHelp = $parsedFunction.GetHelpContent()

$functionHelp.Examples.Count | Should -BeGreaterThan 0
$functionHelp.Examples[0] | Should -Match ([regex]::Escape($function.Name))
$functionHelp.Examples[0].Length | Should -BeGreaterThan ($function.Name.Length + 10)

}
$script:functionHelp = $parsedFunction.GetHelpContent()
}

It 'Should have described all parameters for <Name>' -ForEach $testCases {
$functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1"
It 'Should have .SYNOPSIS' {
$functionHelp.Synopsis | Should -Not -BeNullOrEmpty
}

$scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName
It 'Should have a .DESCRIPTION with length greater than 40 characters for <Name>' {
$functionHelp.Description.Length | Should -BeGreaterThan 40
}

$abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null)
It 'Should have at least one (1) example for <Name>' {
$functionHelp.Examples.Count | Should -BeGreaterThan 0
$functionHelp.Examples[0] | Should -Match ([regex]::Escape($function.Name))
$functionHelp.Examples[0].Length | Should -BeGreaterThan ($function.Name.Length + 10)
}

$astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }
It 'Should have described all parameters for <Name>' {
$parameters = $parsedFunction.Body.ParamBlock.Parameters.Name.VariablePath.ForEach({ $_.ToString() })

$parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) |
Where-Object -FilterScript {
$_.Name -eq $Name
foreach ($parameter in $parameters)
{
$functionHelp.Parameters.($parameter.ToUpper()) | Should -Not -BeNullOrEmpty -Because ('the parameter {0} must have a description' -f $parameter)
$functionHelp.Parameters.($parameter.ToUpper()).Length | Should -BeGreaterThan 25 -Because ('the parameter {0} must have descriptive description' -f $parameter)
}

$functionHelp = $parsedFunction.GetHelpContent()

$parameters = $parsedFunction.Body.ParamBlock.Parameters.Name.VariablePath.ForEach({ $_.ToString() })

foreach ($parameter in $parameters)
{
$functionHelp.Parameters.($parameter.ToUpper()) | Should -Not -BeNullOrEmpty -Because ('the parameter {0} must have a description' -f $parameter)
$functionHelp.Parameters.($parameter.ToUpper()).Length | Should -BeGreaterThan 25 -Because ('the parameter {0} must have descriptive description' -f $parameter)
}
}
}
Loading