Skip to content

Commit

Permalink
WIP - prepare to test docs update workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
fflaten committed Jun 16, 2024
1 parent 5426025 commit 9c1ee33
Show file tree
Hide file tree
Showing 3 changed files with 304 additions and 11 deletions.
75 changes: 75 additions & 0 deletions .github/workflows/generate-pester-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Update Pester Docs

on:
workflow_dispatch:
inputs:
docs_version:
description: 'Docs version to update'
required: true
default: 'v5'
type: choice
options:
- Current
- v5
- v4
pester_version:
description: 'Pester version to use for docs generation. Format: 5.6.0 or 6.0.0-alpha1'
required: true
type: string

jobs:
generate_docs:
name: Docs PR
runs-on: ubuntu-latest
env:
PESTER: ${{ github.event.inputs.pester_version }}
DOCS: ${{ github.event.inputs.docs_version }}
permissions:
contents: write
pull-requests: write
steps:
- name: Validate Pester version input
run: |
echo "Validating that the provided pester_version input is a valid version-format (x.y.z or x.y.z-suffix)"
echo "${{ env.PESTER }}" | grep -P '^\d+.\d+.\d+(?:-\w+)?$'
- name: Checkout code
uses: actions/checkout@v4

# This step will also install and import modules incl. selected Pester-version
- name: Update Command Reference
shell: pwsh
run: |
./generate-command-reference.ps1 -PesterVersion '${{ env }}' -DocsVersion '${{ env.DOCS }}'
- name: Update PesterConfiguration docs
if: ${{ env.DOCS != 'v4' }}
shell: pwsh
run: |
./generate-pesterconfiguration-docs.ps1 -PesterVersion '${{ env.PESTER }}' -Style Table -DocsVersion '${{ env.DOCS }}'
- name: Create Pull Request
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5
env:
PR_BRANCH: "docs-update/${{ env.DOCS }}-v${{ env.PESTER }}"
TITLE_PREFIX: "${{ env.DOCS != 'Current' && format('({0}) ', env.DOCS) || '' }}"
with:
branch: ${{ env.PR_BRANCH }}
branch-suffix: short-commit-hash
# Set user triggering the workflow as author (default in action)
author: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>
# Github Action as commit (explicit default)
committer: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
commit-message: "Update generated docs to ${{ env.PESTER }}"
add-paths: |
docs
versioned_docs
title: ${{ env.TITLE_PREFIX }}Update generated docs to Pester v${{ env.PESTER }}
body: |
Updates Command Reference and/or PesterConfiguration documentation.
Docs version being updated: ${{ env.DOCS }}
Pester version used: v${{ env.PESTER }}
*PR created using '${{ github.workflow }}' workflow*
draft: false
78 changes: 67 additions & 11 deletions docs/usage/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,29 @@ title: Configuration
description: Documentation about how to configure the behavior, options and features in Pester
---

### Advanced interface
## Advanced interface

Advanced interface uses `PesterConfiguration` object which contains all options that you can provide to Pester and contains descriptions for all the configuration sections and as well as default values. Here is what you see when you look at the default Debug section of the object:

```powershell
[PesterConfiguration]::Default.Debug | Format-List
(New-PesterConfiguration).Debug | Format-List
ShowFullErrors : Show full errors including Pester internal stack. (False, default: False)
ShowFullErrors : Show full errors including Pester internal stack. This property is deprecated, and if set to true it will override Output.StackTraceVerbosity to 'Full'. (False, default: False)
WriteDebugMessages : Write Debug messages to screen. (False, default: False)
WriteDebugMessagesFrom : Write Debug messages from a given source, WriteDebugMessages must be set to true for this to work. You can use like wildcards to get messages from multiple sources, as well as * to get everything. (*, default: *)
WriteDebugMessagesFrom : Write Debug messages from a given source, WriteDebugMessages must be set to true for this to work. You can use like wildcards to get messages from multiple sources, as well as * to get
everything. (System.String[], default: System.String[])
ShowNavigationMarkers : Write paths after every block and test, for easy navigation in VSCode. (False, default: False)
ReturnRawResultObject : Returns unfiltered result object, this is for development only. Do not rely on this object for additional properties, non-public properties will be renamed without previous notice. (False,
default: False)
```

:::tip New in Pester 5.2.0!
[New-PesterConfiguration](../commands/New-PesterConfiguration) is now available and the recommended way to create the PesterConfiguration-object. It has the added benefit of auto-loading the Pester-module if needed and up-to-date help of available options in the configuration object.
:::

The configuration object can be constructed either via the Default static property or by casting a hashtable to it. You can also cast a hashtable to any of its sections. Here are three different ways to the same goal:

