Skip to content

Commit

Permalink
Fixed: Whiskey fails to fail a build when certain PowerShell terminat…
Browse files Browse the repository at this point in the history
…ing errors are thrown.
  • Loading branch information
splatteredbits committed Nov 23, 2019
1 parent 151d911 commit e7bba95
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 5 deletions.
107 changes: 107 additions & 0 deletions Test/Invoke-WhiskeyBuild.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ $publishPipelineName = 'Publish'

function Init
{
$Global:Error.Clear()

[Whiskey.Context]$script:context = $null
$script:runByDeveloper = $false
$script:runByBuildServer = $false
Expand Down Expand Up @@ -140,6 +142,20 @@ function GivenWhiskeyYml

$Content | Set-Content -Path (Join-Path $testRoot -ChildPath 'whiskey.yml')
}

function ThenBuildFailed
{
param(
$WithErrorMessage
)

$threwException | Should -BeTrue
if( $WithErrorMessage )
{
$Global:Error | Select-Object -First 1 | Should -Match $WithErrorMessage
}
}

function ThenBuildOutputRemoved
{
It ('should remove .output directory') {
Expand Down Expand Up @@ -359,6 +375,35 @@ function WhenRunningBuild
}
}

function WhenRunningBuildFromBuildPs1
{
[CmdletBinding()]
param(
)

$script:threwException = $false
$buildPs1Path = Join-Path $testRoot -ChildPath 'build.ps1'
@"
Set-Location -Path "$($testRoot)"
Import-Module -Name "$(Join-Path -Path $PSScriptRoot -ChildPath '..\Whiskey' -Resolve)"
Import-Module -Name "$(Join-Path -Path $PSScriptRoot -ChildPath 'WhiskeyTestTasks.psm1' -Resolve)"
`$context = New-WhiskeyContext -Environment Verification -ConfigurationPath '.\whiskey.yml'
Invoke-WhiskeyBuild -Context `$context
New-Item -Path 'passed'
"@ | Set-Content -Path $buildPs1Path

# PowerShell's error handling is very different between starting a build from a build.ps1 script vs. a Pester test
# calling Invoke-WhiskeyBuild.
Start-Job -ScriptBlock {
& $using:buildPs1Path
} | Receive-Job -Wait -AutoRemoveJob

if( -not (Test-Path -Path (Join-Path -Path $testRoot -ChildPath 'passed') ) )
{
$script:threwException = $true
}
}

Describe 'Invoke-WhiskeyBuild.when build passes' {
Context 'By Developer' {
Init
Expand Down Expand Up @@ -543,3 +588,65 @@ Build:
$infos | Where-Object { $_ -match 'InformationPreference\ enabled!' } | Should -BeNullOrEmpty
}
}

Describe 'Invoke-WhiskeyBuild.when task violates a strict mode rule' {
It 'should fail the build' {
Init
GivenWhiskeyYml @'
Build:
- Version:
Version: 0.0.0
- SetStrictModeViolationTask
'@
WhenRunningBuildFromBuildPs1 -ErrorAction SilentlyContinue
ThenBuildFailed -WithErrorMessage 'Build\ failed\.'
$Global:Error[1] | Should -Match 'has\ not\ been\ set'
}
}

Describe 'Invoke-WhiskeyBuild.when task invokes a command that doesn''t exist' {
It 'should fail the build' {
Init
GivenWhiskeyYml @'
Build:
- Version:
Version: 0.0.0
- CommandNotFoundTask
'@
WhenRunningBuildFromBuildPs1 -ErrorAction SilentlyContinue
ThenBuildFailed -WithErrorMessage 'Build\ failed.'
$Global:Error[1] | Should -Match 'is\ not\ recognized'
}
}

Describe 'Invoke-WhiskeyBuild.when task fails' {
It 'should fail the build' {
Init
GivenWhiskeyYml @'
Build:
- Version:
Version: 0.0.0
- FailingTask:
Message: fdsafjkfsdafjdsf
'@
WhenRunningBuildFromBuildPs1 -ErrorAction SilentlyContinue
ThenBuildFailed -WithErrorMessage '\bfdsafjkfsdafjdsf\b'
$Global:Error | Should -Not -Match 'Build\ failed\.'
}
}

Describe 'Invoke-WhiskeyBuild.when cmdlet fails because ErrorAction is Stop' {
It 'should fail the build' {
Init
GivenWhiskeyYml @'
Build:
- Version:
Version: 0.0.0
- CmdletErrorActionStopTask:
Path: ruirwemdsfirewmk
'@
WhenRunningBuildFromBuildPs1 -ErrorAction SilentlyContinue
ThenBuildFailed -WithErrorMessage '\bruirwemdsfirewmk\b'
$Global:Error | Should -Not -Match 'Build\ failed\.'
}
}
4 changes: 2 additions & 2 deletions Test/WhiskeyTest.psm1
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

