Using Gulp and Unicorn within a SCORE scaffolded project

I would like to share some findings from my investigation into the replacement of TDS with alternative open source tools such as Gulp and Unicorn.

Gulp is a toolkit that will help you automate painful or time-consuming tasks in your development workflow, including build operations. Gulp is a pure JavaScript module for NodeJS. JavaScript is well known for Web Developers. It can speed up the process of making changes to existing code and writing new Gulp tasks. Gulp has plenty of plugins as well that can help meet a variety of needs.

Unicorn is a utility for Sitecore that solves the issue of moving templates, renderings and other database items between Sitecore instances. It simplifies the process of serializing and sharing items. Unicorn 3 uses YAML spec for serialization of items. YAML is a language that is designed to store object graphs in a human-readable fashion. This post goes into more detail about the ‘hows’ and ‘whys’ of the YAML serializer.

Prerequisites

So, here’s what we need before we begin:

Steps

Let’s do several steps to replace TDS in the currently scaffolded project.

  1. Install Sitecore 8.0 Update-4 rev. 150621 instance to path [your_project_name]\sandbox. For example, in my case it was “D:\Projects\uctest\sandbox” (see screen below):

1

Also, in this step we must install the “Sitecore PowerShell Extensions-3.3 for Sitecore 8” module.

2

As you can see from the screens above, I prefer doing that using SIM. The SIM (Sitecore Instance Manager) is a key tool for managing the park of Sitecore instances. You can install, locate, maintain, reinstall or delete Sitecore products.

  1. Unzip the SCORE+Visual+Studio+Solution+Scaffold+v2.0.14.zip into the root folder of your project. For example, in my case it was “D:\Projects\uctest”.
  1. Remove the TDS project folders from the solutions root directory. To be more exact, the folders to remove are:
  • Rename.Me.TDS.Master
  • Rename.Me.TDS.Master.Content
  • Rename.Me.TDS.Core
  1. Unzip the package (GulpUnicoreTDSReplacement.zip) and copy with replacing into the solutions root folder.
  1. Run PowerShell script “scaffold.ps1” using any preferred command console. I prefer ConEmu. ConEmu-Maximus5 is a Windows console window enhancement which presents multiple consoles and simple GUI applications as one customizable tabbed GUI window with various features. For example, to overcome the issue with execution policy, I ran following:
 
PowerShell.exe -ExecutionPolicy Bypass -File scaffold.ps1

parameters: solution: uctest, tenant: uctest, company: Test company, site: uctest. We can see it in the screen below:

3

  1. Open Visual Studio (in my case, VS2013) and install the following NuGet packages for the solution:
  • Score.8.0.150621.2.0.14.0 – except for Environment project
  • Score.BootstrapUI.8.0.150621.2.0.6.0 – only for Web project
  • Unicorn 3.1.0 – only for Web project

Please see the screens below:

456

  1. Build the solution.
  1. Install Gulp packages which are needed for our tasks, set up initial Unicorn configuration and copy everything into the sandbox. To do that, go to the solutions root folder using command console and run the following:
 
npm install

7

 
gulp Install-Unicorn

8

  1. Log in to the Sitecore instance as administrator and install update packages in the sequence below:
  • Score.TDS.Core
  • Score.TDS.Master
  • ScoreUI.TDS.Master
  • Score.BootstrapUI.TDS.Core
  • Score.BootstrapUI.TDS.Master

via url http://[your_instance]/sitecore/admin/UpdateInstallationWizard.aspx from:

  • “[solution_root]\packages\Score.8.0.150621.2.0.14.0\tools\packages\”
  • “[solution_root]\packages\Score.UI.8.0.150621.2.0.9.0\tools\packages\”
  • “[solution_root]\packages\Score.BootstrapUI.8.0.150621.2.0.6.0\tools\packages\” folders.

Currently, I don’t have a solution for automating the process that is described in this step. I hope it will be solved in the near future.

  1. Install the SCORE+Bootstrap+3+Tenant+Scaffolding+Automation-2.0.1.zip package using the Sitecore control panel.
  1. Open the Unicorn Control Panel to revert item serialization with YAML format from my package that was prepared earlier.

