A couple of weeks ago I had the chance to speak at the Sitecore Technical User Group in Manchester. I gave a talk about experiments into how you can put Sitecore into a NuGet package in order to create low-effort developer instances. Due to time constraints I wasn’t able to get all of the information I wanted into the presentation, so over the course of my next three posts I plan to write up the key info from the presentation with that extra detail.
After many years, I’ve finally decided to start moving off WordPress and onto a blog I host myself. This post is now available at “https://blog.jermdavis.dev/posts/2015/nuget-for-dev-instances-1“. Eventually this version will be retired so please update links on any sites you control, to avoid 404s in the future.
A little background
Some time back there was a bit of debate inside the company I work for about possible better approaches for creating development instances of Sitecore. As we found ourselves working for more clients, and those clients wanted more parallel bits of work, the setup of developer instances of Sitecore was becoming more time consuming. We talked about many of the common approaches to automating this sort of setup, but one of my colleagues suggested the idea packaging Sitecore with NuGet. It seemed like an idea that was worth some investigation to see how it might work in reality.
Having spent a bit of time investigating how the process might work, it seemed worth sharing our findings – so hence the talk.
Building NuGet packages isn’t hard, and can be done via
.nuspec files and some command line tools if you like. However there are also some helpful Visual Studio extensions such as NuGet Package Project that you can use. If you install this into your copy of Visual Studio you get a new project type for “NuGet Package” and some build automation that transforms the files in your project into a package for you.
Big picture it’s pretty simple to put Sitecore into a NuGet package. You have to:
- Get an appropriate version of Sitecore
- Optionally start up Sitecore and do any customisations you want to go into the package – like installing modules for example
- Organise the files into the right structure for a NuGet package
- Modify a few files to make things work correctly
- Build the package
- Publish the package for projects to consume
But there are a couple of decisions about how you want your package to work that need taking before you start.
The first is to do with how much of Sitecore you want to end up in the target development project, and hence how much of it you want committed to source control. A simple package could just include all of the files required for Sitecore to run into the “content” of the package so they would be added to the target project. (And hence end up in source control) Whilst this works, I’m not a fan of having any bits of Sitecore that I’ve not modified as part of my work included in my project. Hence I looked into approaches to try and avoid this situation. The way that seems to have worked best for me is to add the Sitecore files to the package in a way that means they will not be added to the target project file but then use a bit of PowerShell script to ensure that these files are copied to the target project’s folder for use at runtime. More detail on this later.
The second is how you want to deal with accessing the Sitecore databases. The approach that my colleague suggested for this was to make use of LocalDB and its ability to attach databases when they are required by a project. This is quite a simple solution and makes for well isolated development instances – but it may not be suitable for all. Alternatively you can use further PowerShell script to attach the databases to a full instance of SQL Server at the point you install the package.
The third issue is how you’re going to publish your package when you’re done with it. As I mentioned in my previous post about NuGet for referencing Sitecore DLLs, you should not publish theses packages publicly for licensing reasons. Hence you should create yourself a private feed to publish to. I’ve just used a simple “file system share”, but you can also install web apps to replicate the full NuGet.org experience if you wish. Read more on that subject here.
The version of Sitecore
The simplest way to grab a version of Sitecore and start working on your package is to download one of the “zip of web folder files” versions of Sitecore. You can just unzip these files and move on with the process.
But as mentioned above, you might want to have modules or content installed into Sitecore before you package it. In this case it’s probably simpler to install a copy of Sitecore via your favoured route, add your content or modules and then move onto the packaging phase with these files and data. You will need to remember to do stuff like detaching databases before moving stuff about for packaging.
My experiments into this process used Sitecore 6.6 as that’s the version I’m using in my day-to-day development. However the same process should generally work with other version. Though V8 will require some extra work to deal with MongoDB.
Creating the base package project
Use the NuGet Package extension in Visual Studio to create yourself a new package project. The file names aren’t important – but they should reflect what it is you’re packaging. Remove the readme file that’s there by default, and then create the set of folders that we’ll sort files into. You need to create:
- A “Content” folder which will hold the files that will be added to the target project
- A “Lib” folder which will hold any binaries that you want to be references of the target project
- A “Tools” folder which will hold the PowerShell scripts for the package install process
- And a “SitecoreFiles” folder which will hold all the files we need for Sitecore to run that we don’t want to add into the target project file
Your solution explorer should end up looking like:
Then you can set the properties on your project. The NuGet Package project properties dialog lets you set the metadata for your package, as well as some settings relating to building it for you. The key ones to look at are:
- Package ID
- Package Version
- Title, Summary, Description
- Icon and URLs
- Generate Symbol Package
- No Package Analysis
The package ID you choose needs to be suitably descriptive and unique for the work you’re doing. I’ve found the version number needs to reflect both the revision of Sitecore you’ve packaged and the version of your package definition – in case you need to modify the package to add an extra file for example.
The titles and summaries etc need to be suitably descriptive so that people looking at your package feed understand what they’re downloading. And you can add a package icon URL or links to further information as well if you wish.
You should turn off both Symbol Package Generation and Package Analysis. You’re not building any code in this package, so there’s no need to have a separate debug symbols package for it. And if you leave Package Analysis on you’ll get a load of warnings later in the process because we’re going to include binaries in our project that aren’t in the Lib folder.
As a rough example, your properties might look a bit like this:
Adding the Sitecore files
You now need to add the Sitecore files into the package data. This is easiest to do via Windows Explorer rather than Visual Studio. The steps are as follows:
- Move all the files except the web.config from the Website folder of your Sitecore zip/instance to the “SitecoreFiles” folder of the package
- Create an “App_Data” folder under “SitecoreFiles” and move all the SQL Server database files into it
- Move the Data folder of your Sitecore zip/Instance to the “SitecoreFiles” folder of the package
- If there are any Lucene indexes under the Data\Indexes folder, delete these indexes
- Work out the set of binaries that you want to be references when you install your package into a project. Copy these binaries from the bin folder in your “SitecoreFiles” folder to the “Lib” folder.
- Move the web.config skipped over in #1 into the “Content” folder of your package project.
Next, you need to organise the rest of the files in the package.
I’ll cover that in my next post.