We build container images on different OS versions. We support the latest Windows Server LTSC (ltsc2019) as well as two semi-annual versions (currently 2004 and 20H2). We also build certain Sitecore roles on Linux!
In a semi-related post 'Walkthrough: Add Parallel Build Power to your Azure Pipelines with Virtual Machine Scale Sets' I provided the (very detailed) steps required to set up Azure Pipeline agent pools backed by virtual machine scale sets on different OS versions, including Linux.
This post assumes that you have Azure Pipelines agent pools with different OS versions (not necessarily running on VMSS though).
The Matrix Strategy
Initially we set out by building the images consecutively, that meant that for every OS we wanted to build, we had to wait for the previous one to complete. If you've waited for a 30 minute build to complete only to find out that the 3rd stage failed, I feel your pain.
When you're done with this post, take a look at the Azure Pipelines yaml schema reference, in particular the Matrix Strategy. You can use this strategy for a lot more than what I'm writing about today!
The idea, run the same pipeline job steps against different OS versions, at the SAME time!
The syntax for this is pretty simple (and powerful). You define a job (Build_Platform in our case) and you want to run that job, with different variables, in parallel. That's it, really.
You can see in the following snippet that we labeled 3 keys:
Under those keys, we declared 3 variables which are specific to the key:
poolName: name of the agent pool that will run the job.
osVersion: variable which specified which base container OS (windowsservercore) we're building on.
nanoserverVersion: specifies which version of nanoserver we're using.
In my previous VMSS post I mentioned that you should try to name your agent pools using a specific naming convention, this is where it becomes important as it makes it much easier to trace things around when debugging.
1jobs: 2 - job: Build_Platform 3 strategy: 4 matrix: 5 windows2004: 6 poolName: "docker-2004-agents" 7 osVersion: "2004" 8 nanoserverVersion: "2004" 9 ltsc2019: 10 poolName: "docker-ltsc2019-agents" 11 osVersion: "ltsc2019" 12 nanoserverVersion: "1809" 13 20H2: 14 poolName: "docker-20H2-agents" 15 osVersion: "20H2" 16 nanoserverVersion: "20H2" 17 displayName: "Build Windows Docker Images" 18 pool: 19 name: $(poolName)
The other important portion of the snippet is the fact that we're now able to specify the pool
$(poolName) variable which we set in the matrix.
The above is now configured to run this job concurrently across different agent pools (depending on your Azure Parallel job licensing).
That's it, really. There's no magic. Well, it feels like magic! You can run the same job steps, with different values, against different agent pools in parallel!
You can find examples of how we're using the matrix strategy across many of our repositories: