Search code examples
octopus-deploy

How do I prevent users from accidentally deploying to too many tenants in Octopus?


Over the years we’ve had a few instances of Octopus Deploy users accidentally releasing a version to multiple environments, based on a tenant tag.

I usually tell users to check that the Tenant list under ‘Preview and customize’ only contains the 1 environment intended, but we still have some slip through where Octopus deploys to 20+ environments, which I then need to roll back.

Is there a way to alert users when there are more than 1 Tenant in the list, so they can sense check it before proceeding to deploy?


Solution

  • This can be achieved with a PowerShell script, which you add as a deployment step. The script will check for more than one tenant, and alert the user to perform manual intervention if it detects more than 1 target

    To have the script work successfully, you must perform the following:

    • Set a Secret Project Variable named APIKey with the value of an API-Key with access to the deployments within that space.
    • Change the $octopusURL variable in the Script to match your Octopus Hostname.
    • Place the Script at the beginning of your deployment inside a "Run A Script" step.
    • Create a Manual Intervention step as the 2nd process step in your project with the run condition set to: #{Octopus.Action[Run a Script].Output.MultipleTenants}
    • If you decide to change the name of the step that contains the Script below, be sure to place the step name within the square brackets ([]) on the run condition variable.
    $ErrorActionPreference = "Stop";
    
    # Define working variables
    $octopusURL = "http://OctopusURL"
    $octopusAPIKey = "$APIKey"
    $header = @{ "X-Octopus-ApiKey" = $octopusAPIKey }
    $spaceId = $OctopusParameters["Octopus.Space.Id"]
    
    # Get Release Deployment Data
    $releaseData = Invoke-RestMethod -method GET -uri "$($octopusURL)/api/$($spaceId)/releases/#{Octopus.Release.Id}/deployments/" -Headers $header
    
    # Get DateTime of Deployment Created
    $checkDate = Get-Date $OctopusParameters["Octopus.Deployment.Created"] -format "yyyy-MM-dd HH:mm:ss"
    
    write-host "The following tenants are being deployed to at $($checkDate):"
    
    # Instantiate list
    $tenantList = @()
    
    # ForEach Deployment Item inside the Release do the following:
    foreach($item in $releaseData.Items){
    
        # Generate compatible DateTime for comparison with deployment Time
        $date = Get-Date $item.Created.Substring(0,19) -format "yyyy-MM-dd HH:mm:ss"
    
        # Check date equivalence, if equal then do the following:
        if($date -eq $checkDate){
        write-host "The tenant with ID: $($item.TenantId) is included in this deployment at $($date)."
     
        # Add tenant to list
        $tenantList = $TenantList + ($item.TenantId)
    
        # If a release is redeployed, previous tenants may exist in the JSON items, this elseif generates the list of tenants deployed to previously, but not in THIS deployment:
        }elseif($tenantList -notcontains $item.TenantId){
            write-host "The tenant with ID: $($item.TenantId) is not included in this deployment as it was deployed at $($date)."
        }
    }
    
    # Condition check list size, create output variable if more than one Tenant.
    if($tenantList.Count -gt 1){
    Set-OctopusVariable -name "MultipleTenants" -value "True"
    }