Octopus - Check Blue Green Deployment

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.

Report an issue

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"
  }
}

History

Page updated on Tuesday, October 14, 2025