In this post I am expanding on an original question I asked recently where I am looking for an opinionated build/deploy solution. I will provide some context on the software delivery model and tools used today, challenges with it and issues I am seeking to answer.
I live in the backend Java/Kubernetes ecosystem for Cloud/SaaS services so all examples are in context of that world. Tools/frameworks listed are examples only.
There are numerous tools and frameworks that need to be stitched together to perform various necessary steps to deliver a cloud service. I would like an opinionated integration of selected tools and frameworks so that I can follow a pre-defined process that just works without have to glue them together myself.
What do you mean opinionated? I think of it as:
“convention over configuration”
as I first learnt Maven (also see Stack Overflow). There is essentially a “golden path” to using the tool/framework and you are strongly encouraged to follow it. You may diverge but then you are on your own.
Why is it important? It establishes a convention which does not mean it is the “right” or only way but it shows the best practices that are agreeable to most. It also establishes familiarity and shorthand language that practitioners will easily understand even in new situations. For example knowing Maven/Gradle I can goto any project in any company using it and I know how code is organized and you know what I mean if refer to src/test/resources.
Software Delivery Journey
At a conceptual level, as a developer I have the following tasks:
- Write Code — understand the business problem and solve it
- Write Tests — to ensure functional/non-functional success. These are various types of tests like unit, component, integration, end-to-end, performance etc as per the test pyramid
- Deploy — appropriately package all the code and dependencies and make it available in various environments (dev/stage/production or other similar names you may use)
- Observe/Support Environment(s) — monitor/alert/pager duty/debug
These are not necessarily sequential tasks, there is always overlap and let us consider the following simple overlap:
The above conceptual model translates in the following general steps:
Step 1 — Build
This step includes organizing various code dependencies (internal/external libraries and their multiple versions), writing code in some framework, writing unit tests and then finally producing a binary.
For example: Using Gradle with Spring Framework and JUnit tests, doing a code review and producing a Docker image.
In this step Spring Boot provides an excellent opinionated solution. All parts are integrated producing the docker image. One part missing though is the code-review process so depending on your SCM (gitlab, github etc) you need to setup your own merge and gating process.
Step 2 — Verify
This step includes verifying the binary produced in step 1 in the context of the entire system (mocked and/or real) to ensure functional/non-functional success and produce necessary reports (sometimes even just for compliance). The goal is to have higher confidence to release.
For example: deploying a new namespace with new binary along with other dependencies, configuring secrets and running contract tests, e2e tests, manual tests, performance test etc and determine the outcomes.
In this step there is no opinionated solution that I am aware of. You must stitch together your own solution, for example using a CI tool (like Jenkins) along with others like Selenium, Cucumber, JMeter, Sonar, Vault, Jira, Helm, Hoverfly/Wiremock, bash/python glue scripts etc to come up with something that works.
Step 3 — Release
This step includes updating your environment(s) with the binary, running some smoke tests and observing if all is well. It also includes enabling feature toggles if necessary. The goal is to make your software available for use and moving on to the next iteration.
For example: using canary/blue-green or other deployment model to release, observe outcomes and then proceed or rollback.
In this step again you must stitch together your own solution, for example using a CD tool like Spinnaker or even Jenkins along with others like Selenium, WaveFront, Prometheus, Helm, Vault, Jira, bash/python glue scripts, Fluentd to forward logs etc.
What I would like to get to is a state where all the above steps are integrated into a single opinionated stack. This solution dictates the tools and frameworks to use and as a developer I must write my code and various types of tests (unit, integration, e2e etc) in the chosen framework and place them in pre-defined locations. Some configurations necessary would be the location to my git repo, Artifactory, Kubernetes namespace(s) and credentials.
Yes, there will be a trade-off. Using such a system will require following constraints of such a stack but in return a standard operating model can be established across multiple microservices and teams.
An opinionated framework like Spring Boot does not need to end once the jar is created, instead it needs to follow it through the rest of the software delivery journey!
If you have ideas on how to achieve this please share your thoughts and I will be happy to collaborate on open-source projects as well.