The “Accelerate” book by Nicole Forsgren, Jez Humble and Gene Kim identifies 24 key practices and capabilities that characterize high performing teams and organizations. These are the direct result of the State of DevOps research that the authors have led over the past 6 years.
The capabilities are grouped into 5 dimensions:
- Continuous delivery
- Product and process
- Lean management and monitoring
Cultural capabilities are critical for high staff motivation as well as fostering an environment of continuous learning and evolution. Tools can’t change culture directly, although it’s important to consider how different choices might help or hinder collaboration between teams.
In this post, we will discuss how Spinnaker helps support and even nurture capabilities across the remaining 4 dimensions. In particular, we will look at these two practices:
- Version control (“everything-as-code”)
- Trunk-based development
It should be possible to provision our environments and build, test, and deploy our software in a fully automated fashion purely from information stored in version control. (chapter 4)
Version control is no longer just about committing application and test code. High performers understand the importance of treating “everything as code”, from application configuration to infrastructure provisioning, or defining delivery pipelines as code. This is a key enabler for creation of on-demand (ephemeral) environments, testing in parallel (multi-environment), and tracing and auditing changes in production all the way back to version control.
Armory’s Pipelines as Code feature already supports defining pipelines as code with Spinnaker. It relies on JSON configuration files to define pipeline stages, tasks and dependencies. Armory’s Pipelines as Code supports templated stage modules for easier reuse (default values can be replaced in any pipeline module).
Pipelines as code provides the means for repeatable, shareable and automated delivery. But this requires teams to define all the tasks to execute in the pipeline as code as well. In particular, for provisioning resources and environments.
“Following our principle of working in small batches and building quality in, high-performing teams keep branches short-lived (less than one day’s work) and integrate them into trunk/master frequently.” (chapter 4)
The research data from “Accelerate” showed that trunk-based development is correlated with higher delivery performance across industry, organization and team size. So why the reluctance to switch from (long lived) feature or release branches?
Partly because it’s a mind shift, we as engineers are used to work in (semi-)isolation and leave the conflicts (merging) for later. We perceive this approach to be more effective because we repeatedly underestimate the merging and integration testing effort. It’s like driving at 65 mph in a residential area for 10 seconds at a time, then breaking to a halt at the lights. Instead we’d be more efficient driving constantly at 25 mph with smooth breaking when required.
Another reason for reluctance is that it’s much easier to visualize and partition the work in our minds when it’s organized by branches in version control. We feel in control of merge points (and conflicts) and can easily map the branches to sprint and release plans.
Feature toggles is one way to enable trunk-based development, allowing code to be deployed to production in a “switched off” mode (that can be turned on later when the corresponding feature is complete). Although Spinnaker does not have a native mechanism for feature toggles, it does support automated canary analysis (ACA) out of the box. This can help take the “leap of faith” required by trunk-based development.
ACA allows teams using canary releases (exposing a new software version to a small number of users at first, then gradually increasing exposure to all users) to quickly analyse live traffic and assess if there are any problems (Spinnaker also supports rolling back in case of issues). In particular, this means teams can get insights on:
- Are the new (complete) features that got deployed active as expected?
- Are incomplete (under development) features inactive as expected?
- Are previously existing features behaving normally, as before the canary release (no regressions)?
- Are latency, throughput and request error rates for the new version as expected?
Finally, Spinnaker supports traceability of artifacts from production all the way back to source control (which code changes led to building the artifacts that were later released to production). Note that if using Jenkins for CI, the traceability would be to the Jenkins job that triggered the Spinnaker deployment. Jenkins would then provide the traceability all the way to source control.
Also, Armory’s Spinnaker version has a deep integration with JIRA, allowing traceability back to feature/story requests by updating a JIRA ticket with the git commit hash that triggered the pipeline. This allows answering the full question: which features were (at least partially) deployed by version X of this artifact that is running in production?
To be continued in Part 2.