Building a Continuous Integration Environment for Sitecore Part 2 – Octopus Deploy

This is part 2 of the series of post that I am doing about building a Continuous Integration Environment using Sitecore, TeamCity, Octopus Deploy, and Unicorn.

Part 1 – Setting Up TeamCity
Part 2 – This post
Part 3 – Setting up SQL Server for Sitecore
Part 4 – IIS
Part 5 – Octopus Environment and Deployment Configuration
Part 6 – TeamCity Project
Part 7 – OctopusDeploy Project
Part 8 – Sitecore Item Synchronization using Unicorn
Part 9 – Displaying Build number on Sitecore Home Page & Tagging Git
Part 10 – config transformations using Octopus Deploy
Part 11 – Deploying to a Sitecore Multi-Instance Configuration


Just a quick reminder

All the servers are running Windows Server 2012 R2.All the servers are stand alone, and are not part of a domain. All servers have C and D drives.

Everything that is documented here and on subsequent posts are based on freshly installed Windows Servers.

As detailed in part 1, you will need to modify the Local Security Policy so that password don’t expire after 42 days

Getting Started

Before starting download the following software. It will be used during this setup

Create the following drives as they will be needed later

  • D:\SQLBackup
  • D:\SQLData
  • D:\Octopus
  • D:\Tools


SysInternals Handle

This is handy little utility that is used to release locks on files. Previousy I have experienced problems whereby even if stopped the AppPool and an IIS Site, locks where still being held on files, and you could not do a deployment. Using this utility it would force all handles that are still open on a file to be closed. It will be used later as a deployment step with Octopus. For now just Extract the downloaded zip file to D:\tools\Handle

Sidewalk Package Installer

This handy utility on GitHub allows you to install Sitecore Packages from the Command Line. Perfect for when you want to automatically deploy using powershell. However you do need to do a bit of work in that you need to clone the repo and build the executable using the correct Sitecore dll’s as the sitecore solution you want to deploy. After that is completed just copy the bin folder. As I am using a solution Sitecore 7.2 I copied the binary to D:\Tools\SidewalkPackageInstaller.7.2

System Accounts

As with TeamCity, I want to ensure that Octopus runs under an Administrator account

From Control Panel select User Accounts | Manage another Account


Click Add a user Account


You can pick whatever name you want, but I decided on TeamCity-Admin.
For the password, I used to generate a strong password.


Once the account has been created, click on “Change the account type”


Change the account type to be an Administrator, and click the “Change Account Type” button

All Network Access

I have found that if you do not allow Network Access, you will experience all number of weird and wonderful errors messages when trying to get Octopus and TeamCity communicating. Therefore from Control Panel, run Network and Sharing Centre | Change advanced sharing settings


For All Networks select
Select Turn off password protected sharing

Save changes

SQL Server

For this, I am going to be using SQL Server Express. What version you eventually end up using should have no impact on Octopus

From the software downloaded, run SQLEXPRWT_x64_ENU.exe


Select New SQL Server stand-alone installation or add features to an existing installation


Accept the license terms and click Next


Accept default to include SQL Server product updates, and click Next


Let the SQL Server setup files install


For Feature Selection leave as default, click Next


Leave instance configuration with default options and click Next


Change the SQL Server Browser to Automatic Startup Type.
Leave the collation as default.

Click Next


I prefer mixed mode instead of only Windows authentication mode. Generate a secure random password to be assigned to the SA account. Click the Add button as want to add the OctopusAdmin account created earlier as an administrator account

Switch to Data Directories tab:


Set Data root dictionary, User database directory, User database log directory, Temp DB directory, and Temp DB Log directory to D:\SQLData
Set Backup Directory to D:\SQLBackup


No changes are necessary on the User Instances tab


No changes are necessary on the FILESTREAM tab. Click Next


Click Next to install SQL Server


Allow SQL Server to complete installation


Click Close

Run SQL Management Studio

Log in using either Windows Authentication, or using the SA account