$PSModulesDirectoryName = 'PSModules'

$exportPlatformVars = $false
if( -not (Get-Variable -Name 'IsLinux' -ErrorAction Ignore) )
{
Expand Down Expand Up @@ -670,8 +672,6 @@ if( $IsWindows )
$FailureCommandScriptBlock = { cmd /c exit 1 }
}

$PSModulesDirectoryName = 'PSModules'

$variablesToExport = & {
'WhiskeyTestDownloadCachePath'
'SuccessCommandScriptBlock'
Expand Down
43 changes: 41 additions & 2 deletions Test/WhiskeyTestTasks.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ function Clear-LastTaskBoundParameter
{
$script:lastTaskBoundParameters = $null
}

function DuplicateAliasTask1
{
[Whiskey.Task('DuplicateAliasTask1',Aliases=('DuplicateAliasTask'),WarnWhenUsingAlias)]
Expand Down Expand Up @@ -91,10 +92,11 @@ function FailingTask
[Whiskey.Task('FailingTask')]
param(
[Whiskey.Context]$TaskContext,
[hashtable]$TaskParameter
[hashtable]$TaskParameter,
$Message = 'Failed!'
)

Stop-WhiskeyTask -TaskContext $TaskContext -Message 'Failed!'
Stop-WhiskeyTask -TaskContext $TaskContext -Message $Message
}

function Get-LastTaskBoundParameter
Expand Down Expand Up @@ -399,3 +401,40 @@ function WrapsNoOpTask

Invoke-WhiskeyTask -TaskContext $TaskContext -Parameter $TaskParameter -Name 'NoOpTask'
}

function SetStrictModeViolationTask
{
[Whiskey.Task('SetStrictModeViolationTask')]
[CmdletBinding()]
param(
)

Set-StrictMode -Version 'Latest'
$ErrorActionPreference = 'Stop'

Write-Verbose ($fdsocvxkljewqrjfdslk)
}

function CommandNotFoundTask
{
[Whiskey.Task('CommandNotFoundTask')]
[CmdletBinding()]
param(
)

Set-StrictMode -Version 'Latest'
$ErrorActionPreference = 'Stop'

Invoke-SomeCommandfdfdsjkfsdaourewfsdrewmkl
}

function CmdletErrorActionStopTask
{
[Whiskey.Task('CmdletErrorActionStopTask')]
[CmdletBinding()]
param(
$Path = '4lkdfmlfu9jdsfkj09'
)

Resolve-Path $Path -ErrorAction Stop
}
9 changes: 9 additions & 0 deletions Whiskey/Functions/Invoke-WhiskeyBuild.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,13 @@ function Invoke-WhiskeyBuild

$env:PSModulePath = $originalPSModulesPath
}

# There are some errors (strict mode validation failures, command not found errors, etc.) that stop a build, but
# even though ErrorActionPreference is Stop, it doesn't stop the current process, which is what causes a build to
# fail the build. If we get here, and the build didn't succeed, we've encountered one of those errors. Throw a
# guaranteed terminating error.
if( -not $succeeded )
{
Write-Error -Message ('Build failed. See previous error output for more information.') -ErrorAction Stop
}
}
2 changes: 1 addition & 1 deletion Whiskey/Functions/Write-WhiskeyInfo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ function Write-WhiskeyInfo
return
}

if( $Message.Length -eq 0 )
if( -not $Message -or $Message.Length -eq 0 )
{
return
}
Expand Down
1 change: 1 addition & 0 deletions Whiskey/Whiskey.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@
* The `GetPowerShellModule` task now supports installing prerelease versions of modules. Set the `AllowPrerelease` property to `true`.
* The `GetPowerShellModule` task can now install a module into a custom directory instead of the PSModules directory. Pass the path to the `Path` parameter.
* The `GetPowerShellModule` task can now import the module being installed. Set the `Import` property to `true`.
* Fixed: Whiskey fails to fail a build when certain PowerShell terminating errors are thrown (i.e. strict mode violations, command not found error, etc.).
'@
} # End of PSData hashtable

Expand Down
2 changes: 2 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ foreach( $assembly in (Get-ChildItem -Path $whiskeyOutBinPath -Filter '*.dll') )
Copy-Item -Path $assembly.FullName -Destination $whiskeyBinPath
}

$ErrorActionPreference = 'Continue'

& (Join-Path -Path $PSScriptRoot -ChildPath 'Whiskey\Import-Whiskey.ps1' -Resolve)

$configPath = Join-Path -Path $PSScriptRoot -ChildPath 'whiskey.yml' -Resolve
Expand Down

0 comments on commit e7bba95

Please sign in to comment.