Wednesday 30 August 2017

Sitecore continuous deployment setup in IAAS and PAAS architecture - Octopus Deploy Overview

Recently i got an opportunity to setup continuous deployment for our Sitecore sites hosted in Azure IAAS and PAAS environment. I did my research and decided to use Octopus deploy as the deployment tool and use Sitecore Ship for deploying TDS update package. Before explaining my setup I would like to give a quick overview of Octopus deploy and then about Sitecore ship in next blog post. My octopus overview will be from Sitecore perspective , for detailed info i would suggest you to check Octopus Documentation and also the Pluralsight Octopus tutorial .


Octopus Deploy -  Octopus Deploy is a deployment automation tool.

Architecture-  It has below architecture.



Octopus has a centralized octopus deploy server. Octopus server hosts the dashboard from where you can create and deploy your releases.  It contains the packages pushed by TFS. It also hosts a  windows service which sends command to deployment targets. It has a SQL database where it stores release related data , Authenticated user details etc.

Deployment targets are the machines where deployment happens.  They can be either in the same network or in different networks but octopus server should be able to communicate to deployment targets. Tentacle is a light weight windows service installed in deployment targets. It manages communication with octopus server once it receives a communication it passes it to calamari. Calamari is a small console application which is able to run commands like deploying a package.

For installing Octopus server and tentacle please check below link.

https://octopus.com/docs/installation

Environments - Once Octopus server setup is done.You need to add environments in Octopus dashboard. Environments in Octopus are logical grouping of your deployment targets. For example if you have INT , QA and Prod environments. You can create three environments INT , QA and Prod. You can then add your INT CM , INT CD servers/deployment targets to INT environment and same for QA and Prod.  For adding environments and deployment targets please refer below link

https://octopus.com/docs/key-concepts/environments




Environments and deployment targets have a many to many relationship i.e an environment can contain many deployment targets and a deployment target can be present in one or many environments.

Roles - Any deployment target can contain one or many roles. Roles are like tags which you can associate to your deployment targets. You can use roles while setting up your deployment process steps. For example below is my QA environment containing 3 deployment targets





You can see I have a QA environment containing one CM deployment target and two CD deployment targets. CM deployment target has "CM" role assigned and  CD deployment target has "CD" role. Now if you have a deployment process containing a step for publishing which you just have to run for CM you can use Octopus role and specify that you want this step to run only for "CM" Role deployment targets. It will be more clearer when i will walk you through my deployment steps.


Life Cycle - A life cycle in Octopus consists of phases. Each phase can contain one or more environments. Your release goes through the life cycle and its phases. You can not skip any phase i.e you can not move to 2nd phase without deploying to first phase. In below life cycle , you can not deploy your release directly to "Prod US and HK" phase environments before deploying to QA phase environments.




For more details on Life cycle please refer below link.

https://octopus.com/docs/key-concepts/lifecycles


Packages- Packages are the binaries which Octopus deploys to your deployment targets. There are many ways using which you can push packages to octopus . You can refer below link to get more details. I will explain how you can setup TFS to push packages to octopus while walking through my deployment design.

https://octopus.com/docs/api-and-integration/octo.exe-command-line/pushing-packages


Projects - Once you have defined your environments and life cycle. You need to setup your deployment projects. A Project in Octopus is collection of deployment steps specified using variables. Every Project has  a life cycle associated with it. You can create release in your Project and do the deployment by following your defined deployment steps . Again your release has to go through the associated life cycle. For creating project in Octopus please refer below link.

https://octopus.com/docs/key-concepts/projects

Deployment Steps - You can specify your deployment steps by using Octopus step templates. Below screenshot shows deployment steps of a Sitecore site.


Each steps in deployment process above uses step templates. IN Octopus there are three types of steps templates available.


  •  Octopus out of box step templates- These are templates provided by Octopus by default. It has lot of useful step templates which you can use like deploy a package , send email, Run powershell script , Run Azure powershell script etc. 
  •  Octopus Community Provided step templates- These are the step templates provided by Octopus community. You can get lot of step templates related to file operation , SQL Operation etc here. 
  •    
  • Creating your own step Templates - If you need a functionality which is not provided by Octopus or community you can create your own step template. You can use powershell script for it. For creating your own step template please refer below link. 


https://octopus.com/docs/deploying-applications/step-templates/custom-step-templates


Variables - You can use variables for declaring values of parameters in your deployment steps.  You can see in below screenshot i am using a variable for homepageurl parameter in "Smoke Test Home page" deployment step.



You can have different values in variable depending on your environments. You can scope your variables based on your environments or roles . In below screenshow you can see i have different values for HomePageUrl for different environments by using role scope.


 Octopus will dynamically fetch the homepageurl value depending on the environment it is deploying. For more details on variable please refer below link.

https://octopus.com/docs/deploying-applications/variables

