This page is for Octopus Deploy 3.0 and newer versions. You can view this page for Octopus 2.0

Skip to end of metadata
Go to start of metadata

As a convention-oriented deployment tool, Octopus can perform a number of actions automatically, such as managing configuration files, creating IIS websites and application pools, and installing Windows Services. Sometimes however you’ll need to do more than the built-in conventions support – and that’s where custom scripts come in.

Supported script types

Icon

Octopus Deploy supports PowerShell scripts (.ps1), C# scripts (.csx) using ScriptCS, Bash scripts (.sh), and in Octopus 3.4 we introduced support for F# scripts (.fsx).

How your scripts are bootstrapped by Calamari

Icon

Each of your scripts will be bootstrapped by the open-source Calamari project to provide access to variables and helper functions. You can see how your scripts are bootstrapped in the Calamari source code.

Scripts in Packages

In your package, you can add any of the following script files in any of the scripting languages supported by Octopus where <ext> is the appropriate extension for your scripting language of choice:

  • PreDeploy.<ext>
  • Deploy.<ext>
  • PostDeploy.<ext>
  • DeployFailed.<ext>

After extracting your package, Calamari will detect these scripts and invoke them. Which file you use depends on when you need your custom activity to run – see the section on what order are conventions run in for details. Your scripts can do anything your scripting language supports, as well as setting output variables and collecting artifacts. These scripts must be located in the root of your package.

As mentioned above, you can create a file named DeployFailed.<ext>, which will be invoked if the package deployment fails. Our blog post about this feature describes how DeployFailed.<ext> works.

Script Support on Deployment Targets

Icon

Of course, Bash scripts will only be supported on Linux / OSX Targets and PowerShell and Script CS will only run on Windows. So ensure you've selected the correct language for your deployment target

Icon

Make sure that the scripts are included in your package. If you are using OctoPack for an ASP.NET web application, you'll need to make sure the file is marked as Build Action = Content.

If you are using OctoPack to package a Windows Service or console application, set Copy to Output Directory = Copy if newer.

Read more about using OctoPack.

Scripts in package steps

Rather than embed scripts in packages, you can also define scripts within the package step definition in Octopus. This is a feature that can be enabled on package steps:

When enabled, you can define your PreDeploy/Deploy/PostDeploy scripts within the Octopus user interface:

 

Standalone scripts

Octopus also allows you to add standalone script steps to your deployment process. You can use standalone scripts to execute scripts on the Octopus Server or on deployment targets, where the script can be defined inline or as part of a package. Standalone scripts are so useful we've dedicated an entire page to them: Standalone scripts

Azure PowerShell scripts

You can manage your Azure subscription using custom PowerShell scripts and the Azure Resource Management (RM) or Service Management (SM) API - more information.

For information about adding a step to the deployment process, see the add step section.

Variables

Octopus allows you to define variables to parameterize your deployments. These variables, along with some predefined variables, will be available from within your scripts.

All variables are strings

Icon
Note that in scripts all Octopus variables are strings even if they look like numbers or other data types. You will need to cast to the appropriate type before using the value if you need something other than a string. 

Let's consider an example where we have defined a project variable called MyApp.ConnectionString.

PowerShell
ScriptCS
Bash
F#
Icon
To see the F# API available to your F# scripts, take a look at our F# signature file.

Variables in PowerShell scripts

In PowerShell we have pre-defined some script-scoped variables for you as a convenience. Consider the same example as before, a variable named "MyApp.ConnectionString" will be available as both:

  • $OctopusParameters["MyApp.ConnectionString"]
  • $MyAppConnectionString

In the first form the variable name appears just as they appear in the Octopus web portal, while in the second example special characters have been removed. The first form is the most flexible, but in some cases the second form may be more convenient.

$key variable

Icon

We fixed an issue which was causing a collision with variables called $key. You can either rename your variable or update to Octopus 3.3.10 or newer.

Passing parameters to scripts

Icon

Script parameters are available in Octopus 3.3.21 or newer. You can use script parameters for file-based scripts that are sourced from a package.

Octopus can pass parameters to your custom script files for any of the supported scripting languages. This means you can use existing scripts, or write and test your own parameterized scripts that have no knowledge of Octopus, passing Octopus Variables directly to your scripts as parameters. The Octopus scripting API is still available within the context of your script, meaning you can use a mixture of parameters and other Octopus variables and functions.

Consider this example PowerShell script:

PowerShell script using Octopus Variables

You can parameterize this script making it easier to test outside of Octopus:

PowerShell script using parameters

When you call external scripts (sourced from a file inside a package) you can pass parameters to your script. This means you can write "vanilla" scripts that are unaware of Octopus, and test them in your local development environment.

You can define your parameters in the Script Parameters field using the format expected by your scripting execution environment (see below for examples).

