Octopus.Script exported 2025-10-14 by mcasperson belongs to ‘Octopus’ category.
This step checks to ensure that deployments to blue/green environments alternate. The output variable SequentialDeploy is set to True if two deployments are done to the same environment, and False if they are alternating.
A common scenario is to check for SequentialDeploy set to True and display a warning or the manual intervention step to confirm a deployment.
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
The Octopus API key
BlueGreen.Octopus.Api.Key =
Use the documentation at https://octopus.com/docs/octopus-rest-api/how-to-create-an-api-key to create an API key.
The name of the blue environment
BlueGreen.Environment.Blue.Name =
This is the name of the environment in Octopus that represents the blue deployment stack. It will be something like Production - Blue.
The name of the green environment
BlueGreen.Environment.Green.Name =
This is the name of the environment in Octopus that represents the green deployment stack. It will be something like Production - Green.
Script body
Steps based on this template will execute the following PowerShell script.
# We assume that deployments to the production environments alternate between green and blue.
# For example, if the last production deployment was to blue the next one should be to the green environment.
# This check is used to provide a warning if a production environment is deployed to twice in a row.
$octopusUrl = ""
# Check to make sure targets have been created
if ([string]::IsNullOrWhitespace("#{Octopus.Web.ServerUri}"))
{
$octopusUrl = "#{Octopus.Web.BaseUrl}"
}
else
{
$octopusUrl = "#{Octopus.Web.ServerUri}"
}
if (-not "#{BlueGreen.Octopus.Api.Key}".StartsWith("API-")) {
Write-Host "The BlueGreen.Octopus.Api.Key variable has not been defined. We can not validate the deployment environment."
exit 0
}
if ([string]::IsNullOrWhiteSpace("#{BlueGreen.Environment.Blue.Name}")) {
Write-Host "The BlueGreen.Environment.Blue.Name variable has not been defined. We can not validate the deployment environment."
exit 0
}
if ([string]::IsNullOrWhiteSpace("#{BlueGreen.Environment.Green.Name}")) {
Write-Host "The BlueGreen.Environment.Green.Name variable has not been defined. We can not validate the deployment environment."
exit 0
}
$header = @{ "X-Octopus-ApiKey" = "#{BlueGreen.Octopus.Api.Key}" }
# Get environment ID
$blueEnvironmentName = "#{BlueGreen.Environment.Blue.Name}"
$blueEnvironments = Invoke-RestMethod -Uri "$octopusURL/api/#{Octopus.Space.Id}/environments?partialName=$([uri]::EscapeDataString($blueEnvironmentName))&skip=0&take=100" -Headers $header
$blueEnvironment = $blueEnvironments.Items | Where-Object { $_.Name -eq $blueEnvironmentName } | Select-Object -First 1
if ($null -eq $blueEnvironment) {
Write-Host "Could not find an environment called $blueEnvironmentName. We can not validate the deployment environment."
exit 0
}
$greenEnvironmentName = "#{BlueGreen.Environment.Green.Name}"
$greenEnvironments = Invoke-RestMethod -Uri "$octopusURL/api/#{Octopus.Space.Id}/environments?partialName=$([uri]::EscapeDataString($greenEnvironmentName))&skip=0&take=100" -Headers $header
$greenEnvironment = $greenEnvironments.Items | Where-Object { $_.Name -eq $greenEnvironmentName } | Select-Object -First 1
if ($null -eq $greenEnvironment) {
Write-Host "Could not find an environment called $greenEnvironment. We can not validate the deployment environment."
exit 0
}
# Get deployments for the environment and project, excluding the current deployment
$blueDeploymentsUri = "$octopusUrl/api/#{Octopus.Space.Id}/deployments?environments=$($blueEnvironment.Id)&projects=#{Octopus.Project.Id}&take=2"
$blueLatestDeployment = Invoke-RestMethod -Uri $blueDeploymentsUri -Headers $header | Select-Object -ExpandProperty Items | Where-Object { $_.Id -ne "#{Octopus.Deployment.Id}" }
$greenDeploymentsUri = "$octopusUrl/api/#{Octopus.Space.Id}/deployments?environments=$($greenEnvironment.Id)&projects=#{Octopus.Project.Id}&take=2"
$greenLatestDeployment = Invoke-RestMethod -Uri $greenDeploymentsUri -Headers $header | Select-Object -ExpandProperty Items | Where-Object { $_.Id -ne "#{Octopus.Deployment.Id}" }
# This is the first deployment to any environment. It doesn't matter which one we go to first.
if ($greenLatestDeployment.Length -eq 0 -and $blueLatestDeployment.Length -eq 0) {
Write-Host "Neither environment has had a deployment, so we are OK to continue"
Set-OctopusVariable -name "SequentialDeploy" -value "False"
exit 0
}
if ("#{Octopus.Environment.Name}" -eq $blueEnvironmentName) {
if ($blueLatestDeployment.Length -eq 0)
{
Write-Host "We're deploying to blue and there are no blue deployments, so we're OK to continue"
Set-OctopusVariable -name "SequentialDeploy" -value "False"
exit 0
}
# We know we have deployed to blue at least once, but if we have never deployed to green
# then we should not continue.
if ($greenLatestDeployment.Length -eq 0)
{
Write-Host "We're deploying to blue but there are no green deployments, so we should not continue"
Set-OctopusVariable -name "SequentialDeploy" -value "True"
exit 0
}
}
if ("#{Octopus.Environment.Name}" -eq $greenEnvironmentName) {
if ($greenLatestDeployment.Length -eq 0)
{
Write-Host "We're deploying to green and there are no green deployments, so we're OK to continue"
Set-OctopusVariable -name "SequentialDeploy" -value "False"
exit 0
}
# We know we have deployed to green at least once, but if we have never deployed to blue
# then we should not continue.
if ($blueLatestDeployment.Length -eq 0)
{
Write-Host "We're deploying to green but there are no blue deployments, so we should not continue"
Set-OctopusVariable -name "SequentialDeploy" -value "True"
exit 0
}
}
# At this point both blue and green have done at least one deployment. We need to check
# which environment had the last deployment.
$blueLastDeploy = [DateTimeOffset]::Parse($blueLatestDeployment[0].Created)
$greenLastDeploy = [DateTimeOffset]::Parse($greenLatestDeployment[0].Created)
Write-Host "Blue Last Deploy: $blueLastDeploy"
Write-Host "Green Last Deploy: $greenLastDeploy"
# We now check to see if the current environment has had the last deployment. If so,
# we have deployed to this environment twice in a row and we should block the deployment.
if ("#{Octopus.Environment.Name}" -eq $blueEnvironmentName -and $blueLastDeploy -gt $greenLastDeploy) {
Write-Host "The last deployment was to the blue environment, so we should not deploy to it again."
Set-OctopusVariable -name "SequentialDeploy" -value "True"
exit 0
}
if ("#{Octopus.Environment.Name}" -eq $greenEnvironmentName -and $greenLastDeploy -gt $blueLastDeploy) {
Write-Host "The last deployment was to the green environment, so we should not deploy to it again."
Set-OctopusVariable -name "SequentialDeploy" -value "True"
exit 0
}
Write-Host "We're OK to continue with the deployment."
Set-OctopusVariable -name "SequentialDeploy" -value "False"
Provided under the Apache License version 2.0.
To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.
{
"Id": "72db001f-ae7f-4a0f-b952-5f80e2fc4cd2",
"Name": "Octopus - Check Blue Green Deployment",
"Description": "This step checks to ensure that deployments to blue/green environments alternate. The output variable `SequentialDeploy` is set to `True` if two deployments are done to the same environment, and `False` if they are alternating.\n\nA common scenario is to check for `SequentialDeploy` set to `True` and display a warning or the manual intervention step to confirm a deployment.",
"Version": 1,
"ExportedAt": "2025-10-14T06:35:25.515Z",
"ActionType": "Octopus.Script",
"Author": "mcasperson",
"Packages": [],
"Parameters": [
{
"Id": "825689d8-f465-4887-a8fc-b03821c82910",
"Name": "BlueGreen.Octopus.Api.Key",
"Label": "The Octopus API key",
"HelpText": "Use the documentation at https://octopus.com/docs/octopus-rest-api/how-to-create-an-api-key to create an API key.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "b2535aeb-ea47-413b-a387-f2bae47137bd",
"Name": "BlueGreen.Environment.Blue.Name",
"Label": "The name of the blue environment",
"HelpText": "This is the name of the environment in Octopus that represents the blue deployment stack. It will be something like `Production - Blue`.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "7049503a-b6a1-4ba4-b190-55b2f4508d85",
"Name": "BlueGreen.Environment.Green.Name",
"Label": "The name of the green environment",
"HelpText": "This is the name of the environment in Octopus that represents the green deployment stack. It will be something like `Production - Green`.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
}
],
"Properties": {
"Octopus.Action.Script.ScriptBody": "# We assume that deployments to the production environments alternate between green and blue.\n# For example, if the last production deployment was to blue the next one should be to the green environment.\n# This check is used to provide a warning if a production environment is deployed to twice in a row.\n\n$octopusUrl = \"\"\n\n # Check to make sure targets have been created\nif ([string]::IsNullOrWhitespace(\"#{Octopus.Web.ServerUri}\"))\n{\n $octopusUrl = \"#{Octopus.Web.BaseUrl}\"\n}\nelse\n{\n $octopusUrl = \"#{Octopus.Web.ServerUri}\"\n}\n\nif (-not \"#{BlueGreen.Octopus.Api.Key}\".StartsWith(\"API-\")) {\n Write-Host \"The BlueGreen.Octopus.Api.Key variable has not been defined. We can not validate the deployment environment.\"\n exit 0\n}\n\nif ([string]::IsNullOrWhiteSpace(\"#{BlueGreen.Environment.Blue.Name}\")) {\n Write-Host \"The BlueGreen.Environment.Blue.Name variable has not been defined. We can not validate the deployment environment.\"\n exit 0\n}\n\nif ([string]::IsNullOrWhiteSpace(\"#{BlueGreen.Environment.Green.Name}\")) {\n Write-Host \"The BlueGreen.Environment.Green.Name variable has not been defined. We can not validate the deployment environment.\"\n exit 0\n}\n\n$header = @{ \"X-Octopus-ApiKey\" = \"#{BlueGreen.Octopus.Api.Key}\" }\n\n# Get environment ID\n$blueEnvironmentName = \"#{BlueGreen.Environment.Blue.Name}\"\n$blueEnvironments = Invoke-RestMethod -Uri \"$octopusURL/api/#{Octopus.Space.Id}/environments?partialName=$([uri]::EscapeDataString($blueEnvironmentName))&skip=0&take=100\" -Headers $header\n$blueEnvironment = $blueEnvironments.Items | Where-Object { $_.Name -eq $blueEnvironmentName } | Select-Object -First 1\n\nif ($null -eq $blueEnvironment) {\n Write-Host \"Could not find an environment called $blueEnvironmentName. We can not validate the deployment environment.\"\n exit 0\n}\n\n$greenEnvironmentName = \"#{BlueGreen.Environment.Green.Name}\"\n$greenEnvironments = Invoke-RestMethod -Uri \"$octopusURL/api/#{Octopus.Space.Id}/environments?partialName=$([uri]::EscapeDataString($greenEnvironmentName))&skip=0&take=100\" -Headers $header\n$greenEnvironment = $greenEnvironments.Items | Where-Object { $_.Name -eq $greenEnvironmentName } | Select-Object -First 1\n\nif ($null -eq $greenEnvironment) {\n Write-Host \"Could not find an environment called $greenEnvironment. We can not validate the deployment environment.\"\n exit 0\n}\n\n# Get deployments for the environment and project, excluding the current deployment\n$blueDeploymentsUri = \"$octopusUrl/api/#{Octopus.Space.Id}/deployments?environments=$($blueEnvironment.Id)&projects=#{Octopus.Project.Id}&take=2\"\n$blueLatestDeployment = Invoke-RestMethod -Uri $blueDeploymentsUri -Headers $header | Select-Object -ExpandProperty Items | Where-Object { $_.Id -ne \"#{Octopus.Deployment.Id}\" }\n\n$greenDeploymentsUri = \"$octopusUrl/api/#{Octopus.Space.Id}/deployments?environments=$($greenEnvironment.Id)&projects=#{Octopus.Project.Id}&take=2\"\n$greenLatestDeployment = Invoke-RestMethod -Uri $greenDeploymentsUri -Headers $header | Select-Object -ExpandProperty Items | Where-Object { $_.Id -ne \"#{Octopus.Deployment.Id}\" }\n\n# This is the first deployment to any environment. It doesn't matter which one we go to first.\nif ($greenLatestDeployment.Length -eq 0 -and $blueLatestDeployment.Length -eq 0) {\n Write-Host \"Neither environment has had a deployment, so we are OK to continue\"\n Set-OctopusVariable -name \"SequentialDeploy\" -value \"False\"\n exit 0\n}\n\nif (\"#{Octopus.Environment.Name}\" -eq $blueEnvironmentName) {\n if ($blueLatestDeployment.Length -eq 0)\n {\n Write-Host \"We're deploying to blue and there are no blue deployments, so we're OK to continue\"\n Set-OctopusVariable -name \"SequentialDeploy\" -value \"False\"\n exit 0\n }\n\n # We know we have deployed to blue at least once, but if we have never deployed to green\n # then we should not continue.\n if ($greenLatestDeployment.Length -eq 0)\n {\n Write-Host \"We're deploying to blue but there are no green deployments, so we should not continue\"\n Set-OctopusVariable -name \"SequentialDeploy\" -value \"True\"\n exit 0\n }\n}\n\nif (\"#{Octopus.Environment.Name}\" -eq $greenEnvironmentName) {\n if ($greenLatestDeployment.Length -eq 0)\n {\n Write-Host \"We're deploying to green and there are no green deployments, so we're OK to continue\"\n Set-OctopusVariable -name \"SequentialDeploy\" -value \"False\"\n exit 0\n }\n\n # We know we have deployed to green at least once, but if we have never deployed to blue\n # then we should not continue.\n if ($blueLatestDeployment.Length -eq 0)\n {\n Write-Host \"We're deploying to green but there are no blue deployments, so we should not continue\"\n Set-OctopusVariable -name \"SequentialDeploy\" -value \"True\"\n exit 0\n }\n}\n\n# At this point both blue and green have done at least one deployment. We need to check\n# which environment had the last deployment.\n$blueLastDeploy = [DateTimeOffset]::Parse($blueLatestDeployment[0].Created)\n$greenLastDeploy = [DateTimeOffset]::Parse($greenLatestDeployment[0].Created)\n\nWrite-Host \"Blue Last Deploy: $blueLastDeploy\"\nWrite-Host \"Green Last Deploy: $greenLastDeploy\"\n\n# We now check to see if the current environment has had the last deployment. If so,\n# we have deployed to this environment twice in a row and we should block the deployment.\nif (\"#{Octopus.Environment.Name}\" -eq $blueEnvironmentName -and $blueLastDeploy -gt $greenLastDeploy) {\n Write-Host \"The last deployment was to the blue environment, so we should not deploy to it again.\"\n Set-OctopusVariable -name \"SequentialDeploy\" -value \"True\"\n exit 0\n}\n\nif (\"#{Octopus.Environment.Name}\" -eq $greenEnvironmentName -and $greenLastDeploy -gt $blueLastDeploy) {\n Write-Host \"The last deployment was to the green environment, so we should not deploy to it again.\"\n Set-OctopusVariable -name \"SequentialDeploy\" -value \"True\"\n exit 0\n}\n\nWrite-Host \"We're OK to continue with the deployment.\"\nSet-OctopusVariable -name \"SequentialDeploy\" -value \"False\"",
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.Script.Syntax": "PowerShell",
"OctopusUseBundledTooling": "False"
},
"Category": "Octopus",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/a381802920158308/step-templates/octopus-blue-green-check.json",
"Website": "/step-templates/72db001f-ae7f-4a0f-b952-5f80e2fc4cd2",
"Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1QTFRFT6Tl////L5Pg8vj9Y67omsvwPJrisdfzfbzs5fL7y+T32Ov5isLucLXqvt31CJPHWwAABMJJREFUeNrs3deW4jAMAFDF3U75/89dlp0ZhiU4blJEjvQ8hYubLJsA00UCBCIQgQhEIAIRiEAEIhCBCEQgAhGIQAQiEIEIhD8kJm+t+QprfdKfB9HbYpx6CWfspj8HMi+gMgHL/AmQA8W3JTKH+ALFvzCeL0RbpyoCPE9IJeNOSQwh5Z3qd6yRGWQ2qi2cZQWxqj1WzQYSjeoJmJlAklOd4VlArOqPhQEkqBERToeMcfRJBkC0Uep8CfBpjz4JsHJ0zF3dkEWNje0kiB/sUC6eApndaIiCMyAa1PiwJ0AWhRGJHJJQHG2dC7h1rNbO1QOxSA7lNCkkKrQIpJCAB1GREILYIC1NAiwbpKFJgGWDNExcwGstfExcZBCHC6nOglshHtmhViLIig1RNBCN7qjtW8C0Z1UvJcC1Z9XmwMBzzvobmgAyEzgq91dtEEsBsQSQQAFZCSBAATEEEApHZbrVBIkkEIUPSVeB+KtALA0kXQUSrwKZBCIQBnk8Y4i5CsReBeKvkqLM+BCSDWJlrZFvGk9SRTHshkgjZCGAaArIxm3H3grhVzFlW2msfl1ca79UJ1bofYvsDHHlNdTZnlh5MghuPd5NdBDUNZHyCkfktIh03XzALGRPlBDPac7qgWjHZzWcmF5zmmkhidMQ6boKiDXcDTUEaylZqCGJ0Vjvu/fLJtHqhSANEvqb2OYqkOUqEHuVMbJcZdZCGiPhKhC4yjqiIjEE7XThMp8fAWII3mY3kUIQD+AMKQTzPiBhgQ63HlT/KSvgtoi0dq5mCPah1UIE0eh3sT0NhOByvKeAkFzi8PgQomumFhsyOxpIzZN4gLOj5plVwNpR0b2AuePWKBEHQu24pSsJA+LVCeHHQxZ1SiyDIdqok8IOhSSnTottHEQTdyt4ettAj4KkzA4dMikk2Dht2S5ptm1vswnPDxn0YyDZ5oDM3iToo2T5voWaYe+Q+vdjH80QyAzZhCgcDtLMI1Tmtz9w++XHgziHQHJJu/OZ3bs9Xn8gQ72NcP3dKqEfkp10F51xhoIi2I91R+LurXV/5q7pH+wx061CzO16oSQleMyr8fXvwMA0Pro8432DPD/ySx8XrHfSuDAM8n6UhnjQabaiXf5Bq/lREHvEeNtn1rJ08+C/uXkQZHeguxAPC3UvtcJYUogLzZX5hhZZvS6onG5lxXtzWGaygwb79vT/IXhdlNibwlKYOR6T8xjI7W8n+xV7T+GH4tMzWwR+lZhRkJYSsC0thpmCYqyngOz3rN2FLBZ2wZflBCggUHF0Vnp88JKienzIXLSEZCZqU7IKr/gQW9yx3pzV7Y9kvWZWTRRIqDmTtRUnU7b2lLcTYmoqHqnmiO1poER0SPkAeZMAZxaJx0Y3TCdAclsIqDz03ALcyxfTCZBsthoGXWmigGyVhWPLFJJfuuKQWycoEFdXbH4dJJoJxNR1eD/kshz6yn48cF8yW8sFoitflB1w6Q8n+/15Za7oA17/pYNmYgP5fmWm8L1NOHPWgK8kuFew1/JXtOA0yJCv7ah7X8ObUuT5kObU30+fDZm8+zqP+HTIpK0xQ796b5Kv2hSIQAQiEIEIRCACEYhABCIQgQhEIAIRiEAEIpBf8UeAAQAEjtYmlDTcCgAAAABJRU5ErkJggg==",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Tuesday, October 14, 2025