In order to do that we must open the link http://[your_instance]/unicorn.aspx and do the following:

  • Synchronize the Uctest.Core.Items configuration.
  • Synchronize the Uctest.Master.Items configuration.
  • Synchronize the Uctest.Master.Content.Items configuration.

9

I’m aware of the warning shown in the screen below, but it doesn’t matter given the scope of this particular demonstration. So, disregard it please. 🙂

10

 

  1. Let’s create some code :). Create a new class with the name HomeController.cs in Web project/Areas/your_tenant_name/Controllers. The code must contain something like what is shown below:
 
using System.Web.Mvc;

namespace uctest.Web.Areas.uctest.Controllers
{
	public class HomeController : Controller
	{
		[HttpGet]
		public ActionResult Index()
		{
			ViewBag.Message = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy " +
							  "text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has " +
							  "survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised " +
							  "in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software " +
							  "like Aldus PageMaker including versions of Lorem Ipsum.";

			return View();
		}
	}
}

Create a new Razor view with the name Index.cshtml in Web project/Areas/your_tenant_name/Views/Home. The code must contain something like what is shown here:

 
@model dynamic

@{
	ViewBag.Title = "Something from controller:";
}

@ViewBag.Message

Save All in Visual Studio. Our view and controller must be situated like in the screen below:

11

  1. Open your Web project file (your_project_name.Web.scproj) with your preferred text editor. In my case it’s Notepad++. Uncomment AfterBuild target and insert the following commands:
 
<Exec Command="cd $(SolutionDir)" ContinueOnError="false" />
<Exec Command="gulp" ContinueOnError="false" />

It’s a very important step that binds the Visual Studio build process with Gulp’s default task running.

12

  1. Build the solution.
  1. Log in to Sitecore as an administrator and execute the “Publish Site” command.
  1. Open link http://[your_instance]/[your_tenant_name]/home and…voilà, it works!!!

13

What was done

To ensure proper operation of Unicorn, I prepared in advance an item serialization for controller rendering (controller: Home, action: Index) and showed it on the home page for our tested tenant. We can make changes in the controller or razor view and, after building the solution, we can see those changes in the browser.

I’ve created the *.Core.Items serialization for checking Unicorn functionality regarding Core database without any reason except testing. Those items can be found by following the paths:

  • /sitecore/templates/uctest/extended user
  • /sitecore/system/Settings/Security/Profiles/extended user

They must not be included in the scaffolding package.

That “extended user” is for example only and must be removed from scaffolding in the future if these item serializations are to be approved for inclusion in the scaffolded project.

The package we copied into the SCORE scaffolded project folder in step 4 contains the following:

14

Where:

File name Description
Serializations Folder with prepared serialization and subdirectory with *.nuspec files named “specs” which are needed for creation of Nuget packages from serialized items for each Unicorn configuration part. Serialized items have “Rename.Me” placeholders which will be replaced during running of “scaffold.ps1”. The replacement of “Rename.Me” placeholder old and good functionality of “scaffold.ps1” so I didn’t change any line of code. Also there is a subdirectory named “packed” that is for holding Nuget packages from serialized items for each Unicorn configuration part. The packages were created after each “build solution” command in Visual Studio, of course, if we did step 13.
gulpfile.js This is a file that will act as a manifest to define our Gulp tasks. Tasks that we want to execute will be found within this file.
package.json This file is used to give information to Node (npm) that allows it to identify the project as well as handle the project’s dependencies.
Rename.Me.sln The current scaffolded project consists of this VS solution file. But links to *.TDS* projects in my version have been removed. That’s why we did copy with replacing in step 4.

15

The most interesting of them all is gulpfile.js which consists the Gulp tasks. The main tasks from this one are:

Task name Description
“Pack-serializations This task creates Nuget packages from Unicorn item serialization folders. It will be needed in the future for continuous integration tasks.
“Copy-To-Sandbox” Copies everything necessary from our project files except serialization into the “sandbox” folder.
“Install-Unicorn” Because Unicorn was installed into the project as a Nuget package, we need to configure and install it into “sandbox” with our preferences.

