A better Sitecore Developing experience -Configurations
A big grief for me when working with Sitecore has always been the way, transformations are handled. Generally, the fact that you need to clutter your solution with build configurations for each environment is a pain. Especially when dealing with cd-cm solutions. So, when we decided to use Octopus Deploy, I felt it was time to find a solution that plays nicely with Octopus.
If you just want to have a look at what the scripts and MSbuild files look like, you can head over to bitbucket and have a look at it here: https://bitbucket.org/csindberg/build-tools/src
Requirements of the solution
Before starting any task, I always like to define the requirements of the solution, and here is what I came up with:
1. The result package from my build server needs to contain transformation files for all environments.
2. I want the scripts Octopus Invokes to be solution specific. Customers solutions and environments differ!
3. I want actual MSbuild builds [JRR1] to execute quickly! Nothing is worse than trying to do TDD when build times are slow.
4. I want complete control over the transforms.
5. It needs to be easy for new developers to pick up and work with.
6. Since I have picked up Rider, I want it to work in both VS2017 and Rider.
To accommodate these requirements, I decided to go for a publish approach. When doing the publish locally, we will use the same process as we use when Octopus is deploying on the other environments. The scripts run locally, will need to be packaged and used by Octopus as well.
This means that locally, I publish changes to a folder. This entire process will be a bit heavy for a single blog post, so I’m going to be splitting this process into multiple blog posts. This first post, is going to be focusing on the Config transformations.
First things first. We need to figure out what we want our transformation files to look like. The usual problem with transformations in Sitecore projects are:
1. Transformation files in Sitecores include folder are included by Sitecore at runtime. This is usually solved by renaming the transformation files “.transform” or something else, since Sitecore will not include them unless they are named “.config”
2. You can’t have transformations that transform the base file, since the transformation would change the base file and be committed to source control.
3. You need a build configuration in your solution to match each environment. Also, you need two per environment if you are using content delivery. (Since you have a cd and a cm server per environment.)
4. You can’t have multiple transformations on files. For example, I might want a “cd” to be transformed for all cd environments, as well as the environment specific transformations. Or for example, for a content delivery test environment I might want to have the following transformations run: “all,test,test-cd,cd”
Since I want to be able to transform the base file and not have the result committed to source control, I cannot do the transform on the actual files. This means we need the result of the transformation to be in another folder. So, I decided on a publish approach. This means that when I have made my changes, I will publish the website to another folder. Leaving the base files all intact.
I need the solution for transformations to be part of source control, so I can use them when deploying with Octopus. Therefore, I use powershell. I set out to create a script that given a folder would transform config files based on a list of names. This means I could invoke the script with a list of config names like “all,cd,dev,local”. This would transform all the files named “*.all.config”, “*.cd.config”, in the order given in the list. This gives full control over which transformations to invoke, and makes it easy to control from Octopus. Since, we are just invoking a script with different parameters, I think we are on to something here.
The script responsible for handling these transforms is linked below. What it does, is looping the transformation names and find the transformation files that match below a given folder. Then it uses a “Microsoft.Web.XmlTransform.XmlTransformableDocument” to do the transform. The script takes a path from which to evalutate transformation files recursively and the names of the transform targets. (Remember the “all,cd,dev,local” list?)
Obviously, we also need to clean up on the transformations after we are done. Therefore, we need a script that cleans up in the transformation files. The script basically just looks for files containing the namespace ”http://schemas.microsoft.com/XML-Document-Transform” and deletes them.
I have also included a FeatureTransforms script that allows you to transform the web.config with transform files placed in a folder. (In this case a folder named “App_Config\Impact”)
Using these transformation scripts, we are left with a folder that only contain the actual config files with the transformations applied to them. We control which transformations to process and we can process multiple transformations per file.
In the next blog post, I will have a look at the file publishing part of the build that will allow us to actually use our transformation scripts. Hope you enjoyed this, and I would love your input and improvements.