tooling/ActionTypes/Script.xscript.ps1
#:xheader: #Type=ActionType; #:xheader: @{ Clean = { Param([ConfigAutomationContext] $context,[UIAction] $action) return $true }; Action = { Param([ConfigAutomationContext] $context,[UIAction] $action) $extracted = $action.Parameters().Extract(@("ScriptType", "OutputVariables", "ScriptScope", "WorkingDirectory")) $WorkingDirectory = $extracted.WorkingDirectory if($WorkingDirectory){ $context.Display("{magenta}Working Directory: {gray}'{white}$($WorkingDirectory){gray}'") if(-not (Test-Path $WorkingDirectory)){ $context.Error("Action {white}$($action.Name()){gray} of type {white}$($action.ActionType().Name()){gray} - WorkingDirectory {white}$($WorkingDirectory){gray} was not found") return $false } $WorkingDirectory = [System.IO.Path]::GetFullPath($WorkingDirectory) } else{ $context.Display("{magenta}Working Directory: {gray}'{red}Not Found...{gray}'") } if($extracted.ScriptType -eq "Inline"){ $extracted = $action.Parameters().Extract(@("ScriptBlock")) $tempFile = New-TemporaryFile $tempPs1 = [System.IO.Path]::ChangeExtension($tempFile, "ps1") ren $tempFile $tempPs1 ($extracted.ScriptBlock) | Set-Content $tempPs1 $extracted | Add-Member -MemberType NoteProperty -Name "ScriptPath" -Value $tempPs1 -Force $extracted | Add-Member -MemberType NoteProperty -Name "ScriptArguments" -Value "" -Force } elseif($extracted.ScriptType -eq "ScriptFile" -or (-not $extracted.ScriptType )){ $extracted = $action.Parameters().Extract(@("ScriptPath", "ScriptArguments", "ScriptScope")) } # Run Actual Script $extracted.ScriptArguments = $extracted.ScriptArguments -replace "`n",'' $extracted.ScriptArguments = $extracted.ScriptArguments -replace "`r",'' $__vsts_input_failOnStandardError = $action.TestProperty("failOnStandardError","true") $__vsts_input_errorActionPreference = $action.TestProperty("errorActionPreference","true") if(-not $__vsts_input_errorActionPreference){ $__vsts_input_errorActionPreference = "stop" } if($extracted.ScriptScope -eq "NewSession"){ $scriptCommand = "&`"powershell.exe`" `"&'$($extracted.ScriptPath)' $($extracted.ScriptArguments)`"" # $scriptCommand = "&powershell.exe "+'"'+"$($extracted.ScriptPath)"+'"'+" $($extracted.ScriptArguments)" $temp = New-TemporaryFile $scriptCommand += " | Select-WriteHost | out-file '$temp'" if($WorkingDirectory){ $scriptCommand = "pushd '$($WorkingDirectory)'`r`n " + $scriptCommand + "`r`n popd" } $context.Display("{white}Command:{gray}`r`n$($scriptCommand)") $results = Invoke-Expression $scriptCommand $content = Get-Content $temp -Raw del $temp } elseif(-not $extracted.ScriptScope){ $scriptCommand = "&'$($extracted.ScriptPath)' $($extracted.ScriptArguments)" # $scriptCommand = "&powershell.exe "+'"'+"$($extracted.ScriptPath)"+'"'+" $($extracted.ScriptArguments)" $temp = New-TemporaryFile $scriptCommand += " | out-file '$temp'" if($WorkingDirectory){ $scriptCommand = "pushd '$($WorkingDirectory)'`r`n " + $scriptCommand + "`r`n popd" } $context.Display("{white}Command:{gray}`r`n$($scriptCommand)") $results = Invoke-Expression $scriptCommand $content = Get-Content $temp -Raw del $temp } else{ $context.Error("Unknown valid of {white}ScriptScope{gray} ({white}$($extracted.ScriptScope){gray}). Allowed values are '{white}NewSession{gray}' and '{white}SameSession{gray}'") return $false } $context.Display("{white}Result:{gray}`r`n$($content)") $results = $results | ForEach-Object { if($_ -is [System.Management.Automation.ErrorRecord]) { if($_.FullyQualifiedErrorId -eq "NativeCommandError" -or $_.FullyQualifiedErrorId -eq "NativeCommandErrorMessage") { ,$_ if($__vsts_input_failOnStandardError -eq $true) { "##vso[task.complete result=Failed]" } } else { if($__vsts_input_errorActionPreference -eq "continue") { ,$_ if($__vsts_input_failOnStandardError -eq $true) { "##vso[task.complete result=Failed]" } } elseif($__vsts_input_errorActionPreference -eq "stop") { throw $_ } } } else { ,$_ } } $expectedVariables = [hashtable]::new() $OutputVariables = $action.Parameters().Get("OutputVariables").Value($false) if($OutputVariables) { $matches = ([regex]'([^,]+)').Matches($OutputVariables) if($matches.Count -gt 0){ foreach($match in $matches){ $varName = $match.Groups[1].Value $expectedVariables.Add($varName, $null) } } } $actualVariables = [hashtable]::new() if($content){ $matches = ([regex]"(\#\#vso\[task.setvariable variable\=)([^\;]+?)(;{0,1}\])([^`r`n]*)").Matches($content) if($matches.Count -gt 0){ $context.Display("{gray}{white}Output Variables{gray} - Found [{white}$($matches.Count){gray} variables") $context.PushIndent() foreach($match in $matches){ $varName = $match.Groups[2].Value $varValue = $match.Groups[4].Value if(-not $expectedVariables.ContainsKey($varName)){ $context.Error("Action {white}$($action.Name()){gray} of type {white}$($action.ActionType().Name()){gray} - Output Variable {white}$($varName){gray} was not expected") continue } $actualVariables.Add($varName, $varValue) $context.InjectOutputVariable($action, $varName, $varValue) } $context.PopIndent() } $expectedVariables.GetEnumerator() | % { if(-not $actualVariables.ContainsKey($varName)){ $context.Error("Action {white}$($action.Name()){gray} of type {white}$($action.ActionType().Name()){gray} - Output Variable {white}$($varName){gray} was expected but not found in the output") } } $context.Display("`r`n{white}Result:{gray}`r`n{gray}" + $content) } return $true }; CanExecute = { Param([ConfigAutomationContext] $context,[UIAction] $action) return $true }; Validate = { Param([ConfigAutomationContext] $context,[UIAction] $action) # $parameterNames = (($action.Parameters().Items() | Foreach {"$($_.ToString())"})) -join "`r`n " $extracted = $action.Parameters().Extract(@("ScriptType", "WorkingDirectory")) $context.Display("{cyan}Parameters: {gray}'{white}$($parameterNames){gray}'") if($extracted.WorkingDirectory){ $context.Display("{magenta}Working Directory: {gray}'{white}$($extracted.WorkingDirectory){gray}'") if(-not (Test-Path $extracted.WorkingDirectory)){ $context.Error("Action {white}$($action.Name()){gray} of type {white}$($action.ActionType().Name()){gray} - WorkingDirectory {white}$($extracted.WorkingDirectory){gray} was not found") return $false } } else{ $context.Display("{magenta}Working Directory: {gray}'{red}Not Found...{gray}'") } if($extracted.ScriptType -eq "Inline"){ if(-not $action.Parameters().Validate(@("ScriptBlock"))){ return $false } $OutputVariables = $action.Parameters().Get("OutputVariables").Value($false) if($OutputVariables) { $matches = ([regex]'([^,]+)').Matches($OutputVariables) if($matches.Count -gt 0){ $context.Display("{gray}{white}Output Variables{gray} - Found [{white}$($matches.Count){gray} variables") $context.PushIndent() foreach($match in $matches){ $varName = $match.Groups[1].Value $varValue = $false $context.InjectOutputVariable($action, $varName, $varValue) } $context.PopIndent() } } } elseif($extracted.ScriptType -eq "ScriptFile" -or (-not $extracted.ScriptType )){ if(-not $action.Parameters().Validate(@("ScriptPath", "ScriptArguments"))){ return $false } $OutputVariables = $action.Parameters().Get("OutputVariables").Value($false) if($OutputVariables) { $matches = ([regex]'([^,]+)').Matches($OutputVariables) if($matches.Count -gt 0){ $context.Display("{gray}{white}Output Variables{gray} - Found [{white}$($matches.Count){gray} variables") $context.PushIndent() foreach($match in $matches){ $varName = $match.Groups[1].Value $varValue = $false $context.InjectOutputVariable($action, $varName, $varValue) } $context.PopIndent() } } $extracted = $action.Parameters().Extract(@("ScriptPath", "ScriptArguments", "ValidationScriptPath", "ValidationScriptArguments")) if(-not (Test-Path $extracted.ScriptPath)){ $context.Error("Action {white}$($action.Name()){gray} of type {white}$($action.ActionType().Name()){gray} - ScriptPath {white}$($extracted.ScriptPath){gray} was not found") return $false } $extracted.ScriptArguments = $extracted.ScriptArguments -replace '`n','' if($extracted.ValidationScriptPath){ $context.Error("{white}ValidationScriptPath{gray} not implmented currently...") return $false } return $true } else{ $context.Error("Unknown Script Type '{white}$($extracted.ScriptType){gray}'") return $false } $extracted = $action.Parameters().Extract(@("ValidationScriptBlock","ValidationScriptPath", "ValidationScriptArguments")) if($extracted.ValidationScriptBlock){ $tempFile = New-TemporaryFile $tempPs1 = [System.IO.Path]::ChangeExtension($tempFile, "ps1") ren $tempFile $tempPs1 ($extracted.ValidationScriptBlock) | Set-Content $tempPs1 $extracted | Add-Member -MemberType NoteProperty -Name "ValidationScriptPath" -Value $tempPs1 -Force if(-not $extracted.ValidationScriptArguments){ $extracted | Add-Member -MemberType NoteProperty -Name "ValidationScriptArguments" -Value "" -Force } } if($extracted.ValidationScriptPath){ if($extracted.ValidationScriptScope -eq "NewSession"){ $scriptCommand = "&`"powershell.exe`" `"&'$($extracted.ValidationScriptPath)' $($extracted.ValidationScriptArguments)`"" # $scriptCommand = "&powershell.exe "+'"'+"$($extracted.ScriptPath)"+'"'+" $($extracted.ValidationScriptArguments)" $temp = New-TemporaryFile $scriptCommand += " | Select-WriteHost | out-file '$temp'" $context.Display("{white}Command:{gray}`r`n$($scriptCommand)") $results = Invoke-Expression $scriptCommand $content = Get-Content $temp -Raw del $temp } else{ $scriptCommand = "&'$($extracted.ValidationScriptPath)' $($extracted.ValidationScriptArguments) -Verbose" # $scriptCommand = "&powershell.exe "+'"'+"$($extracted.ValidationScriptPath)"+'"'+" $($extracted.ValidationScriptArguments)" $temp = New-TemporaryFile $scriptCommand += " | out-file '$temp'" $context.Display("{white}Command:{gray}`r`n$($scriptCommand)") $results = Invoke-Expression $scriptCommand $content = Get-Content $temp -Raw del $temp } $context.Display("{white}Result:{gray}`r`n$($content)") $results = $results | ForEach-Object { if($_ -is [System.Management.Automation.ErrorRecord]) { if($_.FullyQualifiedErrorId -eq "NativeCommandError" -or $_.FullyQualifiedErrorId -eq "NativeCommandErrorMessage") { ,$_ if($__vsts_input_failOnStandardError -eq $true) { "##vso[task.complete result=Failed]" } } else { if($__vsts_input_errorActionPreference -eq "continue") { ,$_ if($__vsts_input_failOnStandardError -eq $true) { "##vso[task.complete result=Failed]" } } elseif($__vsts_input_errorActionPreference -eq "stop") { throw $_ } } } else { ,$_ } } } return $true }; } |