AWS CodeDeploy provides the ability to run scripts on instances during the deployment lifecycle. Scripts are associated with the AppSpec 'hooks' Section of the appspec.yml file described at AWS CodeDeploy AppSpec File Reference. When CodeDeploy runs a PowerShell cmdlet, the cmdlet can return an exit code of 0 (success) even if the cmdlet encountered errors. If a cmdlet error occurs while performing an operation required by the associated deployment lifecycle event hook, the deployment will not be successful even though CodeDeploy interprets a script exit code of 0 as "success".

Default behavior for PowerShell cmdlets is to return an exit code of 0 unless an unrecoverable or terminating error occurs, such as when attempting to divide by 0. If a PowerShell cmdlet encounters an error that it can recover from, such as when attempting to read a non-existent directory, then it will throw an error and run to completion with an exit code of 0. An exit code of 0 will not cause CodeDeploy to fail a deployment.

By default, PowerShell cmdlets only return an exit code of 1 when encountering terminating errors. When an exit code of 1 is returned, CodeDeploy fails the deployment.

1.    Change how a PowerShell cmdlet responds to non-terminating errors with the PowerShell preference variable $ErrorActionPreference. Add the following line to the beginning of your cmdlet to cause PowerShell to halt execution of the cmdlet and return an exit code of 1 for both terminating and non-terminating errors.

$ErrorActionPreference = ‘Stop’

For more information about this preference variable, see about_Preference_Variables.

2.    To ensure the correct exit code from a script is passed to CodeDeploy, you can use the PowerShell Try-Catch-Finally blocks for basic error handling as illustrated in this example:

#BeforeInstallWithTryCatch.PS1

# Define global variables. $errvar will be used to store error messages upon command failures. This variable will be used to output the error message to a log file.

$errvar

# Here is where we set up the Try, Catch, and Finally blocks. The Try block is where we add the code that we want to execute.

# The Catch block contains code that will execute if code in the Try block fails and generates an error.

# The Finally block is used in this example to write a time stamp and the contents of $errvar to the specified log file.

Try

{

        $ErrorActionPreference = ‘Stop’    # Change how PowerShell responds to non-terminating errors, this causes PowerShell to stop execution for all errors.

        Get-InstalledModule -ev errvar    # The -ev parameter (-ErrorVariable) captures and writes errors to the global variable. It is set on each command.

        Get-ACMCertificate -ev errvar    # This command will generate a missing parameter error

        Get-Module -ev errvar

        net user thiswillerror > c:\stderr.log 2>&1     # To handle the error outside of the try catch using a traditional DOS method

}

Catch

{

    Write-Warning $_

        if ($_ -ne "") {$errvar = $_}

        exit 1&    #This command instructs the session to exit and return an exit code value of 1, which causes CodeDeploy to fail the deployment.

}

Finally

{

    $time=Get-Date    # Defines a time variable with the current date and time.

    "Attempt to run the script was made at $time with error $errvar " | out-file C:\temp\scriptExec.log -Append    # Outputs string and error to designated file

}

# Append option will add to any existing content

  • In this example, the global variable named ‘errvar’ is defined and will store any errors that are generated.
  • The Try block is where we insert the command(s) that we want run for the deployment.
    • The ‘-ev’ (-ErrorVariable) parameter is appended to each command. This captures the error output and writes the captured output into the global variable.
    • For native commands executed in the PowerShell script, we use ‘2>&1’ to pass the ErrOut channel to stdout.
  • The contents of the Catch block run only if an error occurs in the Try block.
    • The If statement evaluates whether $_ is not equal to ""; if this condition is met, it sets the value of the global variable to the contents of $_.
    • We tell the PowerShell session to exit/close with a user-defined exit code of 1. This exit code will be passed to the Command shell and read by CodeDeploy. CodeDeploy will then fail the deployment.
  • In the Finally block, we write the date and time to the local variable ‘time’. We then create a string that concatenates the time to the contents of our global and local variables. Finally, we write the string to a log file. The resulting time-stamped error message provides information that can be used to troubleshoot issues for future deployments.

3.    Finally, update your appspec.yml file and add your .PS1 file to the appropriate lifecycle hook for this deployment:

Version: 0.0

Os: windows

files:

    - source: files/index.html

    destination: C:\inetpub\wwwroot\

hooks:

    BeforeInstall:

        - location: scripts/BeforeInstallWithTryCatch.ps1

        timeout: 900

For more information about how lifecycle hooks are referenced in the appspec.yml file, see AppSpec ‘hooks’ Section.

$ErrorActionPreference, AppSpec.yml, Get-Process, stdout, exit, deployment log, STDOUT, STDERR, AWS CodeDeploy, PowerShell, .PS1, cmdlet, script


Did this page help you? Yes | No

Back to the AWS Support Knowledge Center

Need help? Visit the AWS Support Center

Published: 2016-12-05