This is the third part in our examination of dependencies in build and release.
In part two, we looked at how builds often have both source code and dependencies on libraries. A web application might pull in a third party library that provides XML parsing, and a home grown profanity filter.
At deployment time, we’re worried about a new set of dependencies. That web application probably depends on other components in order to function properly. There may be databases, web services, message buses, third party applications, or content that the application relies on in order to deliver correctly.
Test teams are acutely aware of these challenges. They know that once things get serious, they are rarely testing any single ‘build’ but rather a collection of builds, updates and infrastructure.
There are three major strategies that we see for managing these dependencies:
- Minimize: By using interpreted languages like Java, we lessen our reliance on the hardware specifics. Web services can endeavor to maintain backwards compatible APIs. Databases can use expand / contract patterns to support various queries for a period of time. In short, use extra engineering effort to ensure that each component is compatible with a wide range of versions for other components.
- Track: A release manager learns from developers what they believe to be dependent. Release managers then cross-reference deployment requests with the model of relationships they have built and approve only ones that should work.
- Aggregate and Test: When the oral histories used for #2 don’t work, we use integration shakeout environments to validate which set of components actually work well together. We then promote the collection of stuff that passed tests together as a unit. In uDeploy we call this collection a ‘Snapshot’. The DevOps principal of “Infrastructure as Code” is meant to make you think of everything else down to the VM as part of this promotable set.