run the following SQL script

    NAME = N'OctopusDeploy', 
    FILENAME = N'D:\SQLData\OctopusDeploy.mdf' , 
    SIZE = 256000KB , 
    FILEGROWTH = 51200KB )
    NAME = N'OctopusDeploy_log', 
    FILENAME = N'D:\SQLData\OctopusDeploy.ldf' , 
    SIZE = 102400KB , 
    FILEGROWTH = 10240KB )


As this is going to be used for deploying Sitecore solutions, and Octopus is designed to work with NuGet packages, I needed to create a NuGet packages for the version of Sitecore I am using to be using.

I have looked at the Sitecore Instance Manager but that solutions does not work with the way that I want to.

So what I am doing may involve some extra work, but I am happier with how it works in my environment. Feel free to disagree in the comments.

Download the version of Sitecore you are working with. 8.0 and above, download from and for versions prior to 8.0 download from

Just remember, only a Certified Sitecore Developer will be able to access these sites and have the ability to download files.

Download the zip file of the relevant version of Sitecore, and extract the zip file to a relevant location on disk. e.g. c:\inetpub\wwwroot\

For the project I am working on that is based on currently using 7.2 rev 140526

The Sitecore password recovery page has hard coded values as to who the email is from. When I am deploying Sitecore using Octopus I want to replace this during the deployment process. Therefore the following need to be done
Open file \sitecore\login\passwordrecovery.aspx
Replace with #{email.from}

#{email.from} will be defined as a variable within an Octopus project, and will be replaced during the deployment process. I will detail how this is done.

Now its time to build the NuGet package.

Build NuGet Package

I have tried in the past to create a NuGet file using a simple .nuspec file, but Sitecore has empty folders defined within the blank solution, and there is no easy way to ensure that blank folders are created, so I have found that the quickest way to create Nuget files is to run the NuGet Package Explorer.


Once the app starts, click Create a new package


Select Edit | Edit Metadata


Configure the metadata as required but I usually set the Id to the version of Sitecore, and the Version to the Actual version. Therefore Sitecore_7.2_140526 and 7.2.140526 respectivelty and a description of Vanilla Sitecore Website

Click green tick to save the Metadata


Once back to the main editor, select Content | Add | Existing File


From Windows Explorer, navigate to the folder where saved Sitecore, and select all files within the Website root. Drag and Drop all files onto the Package Contents on the NuGet Package Explorer. This may take several seconds to complete. You will get a warning about including files in the package root.


Ensure that “Do this for the next 6 file(s)” and click No

Select File | Save.

Keep the default name, but make a note of where the file is created, as this file will be uploaded to Octopus in later steps.

This step will take some time to complete.

Install Octopus

Run the Octopus installation exe that was downloaded previously. At the time Iused Octopus.3.3.1-x64.msi


Click Next


Accept the License Agreement and click Next


Use the default folder and click Next


Click Install.


Once the installation is complete click Finish

The installation will verify that the prerequisites required are installed


And present you with the Welcome screen


Click “Get Started”


Enter your details to start a free trail. Don’t worry you can continue to use Octopus after 45 days. You only need to pay for a licence when you reach a threshold of projects

Once complete click Activate. You will need to use a valid email address as Octopus will send you a licence key to that address


Change the Home directory to D:\Octopus, click Next


Use a Custom Domain Account, selecting the Administrative user created earlier. The wording is misleading you can use a local account with no problems.

Click Next


To select the SQL Server instance created earlier, click on the server name drop down and it will be discovered automatically. Once it has selected the server, click the database drop down, and select the database created during the installation of SQL Server

Click Next


Leave the default port as default value of 80 and click Next


Change the authentication mode to Username/passwords stored in Octopus, and then create a new user. To keep consistent I created Octopus-Admin account. Ensure you create the account using a strong password

Click Next


Click Install

If you want you can clock on Show Script and Octopus will show you the powershell script that I will be using

Wait until the installation is completed, and click Finish


The Octopus Manager should start automatically.


