Header Right

Main navigation

Rolling Forward Deployment Logic

DeployHub can Roll Your Deployments Forward.

DeployHub uses a rolling forward deployment logic to perform incremental application deployments. I was working with a customer who had an DeployHub issue and since the problem was subtle I thought I’d share the solution in case anyone else stumbles across the same thing.

The Attributes Problem

The user had set up DeployHub as a Continuous Delivery server using the DeployHub Jenkins plug-in. He was using Jenkins to trigger the deployment by calling DeployHub. The DeployHub Jenkins plug-in was setting attributes against the associated DeployHub Component (including the git commit id). The deployment did not involve simply pulling build artifacts from Jenkins and delivering them to the target. The change involved updating a third-party application through its API. So rather than setting up component items to pull the files, the client was using a custom component action to deliver the change. This custom action would then use the attributes associated with the component to drive the delivery process.

Failing a Rolling Forward Deployment

When deploying into an Environment which already had a previous version installed, everything was working fine. However, when deploying into a clean (newly provisioned) environment DeployHub rolling forward deployment was initiated. The deployment was failing because the custom component action was not seeing any of the attributes associated with the component. The attributes were definitely there, so why couldn’t the action resolve them? This had all the hallmarks of a bug in DeployHub.

What was Happening?

The answer is subtle and comes down to the way DeployHub deploys applications and uses rolling forward deployment. When deploying into an Environment, DeployHub looks at the version of the application currently loaded into that Environment and compares it to the one it is about to deploy. It then loops between these two versions, deploying each interim version of the application in sequence.

Note, this is always done regardless of whether any of the interim versions have component items that are marked as being involved in rollup or rollback operations. If component items are marked as being involved in rollup or rollback then those component items are delivered. This is how DeployHub delivers database changes in sequence to roll the database schema forward or backward to the desired version.

If no component items in the component are marked as rollup or rollback then the component is not delivered. When delivering an application with no rollup/rollback components then the application version is not deployed and it looks – to all intents and purposes – as if only the selected application version has been deployed.

But here, of course, there were no component items at all. But there was a component with a custom action.

Looping Through Each Version

So when deploying the application version into an Environment which already had a version associated, DeployHub simply deployed the new one. However, when deploying into a new environment, DeployHub was looping through each version of the application, from the BASE Application to the one being deployed. Normally this would not deploy anything except for the version being deployed and the looping process would be invisible in the rolling forward deployment process. However, since the BASE component (and subsequent components) had a custom action, this action was being executed each time.

The Jenkins plug-in had added the attributes to the latest component version. But when deploying into a new Environment, DeployHub would first try and deploy the BASE application which was associated with the BASE version of the component. It executed the custom action for this BASE component which had no attributes associated with it. So the custom action failed, reporting that the values it was expecting to see associated with the component were not there.

Solution

Once we worked out what was going on, the rolling forward deployment solution was relatively simple. We simply amended the custom action to only execute for the last application version in the loop (i.e.: the one being deployed). To do this, we simply added a conditional statement to the top of the action (an IF statement) and we connected the rest of the action to the TRUE output. The expression was simply:

${dep.last}

This is a boolean flag which is set when the Application Version Loop is on its last iteration (i.e.: it is deploying the actual requested version and not any of the interim versions). If this flag is set, we want to run the custom action. If it is not set, the custom action simply exits.

This fixed the problem.

Conclusion

The user assumed a bug since it was not clear from DeployHub’s output log that it was trying to deliver the BASE component. We may look at improving the feedback here to make it clearer what’s going on. But the flags ${dep.first}, ${dep.last}, ${dep.rollforward}, ${dep.rollback} and ${dep.same} are always set and are available for pre, post and custom actions for both Components and Applications. You can use these flags to determine which application version is being deployed and whether you’re rolling forward (deploying a later one) or rolling back (deploying an earlier one). You can – for example – use these flags to create a custom component action which takes a snapshot of the database when rolling forward (${dep.rollforward} is set) or restores from backup when rolling back (${rep.rollback} is set).