Release - For deploying your package you can  create release in your project and then deploy it. The release will follow the life cycle associated with the project.


This was a quick overview of Octopus deploy automation tool. In the next blog post i will talk about how we can use Sitecore Ship and Curl to deploy  a TDS package. After that  I will walk you through my octopus deployment design for Azure IAAS and PAAS architecture. I will also share my custom step templates which i am using in my deployment steps.



















Sunday 6 August 2017

Switching from Azure Search to Lucene Search in Sitecore 8.2 Azure App Service


For switching to Lucene Search from Azure search in Sitecore 8.2 Azure App service follow below steps.


  •  Unzip the scwdp package of all the Sitecore instances
  • Copy below script in a bat file. Replace the "WebsitefolderPath" by your scwdp package extracted  website folder path. 
  • Run the bat file script as admin. 



echo Disabling Azure search config files

ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Azure.DefaultIndexConfiguration.config" Sitecore.ContentSearch.Azure.DefaultIndexConfiguration.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Azure.Index.Core.config" Sitecore.ContentSearch.Azure.Index.Core.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Azure.Index.Master.config" Sitecore.ContentSearch.Azure.Index.Master.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Azure.Index.Web.config" Sitecore.ContentSearch.Azure.Index.Web.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Social\Sitecore.Social.Azure.Index.Master.config" Sitecore.Social.Azure.Index.Master.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Social\Sitecore.Social.Azure.Index.Web.config" Sitecore.Social.Azure.Index.Web.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Social\Sitecore.Social.Azure.IndexConfiguration.config" Sitecore.Social.Azure.IndexConfiguration.config.disabled
ren "WebsiteFolderPath\App_Config\Include\ListManagement\Sitecore.ListManagement.Azure.Index.List.config" Sitecore.ListManagement.Azure.Index.List.config.disabled
ren "WebsiteFolderPath\App_Config\Include\ListManagement\Sitecore.ListManagement.Azure.IndexConfiguration.config" Sitecore.ListManagement.Azure.IndexConfiguration.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Azure.Index.Master.config" Sitecore.Marketing.Azure.Index.Master.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Azure.Index.Web.config" Sitecore.Marketing.Azure.Index.Web.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Azure.IndexConfiguration.config" Sitecore.Marketing.Azure.IndexConfiguration.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Azure.Index.Master.config" Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Azure.Index.Master.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Azure.Index.Web.config" Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Azure.Index.Web.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Azure.IndexConfiguration.config" Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Azure.IndexConfiguration.config.disabled
ren "WebsiteFolderPath\App_Config\Include\FXM\Sitecore.FXM.Azure.DomainsSearch.DefaultIndexConfiguration.config" Sitecore.FXM.Azure.DomainsSearch.DefaultIndexConfiguration.config.disabled
ren "WebsiteFolderPath\App_Config\Include\FXM\Sitecore.FXM.Azure.DomainsSearch.Index.Master.config" Sitecore.FXM.Azure.DomainsSearch.Index.Master.config.disabled
ren "WebsiteFolderPath\App_Config\Include\FXM\Sitecore.FXM.Azure.DomainsSearch.Index.Web.config" Sitecore.FXM.Azure.DomainsSearch.Index.Web.config.disabled
ren "WebsiteFolderPath\App_Config\Include\ContentTesting\Sitecore.ContentTesting.Azure.IndexConfiguration.config" Sitecore.ContentTesting.Azure.IndexConfiguration.config.disabled
ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Azure.Index.Analytics.config" Sitecore.ContentSearch.Azure.Index.Analytics.config.disabled