Just click “Open in browser”


Community Edition

Now that Octopus has been deployed its time to switch it to the free Community Edition

Select Configuration | Licence

Select “I want to the use free Community Edition”


Click Save

Additional Users

As with TeamCity I don’t want to use the Administrator account for day to day work.

Select Configuration Users


Insert details and click Create User


The user account just created still needs to be configured

Select Configuration | Teams


Click Octopus Administrators


Click Add Members


Start typing in the name of account you created. Once the account has been selected click Add


Once back on the Teams configuration, click Save

Api Key

As we will need to push to Octopus, the artifacts that TeamCity produces, we need to create an API key

Select User | Profile API Keys


Click New API Key


Enter the purpose of the API Key. I entered “For TeamCity to push packages for deployment”

Click Generate new


Make a note of the key as it will be required later. Be aware of the warning from Octopus that keys cannot be retrieved once they are created.

Click Close

Global Library Packages

As I have continually mentioned I am building all this for Sitecore solutions. Now its time to add in the Sitecore NuGet package created earlier to the Octopus’s built in package repository.

Select Library | Packages


Click on Upload Package


For Choose file select the Sitecore nupkg file that was created earlier

As this is the first time that this action is being performed you don’t need to tick Replace this version if it exists

Click Upload

Next Image shows the package successfully uploaded into Octopus


Global Variable Sets

Select Library | Variable Sets

As detailed Variable sets are collections of variables that can be included in multiple projects.


I use this to store paths for tools / utilities that will be needed for all projects.

Click Add variable set


For the Name, External Software Path, and for the Description, you can enter what is relevant


Click Save

This will take you to where you can define the variables to be used within the set


Click within the name to create a new row

The variable I want to create is to the path for the SysInternals tool handle.exe which can be used to free any locks that are on a file, The Sidewalk Package Installer which can be used to install Sitecore packages from the command line, and MicroChap, which is used by Unicorn for authentication


Variable Name Variable Value
handle.path D:\Tools\Handle\handle.exe
SidewalkPackageInstaller.path D:\Tools\SidewalkPackageInstaller.7.2\Sidewalk.SC.PackageInstaller.Client.exe
MicroChap.path D:\Tools\UnicornSync\MicroCHAP.dll

None of the values needed to be limited in scope

Step Templates

Octopus has the Community Library and I want to install several libraries that are supplied by the community

When you first visit the site, it will list all current contributions


To select for a script, just type away, and the list will be automatically filtered

This is the page when filtered for “iis apppool – start”


Its extremely simple to install a script. After filtering and finding the script you want, then click on it to description page. All sample screen shots are from IIS AppPool – Start script


Click Copy to clipboard

Within Octopus, to go Library | Step templates, and click Import.


Just paste the contents of the clipboard into JSON Object


Click Import


You are presented with the standard Step template dialog. Generally there is nothing that needs to be altered, so just click Save

For my solution, I imported the following step templates from the community

  • IIS AppPool – Stop
  • Variables – Substitute in Files
  • File System – Create Folder
  • IIS Website – Create
  • IIS AppPool – Create
  • Windows – Ensure Hosts File Entry Exists

Custom Step Template – Close Process

As mentioned earlier, I have witnessed previously where even after stopping a website and the AppPool, the O/S is still keeping locks on files within the site. The only way to solve this is to force the release as the O/S will keep the files in a locked state until a reboot. So this script will be used to force all open handles on any file within the deployment folder to be released

From Library | Step Templates, clck Add Step Template


From the Choose step type dialog, click Run a Script

This will take you to the Setting of the Step template


I just gave this a name of Close process locking deployment folder

Switch to the Step

The script source should be Source code, and the script is a powershell script

$pathToHandle = $OctopusParameters['handle.path']
$pathToWebsite = $OctopusParameters['rootFolder']

#Make sure handle is registered before using it
& reg.exe ADD "HKCU\Software\Sysinternals\Handle" /v EulaAccepted /t REG_DWORD /d 1 /f

