Using Kentico CI and Git to help with releases

Iterative deployment of Kentico EMS portal sites can be quite a manual process. If you're not using things like Content Staging then it's likely that you've either got your own special process or that you're using Kentico exports to deploy changes. This tip may help to speed up that process.

Our production team use Kentico's Continuous Integration (CI) for most new projects and each of those projects goes through a daily build pipeline in Team City that is available for anyone on our network to see.  The point of this article isn't how we've set up Team City (that should probably be another post), but us just a reflection on how we've used Kentico CI with Git in our most recent project to streamline live deployments.

The key here is that, while we're using CI, we don't have a continuous delivery (CD) setup; deployments to our UAT and live environments are a fairly manual process. They usually involve a combination of file, Kentico exports, SQL scripts, and manual CMS changes. All of the changes that need to be deployed are collated by the developer doing the release and this is checked by the project lead.

Why did we take this approach?

Before I go into the detail of how this is useful let me tell you why we wanted it.

Kentico export is pretty good at exporting either global or site-specific objects. You can even specify a date and go and get all of the changes that have happened since then. This is great, but only if you want everything. When using Kentico CI, you learn pretty quickly that there are some things that you just don't want to be included. For our most recent project, we wanted to exclude anything that could be considered to be content from the CI pipeline. This was so that our project management and QA team were not constantly frustrated by their nicely curated tests and content being obliterated by hipster-ipsum copy and pictures of cats stealing food (or whatever crazy crap developers used when trying to test that the feature they're working on actually works). Because of this, we had a lengthy period in the project where we were constantly fiddling with the CI configuration to exclude the objects that we did not want to be synchronised.

With Kentico CI, it can be better to specify what you do want, rather than what you don't.

So what did we do?

The short story is that we used the name-only log in Git to tell us which items have actually changed since we last did a release. Preparing backups, release files, and exports are much simpler when you have a definitive list of changes.

The first things that we needed was a list of all of the files that have changed, so we dropped into git bash and came up with the following script:

What this has given us is a list of file and folder named that have been impacted by any commit between to two SHAs. This particular script also takes a copy of the changed files - I found it useful at the time, but we don't really use them any more.

We don't really care about the folder names, so these can be excluded. What we soon found was that - for releases including a large number of changes - cleaning this file up was frankly quite boring. So we created a simple c# script to remove the entries that we don't need.

Once we have a clean text file, we can look through the contents to determine what we actually need to deploy. Most of this is pretty standard, but where we found a real advantage is in preparing our Kentico exports.

The whole file is the loaded into a spreadsheet and we then separated the rows based upon their file type and location. The following list is what we ran (in order) to achieve that:

  • */CIRepository/@global/*:  Each file in this list is used to identify an item to be taken as part of a global export from the Kentico Sites application.
  • */CIRepository/{sitename}/*: Each file in this list is used to identify an item to be taken as part of a site export from the Kentico Sites application.
  • *.xml|*.aspx|*.ascx|*.html: These are individual files that will need to be copied as part of the deployment.
  • *.config: These are individual files that will need to be copied as part of the deployment.

For this article, we're only really interested in the rows that need to be exported, so we can apply a filter on that column to show only the site export and global export rows.  What we are left with is a list of changed files which can be matched up with individual items in the Kentico export tool in the Sites application.

As an example, anything in /CIRepository/@global/cms.pagetemplate be found when performing a global export in the Development > Page templates section.  There are a few exceptions to the rule - things like settings categories don't get exported, so you can ignore things in /CIRepository/@global/cms.settingscategory, but you'll learn those as you go.


We've used this in a single project so far, but it's worked really well. The approach has dramatically reduced the amount of time we spend preparing releases and improved the team's overall confidence in the release process itself. Until we get a CI/CD pipeline that does what we need, I think we'll be using this method to prepare releases and probably working to automate it more. If you don't use Kentico CI to deploy, you can still use it to help you prepare.