```powershell
# import module before creating the object
Import-Module Pester
# get default from static property
$configuration = [PesterConfiguration]::Default
$configuration = New-PesterConfiguration
# adding properties & discover via intellisense
$configuration.Run.Path = 'C:\projects\tst'
$configuration.Filter.Tag = 'Acceptance'
Expand Down Expand Up @@ -69,14 +68,14 @@ $configuration.CodeCoverage.Enabled = $true

This configuration object contains all the options that are currently supported and the Simple interface is internally translates to this object internally. It is the source of truth for the defaults and configuration. The Intermediate api will be figured out later, as well as all the other details.

### PesterPreference
## PesterPreference

There is one more way to provide the configuration object which is `$PesterPreference`. On `Invoke-Pester` (in case of interactive execution `Invoke-Pester` is called inside of the first `Describe`) the preference is collected and merged with the configuration object if provided. This allows you to configure everything that you would via Invoke-Pester also when you are running interactively (via `F5`). You can also use this to define the defaults for your session by putting $PesterPreference into your PowerShell profile.

Here is a simple example of enabling Mock logging output while running interactively :

```powershell
$PesterPreference = [PesterConfiguration]::Default
$PesterPreference = New-PesterConfiguration
$PesterPreference.Debug.WriteDebugMessages = $true
$PesterPreference.Debug.WriteDebugMessagesFrom = "Mock"
Expand Down Expand Up @@ -123,3 +122,60 @@ Mock: Removing function PesterMock_b0bde5ee-1b4f-4b8f-b1dd-aef38b3bc13d and alia
Tests completed in 1.12s
Tests Passed: 1, Failed: 0, Skipped: 0, Total: 1, NotRun: 0
```

## PesterConfiguration Options

<!--GENERATED_PESTER_CONFIGURATION_DOCS_START-->

*This configuration documentation is generated from Pester 6.1.0-alpha1.*

### Run

### Should

Should configuration.

| Option | Description | Type | Default |
|--------|-------------|-----:|--------:|
| ErrorAction | Controls if Should throws on error. Use 'Stop' to throw on error, or 'Continue' to fail at the end of the test. | `string` | `'Stop'` |

### Debug

Debug configuration for Pester. Use at your own risk!

| Option | Description | Type | Default |
|--------|-------------|-----:|--------:|
| ShowFullErrors | Show full errors including Pester internal stack. This property is deprecated, and if set to true it will override Output.StackTraceVerbosity to 'Full'. | `bool` | `$false` |
| WriteDebugMessages | Write Debug messages to screen. | `bool` | `$false` |
| WriteDebugMessagesFrom | Write Debug messages from a given source, WriteDebugMessages must be set to true for this to work. You can use like wildcards to get messages from multiple sources, as well as * to get everything. | `string[]` | `@('Discovery', 'Skip', 'Mock', 'CodeCoverage')` |
| ShowNavigationMarkers | Write paths after every block and test, for easy navigation in VSCode. | `bool` | `$false` |
| ReturnRawResultObject | Returns unfiltered result object, this is for development only. Do not rely on this object for additional properties, non-public properties will be renamed without previous notice. | `bool` | `$false` |

### Output

Output configuration

| Option | Description | Type | Default |
|--------|-------------|-----:|--------:|
| Verbosity | The verbosity of output, options are None, Normal, Detailed and Diagnostic. | `string` | `'Normal'` |
| StackTraceVerbosity | The verbosity of stacktrace output, options are None, FirstLine, Filtered and Full. | `string` | `'Filtered'` |
| CIFormat | The CI format of error output in build logs, options are None, Auto, AzureDevops and GithubActions. | `string` | `'Auto'` |
| CILogLevel | The CI log level in build logs, options are Error and Warning. | `string` | `'Error'` |
| RenderMode | The mode used to render console output, options are Auto, Ansi, ConsoleColor and Plaintext. | `string` | `'Auto'` |

### TestDrive

TestDrive configuration.

| Option | Description | Type | Default |
|--------|-------------|-----:|--------:|
| Enabled | Enable TestDrive. | `bool` | `$true` |

### TestRegistry

TestRegistry configuration.

| Option | Description | Type | Default |
|--------|-------------|-----:|--------:|
| Enabled | Enable TestRegistry. | `bool` | `$true` |
<!--GENERATED_PESTER_CONFIGURATION_DOCS_END-->
162 changes: 162 additions & 0 deletions generate-pesterconfiguration-docs.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<#
.SYNOPSIS
Updates the Configuration page with latest PesterConfiguration Sections and Options
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $False)]
[string] $PesterVersion,
[ValidateSet('Current','v5')]
[string] $DocsVersion = 'Current',
[ValidateSet('List','Table')]
[string] $Style = 'List'
)

#region helpers
function Format-NicelyMini ($value) {
if ($value -is [bool]) {
if ($value) {
'$true'
} else {
'$false'
}
}

if ($value -is [int] -or $value -is [decimal]) {
return $value
}

if ($value -is [string]) {
if ([String]::IsNullOrEmpty($value)) {
return '$null'
} else {
return "'$value'"
}
}

# does not work with [object[]] when building for some reason
if ($value -is [System.Collections.IEnumerable]) {
if (0 -eq $value.Count) {
return '@()'
}
$v = foreach ($i in $value) {
Format-NicelyMini $i
}
return "@($($v -join ', '))"
}
}

function generateSectionsMarkdownAsTable {
$configObject = New-PesterConfiguration
foreach ($configSection in $configObject.PSObject.Properties) {
$sectionName = $configSection.Name
$sectionDescription = $configSection.Value -as [string]
$section = $configSection.Value

$options = foreach ($configOption in $section.PSObject.Properties) {
$optionName = $configOption.Name
$option = $configOption.Value
$default = Format-NicelyMini $option.Default
$type = $option.Default.GetType() -as [string] -replace '^Pester\.'
"| $optionName | $($option.Description) | ``$type`` | ``$default`` |"
}

@"
### ${sectionName}
$sectionDescription
| Option | Description | Type | Default |
|--------|-------------|-----:|--------:|
$($options -join $eol)
"@
}
}

function generateSectionsMarkdownAsList {
$configObject = New-PesterConfiguration
foreach ($configSection in $configObject.PSObject.Properties) {
$sectionName = $configSection.Name
$sectionDescription = $configSection.Value -as [string]
$section = $configSection.Value

$options = foreach ($configOption in $section.PSObject.Properties) {
$optionName = $configOption.Name
$option = $configOption.Value
$default = Format-NicelyMini $option.Default
$type = $option.Default.GetType() -as [string]
@"
#### $sectionName.$optionName
**Type:** ``$type``<br/>
**Default:** ``$default``
$($option.Description)
"@
}

# Output markdown string per section
@"
### ${sectionName}
$sectionDescription
$($options -join $eol)
"@
}
}
#endregion

$loadedModule = if ($PSBoundParameters.ContainsKey('PesterVersion')) {
Import-Module Pester -RequiredVersion ($PesterVersion -replace '-\w+$') -PassThru
} else {
Import-Module Pester -PassThru
}

$loadedVersion = if ($loadedModule.PrivateData -and $loadedModule.PrivateData.PSData -and $loadedModule.PrivateData.PSData.PreRelease) {
"$($loadedModule.Version)-$($loadedModule.PrivateData.PSData.PreRelease)"
} else {
$loadedModule.Version
}

if ($PSBoundParameters.ContainsKey('PesterVersion') -and $loadedVersion -ne $PesterVersion) {
throw "Pester $PesterVersion was requested, but version '$loadedVersion' was loaded. Aborting."
}

# generate help for config object and insert it
$startComment = 'GENERATED_PESTER_CONFIGURATION_DOCS_START'
$endComment = 'GENERATED_PESTER_CONFIGURATION_DOCS_END'
$eol = "`n"
$encoding = 'UTF8'

$ConfigurationPagePath = switch ($DocsVersion) {
'Current' { "$PSScriptRoot/docs/usage/configuration.mdx" }
'v5' { "$PSScriptRoot/versioned_docs/version-v5/usage/configuration.mdx" }
}

$generatedConfigDocs = switch ($Style) {
'List' { generateSectionsMarkdownAsList }
'Table' { generateSectionsMarkdownAsTable }
}

$pageContent = Get-Content $ConfigurationPagePath -Encoding $encoding
$sbf = [System.Text.StringBuilder]''
$sectionFound = $false

foreach ($line in $pageContent) {
if (-not $sectionFound -and $line -match $startComment) {
$null = $sbf.AppendLine("$line$eol")
$null = $sbf.AppendLine("*This configuration documentation is generated from Pester $loadedVersion.*$eol")
$sectionFound = $true
$null = $sbf.AppendJoin($eol, $generatedConfigDocs)
} elseif ($sectionFound -and ($line -match $endComment)) {
$sectionFound = $false
}
if (-not $sectionFound) {
$null = $sbf.AppendLine($line)
}
}

Set-Content -Encoding $encoding -Value $sbf.ToString().TrimEnd() -Path $ConfigurationPagePath

0 comments on commit 9c1ee33

Please sign in to comment.