echo Enabling Lucene search files

ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config.disabled" Sitecore.ContentSearch.Lucene.DefaultIndexConfiguration.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Lucene.Index.Core.config.disabled" Sitecore.ContentSearch.Lucene.Index.Core.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Lucene.Index.Master.config.disabled" Sitecore.ContentSearch.Lucene.Index.Master.config
ren "WebsiteFolderPath\App_Config\Include\Social\Sitecore.Social.Lucene.Index.Master.config.disabled" Sitecore.Social.Lucene.Index.Master.config
ren "WebsiteFolderPath\App_Config\Include\Social\Sitecore.Social.Lucene.IndexConfiguration.config.disabled" Sitecore.Social.Lucene.IndexConfiguration.config
ren "WebsiteFolderPath\App_Config\Include\ListManagement\Sitecore.ListManagement.Lucene.Index.List.config.disabled" Sitecore.ListManagement.Lucene.Index.List.config
ren "WebsiteFolderPath\App_Config\Include\ListManagement\Sitecore.ListManagement.Lucene.IndexConfiguration.config.disabled" Sitecore.ListManagement.Lucene.IndexConfiguration.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Lucene.Index.Master.config.disabled" Sitecore.Marketing.Lucene.Index.Master.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Lucene.IndexConfiguration.config.disabled" Sitecore.Marketing.Lucene.IndexConfiguration.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.Index.Master.config.disabled" Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.Index.Master.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.IndexConfiguration.config.disabled" Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.IndexConfiguration.config
ren "WebsiteFolderPath\App_Config\Include\FXM\Sitecore.FXM.Lucene.DomainsSearch.DefaultIndexConfiguration.config.disabled" Sitecore.FXM.Lucene.DomainsSearch.DefaultIndexConfiguration.config
ren "WebsiteFolderPath\App_Config\Include\FXM\Sitecore.FXM.Lucene.DomainsSearch.Index.Master.config.disabled" Sitecore.FXM.Lucene.DomainsSearch.Index.Master.config
ren "WebsiteFolderPath\App_Config\Include\FXM\Sitecore.FXM.Lucene.DomainsSearch.Index.Web.config.disabled" Sitecore.FXM.Lucene.DomainsSearch.Index.Web.config
ren "WebsiteFolderPath\App_Config\Include\ContentTesting\Sitecore.ContentTesting.Lucene.IndexConfiguration.config.disabled" Sitecore.ContentTesting.Lucene.IndexConfiguration.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Lucene.Index.Analytics.config.disabled" Sitecore.ContentSearch.Lucene.Index.Analytics.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.ContentSearch.Lucene.Index.Web.config.disabled" Sitecore.ContentSearch.Lucene.Index.Web.config
ren "WebsiteFolderPath\App_Config\Include\Social\Sitecore.Social.Lucene.Index.Web.config.disabled" Sitecore.Social.Lucene.Index.Web.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Lucene.Index.Web.config.disabled" Sitecore.Marketing.Lucene.Index.Web.config
ren "WebsiteFolderPath\App_Config\Include\Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.Index.Web.config.disabled" Sitecore.Marketing.Definitions.MarketingAssets.Repositories.Lucene.Index.Web.config
pause





Thursday 27 July 2017

Sitecore Item getting published even when they are not in final workflow state


We found a weird issue today when items were getting published even if they were not in final workflow state. We figured out that somehow enableWorkflow in below setting got changed to false which resulted in this issue. This setting can also be used to disable workflow in your site.

<site name="publisher" domain="sitecore" enableTracking="false" enableWorkflow="true" />


Thursday 12 January 2017

Sitecore -Getting IIS error pages outside the server instead of custom page not found/error page


Recently we faced an issue where custom page redirect on page not found/access denied was working fine inside the server but was showing IIS pages outside the server




One of my colleague Sufal came up with the fix for this which is as below

In web.config  - Add  <httpErrors errorMode="Detailed" /> just above </system.webServer> node.

or you can do the same directly in IIS -> Select your site -> error pages -> Edit feature settting -> Select detailed errors








Sunday 8 January 2017

Sitecore CD server went down - Exception- Tracker.Current is not initialized


Day before yesterday our one of the CD server went down with plenty of below exceptions


2108 03:18:13 ERROR Cannot create tracker.
Exception: System.IndexOutOfRangeException
Message: Index was outside the bounds of the array.
Source: mscorlib
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at Sitecore.Analytics.Model.Framework.ModelFactory.GetConcreteType(Type elementType)
   at Sitecore.Analytics.Model.Framework.ModelFactory.CreateFacet(Type facetType)
   at Sitecore.Analytics.Model.Framework.Faceted.AddFacet(String name, Type type)
   at Sitecore.Analytics.Model.Framework.ModelFactory.CreateContact(ID id, IReadOnlyDictionary`2 facets)
   at Sitecore.Analytics.Data.ContactFactory.Create(ID id)
   at Sitecore.Analytics.Data.ContactRepository.CreateContact(Guid id)
   at Sitecore.Analytics.Pipelines.EnsureSessionContext.LoadContact.Process(InitializeTrackerArgs args)
   at (Object , Object[] )
   at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
   at Sitecore.Analytics.DefaultTracker.EnsureSessionContext()
   at Sitecore.Analytics.Pipelines.CreateTracker.GetTracker.Process(CreateTrackerArgs args)
   at (Object , Object[] )
   at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
   at Sitecore.Analytics.Tracker.Initialize()

We did an iisreset which fixed the issue. We also reported the incident to Sitecore support to find the root cause . They confirmed it as a sitecore knwon issue and asked us to apply the patch following the below article

 https://kb.sitecore.net/articles/032518

The issue is related to the following method:

Sitecore.Analytics.Model.Framework.ModelFactory.GetConcreteType(Type elementType)
The above method use the "private static readonly IDictionary<Type, Type> typeMap;" internal class field which is initialized in static constructor as "Dictionary" collection:
static ModelFactory()
{
    typeMap = new Dictionary<Type, Type>();
}
However, since the above class is used from different threads the type of the collection, the patch replaces it with ConcurrentDictionary for correct threads synchronization.