diff --git a/.azuredevops/platformPipelines/platform.updateStaticTestDocs.yml b/.azuredevops/platformPipelines/platform.updateStaticTestDocs.yml new file mode 100644 index 0000000000..8f12160f03 --- /dev/null +++ b/.azuredevops/platformPipelines/platform.updateStaticTestDocs.yml @@ -0,0 +1,67 @@ +name: ".Platform - Update Static Test Documentation" + +pr: none + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - .azuredevops/platformPipelines/platform.updateStaticTestDocs.yml + - 'utilities/pipelines/staticValidation/module.tests.ps1' + - utilities/tools/platform/Set-StaticTestDocumentation.ps1 + +variables: + - template: "../../settings.yml" + - name: pipelinePrincipalGitUserName + value: "CARMLPipelinePrincipal" + - name: pipelinePrincipalGitUserEmail + value: "CARML@noreply.github.com" + +jobs: + - job: Update_Static_Test_Docs + displayName: Update Static Tests Documentation + pool: + ${{ if ne(variables.vmImage, '') }}: + vmImage: ${{ variables.vmImage }} + ${{ if ne(variables.poolName, '') }}: + name: ${{ variables.poolName }} + steps: + - checkout: self + persistCredentials: true + + - task: PowerShell@2 + displayName: "Update file" + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'tools' 'platform' 'Set-StaticTestDocumentation.ps1') + + $functionInput = @{ + TestFilePath = Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'staticValidation' 'module.tests.ps1' + WikiFilePath = Join-Path '$(System.DefaultWorkingDirectory)' 'docs' 'wiki' 'The CI environment - Static validation.md' + } + + Write-Verbose "Invoke task with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Set-StaticTestDocumentation @functionInput -Verbose + + - task: PowerShell@2 + displayName: "Push changes" + inputs: + targetType: inline + pwsh: true + script: | + git config --global user.email '$(pipelinePrincipalGitUserEmail)' + git config --global user.name '$(pipelinePrincipalGitUserName)' + + git add . + git status + git commit -m 'Push updated API Specs file' + git pull $(Build.Repository.Uri) HEAD:$(Build.SourceBranch) + git push $(Build.Repository.Uri) HEAD:$(Build.SourceBranch) diff --git a/.github/workflows/platform.updateStaticTestDocs.yml b/.github/workflows/platform.updateStaticTestDocs.yml new file mode 100644 index 0000000000..972fa49ff2 --- /dev/null +++ b/.github/workflows/platform.updateStaticTestDocs.yml @@ -0,0 +1,55 @@ +name: ".Platform: Update Static Test Documentation" + +on: + workflow_dispatch: + push: + branches: + - main + paths: + - '.github/workflows/platform.updateStaticTestDocs.yml' + - 'utilities/pipelines/staticValidation/module.tests.ps1' + - utilities/tools/platform/Set-StaticTestDocumentation.ps1 + +env: + pipelinePrincipalGitUserName: "CARMLPipelinePrincipal" + pipelinePrincipalGitUserEmail: "CARML@noreply.github.com" + +jobs: + job_update_static_test_docs: + name: "Update file" + if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' + runs-on: ubuntu-20.04 + steps: + - name: "Checkout" + uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: "${{ secrets.PLATFORM_REPO_UPDATE_PAT }}" # Sets general GIT credentials up + + - name: "Update file" + shell: pwsh + run: | + # Load used functions + . (Join-Path $env:GITHUB_WORKSPACE 'utilities' 'tools' 'platform' 'Set-StaticTestDocumentation.ps1') + + $functionInput = @{ + TestFilePath = Join-Path $env:GITHUB_WORKSPACE 'utilities' 'pipelines' 'staticValidation' 'module.tests.ps1' + WikiFilePath = Join-Path $env:GITHUB_WORKSPACE 'docs' 'wiki' 'The CI environment - Static validation.md' + } + + Write-Verbose "Invoke task with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Set-StaticTestDocumentation @functionInput -Verbose + + - name: "Push changes" + shell: pwsh + run: | + git config --global user.email '${{ env.pipelinePrincipalGitUserEmail }}' + git config --global user.name '${{ env.pipelinePrincipalGitUserName }}' + + git pull + git status + git add . + git commit -m 'Push updated API Specs file' + git push diff --git a/docs/wiki/The CI environment - Static validation.md b/docs/wiki/The CI environment - Static validation.md index 8b2cf2d76c..f59c0e06c9 100644 --- a/docs/wiki/The CI environment - Static validation.md +++ b/docs/wiki/The CI environment - Static validation.md @@ -16,25 +16,61 @@ All module Unit tests are performed with the help of [Pester](https://github.com The following activities are performed by the [`utilities/pipelines/staticValidation/module.tests.ps1`](https://github.com/Azure/ResourceModules/blob/main/utilities/pipelines/staticValidation/module.tests.ps1) script. -- **File & folder tests** validate that the module folder structure is set up in the intended way, e.g.: - - readme.md file exists - - template file (either `deploy.json` or `deploy.bicep`) exists - - compliance with file naming convention -- **Deployment template tests** check the template's structure and elements for errors as well as consistency matters, e.g.: - - template file (or the built bicep template) converts from JSON and has all expected properties - - variable names are camelCase - - the minimum set of outputs is returned (see [module design](./The%20library%20-%20Module%20design#outputs)) -- **Module (readme) documentation** contains all required sections, e.g.: - - is not empty - - contains all the mandatory sections - - describes all the parameters - - describes all outputs - - describes all cross-references -- **Module Test Files**, e.g.: - - at least one `deploy.test.bicep` exists - - files should (optionally) be valid JSON - - must contain all required parameters - - (if tokens are used) Tests that no token values (e.g., `11111111-1111-1111-1111-11111111111`) from the specified token list (i.e., `deploymentSpId`, `subscriptionId`, `managementGroupId`, `tenantId`) are used in the module test files. Instead, the token itself should be referenced. +## Outline + +- **File/folder tests** + - **General module folder tests** + 1. Module should have a GitHub workflow + 1. Module should have an Azure DevOps pipeline + 1. Module should contain a [`deploy.json`/`deploy.bicep`] file + 1. Module should contain a [`readme.md`] file + 1. Module should contain a [`.test`] folder + 1. Module should contain a [`version.json`] file + - **.test folder** + 1. Folder should contain one or more test files + 1. JSON test files in the `.test` folder should be valid json +- **Readme tests** + - **Readme content tests** + 1. `Readme.md` file should not be empty + 1. `Readme.md` file should contain these sections in order: Navigation, Resource Types, Parameters, Outputs, Cross-referenced modules, Deployment examples + 1. Resources section should contain all resources from the template file + 1. Resources section should not contain more resources than the template file + 1. Parameters section should contain a table for each existing parameter category in the following order: Required, Conditional, Optional, Generated + 1. Parameter tables should provide columns in the following order: Parameter Name, Type, Default Value, Allowed Values, Description. Each column should be present unless empty for all the rows. + 1. Parameters section should contain all parameters from the template file + 1. Outputs section should contain a table with these column names in order: Output Name, Type + 1. Output section should contain all outputs defined in the template file + 1. Dependencies section should contain all cross-references defined in the template file + 1. `Set-ModuleReadMe` script should not apply any updates +- **Test file tests** + - **General test file** + 1. Bicep test deployment name should contain [`-test-`] + 1. Bicep test deployment should have parameter [`serviceShort`] + 1. JSON test deployment name should contain [`-test-`] + 1. JSON test deployment should have parameter [`serviceShort`] + - **Token usage** + 1. [Tokens] Test file should not contain the plain value for token guid +- **Deployment template tests** + - **General template** + 1. The template file should not be empty + 1. Template schema version should be the latest + 1. Template schema should use HTTPS reference + 1. All apiVersion properties should be set to a static, hard-coded value + 1. The template file should contain required elements: `schema`, `contentVersion`, `resources` + 1. If delete lock is implemented, the template should have a lock parameter with an empty default value + 1. Parameter names should be camel-cased (no dashes or underscores and must start with lower-case letter) + 1. Variable names should be camel-cased (no dashes or underscores and must start with lower-case letter) + 1. Output names should be camel-cased (no dashes or underscores and must start with lower-case letter) + 1. CUA ID deployment should be present in the template + 1. Location output should be returned for resources that use it + 1. Resource Group output should exist for resources that are deployed into a resource group scope + 1. Resource name output should exist + 1. Resource ID output should exist + 1. All parameters in parameters files exist in template file (`deploy.json`) + 1. All required parameters in template file (`deploy.json`) should exist in parameters files + 1. All non-required parameters in template file should not have description that start with "Required." +- **API version tests** + 1. In used resource type should use one of the recent API version(s). Currently using ## Output example @@ -85,4 +121,3 @@ Test-ModuleLocally @TestModuleLocallyInput -Verbose ``` > You can use the `Get-Help` cmdlet to show more options on how you can use this script. - diff --git a/utilities/pipelines/staticValidation/module.tests.ps1 b/utilities/pipelines/staticValidation/module.tests.ps1 index e512dabf78..28f9f8e005 100644 --- a/utilities/pipelines/staticValidation/module.tests.ps1 +++ b/utilities/pipelines/staticValidation/module.tests.ps1 @@ -37,7 +37,7 @@ $script:templateNotFoundException = 'No template file found in folder [{0}]' # - # Import any helper function used in this test script Import-Module (Join-Path $PSScriptRoot 'helper' 'helper.psm1') -Force -Describe 'File/folder tests' -Tag Modules { +Describe 'File/folder tests' -Tag 'Modules' { Context 'General module folder tests' { @@ -80,7 +80,7 @@ Describe 'File/folder tests' -Tag Modules { } } - It '[] Module should contain a [deploy.json/deploy.bicep] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [`deploy.json`/`deploy.bicep`] file' -TestCases $moduleFolderTestCases { param( [string] $moduleFolderPath ) @@ -89,19 +89,19 @@ Describe 'File/folder tests' -Tag Modules { ($hasARM -or $hasBicep) | Should -Be $true } - It '[] Module should contain a [readme.md] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [`readme.md`] file' -TestCases $moduleFolderTestCases { param( [string] $moduleFolderPath ) (Test-Path (Join-Path -Path $moduleFolderPath 'readme.md')) | Should -Be $true } - It '[] Module should contain a [.test] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { + It '[] Module should contain a [`.test`] folder' -TestCases ($moduleFolderTestCases | Where-Object { $_.isTopLevelModule }) { param( [string] $moduleFolderPath ) Test-Path (Join-Path -Path $moduleFolderPath '.test') | Should -Be $true } - It '[] Module should contain a [version.json] file' -TestCases $moduleFolderTestCases { + It '[] Module should contain a [`version.json`] file' -TestCases $moduleFolderTestCases { param( [string] $moduleFolderPath ) (Test-Path (Join-Path -Path $moduleFolderPath 'version.json')) | Should -Be $true @@ -120,7 +120,7 @@ Describe 'File/folder tests' -Tag Modules { } } - It '[] folder should contain one or more test files' -TestCases $folderTestCases { + It '[] Folder should contain one or more test files' -TestCases $folderTestCases { param( [string] $moduleFolderName, @@ -144,7 +144,7 @@ Describe 'File/folder tests' -Tag Modules { } } - It '[] JSON test files in the .test folder should be valid json' -TestCases $testFolderFilesTestCases { + It '[] JSON test files in the `.test` folder should be valid json' -TestCases $testFolderFilesTestCases { param( [string] $moduleFolderName, @@ -158,7 +158,7 @@ Describe 'File/folder tests' -Tag Modules { } } } -Describe 'Readme tests' -Tag Readme { +Describe 'Readme tests' -Tag 'Readme' { Context 'Readme content tests' { @@ -209,7 +209,7 @@ Describe 'Readme tests' -Tag Readme { } } - It '[] Readme.md file should not be empty' -TestCases $readmeFolderTestCases { + It '[] `Readme.md` file should not be empty' -TestCases $readmeFolderTestCases { param( [string] $moduleFolderName, @@ -218,7 +218,7 @@ Describe 'Readme tests' -Tag Readme { $readMeContent | Should -Not -Be $null } - It '[] Readme.md file should contain these sections in order: Navigation, Resource Types, Parameters, Outputs, Cross-referenced modules, Deployment examples' -TestCases $readmeFolderTestCases { + It '[] `Readme.md` file should contain these sections in order: Navigation, Resource Types, Parameters, Outputs, Cross-referenced modules, Deployment examples' -TestCases $readmeFolderTestCases { param( [string] $moduleFolderName, @@ -316,7 +316,7 @@ Describe 'Readme tests' -Tag Readme { $actualParamCategories | Should -Be $expectedParamCategoriesInOrder } - It '[] parameter tables should provide columns in the following order: Parameter Name, Type, Default Value, Allowed Values, Description. Each column should be present unless empty for all the rows.' -TestCases $readmeFolderTestCases { + It '[] Parameter tables should provide columns in the following order: Parameter Name, Type, Default Value, Allowed Values, Description. Each column should be present unless empty for all the rows.' -TestCases $readmeFolderTestCases { param( [string] $moduleFolderName, @@ -505,7 +505,7 @@ Describe 'Readme tests' -Tag Readme { } } - It '[] Set-ModuleReadMe script should not apply any updates' -TestCases $readmeFolderTestCases { + It '[] `Set-ModuleReadMe` script should not apply any updates' -TestCases $readmeFolderTestCases { param( [string] $moduleFolderName, @@ -540,9 +540,9 @@ Describe 'Readme tests' -Tag Readme { } } -Describe 'Parameter file tests' -Tag 'Parameter' { +Describe 'Test file tests' -Tag 'TestTemplate' { - Context 'Deployment test file tests' { + Context 'General test file' { $deploymentTestFileTestCases = @() @@ -570,7 +570,7 @@ Describe 'Parameter file tests' -Tag 'Parameter' { } } - It "[] Bicep test deployment files should invoke test like [module testDeployment '../.*deploy.bicep' = {]" -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { + It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*deploy.bicep' = {`]" -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { param( [object[]] $testFileContent @@ -581,7 +581,7 @@ Describe 'Parameter file tests' -Tag 'Parameter' { $testIndex -ne -1 | Should -Be $true -Because 'the module test invocation should be in the expected format to allow identification.' } - It '[] Bicep test deployment name should contain [-test-]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { + It '[] Bicep test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { param( [object[]] $testFileContent @@ -592,7 +592,7 @@ Describe 'Parameter file tests' -Tag 'Parameter' { $expectedNameFormat | Should -Be $true -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' } - It '[] Bicep test deployment should have parameter [serviceShort]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { + It '[] Bicep test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.bicep' }) { param( [object[]] $testFileContent @@ -603,7 +603,7 @@ Describe 'Parameter file tests' -Tag 'Parameter' { $hasExpectedParam | Should -Be $true } - It '[] JSON test deployment name should contain [-test-]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { + It '[] JSON test deployment name should contain [`-test-`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { param( [object[]] $testFileContent @@ -618,7 +618,7 @@ Describe 'Parameter file tests' -Tag 'Parameter' { $testResource | Should -Not -BeNullOrEmpty -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' } - It '[] JSON test deployment should have parameter [serviceShort]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { + It '[] JSON test deployment should have parameter [`serviceShort`]' -TestCases ($deploymentTestFileTestCases | Where-Object { (Split-Path $_.testFilePath -Extension) -eq '.json' }) { param( [object[]] $testFileContent @@ -629,7 +629,7 @@ Describe 'Parameter file tests' -Tag 'Parameter' { } } - Context 'Parameter file token tests' { + Context 'Token usage' { # Parameter file test cases $parameterFileTokenTestCases = @() @@ -652,7 +652,7 @@ Describe 'Parameter file tests' -Tag 'Parameter' { } } - It '[] [Tokens] Parameter file [] should not contain the plain value for token [] guid' -TestCases $parameterFileTokenTestCases { + It '[] [Tokens] Test file [] should not contain the plain value for token [] guid' -TestCases $parameterFileTokenTestCases { param ( [string] $testFilePath, [string] $parameterFileName, @@ -672,9 +672,9 @@ Describe 'Parameter file tests' -Tag 'Parameter' { } } -Describe 'Deployment template tests' -Tag Template { +Describe 'Deployment template tests' -Tag 'Template' { - Context 'Deployment template tests' { + Context 'General template' { $deploymentFolderTestCases = [System.Collections.ArrayList] @() foreach ($moduleFolderPath in $moduleFolderPaths) { @@ -755,7 +755,7 @@ Describe 'Deployment template tests' -Tag Template { } } - It '[] the template file should not be empty' -TestCases $deploymentFolderTestCases { + It '[] The template file should not be empty' -TestCases $deploymentFolderTestCases { param( [string] $moduleFolderName, @@ -824,7 +824,7 @@ Describe 'Deployment template tests' -Tag Template { $ApiVersionArray | Should -Not -Contain $false } - It '[] the template file should contain required elements: schema, contentVersion, resources' -TestCases $deploymentFolderTestCases { + It '[] The template file should contain required elements: `schema`, `contentVersion`, `resources`' -TestCases $deploymentFolderTestCases { param( [string] $moduleFolderName, @@ -835,7 +835,7 @@ Describe 'Deployment template tests' -Tag Template { $templateContent.Keys | Should -Contain 'resources' } - It '[] If delete lock is implemented, the template should have a lock parameter with the default value of ['''']' -TestCases $deploymentFolderTestCases { + It '[] If delete lock is implemented, the template should have a lock parameter with an empty default value' -TestCases $deploymentFolderTestCases { param( [string] $moduleFolderName, @@ -933,7 +933,7 @@ Describe 'Deployment template tests' -Tag Template { $enableDefaultTelemetryFlag | Should -Not -Contain $false } - It "[] The Location should be defined as a parameter, with the default value of 'resourceGroup().Location' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { + It "[] The Location should be defined as a parameter, with the default value of '`resourceGroup().Location`' or global for ResourceGroup deployment scope" -TestCases $deploymentFolderTestCases { param( [string] $moduleFolderName, @@ -1034,7 +1034,7 @@ Describe 'Deployment template tests' -Tag Template { $outputs | Should -Contain 'resourceId' } - It "[] parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { + It "[] Each parameters' description should start with a one word category starting with a capital letter, followed by a dot, a space and the actual description text ending with a dot." -TestCases $deploymentFolderTestCases { param( [string] $moduleFolderName, @@ -1108,7 +1108,7 @@ Describe 'Deployment template tests' -Tag Template { } # PARAMETER Tests - It '[] All parameters in parameters files exist in template file (deploy.json)' -TestCases $deploymentFolderTestCases { + It '[] All parameters in parameters files exist in template file (`deploy.json`)' -TestCases $deploymentFolderTestCases { param ( [hashtable[]] $testFileTestCases ) @@ -1122,7 +1122,7 @@ Describe 'Deployment template tests' -Tag Template { } } - It '[] All required parameters in template file (deploy.json) should exist in parameters files' -TestCases $deploymentFolderTestCases { + It '[] All required parameters in template file (`deploy.json`) should exist in parameters files' -TestCases $deploymentFolderTestCases { param ( [hashtable[]] $testFileTestCases ) @@ -1152,53 +1152,9 @@ Describe 'Deployment template tests' -Tag Template { } } } - - Context 'Parameter file token tests' { - - # Parameter file test cases - $parameterFileTokenTestCases = @() - - foreach ($moduleFolderPath in $moduleFolderPaths) { - if (Test-Path (Join-Path $moduleFolderPath '.test')) { - $TestFilePaths = (Get-ChildItem (Join-Path -Path $moduleFolderPath -ChildPath '.test') -Recurse -File -Force).FullName - foreach ($TestFilePath in $TestFilePaths) { - foreach ($token in $tokenConfiguration.Tokens.Keys) { - $parameterFileTokenTestCases += @{ - parameterFilePath = $TestFilePath - parameterFileName = Split-Path $TestFilePath -Leaf - tokenPrefix = $tokenConfiguration.TokenPrefix - tokenSuffix = $tokenConfiguration.TokenSuffix - tokenName = $token - tokenValue = $tokenConfiguration.Tokens[$token] - moduleFolderName = $moduleFolderPath.Replace('\', '/').Split('/modules/')[1] - } - } - } - } - } - - It '[] [Tokens] Parameter file [] should not contain the plain value for token []' -TestCases $parameterFileTokenTestCases { - param ( - [string] $parameterFilePath, - [string] $parameterFileName, - [string] $tokenPrefix, - [string] $tokenSuffix, - [string] $tokenName, - [string] $tokenValue, - [string] $moduleFolderName - ) - $ParameterFileTokenName = -join ($tokenPrefix, $tokenName, $tokenSuffix) - $ParameterFileContent = Get-Content -Path $parameterFilePath - - $incorrectReferencesFound = $ParameterFileContent | Select-String -Pattern $tokenValue -AllMatches - if ($incorrectReferencesFound.Matches) { - $incorrectReferencesFound.Matches.Count | Should -Be 0 -Because ('Parameter file should not contain the [{0}] value, instead should reference the token value [{1}]. Please check the {2} lines: [{3}]' -f $tokenName, $ParameterFileTokenName, $incorrectReferencesFound.Matches.Count, ($incorrectReferencesFound.Line.Trim() -join ",`n")) - } - } - } } -Describe "API version tests [All apiVersions in the template should be 'recent']" -Tag ApiCheck { +Describe 'API version tests' -Tag ApiCheck { $testCases = @() $apiSpecsFilePath = Join-Path $repoRootPath 'utilities' 'src' 'apiSpecsList.json' diff --git a/utilities/tools/platform/Set-StaticTestDocumentation.ps1 b/utilities/tools/platform/Set-StaticTestDocumentation.ps1 new file mode 100644 index 0000000000..f6b01e7741 --- /dev/null +++ b/utilities/tools/platform/Set-StaticTestDocumentation.ps1 @@ -0,0 +1,97 @@ +#region helper +<# +.SYNOPSIS +Get an outline of all Pester test cases implemented in the given test file + +.DESCRIPTION +Get an outline of all Pester test cases implemented in the given test file +The output is returned as Markdown + +.PARAMETER TestFilePath +Mandatory. The path to the test file to get the content from. + +.EXAMPLE +Get-TestsAsMarkdown -TestFilePath 'C:/ResourceModules/utilities/pipelines/staticValidation/module.tests.ps1' + +Get an outline of all Pester tests implemented in the test file 'module.tests.ps1' +#> +function Get-TestsAsMarkdown { + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] $TestFilePath + ) + + $content = Get-Content $TestFilePath + + $relevantContent = [System.Collections.ArrayList]@() + foreach ($line in $content) { + if ($line -match "^\s*Describe '(.*?)'.*$") { + $formatted = $Matches[1] + $formatted = (($formatted -split '\s*\[<.+?>\]\s*') -join ' ').Trim() + $relevantContent += "- **$formatted**" + } elseif ( $line -match "^\s*Context '(.*?)'.*$" ) { + $formatted = $Matches[1] + $formatted = (($formatted -split '\s*\[<.+?>\]\s*') -join ' ').Trim() + $relevantContent += " - **$formatted**" + } elseif ( $line -match "^\s*It '(.*?)'.*$" ) { + $formatted = $Matches[1] + $formatted = (($formatted -split '\s*\[<.+?>\]\s*') -join ' ').Trim() + $relevantContent += " 1. $formatted" + } + } + + return $relevantContent +} +#endregion + +<# +.SYNOPSIS +Update the current documentation in the given wiki file path with the latest test detail of the given test file path. + +.DESCRIPTION +Update the current documentation in the given wiki file path with the latest test detail of the given test file path. + +.PARAMETER TestFilePath +Mandatory. The path to the test file to get the content from. + +.PARAMETER WikiFilePath +Mandatory. The path to the Wiki file to update the data in. It should contain a header '## Outline' + +.EXAMPLE +Set-StaticTestDocumentation -TestFilePath 'C:/ResourceModules/utilities/pipelines/staticValidation/module.tests.ps1' -WikiFilePath 'C:/ResourceModules/docs/wiki/The CI environment - Static validation.md' + +Update the section '## Outline' of Wiki file 'The CI environment - Static validation.md' with the content of the Pester test file 'module.tests.ps1' +#> +function Set-StaticTestDocumentation { + + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [Parameter(Mandatory = $true)] + [string] $TestFilePath, + + [Parameter(Mandatory = $true)] + [string] $WikiFilePath + ) + + # Load external functions + $toolsRoot = Split-Path $PSScriptRoot -Parent + . (Join-Path $toolsRoot 'helper' 'Merge-FileWithNewContent.ps1') + + # Logic + $contentArray = Get-Content -Path $WikiFilePath + + $testOutline = Get-TestsAsMarkdown -TestFilePath $TestFilePath + + $newContent = Merge-FileWithNewContent -oldContent $contentArray -newContent $testOutline -sectionStartIdentifier '## Outline' + + Write-Verbose 'New content:' + Write-Verbose '============' + Write-Verbose ($newContent | Out-String) + + if ($PSCmdlet.ShouldProcess("File in path [$WikiFilePath]", 'Overwrite')) { + Set-Content -Path $WikiFilePath -Value $newContent -Force + Write-Verbose "File [$WikiFilePath] updated" -Verbose + } +}