Run a script step

Octopus also allows you to run standalone scripts as part of your deployment process. You can run a script on the Octopus Server, on workers or across the deployment targets in roles. You can run scripts contained in a package, in a git repository, or ad-hoc scripts you’ve saved as part of the step.

You can use all of the features we provide for custom scripts, like variables, passing parameters, publishing output variables, and collecting artifacts.

Choosing where the script will run

When adding a script you choose where the script will run, and in which context the script will run.

The options will vary based on the infrastructure that’s available to you. For instance, if you do not have any workers configured you will see the following options:

  • Run on the Octopus Server
  • Run on the Octopus Server on behalf of each deployment target
  • Run on each deployment target (default)

If you do have workers configured you will see the following options:

  • Run once on a worker
  • Run on a worker on behalf of each deployment target
  • Run on each deployment target (default)

If you choose to run the step on a worker, you will also need to select which worker pool Octopus should use for the step.

Choosing the right combination of Target and Roles enables some really interesting scenarios. See below for some common examples:

TargetRolesDescriptionVariablesExample scenarios
Deployment targetweb-server app-serverThe script will run on each deployment target with either of the web-server or app-server rolesThe variables scoped to the deployment target will be available to the script. For example, Octopus.Machine.Name will be the deployment target’s nameApply server hardening or ensure standard pre-requisites are met on each deployment target
Octopus ServerThe script will run once on the Octopus ServerScope variables to the Step in order to customize variables for this scriptCalculate some output variables to be used by other steps or run a database upgrade process
Octopus Serverweb-serverThe script will run on the Octopus Server on behalf of the deployment targets with the web-server role. The script will execute once per deployment targetThe variables scoped to the deployment target will be available to the script. For example, Octopus.Machine.Name will be the deployment target’s nameRemove web servers from a load balancer as part of a rolling deployment where access to the load balancer API is restricted

Choosing where to source the script

You may also select the source of the script, either:

  • An ad-hoc or inline script, saved as part of the step itself, or
  • A script file in a git repository, or
  • A script file inside a package (shown below).

Scripts from packages or git repository, versioning and source control Using scripts from inside a package or a git repository are a great way to version and source control your scripts. (You can be assured the correct version of your script will be run when deploying each version of your application.) Both methods have benefits and suit different applications: choose the method best suited to your situation.

From Octopus 2024.1, if you are storing your project configuration in a Git repository using the Configuration as code feature, you can source files from the same Git repository as your deployment process by selecting Project as the Git repository source. When creating a Release, the commit hash used for your deployment process will also be used to source the files.

You can find more information about this feature in this blog post on using Git resources directly in deployments.

When sourcing a script from a file inside a package you cannot choose to run the step before packages are acquired.

Passing parameters to scripts

When you call external scripts (sourced from a file inside a package or git repository) 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. Read about passing parameters to scripts.

Referencing packages

In addition to being able to source the custom script from a package, it is often desirable to reference other packages. Scenarios where this can be useful include:

  • Executing a utility contained in a package
  • Deploying a package in a manner for which there is no built-in steps available; for example pushing a package to a Content-Management-System
  • Performing tasks which require multiple packages. For example:
    • Executing NuGet.exe to push another package (e.g. Acme.Web)
    • Referencing multiple container images and performing docker compose

Script Step Package References

Package references can be added regardless of whether the script is sourced inline, from a git repository or from a package.

Package reference fields

When adding a package reference, you must supply:

Package ID

The ID of the package to be referenced, or a variable-expression.

Feed

The feed the package is sourced from, or a variable-expression.

Name

A unique identifier for the package-reference. In general the Package ID is a good choice for the name. The reasons the Package ID may not be suitable as the name include:

  • The Package-ID may be bound to a variable-expression (e.g. #{Acme.Package.Id}). Some of the places the name is used are not suitable for variable-expressions.
  • In rare situations it may be desirable to reference multiple versions of the same package. In this case they would need to be given different names.

Extract

Whether the package should be extracted. See below for information on the package file locations. This will not be displayed for certain package-types (i.e. container images). This may also be bound to a variable-expression.

Script Step Package References

Accessing package references from a custom script

Having added one or more package references, it’s reasonable to assume you wish to do something with them in your custom script.

Package variables

Package-references contribute variables which can be used just as any other variable. These variables are (assuming a package-reference named Acme):

Variable name and descriptionExample
Octopus.Action.Package[Acme].PackageId
The package ID
Acme
Octopus.Action.Package[Acme].FeedId
The feed ID
feeds-123
Octopus.Action.Package[Acme].PackageVersion
The version of the package included in the release
1.4.0
Octopus.Action.Package[Acme].ExtractedPath
The absolute path to the extracted directory (if the package is configured to be extracted)
C:\Octopus\Work\20210821060923-7117-31\Acme
Octopus.Action.Package[Acme].PackageFilePath
The absolute path to the package file (if the package has been configured to not be extracted)
C:\Octopus\Work\20210821060923-7117-31\Acme.zip
Octopus.Action.Package[Acme].PackageFileName
The name of the package file (if the package has been configured to not be extracted)
Acme.zip

The following PowerShell script example shows how to find the extracted path for a referenced package named Acme:

$ExtractedPath = $OctopusParameters["Octopus.Action.Package[Acme].ExtractedPath"]
Write-Host "PWD: $PWD"
Write-Host "ExtractedPath: $ExtractedPath"

Package files

If the package reference was configured to be extracted, then the package will be extracted to a sub-directory in the working-directory of the script. This directory will be named the same as the package-reference. For example, a package reference named Acme would be extracted to directory similar to C:\Octopus\Work\20180821060923-7117-31\Acme (this is obviously a Windows directory; a script executing on a Linux target may have a path such as /home/ubuntu/.octopus/Work/20180821062148-7121-35/Acme).

If the package reference was not configured to be extracted, then the un-extracted package file will be placed in the working directory. The file will be named as the package reference name, with the same extension as the original package file. For example, for a package reference named Acme, which resolved to a zip package, the file would be copied to a path such as C:\Octopus\Work\20180821060923-7117-31\Acme.zip (for Linux: /home/ubuntu/.octopus/Work/20180821062148-7121-35/Acme.zip).

These locations were designed to be convenient for use from custom scripts, as the relative path can be predicted, e.g. ./Acme or ./Acme.zip. If the absolute path is required the variables above may be used.

Help us continuously improve

Please let us know if you have any feedback about this page.

Send feedback

Page updated on Wednesday, November 1, 2023