Automatically deploying previous successful release

I have a deployment where TeamCity builds and creates Octopus releases. Our deployment process in Octopus then deploys the release, we run some automated regression tests, and that’s it.

What i’m trying to do, but can’t quite figure out how to do, is to also do a rollback if my tests fail.
Has anyone done anything similar or have any tips on how i can have a step that finds the last successfull release for the current environment and re-deploy that release?

Any advice would be much appreciated.

Hi Espeng,

That is an interesting question. It is possible to do that, but you’ll need to leverage the run a script step with Octopus Deploy API. As much as I’d like a step like that to come built-in, automatically re-deploying the last successful release is like “playing with fire.”

You’ll have to contend with triggering the step. In your step that runs the integration tests, I’d recommend setting an output variable at the start. For example:

Set-OctopusVariable -name "RunningIntegrationTests" -value "1"

If the integration tests fail, then at the end of the step make sure to return an exit code of anything but 0. When Octopus sees an exit code of anything but 0 it will think an error has occurred.

The step that will automatically trigger a rollback will need a variable run condition set to:

#{if Octopus.Deployment.Error}#{if Octopus.Action[INTEGRATION STEP NAME HERE].Output.RunningIntegrationTests== ""1""}True#{else}False#{/if}#{/if}

That will tell the step to only run when the integration tests fail.

Finally, here is a sample API script I’ve used in the past on a personal instance. It was for a simple project, it has no tenants, or prompted variables. I haven’t run it in a while, so you might have to fiddle with it a bit.

###CONFIG###

$OctopusURL = # YOUR URL
$APIKey = # YOUR API KEY
$SpaceId = $OctopusParameters["Octopus.Space.Id"]
$EnvironmentId = $OctopusParameters["Octopus.Environment.Id"]
$ProjectId = $OctopusParameters["Octopus.Project.Id"]
$DeploymentId = $OctopusParameters["Octopus.Deployment.Id"]

###PROCESS###

$header = @{ "X-Octopus-ApiKey" = $APIKey }

$progressionInformation = Invoke-RestMethod "$OctopusURL/api/$spaceId/progression/$projectId" -Headers $header

# Uncomment this section to see the entire response, it is quite large

# Write-Host "Progression information is a bit hard to wrap our head around, it would be easier to write it out so we can look at it"

# Write-Host $progressionInformation

$releaseId = ""
$releaseForEnvironment = 0

foreach($release in $progressionInformation.Releases)
{            
    $releaseVersion = $release.Release.Version
    Write-Host "Checking $releaseVersion"

    foreach ($deployEnv in $release.Deployments)
    {                   
        if (Get-Member -InputObject $deployEnv -Name $environmentId -MemberType Properties)
        {                    
            Write-Host "$releaseVersion has been deployed to $environmentId, checking the status"
            $deploymentList = $deployEnv.$environmentId 

            # This release has gone to the environment we are interested in, now let's find the most recent release and check the status on that

            $lastDeploymentIndex = $deploymentList.Count - 1
            $lastDeploymentForEnvironment = $deploymentList[$lastDeploymentIndex]

            $lastDeploymentId = $lastDeploymentForEnvironment.DeploymentId
            $lastDeploymentStatus = $lastDeploymentForEnvironment.State        

            Write-Host "The last deployment id for version $releaseVersion is $lastDeploymentId, the status is $lastDeploymentStatus"                          

            if ($DeploymentId -eq $lastDeploymentId)
            {
                Write-Host "DeploymentId $lastDeploymentId for version $releaseVersion is the current active deployment, skipping"
            }
            elseif($lastDeploymentStatus -ne "Success")
            {
                Write-Host "DeploymentId $lastDeploymentId for version $releaseVersion has a status of $lastDeploymentStatus.  We are only interested in success, skipping"
            }
            else
            {
                Write-Host "DeploymentId $lastDeploymentId for version $releaseVersion is not the current deployment and has a successful status, using" 
                $releaseId = $release.Release.Id
                break
            }                              
        }            
    }

    if ([string]::IsNullOrWhiteSpace($releaseId) -eq $false)
    {
        break
    }
}

if ([string]::IsNullOrWhiteSpace($releaseId) -eq $false)
{
    Write-Host "The last successful release found is $releaseId"

    $bodyRaw = @{
        EnvironmentId = "$environmentId"
        ExcludedMachineIds = @()
        ForcePackageDownload = $False
        ForcePackageRedeployment = $false
        FormValues = @{}
        QueueTime = $null
        QueueTimeExpiry = $null
        ReleaseId = "$releaseId"
        SkipActions = @()
        SpecificMachineIds = @()
        TenantId = $null
        UseGuidedFailure = $false
    } 

    $bodyAsJson = $bodyRaw | ConvertTo-Json
 
    $redeployment = Invoke-WebRestMethod "$OctopusURL/api/$SpaceId/deployments" -Headers $header -Method Post -Body $bodyAsJson -ContentType "application/json"
    $taskId = $redeployment.TaskId
    Write-Host "The previous deployment has been successfully triggered"
}
else {
    Write-Host "No previous successful release was found for this environment"
}

I hope that helps get you started!

Thanks a lot for your answer, Bob. Looks just like what i need :+1:

1 Like

Happy to help!