Tasks/Invoke-WhiskeyPowerShell.ps1
function Invoke-WhiskeyPowerShell { [Whiskey.Task("PowerShell")] [CmdletBinding()] param( [Parameter(Mandatory=$true)] [object] $TaskContext, [Parameter(Mandatory=$true)] [hashtable] $TaskParameter ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if( -not ($TaskParameter.ContainsKey('Path'))) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('Element ''Path'' is mandatory. It should be one or more paths, which should be a list of PowerShell Scripts to run, e.g. BuildTasks: - PowerShell: Path: - myscript.ps1 - myotherscript.ps1 WorkingDirectory: bin') } $path = $TaskParameter['Path'] | Resolve-WhiskeyTaskPath -TaskContext $TaskContext -PropertyName 'Path' if( $TaskParameter.ContainsKey('WorkingDirectory') ) { if( -not [IO.Path]::IsPathRooted($TaskParameter['WorkingDirectory'])) { $workingDirectory = $TaskParameter['WorkingDirectory'] | Resolve-WhiskeyTaskPath -TaskContext $TaskContext -PropertyName 'WorkingDirectory' } else { $workingDirectory = $TaskParameter['WorkingDirectory'] } } else { $WorkingDirectory = $TaskContext.BuildRoot } $argument = $TaskParameter['Argument'] if( -not $argument ) { $argument = @{ } } $moduleRoot = Join-Path -Path $PSScriptRoot -ChildPath '..' -Resolve foreach( $scriptPath in $path ) { if( -not (Test-Path -Path $WorkingDirectory -PathType Container) ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('Can''t run PowerShell script ''{0}'': working directory ''{1}'' doesn''t exist.' -f $scriptPath,$WorkingDirectory) continue } $scriptCommand = Get-Command -Name $scriptPath -ErrorAction Ignore if( -not $scriptCommand ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('Can''t run PowerShell script ''{0}'': it has a syntax error.' -f $scriptPath) continue } $passTaskContext = $scriptCommand.Parameters.ContainsKey('TaskContext') if( (Get-Member -InputObject $argument -Name 'Keys') ) { $scriptCommand.Parameters.Values | Where-Object { $_.ParameterType -eq [switch] } | Where-Object { $argument.ContainsKey($_.Name) } | ForEach-Object { $argument[$_.Name] = $argument[$_.Name] | ConvertFrom-WhiskeyYamlScalar } } $resultPath = Join-Path -Path $TaskContext.OutputDirectory -ChildPath ('PowerShell-{0}-ExitCode-{1}' -f ($scriptPath | Split-Path -Leaf),([IO.Path]::GetRandomFileName())) $job = Start-Job -ScriptBlock { $workingDirectory = $using:WorkingDirectory $scriptPath = $using:ScriptPath $argument = $using:argument $taskContext = $using:TaskContext $moduleRoot = $using:moduleRoot $resultPath = $using:resultPath $passTaskContext = $using:passTaskContext Invoke-Command -ScriptBlock { $VerbosePreference = 'SilentlyContinue'; Import-Module -Name $moduleRoot } $VerbosePreference = $using:VerbosePreference $contextArgument = @{ } if( $passTaskContext ) { $contextArgument['TaskContext'] = $taskContext } Set-Location $workingDirectory $Global:LASTEXITCODE = 0 & $scriptPath @contextArgument @argument $Global:LASTEXITCODE | Set-Content -Path $resultPath } do { $job | Receive-Job } while( -not ($job | Wait-Job -Timeout 1) ) $job | Receive-Job if( -not (Test-Path -Path $resultPath -PathType Leaf) ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('PowerShell script ''{0}'' threw a terminating exception.' -F $scriptPath) } [int]$exitCode = Get-Content -Path $resultPath | Select-Object -First 1 if( $exitCode ) { Stop-WhiskeyTask -TaskContext $TaskContext -Message ('PowerShell script ''{0}'' failed, exited with code {1}.' -F $scriptPath,$exitCode) } } } |