Considerations when setting up a build (migration) strategy
In previous posts, I wrote about migrating builds to TeamCity and after that back to Azure DevOps . Next to that, I talked about "setting up an Enterprise Cake build framework" and getting Cake to work in Azure DevOps (artifacts) to make those migrations easier in an enterprise context, where a lot of build pipelines need to be managed by you and the development teams that you support. In those posts, I mostly talked about the "HOW", but I did not really focus on 2 very important elements:
- the "implementation" part of the builds (The builds themselves, with their "logic"). The idea was that I wanted to help you get started with the "foundations" of centralized approach and the considerations of the migration aspect. I assumed that you would "understand" that there is also (a quite significant amount of) work to be done with regards to get the actual builds running. I will not go into this in this post as it is really specific and dependent on the organization that you operate in...
- The "why" of your story: this one is really important; changing stuff, just for the sake of it has never helped someone. You really need to understand "why" you are doing something and this will guide you all the way...
It is important to note that each and every environment is different and you first need to find out the why behind your "pains" and really try to understand the root cause of your situation. When you have an answer to this, then you most likely will be able to come up with a strategy that gets you from an "as-is" to a "to-be". This strategy will have take into account any number of factors that are important to you, the development team(s) and (of course) the organization you are active in. It is important to understand that your "as-is" will have a very important impact on your "why", but also on your build (and migration) story!
A little framework to get my idea across
There are multiple ways to go from "A" to "B" and one might be more complex than the other. Just starting, without really understanding where you are (what your "A" is), is a useless act and you should be aware of this. (Not knowing where you are can send you on a very long and complex path towards your goal, which you possibly will never reach).
Start by finding where you are and then find out where you want to get to! This is possibly complex and this complexity depends largely on the context/organization that you are active in. To help you define your "A" and your "B", we first need to come up with a framework (you can see it as a map) that will allow you to classify your "current state".
For the definition of this framework, we will work with the following 2 dimensions which will be discussed below:
- custom (a specific build process per product) <-> centralized (templating/build framework)
- use (integrated) platform functionality <-> work with a third party (build runner) that gives you freedom of "easy migration"
Dimension 1: custom vs centralized approach (and everything in between)
For this dimension, I haven chosen the horizontal axis:
In the left hand, you have the "custom" approach (discussed below) and on the right hand, you have the "template based" approach (also discussed below). The idea is that your approach should not be the "one" or the "other". You can perfectly have configurations that sit in the one, and others that sit in the other.
you can work with a "tailored" approach for each build that you are setting up. This gives you (and the development teams) a lot of flexibility. You can set up the build the way you want it and in such a fashion that it helps you to achieve your goal(s). When you need to set up another build, then you start over, or copy what you have as a basis for this new thing you want to achieve. When technology evolves or when there are new needs, then you need to apply (the same changes) in all your builds.
This way of working (WOW) is typically interesting:
- in small contexts
- where you only have a handful (less than 10) of builds to manage and
- where the so called overhead of managing a more "central approach" just isn't worth it...
In the beginning You (and your team), typically go faster, but if the amount of builds grows, then your development speed will (most likely) go down as the overhead om managing the (scattered) builds grows. It is at this moment that you should consider looking at a centralized approach with (most likely) templates...
Centralized (eg: templating)
Once the number of builds increases, you will notice more and more that your changes (and/or upgrades) need to be applied in more and more places. This is typically the moment you will start to have more and more issues with this "custom" approach as you start losing more and more time. An approach that has proven itself over and over again (and not only in DEV environments) is the use of templates. This allows you to centrally define a set of steps that have to be processed in the context of the build process. The idea is that you only need to specify some variables/parameters that the build needs to find your code and/or to know what to do in specific situations. Those variables also allow you to give some kind of "flexibility"
This way of working (WOW) is typically interesting:
- in big contexts contexts with multiple development teams
- where you only have a big amount of (similar) builds to manage and
- where the "central approach" provides structure and more focus for the development teams
Dimension 2: using the built-in platform functionality vs a third party solution (build runner) (eg: Cake)
For this dimension, I haven chosen the vertical axis:
When setting up a build pipeline (in eg Azure DevOps), the platform tries to help to get you started. Azure DevOps (to stay with this example) will analyze your codebase and propose a set of steps. This is particularly useful:
- if you have a small set of builds to manage (cfr. Dimension 1).
- if you can use the out of the box functionality and you don't want/need to do complex things
- when you don't have complex issues in the development team(s() that you are supporting
- when you are perfectly happy with the platform that you are using
Third party solution (build runner)
If you, on the other hand, know that you are in a (less than ideal) situation where your build platform (for whatever reason) cannot support your needs, then you should look ad a (third party) build runner (such as Cake ). It will help you to take the management of your builds (and possibly) the complexity of that management out of your build platform.
There are quite some benefits:
- you can define the build processes on your local machine (and run/debug there too)
- The development teams can better support themselves (when they have issues)
- you can better account for complex (and/or) company specific scenarios (discussed in depth in this post on Cake in the enterprise )
- you will be able to migrate easier to another build platform (if the need would rise for this)
But, ( and there is a big but) be aware of the pitfalls; Working with an additional solution for your build management also means that:
- there is a learning curve
- you need to invest in the support and evolution of what you create
- I mentioned that you can build/debug locally on your development machine; you need to account for the fact that you typically do not want to be able to bypass the build on (secured) build infrastructure. If you create a framework for this, then it needs to be aware!!
Putting it together
Dimensions 1 and 2 result (together) in this classic for quadrant model where there are pro's and con's for each:
I started this post with an elaborate explanation on the idea that you need to find out where you are and where you want to (or need to) be in a given amount of time. This should help you with this. In my experience, quadrants 1 and 3 will be used most in small(er) environments there standardization/industrialization is not a thing (yet). It will give the teams to go fast in their development work as they do not really have to care about the implications for other teams.
Bigger environments will typically be found (hopefully) in quadrants 2 and 4 and depending on the future needs, they might evolve from one to the other or the other way.
Over time, based on the "why", "org size" and the defined trajectory from "A" to "B" organizations most likely will be able to evolve from one quadrant to another and this "map" should at least help you to get started. There is no "ideal trajectory" and I'm not going to impose my opinion here as I am very well aware that an organization needs to be ready for such a change, but most of all: to absorb it. This will (almost dominantly) determine the speed in which you will be able to complete your migration.
"Your" role in this story
One big takeaway that I want to give you from my own experience is that you (as an architect) typically have figured out everything (the "A", the "B", the strategy, etc.) way ahead of the users/teams/organization that you are supporting. This also means that you have work to do with regard to "getting your ideas over to your users" (evangelization), but also to make it digestible to them. The change (roadmap) that you envision might be very big and not really feasible to roll-out at once. Therefore, you will have to work your "stakeholder management" skills! To make it digestible for you, I split it up a bit:
- Strategize: It is your job to think about (most of) the before anyone else does. The better you do your job, the easier everything will be 😉 (And no, I'm not referring to a waterfall approach: And it's a fact that you can't have all the answers up front, but be sure to have a good understanding of the core principles, the main goal and the overall direction)
- Impact: Think about the impact that you want to make; will it improve the lives of your (end-)users? How much time will you (potentially) save (overall)? (Time is not the only metric, but always gives an idea)
- (Your) patience is key": This means that you most likely will have to separate such a transition in phases that have to be digestible by your users and organization.
- Be agile: whatever you provide will most likely have to change/evolve as you migrate more and more builds (there is always something ultra-specific, trust me on this one!). Be ready for this change and (most of all) do not resist it!
- Understand the notion of an adaptation curve: You will need to ensure that you leave no one behind! You will have enthusiasts and early adopters that will be ready when you are, but the contrary is also true. There are "laggards" that will only migrate when they really have to. (And this typically has to be done when you are already working on the next thing)
- Tooling: Your role is to make this migration as smooth and easy as possible (for the end-user). (This can be in the form of tooling, processes or whatever works for you.)
- Facilitate: Be ready to facilitate as much as possible. When the user gets to that point when he/she/x is ready to do what you asked them to do, then you really want to make sure that it goes super-smooth and if that means that you need to invest some (additional) time, then so be it. That time can be used for helping, but also for yo to learn and to improve the process for the ones that need to migrate next.
- Document: You will most likely initiate a change and you will have to be ready for a lot of questions: I can tell you (from experience) that it is a lot easier to answer a question with a pointer to an answer than having to write it out over and over again. (This doesn't mean that you have to be a wise-ass and go "RTFM " against your users 😃)
My main takeaway; Be ready to be in it for the long run: this means that you need to approach it as an evolution (which might take a long time) as you can not always (for several reasons) approach it as a revolution. Ignoring this aspect will give you some (personal) speed in the short term, but you will loose "the long term support of your users" and this is far worse! (Never forget this)
This post has been a long one that concludes (for now) this series on build (migration) management. I really hope that you like(d) it and that I could provide you with some insights in what I do from day to day. I understand perfectly that this is a topic that is a bit out of your own context of your personal context are not always evident in a somewhat bigger context. I can really go on about this for days and tried to squeeze it in a few posts...
If you want to read more, then I really encourage you to check out the following links:
- Migrating your builds to TeamCity
- Dealing with error TF401019 when using submodules in Azure Pipelines
- Extending build.cake with your (enterprise) functionality
- Automatically migrating your builds to Azure DevOps
- Running Cake in Azure Pipelines and accounting for optional build-process-variables
- Running a build in Azure DevOps with Cake and Azure Artifacts
ps: The thumbnail drawing in this post is drawn from the bikablo publications, www.bikablo.comcomments powered by Disqus