The “Pack-serializations” and “Copy-To-Sandbox” Gulp tasks run after every VS build as part of the scope of the default Gulp task.

 gulp.task("default", ["Pack-serializations", "Copy-To-Sandbox"], function () { }); 

The “Install-Unicorn” task was run in step 8. But if we need reconfigure Unicorn it will be better to make changes in this task and run it again.

Unicorn provides an include/exclude predicate system for configuring serialization. It’s explained very well in Kam Figy’s post on Unicorn 3.1. I want to show the configuration of this project below. Here is part of the configuration from the Unicorn.config file that describes what item paths we include and/or exclude (configuration names, descriptions, etc.). We can compare that with the Unicorn Control Panel shown in step 11:

<sitecore>
	<unicorn>
...
		<configurations>
			<configuration name="Uctest.Core.Items" description="Testing of Unicorn multiple configuration. Items serialization of our project from Core DB.">
					<predicate type="Unicorn.Predicates.SerializationPresetPredicate, Unicorn" singleInstance="true">
						<include name="CoreTemplates" database="core" path="/sitecore/templates/uctest" />
						<include name="CoreExtendedUser" database="core" path="/sitecore/system/Settings/Security/Profiles/extended user" />
					</predicate>
				</configuration>
				<configuration name="Uctest.Master.Items" description="Testing of Unicorn multiple configuration. Items serialization of our project from Master DB.">
					<predicate type="Unicorn.Predicates.SerializationPresetPredicate, Unicorn" singleInstance="true">
						<include name="Layouts" database="master" path="/sitecore/layout/Layouts/uctest" />
						<include name="Renderings" database="master" path="/sitecore/layout/Renderings/uctest" />
						<include name="Models" database="master" path="/sitecore/layout/Models/uctest" />
						<include name="Placeholder Settings" database="master" path="/sitecore/layout/Placeholder Settings/uctest" />
						<include name="Templates" database="master" path="/sitecore/templates/uctest" />
						<include name="Branches" database="master" path="/sitecore/templates/Branches/uctest" />
					</predicate>
				</configuration>
				<configuration name="Uctest.Master.Content.Items" description="Testing of Unicorn multiple configuration. Items serialization of our project from Master DB and related to content only.">
					<predicate type="Unicorn.Predicates.SerializationPresetPredicate, Unicorn" singleInstance="true">
						<include database="master" path="/sitecore/content/uctest" name="Content" >
							<exclude path="/sitecore/content/uctest/Selections" />
						</include>
					</predicate>
				</configuration>
		</configurations>
...

That is another important setting from the Unicorn.config file. The target data store is where we write serialized items to.

<sitecore>
	<unicorn>
...
		<defaults>
...
			<targetDataStore type="Rainbow.Storage.SerializationFileSystemDataStore, Rainbow" physicalRootPath="~/../../Serializations/$(configurationName)" useDataCache="false" singleInstance="true"/>
...

Conclusion

Of course, this isn’t a complete solution. Many steps are unpolished. Many things must be added and many givens must be reviewed. For example, we need a Gulp watch task to observe and record deleted files from Web project and have relevant file data in “sandbox.” Also, we need to automate the process described in step 9. I have provided only a basic direction that is just my personal opinion on the issue of TDS replacement. Due to my own delusions, I used to have some doubts regarding the debug process into “sandbox.” But, as it turns out, the debugging process isn’t impacted negatively. We can attach the w3wp.exe process as before and all works well. So I think that we are on the right path.

Sergey Ivanov

I am an ASP .NET Developer with more than 8 years of experience. My favorite programming language is C#. I like beautiful UI and fast responses on the server side; I really enjoy working on UIs using Javascript, CSS and HTML. In addition to development, playing guitar, rock music and bike riding. I strive to make BrainJocks better by furthering research into the technical and UX aspects of development–research I look forward to sharing with you through Jocks to the Core! Learn more about sergey.

Add a Comment

Your email address will not be published. Required fields are marked *

Or request call back