Setup continuous deployment for a Sitefinity project
HOW-TO: Setup continuous deployment for a Sitefinity project with Visual Studio Team Services and Octopus
Onze technische blogs zijn in het Engels. Dit doen wij omdat wij menen dat technische kennis van Sitecore en Sitefinity grensoverschrijdend moet zijn. Wij leren veel van buitenlandse developers, wij delen onze kennis ook graag met hen. Mochten er in de code fouten zitten of punten ter verbetering, dan gaan we graag het gesprek aan.
Octopus and VSTS builds are very popular tools these days for automating your .Net based applications deployment. These tools qualify as the missing links between the source control, build- and webserver.
The combination of these tools is able to build your source-code, create packages and deploy them to a target server, and every step in this process can be configured pretty easily.
A big difference with a classic deployment method, is how Octopus deals with your deployment street. After a deployment is tested and accepted, it promotes your deliverables physically to the next-base in your deployment-street and that requires a whole new mindset for structuring your Sitefinity project.
There are endless combinations of possible infrastructure setup but this HOW-TO is based on the following setup:
- VSTS: Git repository
- VSTS: Build definitions
- VS Build server
- On-premise Octopus deploy server
- Azure Cloud Services and Azure databases
Prepare your Sitefinity project for Octopus deployments
When we say “a classic deployment method” at Suneco, we mean the use of code promotion as a branching strategy and using Solution configurations to separate the several environments (dev, test, uat, prod).
We need so say goodbye to the solution configurations where it comes to deployment settings because Octopus deploy promotes a packaged webroot that has been tested or accepted. So how do we establish environment dependent config to work in our setup?
We can manage this by creating nuspec files and associating Azure deployment projects.
There are references to the nuspec files in the build configuration. In the nuspec file we refer to the associated deployment package, and also the ServiceConfiguration config file.
<!-- end of the nuspec file à
<file src="[SomeProject].Website.Deploy.Acc\bin\Release\app.publish\="[SomeProject].Website.Deploy.Acc.cspkg" target="" />
<file src="="[SomeProject].Website.Deploy.Acc\bin\Release\app.publish\ServiceConfiguration.Cloud.cscfg" target="" />
The configuration settings need to be set in the properties of the deployment project. In case of Sitefinity we need to set SitefinityConnectionString that will be processed programmatically. This setting can be controlled in Octopus Deploy as an environment variable to ensure that the package will be deployed using the correct connectionstring.
By default, the connectionstring is set in the web.config file when you have migrated your Sitefinity project to Azure. To override it in code, we create a cutom DataConfig.config file, we inject the connectionstring and we overwrite DataConfig in the AppData folder. This all is controlled with the following code in the global.asax.cs file.
protected void Application_Start(object sender, EventArgs e)
// check for running workerrole
// set connectionstring by reading setting in the deployment project
string connectionString = RoleEnvironment.GetConfigurationSettingValue("SitefinityConnectionString");
string dataConfigText = System.IO.File.ReadAllText(Server.MapPath("/DeploymentConfig/DataConfig.config"));
System.IO.File.WriteAllText(Server.MapPath("/App_Data/Sitefinity/Configuration/DataConfig.config"), string.Format(dataConfigText, connectionString));
When the application starts, Sitefinity will read the connectionstring in the dataconfig, and after that, all the other Sitefinity config will be read from the database.
When there are more environment dependent settings, my advice is to move them to content where this is possible. For instance when you run your Sitefinity backend protected by SSL and you have configured the URL’s for the RelyingParties, then you should move these to settings in the CMS.
So the following code:
<wsFederation passiveRedirectEnabled="true" issuer="http://localhost" realm="http://Environment.url" requireHttps="true" />
<cookieHandler requireSsl="false" />
Moves to the Sitefinity backend settings:
Settings > Advanced > Security > RelyingParties > [set your environment urls here]
This scenario will only work when you have set your configuration to be saved in the Sitefinity database (which is automatically the case when you have migrated to Azure).
Why have we done all this? The build configuration on Visual Studio Team Services will have references to the nuspec file, the deployment package and the deployment config settings.
Configure the build in Visual Studio Team Services
An important step is to set a publish build argument in the build step of the build configuration. This will create the package which is referred in the nuspec files.
Create a NuGet Packager step in the build configuration for each deployment environment, so an UAT and Production package will always be placed. Octopus controls which package will be used on the target environment.
Another crucial step is to publish the package to the Octopus server. You can choose to automate a build on a Git-push action on the master branch, or a scheduled nightly build task or whatever suits best for your situation.
Now all we have to do is setting the SitefinityConnectionString property that we made available in the deployment projects. When a deployment package is promoted to a target environment in Octopus (e.g. UAT > Prod), the proper connection string is pushed with the deployment that will be read by Sitefintiy on the target webserver.
What have we achieved?
We have spared no effort to automatically deploy a Sitefinity website with Visual Studio Team Services and Octopus. A critical note should also be mentioned: Not being able to use the solution configurations like we were used to feels a bit inconvenient. Besides that, we need to set environment settings in codebehind which feels like a step backwards in architecture.
But looking at the goals we have reached, it’s all worth it:
- Continuous deployments saves you time, and ensures that your target server is updated frequently.
- Developer effort is no longer required to do a release. Deployments can now be a responsibility for let’s say a maintenance department.
Yet another step forwards is automating tasks that otherwise would be done by a developer.