Some things to be aware of when using Windows PowerShell tasks.

GoCD Agent default installation

The default installation of a GoCD agent will use a 32-bit JRE unless you indicate otherwise. This JRE is embedded in the GoCD agent installer.

If you want to use an alternative JRE (must satisfy GoCD's JRE requirements) after the initial installation, you can alter the "wrapper.java.command" key's value in the [InstallDirectory]\config\wrapper-agent.conf file to point to a different JRE. You will then need to restart the GoCD agent service to start using the alternative JRE.

The [InstallDirectory] refers to the GoCD agents installation directory which by default is "C:\Program Files (x86)\Go Agent".

Pre-requisites for running PowerShell task commands

  • You can only run on Windows based agents
  • You should tag the agents if your are also using linux agents
  • You probably want to ensure your agents all have the same version of PowerShell

32-bit GoCD agent

If you are running a default GoCD agent installation then you will be running a 32-bit JRE.

The 32-bit JRE will try to run PowerShell tasks in the 32-bit version of PowerShell, even if you give the full path to the 64-bit PowerShell executable in the task. If you need to execute a PowerShell script then you will need to alter the execution policy as follows:

  • Open 32-bit version of PowerShell as an administrator: Start -> All Programs -> Accessories -> Windows Powershell -> Windows Powershell (x86) and type:

    # Alter execution policy
    set-executionpolicy remotesigned -force
    

This will allow you to run local scripts on the Windows GoCD agent box.

64-bit GoCD agent

If you are running a GoCD agent using a 64-bit JRE, it will run PowerShell tasks in the 64-bit version of PowerShell.

If you need to execute a PowerShell script, then you will need to alter the execution policy as follows:

  • Open 64-bit version of PowerShell as an administrator: Start -> All Programs -> Accessories -> Windows Powershell -> Windows Powershell and type:

    # Alter execution policy
    set-executionpolicy remotesigned -force
    

This will allow you to run local scripts on the Windows GoCD agent box.

PowerShell task commands

You can configure the task as follows:

command: powershell
arg: .\run.ps1 arg1value

This assumes that the run.ps1 script is in the task's working directory.

If you create the run.ps1 file with the following content you can see details of the execution context in the console log for the pipeline:

param
(
  [string] $arg1
)
write-host "Script:            " $MyInvocation.MyCommand.Path
write-host "Pid:               " $pid
write-host "Host.Version:      " $host.version
write-host "Is 64-bit process: " $([Environment]::Is64BitProcess)
write-host "Execution policy:  " $(get-executionpolicy)
write-host "Arg1:              " $arg1

Propagating failures

You need to ensure that PowerShell exits with an exit code that is not 0 in the event of a failure, this needs to cater to:

  • Script errors
  • External process calls that indicate failure

You will need to decide how to handle these failures and if they should indicate the PowerShell task has been successful or not. This may mean that some script errors and external process calls failing is okay in your context.

The following script demonstrates a strategy I use where I exit with a non zero code if any script error was encountered or an external process call fails:

set-strictmode -version latest
$ErrorActionPreference = 'Stop'

function execute-externaltool
(
  [string] $context,
  [scriptblock] $actionBlock
)
{
  # This function exists to check the exit code for the external tool called within the script block, so we don't have to do this for each call
  & $actionBlock
  if ($LastExitCode -gt 0) { throw "$context : External tool call failed" }
}


try
{
  write-host "Script:            " $MyInvocation.MyCommand.Path
  write-host "Pid:               " $pid
  write-host "Host.Version:      " $host.version
  write-host "Execution policy:  " $(get-executionpolicy)

  # Query a service that does not exist, sc.exe will return with a non 0 exit code
  execute-externaltool "Query a non existent service, will return with exit code != 0" { c:\windows\system32\sc.exe query service_does_not_exist }
}
catch
{
  write-host "$pid : Error caught - $_"
  if ($? -and (test-path variable:LastExitCode) -and ($LastExitCode -gt 0)) { exit $LastExitCode }
  else { exit 1 }
}
  • This script uses a try catch block to handle all errors
    • The $? and $LastExitCode caters to both script and external process calls
    • We fall back on an exit code of 1 if we do not have an external process exit code
  • This script uses an execute-externaltool function which takes a script block argument
    • The script will invoke the script block
    • It will then check for a non zero exit code (Assumes the script block just calls an external process), if so it will throw an exception.

See also

PowerShell execution policy Bypassing PowerShell execution policy Setting execution policy directly in the registry GoCD PowerShell runner plugin - I believe it can only be configured on Windows based GoCD servers

About the author

This is a guest post by Pat Mc Grath. You can find Pat on GitHub.