Delimiting string values

Icon

Don't forget to correctly delimit your parameters correctly for the scripting engine. In the example above we have surrounded the parameter value in double-quotes to handle cases where the Environment Name has spaces: "#{Octopus.Environment.Name}"

Passing parameters to PowerShell scripts

You can pass parameters to PowerShell scripts as if you were calling the script yourself from PowerShell, using positional or named parameters.

Script Parameters in Octopus
Usage in PowerShell script

Passing parameters to C# scripts

You can pass parameters to C# scripts as described here for the ScriptCS engine. ScriptCS only supports positional parameters.

Script Parameters in Octopus
Usage in C# script

Passing parameters to Bash scripts

You can pass parameters to Bash scripts as described in Bash manual.

Script Parameters in Octopus
Usage in Bash script

Passing parameters to F# scripts

You can pass parameters to FSharp scripts as described in MSDN.

Script Parameters in Octopus
Usage in F# script

Logging

When your scripts emit messages Octopus will display the messages in the Task Logs at the most appropriate level for the message. For example:

PowerShell
ScriptCS
Bash
F#

Try these out for yourself using the Script Console!

Error handling

Calamari examines the exit code of the script engine to determine whether the script failed. If the exit code is zero, Calamari assumes the script ran successfully. If the exit code is non-zero, then Calamari assumes the script failed. 

Syntax errors and unhandled exceptions will result in a non-zero exit code from the script engine, which will fail the deployment

Error handling in PowerShell scripts

For PowerShell scripts Calamari also sets the $ErrorActionPreference to Stop before invoking your script. This means that if a command fails, the rest of the script won't be executed. For example:

The third line will not be executed. To change this behavior, set $ErrorActionPreference to Continue at the top of your script. 

At the end of the script, Calamari also checks $LastExitCode to see if the last Windows-based program that you invoked exited successfully. Note that some Windows programs use non-zero exit codes even when they run successfully - for example, Robocopy returns the number of files copied. This can mean that Calamari assumes your script failed even if it actually ran successfully. Best practice is to call Exit 0 yourself if your script ran successfully. 

Note that you'll need to check $LastExitCode yourself if you run multiple Windows programs. For example, with this script, Calamari would correctly see that ping returned an exit code of 1 (the host couldn't be contacted) and will assume the script failed:

But if your script looks like this, Calamari will only examine the exit code from the last line (which is successful), so it will assume the script was successful. 

The best practice here is to always check the exit code when invoking programs:

Output variables

Your scripts can emit variables that are available in subsequent deployment steps. This means you can factor your deployment into smaller, more well-defined steps that leverage the result of prior steps. It is an extremely powerful feature and you should refer to the documentation on output variables for more information.

This example is from the sample project in the Channels Walkthrough which is also available on our demo server. Step 1 calculates a name by convention, which is used by subsequent steps.

 

Collecting artifacts

Does your deployment produce a log file, configuration files, binaries, or test results you want to publish and keep as part of your deployment? Your scripts can instruct the Octopus server to collect files as deployment artifacts. Refer to the documentation on artifacts for more information.

This example comes from our VSTS Extension which builds a VSIX package as part of the deployment process, which is then published as an artifact for convenience.

Security and permissions

Keep in mind that scripts are executed in the context of the account that the Tentacle Windows Service (which invokes Calamari) or SSH session runs as.

Icon
By default Tentacle runs as Local System, which has extensive local privileges, but usually cannot access file shares, remote SQL databases, or other external resources. If you need wider permissions, you’ll need to configure Tentacle to run under a custom service account.

PowerShell ExecutionPolicy: Unrestricted

Icon
When Calamari invokes PowerShell.exe, it uses the unrestricted execution policy for the session. You can see how PowerShell scripts are executed in more detail by looking at the open-source Calamari project.

Testing scripts

You may find that your script runs differently under Calamari than it does when run from PowerShell directly. 

The easiest way to test your scripts under Calamari is to use the Script Console. Alternatively you can invoke Calamari.exe run-script via the command line to test a script.

Calamari run-script command


Working directories

Octopus Scripts are executed by Calamari, the command-line tool invoked by the Octopus Server or Tentacle during a deployment, within a the context of a working directory.  This location is C:\Octopus\Work\ by default.  If you're executing a script contained within a package, the package contents will be uncompressed and copied to this directory but the working directory is the directory containing the script within it.

Scripts that block deployments

Sometimes a script launches a service or application that runs continuously. In this case the script does not complete until the application is terminated.  When the script is run in an Octopus deployment, the deployment will continue executing until the script exits.  In most cases this is undesirable. In order to avoid this behaviour the service or application should be launched in a separate process or session, allowing the deployment to continue executing immediately. For example:

PowerShell
Bash
  • No labels