$data = (& $pathToHandle $pathToWebsite)
$lenData = $data.Length - 1

for($index = 5; $index -le $lenData; $index++) {
	#split data ignoring blanks
	$splitData = $data[$index].ToString().split(": ") | where {$_ -ne ""}
	#get process id for each open file
	$procId = $splitData[2]
	#get hex data for each open file
	$hexId = $splitData[5]
	#close the file if any
		(& $pathToHandle -c $hexId.toString() -p $procId.toString() -y) #|out-null
	write-host $hexId


Click Parameters


Click Add parameter


Variable name: rootFolder
Label: Folder where deploy website

Click Apply


Click Save to save the template

Here is the json package to easily import

  "Id": "ActionTemplates-1",
  "Name": "Close process locking deployment folder",
  "Description": null,
  "ActionType": "Octopus.Script",
  "Version": 2,
  "Properties": {
    "Octopus.Action.Package.NuGetFeedId": "feeds-builtin",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.RunOnServer": "false",
    "Octopus.Action.Script.ScriptBody": "$pathToHandle = $OctopusParameters['handle.path']\r\n$pathToWebsite = $OctopusParameters['rootFolder']\r\n\r\n#Make sure handle is registered before using it\r\n& reg.exe ADD \"HKCU\\Software\\Sysinternals\\Handle\" /v EulaAccepted /t REG_DWORD /d 1 /f\r\n\r\n$data = (& $pathToHandle $pathToWebsite)\r\n$lenData = $data.Length - 1\r\n\r\nfor($index = 5; $index -le $lenData; $index++) {\r\n\t#split data ignoring blanks\r\n\t$splitData = $data[$index].ToString().split(\": \") | where {$_ -ne \"\"}\r\n\t\r\n\t#get process id for each open file\r\n\t$procId = $splitData[2]\r\n\t\r\n\t#get hex data for each open file\r\n\t$hexId = $splitData[5]\r\n\t\r\n\t#close the file if any\r\n\tif($hexId)\r\n\t{\r\n\t\t(& $pathToHandle -c $hexId.toString() -p $procId.toString() -y) #|out-null\r\n\t}\r\n\twrite-host $hexId\r\n}\r\n"
  "Parameters": [
      "Name": "rootFolder",
      "Label": "Folder where website deploy to",
      "HelpText": null,
      "DefaultValue": null,
      "DisplaySettings": {}
  "$Meta": {
    "OctopusVersion": "3.3.1",
    "Type": "ActionTemplate"

This step will use the handle.path template defined in the global Variable set, and rootFolder which you will configure when the step is used within a deployment process

Custom Step Template – Deploy Base Sitecore Website

This step is used to deploy the base vanilla Sitecore NuGet package that a deployment uses. When it is being used the deployment process will need to supply the version number of the Nuget package to be deployed

  "Id": "ActionTemplates-21",
  "Name": "Deploy Base Sitecore Website",
  "Description": "Deploy Vanilla Sitecore site, as supplied from ( Sitecore v8 or above ) or ( Sitecore 7.5 or below ) and created as a NuGet package.",
  "ActionType": "Octopus.TentaclePackage",
  "Version": 9,
  "Properties": {
    "Octopus.Action.EnabledFeatures": "Octopus.Features.CustomDirectory,Octopus.Features.SubstituteInFiles",
    "Octopus.Action.Package.AutomaticallyRunConfigurationTransformationFiles": "False",
    "Octopus.Action.Package.AutomaticallyUpdateAppSettingsAndConnectionStrings": "False",
    "Octopus.Action.Package.DownloadOnTentacle": "False",
    "Octopus.Action.Package.NuGetFeedId": "feeds-builtin",
    "Octopus.Action.Package.NuGetPackageId": "#{sitecore.version}",
    "Octopus.Action.Package.CustomInstallationDirectory": "#{website.root}",
    "Octopus.Action.Package.CustomInstallationDirectoryShouldBePurgedBeforeDeployment": "True",
    "Octopus.Action.SubstituteInFiles.Enabled": "True",
    "Octopus.Action.SubstituteInFiles.TargetFiles": "sitecore\\login\\passwordrecovery.aspx"
  "Parameters": [
      "Name": "website.root",
      "Label": "Folder where to deploy website to",
      "HelpText": null,
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
  "$Meta": {
    "OctopusVersion": "3.3.1",
    "Type": "ActionTemplate"

This step is based on Deploy a Package step template.
However, it has has custom features:

  • Custom installation directory
  • Substitute variables in files

It does not have the following preselected configurations

  • Configuration Variables
  • Configuration transforms

The custom installation directory is determine by a variable named #{website.root}

Custom Step Template – Copy Sitecore Licence Key

The Deployment process that is going to be built can be used on a freshly installed server running just the Octopus Tentacle and having IIS installed. This step, will do as the name suggests and will copy the Sitecore Licence file from a central location to the web site.

This is based on the Run a script step type

  "Id": "ActionTemplates-26",
  "Name": "Copy Sitecore Licence File",
  "Description": "Copy the sitecore licence file",
  "ActionType": "Octopus.Script",
  "Version": 11,
  "Properties": {
    "Octopus.Action.Package.NuGetFeedId": "feeds-builtin",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.RunOnServer": "false",
    "Octopus.Action.Script.ScriptBody": "$sourcePath = $OctopusParameters['sourcePath']\r\n$destinationPath = $OctopusParameters['destinationPath']\r\n\r\nWrite-Output \"sourcePath: \" $sourcePath\r\nWrite-Output \"destinationPath: \" $destinationPath\r\n\r\ncopy-item -Path $sourcePath\\License.xml -Destination $destinationPath"
  "Parameters": [
      "Name": "sourcePath",
      "Label": "Location where Licence Key is stored",
      "HelpText": null,
      "DefaultValue": "\\\\\\NetworkShare\\SitecoreLicenceFile",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      "Name": "destinationPath",
      "Label": "Location where the Licence Key is to be copied to",
      "HelpText": null,
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
  "$Meta": {
    "OctopusVersion": "3.3.1",
    "Type": "ActionTemplate"

All that will be required is to specify the location of the licence file when this template is used.

Custom Step Template – Deploy Site

This is step is based on Deploy a package step type.

This step is used to deploy the actual custom solution build. It will deploy the artifect that is produced by TeamCity

  "Id": "ActionTemplates-22",
  "Name": "Deploy Site",
  "Description": "Step used to deploy  the NuGet sent from TeamCity",
  "ActionType": "Octopus.TentaclePackage",
  "Version": 16,
  "Properties": {
    "Octopus.Action.EnabledFeatures": "Octopus.Features.CustomDirectory,Octopus.Features.ConfigurationVariables,Octopus.Features.ConfigurationTransforms,Octopus.Features.SubstituteInFiles",
    "Octopus.Action.Package.AutomaticallyRunConfigurationTransformationFiles": "True",
    "Octopus.Action.Package.AutomaticallyUpdateAppSettingsAndConnectionStrings": "True",
    "Octopus.Action.Package.DownloadOnTentacle": "False",
    "Octopus.Action.Package.NuGetFeedId": "feeds-builtin",
    "Octopus.Action.Package.NuGetPackageId": "#{packageName}",
    "Octopus.Action.Package.CustomInstallationDirectory": "#{website.root}",
    "Octopus.Action.SubstituteInFiles.Enabled": "True",
    "Octopus.Action.SubstituteInFiles.TargetFiles": "App_Config\\Include\\Z_#{Octopus.Project.Name}.#{Octopus.Environment.Name}.config\nApp_Config\\Include\\SiteDefinition.#{Octopus.Environment.Name}.config\nWeb.#{Octopus.Environment.Name}.config"
  "Parameters": [
      "Name": "website.root",
      "Label": "Folder where to deploy website to",
      "HelpText": null,
      "DefaultValue": null,
      "DisplaySettings": {}
  "$Meta": {
    "OctopusVersion": "3.3.1",
    "Type": "ActionTemplate"

For this template it will

  • Install to a Custom installation directory
  • Transform Configuration variables
  • Configuration transforms
  • Substitute variables in files

Sitecore’s best practice now appear to be that when creating your custom patch file to prefix it with Z_ to ensure that it is run last. As part of the deployment still want to have the sitecore .config files transformed, hence why the Substitute variables in files is set to


There is only one parameter defined that is where the website is to be deployed to

Custom Step Template – Load Site

This step is based on Run a Script step type

  "Id": "ActionTemplates-42",
  "Name": "Load Site",
  "Description": "Used to preload load a site",
  "ActionType": "Octopus.Script",
  "Version": 0,
  "Properties": {
    "Octopus.Action.Package.NuGetFeedId": "feeds-builtin",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.RunOnServer": "false",
    "Octopus.Action.Script.ScriptBody": "Begin {\r\n    $counter = 1\r\n    $web = New-Object System.Net.WebClient\r\n    $flag = $false\r\n    $retries = 20\r\n    $websiteName = $OctopusParameters['']\r\n    $delay = $OctopusParameters['website.delay']\r\n}\r\nProcess {\r\n    While ($flag -eq $false -and $counter -le $retries) {\r\n        Try {\r\n            Write-Output \"$counter/$retries waiting for website $websiteName\"\r\n            $html = $web.DownloadString(\"http://$websiteName/\")\r\n            $counter++\r\n            Start-Sleep -Milliseconds $delay\r\n            $flag = $True\r\n        }\r\n        Catch {\r\n            $counter++\r\n        }\r\n    }\r\n}\r\nEnd {\r\n    Write-Host -fore Green \"$websiteName is available\"\r\n}"
  "Parameters": [
      "Name": "website.delay",
      "Label": "Website Load interval",
      "HelpText": "The delay, in milliseconds, between each attempt to query the website",
      "DefaultValue": "500",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
  "$Meta": {
    "OctopusVersion": "3.3.1",
    "Type": "ActionTemplate"

With .net, and especially Sitecore, the first time the site is accessed there is a delay. This script will load the site so that it is ready, and all subsequent requests will not be delayed while the solution is loaded. This is especially useful when deploying sitecore packages from the command line so that those tasks do not time out

The script will try 20 times to load a site.

Custom Step Template – Load Site

This step is based on Run a Script step type

  "Id": "ActionTemplates-41",
  "Name": "Deploy Sitecore Module-Package",
  "Description": "Deploy a sitecore module. Ie package downloaded from Sitecore Marketplace",
  "ActionType": "Octopus.Script",
  "Version": 3,
  "Properties": {
    "Octopus.Action.Package.NuGetFeedId": "feeds-builtin",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.RunOnServer": "false",
    "Octopus.Action.Script.ScriptBody": "$sourcePath = $OctopusParameters['sourcePath']\n$destinationPath = $OctopusParameters['destinationPath']\n$packageInstaller = $OctopusParameters['SidewalkPackageInstaller.path']\n$websitePath = $OctopusParameters['website.folder']\n$websiteName = $OctopusParameters['']\n$packageName = $OctopusParameters['']\n\nWrite-Output $sourcePath\nWrite-Output $destinationPath\nWrite-Output $packageInstaller\nWrite-Output $websitePath\nWrite-Output $websiteName\nWrite-Output $packageName\n\nWrite-Host copy-item -Path \"$sourcePath\\$packageName\" -Destination $destinationPath\n\ncopy-item -Path \"$sourcePath\\$packageName\" -Destination $destinationPath\n\nWrite-Output $packageInstaller -sitecoreUrl \"http://$websiteName\" -sitecoreDeployFolder \"$websitePath\" -packagePath $destinationPath\\$packageName -connector \"sitecore\"\n\n& $packageInstaller -sitecoreUrl \"http://$websiteName\" -sitecoreDeployFolder \"$websitePath\" -packagePath $destinationPath\\$packageName -connector \"sitecore\"\n\nRemove-Item $destinationPath\\$packageName\n"
  "Parameters": [
      "Name": "sourcePath",
      "Label": "Location where the Sitecore Module is stored",
      "HelpText": null,
      "DefaultValue": "\\\\\\NetworkShare\\Sitecore.Modules",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      "Name": "destinationPath",
      "Label": "Where to copy the zip file",
      "HelpText": null,
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      "Name": "",
      "Label": "Sitecore Module Name",
      "HelpText": null,
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
  "$Meta": {
    "OctopusVersion": "3.3.1",
    "Type": "ActionTemplate"

One of the issues that I have experienced in the past is when you install a Sitecore package when you develop, the dll’s and Sitecore items should not be included within your Visual Studio solution. In later posts I will detail a command line application that will install Sitecore Packages. This step is used to call Sidewalk Package Installer.

This step will call this utility passing in the location of the Sitecore Package to install.

External Feeds

We need to configure Octopus to inform it of the location of the TeamCity server so it knows where to pull the artifacts from

Select Library | External Feeds


Click Add Feed


Enter the ip address of the TeamCity NuGet server, and enter the TeamCity-Admin credentials created earlier when configurating the TeamCity server.

Click Save and test

You will be asked to specify a Package Name. If you leave the package name blank it will list every Nuget package currently on TeamCity.


I prefer to create a custom lifecycle for each deployment solution created, rather than having multiple projects use the Default Lifecycle. This way it is much easier to customize if required later

Select Library | Lifecycles


Click Add lifecycle


Base the name for the project to be created.

I like to have a default retention policy of three releases.

This is set via Change on the Default retention policy


Click Apply, and the Save on the lifecyle


Next Steps

This is the minimum configuration needed to get Octopus ready.

The next steps will be to build and configure the solution environment, the IIS server that Sitecore will run on, and the DB server that Sitecore will use. The solution environment needs to be configured now because you cannot create a deployment solution without first making sure that the Octopus Tentacle is installed.

How these are setup and configured will be detailed in the next post. Building a Continuous Integration Environment for Sitecore Part 3 – SQL Server


My musing about anything and everything

Tagged with: , , , ,
Posted in CI, Continuous Integration, Octopus, Octopus Deploy
4 comments on “Building a Continuous Integration Environment for Sitecore Part 2 – Octopus Deploy
  1. MJ says:

    Hi Darren,

    Many thanks for this thorough illustration.

    I have a question, Do you have any suggestions or previous experiencing in performing this set up for multiple Sitecore projects/clients? that is to utilize a template set up to be used on separate servers when provisioning a whole new environment for another project.

    • Darren Guy says:

      Unfortunately this is a shortcoming from Octopus whereby you cannot create a project template. All that can be done is to clone an existing project. And this is what I have ended up doing. Problems occur when you want to add a step, you have to create a step template and then add it to every deployment process. Remembering to include any new variables that may be required.

      It would be great if in a future version of Octopus, they introduced templates, similar to what can be done with TeamCity. Maybe this is something to be recommended on if not already done

  2. alisuleymantopuz says:


    Firstly, thanks for these blog series.

    At this chapter, I’m getting an error from a script block which written in `Close process locking deployment folder`

    + $data = (&$pathToHandle $pathToWebsite)

    Message: `The expression after ‘&’ in a pipeline element produced an object that was not
    valid. It must result in a command name, a script block, or a CommandInfo

    Do you have an idea about this ?

    • Darren Guy says:

      What I would normally do in this instance is make sure that somewhere I am outputting all the variables to the log, and then I would try and execute the command manually from within powershell. Most of the problems I have discovered in the past relate to having the variable value being incorrect and attempting to manually execute a command directly in powershell has helped highlight the problem.

      You can also set these variables in your process
      to true, and the next time you create a release it will include a log more logging information to assist with debugging.

      Doing this should help

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 13 other subscribers
%d bloggers like this: