diff --git a/Assets/Splatter-16x9.png b/Assets/Splatter-16x9.png
new file mode 100644
index 0000000..7ad03a6
Binary files /dev/null and b/Assets/Splatter-16x9.png differ
diff --git a/Assets/Splatter.png b/Assets/Splatter.png
new file mode 100644
index 0000000..b0b8875
Binary files /dev/null and b/Assets/Splatter.png differ
diff --git a/Out-Splat.ps1 b/Out-Splat.ps1
index 3255083..e82540e 100644
--- a/Out-Splat.ps1
+++ b/Out-Splat.ps1
@@ -9,6 +9,10 @@
Initialize-Splatter
.Example
Out-Splat -CommandName Get-Command
+ .Example
+ Out-Splat -FunctionName Get-MyProcess -Example Get-MyProcess -CommandName Get-Process -DefaultParameter @{
+ Id = '$pid'
+ } -ExcludeParameter *
#>
[CmdletBinding(DefaultParameterSetName='JustTheSplatter')]
[OutputType([ScriptBlock])]
@@ -84,11 +88,39 @@
[string]
$Description,
+ # One or more examples.
+ # This is used to make comment-based help in a generated function.
+ [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='FunctionalSplatter')]
+ [Alias('Examples')]
+ [string[]]
+ $Example,
+
+ # One or more links.
+ # This is used to make comment-based help in a generated function.
+ [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='FunctionalSplatter')]
+ [Alias('Links')]
+ [string[]]
+ $Link,
+
+ # Some notes.
+ # This is used to make comment-based help in a generated function.
+ [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='FunctionalSplatter')]
+ [Alias('Notes')]
+ [string]
+ $Note,
+
# The CmdletBinding attribute for a new function
[Parameter(ValueFromPipelineByPropertyName,ParameterSetName='FunctionalSplatter')]
[string]
$CmdletBinding,
+ # The [OutputType()] of a function.
+ # If the type resolves to a [type], it's value will be provided as a [type].
+ # Otherwise, it will be provided as a [string]
+ [Parameter(ValueFromPipelineByPropertyName,ParameterSetName='FunctionalSplatter')]
+ [string[]]
+ $OutputType,
+
# A set of additional parameter declarations.
# The keys are the names of the parameters, and the values can be a type and a string containing parameter binding and inline help.
[Parameter(ValueFromPipelineByPropertyName,ParameterSetName='FunctionalSplatter')]
@@ -441,13 +473,48 @@ $parameterHelp
$paramBlock = $paramBlockParts -join (',' + ([Environment]::NewLine * 2))
-if (-not $Synopsis) {
- $Synopsis = "Wraps $CommandName"
-}
+ if (-not $Synopsis) {
+ $Synopsis = "Wraps $CommandName"
+ }
-if (-not $Description) {
- $Description = "Calls $CommandName, using splatting"
-}
+ if (-not $Description) {
+ $Description = "Calls $CommandName, using splatting"
+ }
+
+ $exampleText =
+ if ($Example) {
+ @(foreach ($ex in $Example) {
+ " .Example"
+ foreach ($ln in $ex -split '(?>\r\n|\n)') {
+ " $ln"
+ }
+ }) -join [Environment]::NewLine
+ } else { ''}
+
+ $noteText =
+ if ($Note) {
+ @(
+ " .Notes"
+ foreach ($ln in $Note -split '(?>\r\n|\n)') {
+ " $ln"
+ }
+ ) -join [Environment]::NewLine
+ } else { ''}
+
+
+
+ $linkText =
+ if ($Link) {
+ @(foreach ($lnk in $Link) {
+ " .Link"
+ " $lnk"
+ }) -join [Environment]::NewLine
+ } else { @"
+ .Link
+ $CommandName
+"@
+ }
+
[ScriptBlock]::Create("function $FunctionName
{
@@ -455,9 +522,13 @@ if (-not $Description) {
.Synopsis
$Synopsis
.Description
- $Description
- .Link
- $CommandName
+ $Description$(
+ if ($exampleText) { [Environment]::NewLine + $exampleText}
+ )$(
+ if ($linkText) { [Environment]::NewLine + $linkText}
+ )$(
+ if ($NoteText) { [Environment]::NewLine + $noteText}
+ )
#>$(if ($CmdletBinding) {
if ($CmdletBinding -like "*CmdletBinding*") {
[Environment]::NewLine + (' '*4) + $CmdletBinding
@@ -466,9 +537,18 @@ if (-not $Description) {
}
} elseif ($originalCmdletBinding) {
[Environment]::NewLine + (' '*4) + $originalCmdletBinding
- })
+ })$(
+ if ($OutputType) {
+ [Environment]::NewLine + (' '*4) + '[OutputType(' + @(foreach ($ot in $outputtype) {
+ if ($ot -as [type]) {"[$ot]"} else { "'$ot'"}
+ }) -join ',' + ')]'
+ } else {
+ [Environment]::NewLine + (' '*4) + '[OutputType([PSObject])]'
+ }
+ )
param(
-$paramBlock)
+$paramBlock
+ )
process {
$(@(foreach ($line in $coreSplat -split ([Environment]::Newline)) {
diff --git a/README.md b/README.md
index aa24a42..4522aa0 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,11 @@
-## Splatter is a simple Splatting toolkit
+
+

+
Simple Scripts to Supercharge Splatting
+
+
+[](https://github.com/StartAutomating/Splatter/actions/workflows/TestBuildAndPublish.yml)
+
+## Splatter is a simple Splatting toolkit
Splatting is a technique of passing parameters in PowerShell.
@@ -179,14 +186,14 @@ If you don't need all of the commands, you can use -Verb
### Generating Splatting Code
-You can use Out-Splatter to generate code that splats.
+You can use Out-Splat to generate code that splats.
- Out-Splatter -CommandName Get-Command -DefaultParameter @{Module='Splatter';CommandType='Alias'} | Invoke-Expression
+ Out-Splat -CommandName Get-Command -DefaultParameter @{Module='Splatter';CommandType='Alias'} | Invoke-Expression
You can use also use Out-Splatter to generate whole functions, including help.
$scriptBlock =
- Out-Splatter -FunctionName Get-SplatterAlias -CommandName Get-Command -DefaultParameter @{
+ Out-Splat -FunctionName Get-SplatterAlias -CommandName Get-Command -DefaultParameter @{
Module='Splatter';CommandType='Alias'
} -ExcludeParameter * -Synopsis 'Gets Splatter Aliases' -Description 'Gets aliases from the module Splatter'
. ([ScriptBlock]::Create($scriptBlock))
diff --git a/Splatter.psd1 b/Splatter.psd1
index d4b9c94..a5cca26 100644
--- a/Splatter.psd1
+++ b/Splatter.psd1
@@ -3,7 +3,7 @@
Copyright = '2019-2021 Start-Automating'
RootModule = 'Splatter.psm1'
Description = 'Simple Scripts to Supercharge Splatting'
- ModuleVersion = '0.5.2'
+ ModuleVersion = '0.5.3'
AliasesToExport = '*'
VariablesToExport = '*'
GUID = '033f35ed-f8a7-4911-bb62-2691f505ed43'
@@ -12,8 +12,14 @@
PSData = @{
ProjectURI = 'https://github.com/StartAutomating/Splatter'
LicenseURI = 'https://github.com/StartAutomating/Splatter/blob/master/LICENSE'
+ IconURI = 'https://raw.githubusercontent.com/StartAutomating/Splatter/master/Assets/Splatter.png'
Tags = 'Splatting'
ReleaseNotes = @'
+### 0.5.3:
+* Out-Splat now supports -Examples, -Links, -Notes, and -OutputTypes (Issue #9)
+* Adding logo
+* Documentation updates.
+
### 0.5.2:
* Improved pipeline support (Fixes #6)
* Out-Splat -CrossStream will now output all streams in generated commands, not just error and output.
diff --git a/Splatter.tests.ps1 b/Splatter.tests.ps1
index 803cc5d..63b11b6 100644
--- a/Splatter.tests.ps1
+++ b/Splatter.tests.ps1
@@ -4,13 +4,13 @@ describe Splatter {
context 'Get-Splat makes splatting more gettable' {
it 'Will Find Matching Parameters for a Command' {
$splatOut = @{id = $pid;Foo='bar'} | Get-Splat -Command Get-Process
- $splatOut.Keys.Count | should be 1
+ $splatOut.Keys.Count | should -Be 1
}
it 'Will remove invalid input' {
@{id = $pid;Timeout=65kb} |
Get-Splat -Command Wait-Process |
Select-Object -ExpandProperty Count |
- should be 1
+ should -Be 1
@{id="blah"} | Get-Splat -Command Get-Process
}
@@ -43,7 +43,7 @@ describe Splatter {
}
(foo -id $pid).id|
- should be $pid
+ should -Be $pid
}
}
@@ -65,7 +65,7 @@ describe Splatter {
it '*@ merges splats' {
@{a='b'}|
Merge-Splat -Add @{c='d'} |
- Select-Object -ExpandProperty Keys | should be a,c
+ Select-Object -ExpandProperty Keys | should -Be a,c
}
it '.@ (Use-Splat)' {
@@ -80,7 +80,7 @@ describe Splatter {
$splat =@{Message='hi'}
$splat | Use-Splat {
param([Parameter(Mandatory=$true)][string]$Message) $Message
- } | should be hi
+ } | should -Be hi
}
it 'Can find matching scripts for a piece of data' {
@@ -108,17 +108,17 @@ describe Splatter {
Get-Splat $Fruit,$vegetable
$matchedSplat |
Select-Object -ExpandProperty Command |
- should be $Fruit
+ should -Be $Fruit
- $matchedSplat | Use-Splat | should be 'apricot is a fruit'
+ $matchedSplat | Use-Splat | should -Be 'apricot is a fruit'
}
it 'Can pass additional arguments' {
$2Splat = @{} | Get-Splat {$args}
$123 = $2Splat | Use-Splat -ArgumentList 1,2,3
$Another123 = @{} | Use-Splat {$args} 1 2 3
- $123 | should be 1,2,3
- $Another123 | should be 1,2,3
+ $123 | should -Be 1,2,3
+ $Another123 | should -Be 1,2,3
}
}
@@ -127,7 +127,7 @@ describe Splatter {
@{a='b'}|
Merge-Splat -Add @{c='d'} |
Select-Object -ExpandProperty Keys |
- should be a,c
+ should -Be a,c
}
it 'Is easy to remove keys from a Splat' {
@@ -140,7 +140,7 @@ describe Splatter {
@{a='b'} | Merge-Splat -Map @{a='b',@{c='d'},{@{e='f'}}} |
Select-Object -ExpandProperty Keys |
Sort-Object |
- should be a,b,c,e
+ should -Be a,b,c,e
}
it 'Can -Map back objects,if a key was found' {
@@ -153,30 +153,30 @@ describe Splatter {
@{a='b';"c$(Get-Random)"='d'} |
Merge-Splat -Exclude c* |
Select-Object -ExpandProperty Keys |
- should be a
+ should -Be a
}
it 'Can -Include Keys' {
@{a='b';"c$(Get-Random)"='d'} |
Merge-Splat -Include c* |
Select-Object -ExpandProperty Keys |
- should belike c*
+ should -Belike c*
}
it 'Will squish collisions' {
$merged = @{a='b'},[Ordered]@{a='a';b='b';c='c'} | Merge-Splat
- $merged.keys | should be a,b,c
- $merged.a | should be b,a
+ $merged.keys | should -Be a,b,c
+ $merged.a | should -Be b,a
}
it 'If passed -Keep, it will Keep the first one' {
$merged = @{a='b'},[Ordered]@{a='a';b='b';c='c'} | Merge-Splat -Keep
- $merged.keys | should be a,b,c
- $merged.a | should be b
+ $merged.keys | should -Be a,b,c
+ $merged.a | should -Be b
}
it 'If passed -Replace, it will Replace collisions with new items' {
$merged = @{a='b'},[Ordered]@{a='a';b='b';c='c'} | Merge-Splat -Replace
- $merged.keys | should be a,b,c
- $merged.a | should be a
+ $merged.keys | should -Be a,b,c
+ $merged.a | should -Be a
}
}
@@ -219,7 +219,7 @@ describe Splatter {
}
(foo -id $pid).id|
- should be $pid
+ should -Be $pid
}
}
@@ -232,21 +232,21 @@ describe Splatter {
throw 'Splatter failed to embed'
}
$splatterModule = Get-Module Splatter
- ${.@} | should not be $splatterModule.ExportedVariables['.@']
+ ${.@} | should -Not -Be $splatterModule.ExportedVariables['.@']
@{id=$pid} | & ${.@} gps
}
it 'is pretty small' {
$embeddedSplatter = Initialize-Splatter
- $embeddedSplatter.Length | should belessthan 30kb
+ $embeddedSplatter.Length | should -Belessthan 30kb
}
- it 'can be minified and compressed' {
+ it 'can -Be minified and compressed' {
$embeddedSplatter = Initialize-Splatter -Minify -Compress
- $embeddedSplatter.Length | should belessthan 10kb
+ $embeddedSplatter.Length | should -Belessthan 10kb
}
- it 'Can be embedded as a functionl' {
+ it 'Can -Be embedded as a functionl' {
$embeddedSplatter = Initialize-Splatter -Verb Get
. ([ScriptBlock]::Create($embeddedSplatter))
}
@@ -257,9 +257,9 @@ describe Splatter {
. ([ScriptBlock]::Create($embeddedSplatter))
if (${??@} -ne $null) {
- throw '${??@} should be undefined'
+ throw '${??@} should -Be undefined'
}
- $embeddedSplatter.Length | should belessthan 20kb
+ $embeddedSplatter.Length | should -Belessthan 20kb
}
}
@@ -267,7 +267,7 @@ describe Splatter {
it 'Can write you a splatting script' {
$splatScript = Out-Splat -CommandName Get-Command -DefaultParameter @{Module='Splatter';CommandType='Alias'}
- $splatScript| should belike '*Get-Command*@*'
+ $splatScript| should -Belike '*Get-Command*@*'
}
it 'Can write you a splating function' {
$splatFunction =
@@ -275,11 +275,19 @@ describe Splatter {
Module='Splatter';CommandType='Alias'
} -ExcludeParameter * -Synopsis 'Gets Splatter Aliases' -Description 'Gets aliases from the module Splatter'
- $splatFunction | should belike '*function Get-SplatterAlias*{*Get-Command*@*'
+ $splatFunction | should -Belike '*function Get-SplatterAlias*{*Get-Command*@*'
+ }
+
+ it 'Can write -Examples' {
+ $splatFunction =
+ Out-Splat -FunctionName Get-SplatterAlias -CommandName Get-Command -DefaultParameter @{
+ Module='Splatter';CommandType='Alias'
+ } -ExcludeParameter * -Synopsis 'Gets Splatter Aliases' -Description 'Gets aliases from the module Splatter' -Example 'Get-SplatterAlias'
+ $splatFunction | should -Belike '*.Example*Get-SplatterAlias*'
}
}
- context 'Splatter can be smart about pipelines' {
+ context 'Splatter can -Be smart about pipelines' {
it 'Can determine which parameters can pipe' {
$r =
@{Foo='Bar';Baz='Bing'} |
@@ -291,8 +299,8 @@ describe Splatter {
$baz
)
}
- $r.PipelineParameter.Keys | should be foo
- $r.NonPipelineParameter.Keys | should be baz
+ $r.PipelineParameter.Keys | should -Be foo
+ $r.NonPipelineParameter.Keys | should -Be baz
}
it 'Can -Stream splats' {
@@ -306,29 +314,29 @@ describe Splatter {
$baz
)
- begin { $baz }
+ Begin { $baz }
process { $foo }
- } -Stream | should be bing,bar,foo
+ } -Stream | should -Be bing,bar,foo
}
}
- context 'Splatter tries to be fault-tolerant' {
+ context 'Splatter tries to -Be fault-tolerant' {
it 'Will complain if Use-Splat is not provided with a -Command' {
$problem = $null
@{aSplat='IMadeMySelf'} | Use-Splat -ErrorAction SilentlyContinue -ErrorVariable Problem
- if (-not $Problem) { throw "There should hae been a problem" }
+ if (-not $Problem) { throw "There should hae -Been a problem" }
}
it 'Will output properties containing invalid parameters' {
$o = @{Date='akllaksjasklj'} | Get-Splat Get-Date -Force
- $o.Invalid.keys | should be Date
+ $o.Invalid.keys | should -Be Date
}
- it 'Will mark parameters that could not be turned into a ScriptBlock as invalid' {
+ it 'Will mark parameters that could not -Be turned into a ScriptBlock as invalid' {
$o = @{Command='{"hi"'} | Get-Splat Invoke-Command -Force
- $o.Invalid.keys | should be Command
+ $o.Invalid.keys | should -Be Command
}
}
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
deleted file mode 100644
index aa08607..0000000
--- a/azure-pipelines.yml
+++ /dev/null
@@ -1,343 +0,0 @@
-
-parameters:
- - name: ModulePath
- type: string
- default:
- - name: PesterMaxVersion
- type: string
- default: '4.99.99'
-stages:
- - stage: PowerShellStaticAnalysis
- displayName: Static Analysis
- condition: succeeded()
- jobs:
- - job: PSScriptAnalyzer
- displayName: PSScriptAnalyzer
- pool:
- vmImage: windows-latest
- steps:
- - powershell: |
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
- Install-Module -Name PSDevOps -Repository PSGallery -Force -Scope CurrentUser
- Import-Module PSDevOps -Force -PassThru
- displayName: InstallPSDevOps
- - powershell: |
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
- Install-Module -Name PSScriptAnalyzer -Repository PSGallery -Force -Scope CurrentUser
- Import-Module PSScriptAnalyzer -Force -PassThru
- displayName: InstallPSScriptAnalyzer
- - powershell: |
- Import-Module PSScriptAnalyzer, PSDevOps
- $invokeScriptAnalyzerSplat = @{Path='.\'}
- if ($ENV:PSScriptAnalyzer_Recurse) {
- $invokeScriptAnalyzerSplat.Recurse = $true
- }
- $result = Invoke-ScriptAnalyzer @invokeScriptAnalyzerSplat
-
- foreach ($r in $result) {
- if ('information', 'warning' -contains $r.Severity) {
- Write-ADOWarning -Message $r.Message -SourcePath $r.ScriptPath -LineNumber $r.Line -ColumnNumber $r.Column
- }
- elseif ($r.Severity -eq 'Error') {
- Write-ADOError -Message $r.Message -SourcePath $r.ScriptPath -LineNumber $r.Line -ColumnNumber $r.Column
- }
- }
- displayName: RunPSScriptAnalyzer
-
- - stage: TestPowerShellCrossPlatform
- displayName: Test
- jobs:
- - job: Windows
- displayName: Windows
- pool:
- vmImage: windows-latest
- steps:
- - powershell: |
- $Parameters = @{}
- $Parameters.PesterMaxVersion = ${{coalesce(format('"{0}"',parameters.PesterMaxVersion), '$null')}};
- foreach ($k in @($parameters.Keys)) {
- if ([String]::IsNullOrEmpty($parameters[$k])) {
- $parameters.Remove($k)
- }
- }
- & {param(
- [string]
- $PesterMaxVersion = '4.99.99'
- )
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
- Install-Module -Name Pester -Repository PSGallery -Force -Scope CurrentUser -MaximumVersion $PesterMaxVersion -SkipPublisherCheck -AllowClobber
- Import-Module Pester -Force -PassThru -MaximumVersion $PesterMaxVersion} @Parameters
- displayName: InstallPester
- - powershell: |
- $Parameters = @{}
- $Parameters.ModulePath = ${{coalesce(format('"{0}"',parameters.ModulePath), '$null')}};
- $Parameters.PesterMaxVersion = ${{coalesce(format('"{0}"',parameters.PesterMaxVersion), '$null')}};
- foreach ($k in @($parameters.Keys)) {
- if ([String]::IsNullOrEmpty($parameters[$k])) {
- $parameters.Remove($k)
- }
- }
- & {param(
- [string]
- $ModulePath,
- [string]
- $PesterMaxVersion = '4.99.99'
- )
-
- $orgName, $moduleName = $env:BUILD_REPOSITORY_ID -split "/"
- if (-not $ModulePath) {
- $orgName, $moduleName = $env:BUILD_REPOSITORY_ID -split "/"
- $ModulePath = ".\$moduleName.psd1"
- }
- Import-Module Pester -Force -PassThru -MaximumVersion $PesterMaxVersion | Out-Host
- Import-Module $ModulePath -Force -PassThru | Out-Host
- $result =
- Invoke-Pester -PassThru -Verbose -OutputFile ".\$moduleName.TestResults.xml" -OutputFormat NUnitXml `
- -CodeCoverage "$(Build.SourcesDirectory)\*-*.ps1" -CodeCoverageOutputFile ".\$moduleName.Coverage.xml"
-
- $psDevOpsImported = Import-Module PSDevOps -Force -PassThru -ErrorAction SilentlyContinue
-
- if ($psDevOpsImported) {
- foreach ($pesterTestResult in $pesterResults.TestResult) {
- if ($pesterTestResult.Result -eq 'Failed') {
- $foundLineNumber = [Regex]::Match($pesterTestResult.StackTrace, ':\s{0,}(?\d+)\s{0,}\w{1,}\s{0,}(?.+)$', 'Multiline')
- $errSplat = @{
- Message = $pesterTestResult.ErrorRecord.Exception.Message
- Line = $foundLineNumber.Groups["Line"].Value
- SourcePath = $foundLineNumber.Groups["File"].Value
- }
-
- Write-ADOError @errSplat
- }
- }
- } else {
- if ($result.FailedCount -gt 0) {
- throw "$($result.FailedCount) tests failed."
- }
- }} @Parameters
- displayName: RunPester
- - task: PublishTestResults@2
- inputs:
- testResultsFormat: NUnit
- testResultsFiles: '**/*.TestResults.xml'
- mergeTestResults: true
- - task: PublishCodeCoverageResults@1
- inputs:
- codeCoverageTool: JaCoCo
- summaryFileLocation: '**/*.Coverage.xml'
- reportDirectory: $(System.DefaultWorkingDirectory)
- - job: Linux
- displayName: Linux
- pool:
- vmImage: ubuntu-latest
- steps:
- - script: |
-
- curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
- curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list | sudo tee /etc/apt/sources.list.d/microsoft.list
- sudo apt-get update
- sudo apt-get install -y powershell
-
- displayName: Install PowerShell Core
- - pwsh: |
- $Parameters = @{}
- $Parameters.PesterMaxVersion = ${{coalesce(format('"{0}"',parameters.PesterMaxVersion), '$null')}};
- foreach ($k in @($parameters.Keys)) {
- if ([String]::IsNullOrEmpty($parameters[$k])) {
- $parameters.Remove($k)
- }
- }
- & {param(
- [string]
- $PesterMaxVersion = '4.99.99'
- )
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
- Install-Module -Name Pester -Repository PSGallery -Force -Scope CurrentUser -MaximumVersion $PesterMaxVersion -SkipPublisherCheck -AllowClobber
- Import-Module Pester -Force -PassThru -MaximumVersion $PesterMaxVersion} @Parameters
- displayName: InstallPester
- - pwsh: |
- $Parameters = @{}
- $Parameters.ModulePath = ${{coalesce(format('"{0}"',parameters.ModulePath), '$null')}};
- $Parameters.PesterMaxVersion = ${{coalesce(format('"{0}"',parameters.PesterMaxVersion), '$null')}};
- foreach ($k in @($parameters.Keys)) {
- if ([String]::IsNullOrEmpty($parameters[$k])) {
- $parameters.Remove($k)
- }
- }
- & {param(
- [string]
- $ModulePath,
- [string]
- $PesterMaxVersion = '4.99.99'
- )
-
- $orgName, $moduleName = $env:BUILD_REPOSITORY_ID -split "/"
- if (-not $ModulePath) {
- $orgName, $moduleName = $env:BUILD_REPOSITORY_ID -split "/"
- $ModulePath = ".\$moduleName.psd1"
- }
- Import-Module Pester -Force -PassThru -MaximumVersion $PesterMaxVersion | Out-Host
- Import-Module $ModulePath -Force -PassThru | Out-Host
- $result =
- Invoke-Pester -PassThru -Verbose -OutputFile ".\$moduleName.TestResults.xml" -OutputFormat NUnitXml `
- -CodeCoverage "$(Build.SourcesDirectory)\*-*.ps1" -CodeCoverageOutputFile ".\$moduleName.Coverage.xml"
-
- $psDevOpsImported = Import-Module PSDevOps -Force -PassThru -ErrorAction SilentlyContinue
-
- if ($psDevOpsImported) {
- foreach ($pesterTestResult in $pesterResults.TestResult) {
- if ($pesterTestResult.Result -eq 'Failed') {
- $foundLineNumber = [Regex]::Match($pesterTestResult.StackTrace, ':\s{0,}(?\d+)\s{0,}\w{1,}\s{0,}(?.+)$', 'Multiline')
- $errSplat = @{
- Message = $pesterTestResult.ErrorRecord.Exception.Message
- Line = $foundLineNumber.Groups["Line"].Value
- SourcePath = $foundLineNumber.Groups["File"].Value
- }
-
- Write-ADOError @errSplat
- }
- }
- } else {
- if ($result.FailedCount -gt 0) {
- throw "$($result.FailedCount) tests failed."
- }
- }} @Parameters
- displayName: RunPester
- - task: PublishTestResults@2
- inputs:
- testResultsFormat: NUnit
- testResultsFiles: '**/*.TestResults.xml'
- mergeTestResults: true
- - task: PublishCodeCoverageResults@1
- inputs:
- codeCoverageTool: JaCoCo
- summaryFileLocation: '**/*.Coverage.xml'
- reportDirectory: $(System.DefaultWorkingDirectory)
- - job: MacOS
- displayName: MacOS
- pool:
- vmImage: macos-latest
- steps:
- - script: |
- brew update
- brew tap caskroom/cask
- brew cask install powershell
- displayName: Install PowerShell Core
- - pwsh: |
- $Parameters = @{}
- $Parameters.PesterMaxVersion = ${{coalesce(format('"{0}"',parameters.PesterMaxVersion), '$null')}};
- foreach ($k in @($parameters.Keys)) {
- if ([String]::IsNullOrEmpty($parameters[$k])) {
- $parameters.Remove($k)
- }
- }
- & {param(
- [string]
- $PesterMaxVersion = '4.99.99'
- )
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
- Install-Module -Name Pester -Repository PSGallery -Force -Scope CurrentUser -MaximumVersion $PesterMaxVersion -SkipPublisherCheck -AllowClobber
- Import-Module Pester -Force -PassThru -MaximumVersion $PesterMaxVersion} @Parameters
- displayName: InstallPester
- - pwsh: |
- $Parameters = @{}
- $Parameters.ModulePath = ${{coalesce(format('"{0}"',parameters.ModulePath), '$null')}};
- $Parameters.PesterMaxVersion = ${{coalesce(format('"{0}"',parameters.PesterMaxVersion), '$null')}};
- foreach ($k in @($parameters.Keys)) {
- if ([String]::IsNullOrEmpty($parameters[$k])) {
- $parameters.Remove($k)
- }
- }
- & {param(
- [string]
- $ModulePath,
- [string]
- $PesterMaxVersion = '4.99.99'
- )
-
- $orgName, $moduleName = $env:BUILD_REPOSITORY_ID -split "/"
- if (-not $ModulePath) {
- $orgName, $moduleName = $env:BUILD_REPOSITORY_ID -split "/"
- $ModulePath = ".\$moduleName.psd1"
- }
- Import-Module Pester -Force -PassThru -MaximumVersion $PesterMaxVersion | Out-Host
- Import-Module $ModulePath -Force -PassThru | Out-Host
- $result =
- Invoke-Pester -PassThru -Verbose -OutputFile ".\$moduleName.TestResults.xml" -OutputFormat NUnitXml `
- -CodeCoverage "$(Build.SourcesDirectory)\*-*.ps1" -CodeCoverageOutputFile ".\$moduleName.Coverage.xml"
-
- $psDevOpsImported = Import-Module PSDevOps -Force -PassThru -ErrorAction SilentlyContinue
-
- if ($psDevOpsImported) {
- foreach ($pesterTestResult in $pesterResults.TestResult) {
- if ($pesterTestResult.Result -eq 'Failed') {
- $foundLineNumber = [Regex]::Match($pesterTestResult.StackTrace, ':\s{0,}(?\d+)\s{0,}\w{1,}\s{0,}(?.+)$', 'Multiline')
- $errSplat = @{
- Message = $pesterTestResult.ErrorRecord.Exception.Message
- Line = $foundLineNumber.Groups["Line"].Value
- SourcePath = $foundLineNumber.Groups["File"].Value
- }
-
- Write-ADOError @errSplat
- }
- }
- } else {
- if ($result.FailedCount -gt 0) {
- throw "$($result.FailedCount) tests failed."
- }
- }} @Parameters
- displayName: RunPester
- - task: PublishTestResults@2
- inputs:
- testResultsFormat: NUnit
- testResultsFiles: '**/*.TestResults.xml'
- mergeTestResults: true
- - task: PublishCodeCoverageResults@1
- inputs:
- codeCoverageTool: JaCoCo
- summaryFileLocation: '**/*.Coverage.xml'
- reportDirectory: $(System.DefaultWorkingDirectory)
-
- condition: succeeded()
- - stage: UpdatePowerShellGallery
- displayName: Update
- condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
- variables:
- - group: Gallery
- jobs:
- - job: Publish
- displayName: PowerShell Gallery
- pool:
- vmImage: windows-latest
- steps:
- - powershell: |
- $orgName, $moduleName = $env:BUILD_REPOSITORY_ID -split "/"
- $imported = Import-Module ".\$moduleName.psd1" -Force -PassThru
- $foundModule = Find-Module -Name $ModuleName
- if ($foundModule.Version -ge $imported.Version) {
- Write-Warning "##vso[task.logissue type=warning]Gallery Version of $moduleName is more recent ($($foundModule.Version) >= $($imported.Version))"
- } else {
- $gk = '$(GalleryKey)'
- $stagingDir = '$(Build.ArtifactStagingDirectory)'
- $moduleTempPath = Join-Path $stagingDir $moduleName
-
- Write-Host "Staging Directory: $ModuleTempPath"
-
- $imported | Split-Path | Copy-Item -Destination $moduleTempPath -Recurse
- $moduleGitPath = Join-Path $moduleTempPath '.git'
- Write-Host "Removing .git directory"
- Remove-Item -Recurse -Force $moduleGitPath
- Write-Host "Module Files:"
- Get-ChildItem $moduleTempPath -Recurse
- Write-Host "Publishing $moduleName [$($imported.Version)] to Gallery"
- Publish-Module -Path $moduleTempPath -NuGetApiKey $gk
- if ($?) {
- Write-Host "Published to Gallery"
- } else {
- Write-Host "Gallery Publish Failed"
- exit 1
- }
- }
- displayName: PublishPowerShellGallery
-
-