onsdag den 5. november 2014

Sitecore as a Nuget-package - Buildsetup Part 1


One of our main issues when developing Sitecore solutions is to keep our sites up to date with Sitecore files.

The solution to this issue has for years been to run a custom robocopy script that copies the files from the public development server.
This requires that the server is always reachable, up to date and not infected with misplaced files.


I have made a script that takes a Sitecore zip installation file as input and creates a nuget-package from it.

This article will show how this is done.

Following steps are taken when creating the nuget-package
  1. Initializing variables
  2. Unpacking zip-file
  3. Moving data-folder to App_Data/Sitecore
  4. Creating force.txt files to force empty directories to be included in nuget-package
  5. Copy developer license file to App_Data/Sitecore/License
  6. web.config changes - Correcting paths to dataFolder and license file 
  7. Creating nuspec file - Syncronising version of Sitecore with the nuget-package
  8. Creating nuget package
The script requires three parameters.
  1. Path to license-file
  2. Path to Sitecore zip-file
  3. Path to nuspec file
I am calling the script using a bat-file

 CScript "Create Sitecore Nuget.vbs" License.xml" "Sitecore 7.5 rev. 141003.zip" Sitecore.nuspec   


Below is shown the set of files needed for the script to work

  1. Create Sitecore Nuget.bat - bat file for calling vbs-script file
  2. Create Sitecore Nuget.vbs - vbs script file that does all the work and is explained below
  3. license.xml - The licensfile to use in the nuget-package
  4. NuGet.exe - exe for creating nuget-package
  5. Sitecore 7.5 rev. 141003.zip - Sitecore zip file containing Sitecore installation
  6. Sitecore .nuspec - Nuspec file used when creating nuget-package

 1. Initializing variables

 dim sourceLicenseFile  
 dim sourceSitecoreZipPackage  
 dim nuspecFile  
 Set WshShell = WScript.CreateObject("WScript.Shell")  
 Set fileSystemObject = CreateObject("Scripting.FileSystemObject")  
 Set currentFolder = fileSystemObject.GetFolder(".")  
 Const ForReading = 1  
 Const ForWriting = 2  
 sourceLicenseFile = Wscript.Arguments.Item(0)   
 sitecoreSourceZipPackage = Wscript.Arguments.Item(1)   
 nuspecFile = Wscript.Arguments.Item(2)   
 if NOT fileSystemObject.FileExists(sourceLicenseFile) then  
      wScript.Echo "License file not found"  
      wScript.Quit -1  
 end if  
 if NOT fileSystemObject.FileExists(sitecoreSourceZipPackage) then  
      wScript.Echo "Sitecore zip not found"  
      wScript.Quit -1  
 end if  
 if NOT fileSystemObject.FileExists(nuspecFile) then  
      wScript.Echo "nuspec file not found"  
      wScript.Quit -1  
 end if  
 sitecoreVersion = fileSystemObject.GetBaseName(sitecoreSourceZipPackage)  
 extractFolder = currentFolder.Path + "\" + sitecoreVersion  
 if fileSystemObject.FolderExists(extractFolder) then  
      wScript.Echo "Deleting extract folder"  
      fileSystemObject.DeleteFolder extractFolder  
 end if  
 extractFolder = extractFolder + "\"   

First we checks if the licensefile, Sitecore zipfile and the nuspec file exists.
After this we deletes the extractfolder if it exists to clean up from ealier nuget-packages.

2. Extract zip-file

 ' Extract sitecore in .zip file  
 wScript.Echo "Extracting Sitecore site"  
 WshShell.Run """%PROGRAMFILES%\7-zip\7z.exe"" x """ + sitecoreSourceZipPackage + """", 1, true  

This step extracts the zipfile. NB! 7-zip is required.

3. Moving datafolder

 wScript.Echo "Moving datafolder to App_Data\Sitecore"  
 ' Move Data folder to App_Data\Sitecore  
 If fileSystemObject.FolderExists(extractFolder + "Website") then  
      If fileSystemObject.FolderExists(extractFolder + "Data") then  
           if fileSystemObject.FolderExists(extractFolder + "Website\App_Data") then  
                fileSystemObject.DeleteFolder extractFolder + "Website\App_Data"  
           end if  
           fileSystemObject.CreateFolder extractFolder + "Website\App_Data"  
           fileSystemObject.MoveFolder extractFolder + "Data", extractFolder + "Website\App_Data\Sitecore"  
           wScript.Echo "Data folder not found"  
      End If  
      wScript.Echo "Website folder not found"  
 End if  

This step moves the Data folder inside the Website folder. This is done to be able to reference the Data folder using af relative path.

4. Creating force.txt files in empty folders

 Set objFile = fileSystemObject.CreateTextFile(extractFolder + "force.txt", true)  
 objFile.WriteLine "force"  
 wScript.Echo "Copying force.txt files to force empty folders in nuget-package"  
 fileSystemObject.CopyFile extractFolder + "force.txt", extractFolder + "Website\sitecore modules\Shell\force.txt"  
 fileSystemObject.CopyFile extractFolder + "force.txt", extractFolder + "Website\sitecore modules\Web\force.txt"  
 fileSystemObject.CopyFile extractFolder + "force.txt", extractFolder + "Website\sitecore\shell\Override\force.txt"  

This step assures that empty folders are present in the created nuget-package because nuget.exe ignores empty folders.

5. Copy license file

 wScript.Echo "Copy licensfile"  
 ' Copy license file  
 licenseDestinationFolder = "\App_Data\Sitecore\License\"  
 fileSystemObject.CreateFolder extractFolder + "Website" + licenseDestinationFolder  
 fileSystemObject.CopyFile sourceLicenseFile, extractFolder + "Website" + licenseDestinationFolder  

This step copies the supplied license file to App_Data\Sitecore\License

6. Setting path to datafolder and license file

 wScript.Echo "Fixing web.config"  
 Set objFile = fileSystemObject.OpenTextFile(extractFolder + "Website\web.config", ForReading)  
 strText = objFile.ReadAll  
 strNewText = Replace(strText, "<sc.variable name=""dataFolder"" value=""/data"" />", "<sc.variable name=""dataFolder"" value=""/App_Data/Sitecore"" />")  
 strNewText = Replace(strNewText, "<setting name=""LicenseFile"" value=""$(dataFolder)/license.xml"" />", "<setting name=""LicenseFile"" value=""$(dataFolder)/License/license.xml"" />")  
 Set objFile = fileSystemObject.OpenTextFile(extractFolder + "Website\web.config", ForWriting)  
 objFile.WriteLine strNewText  

This step fixes the paths in the web.config that is now invalid due to moved Data folder.

7. Creating nuspec file

 ' Now create nuget package  
 wScript.Echo "Creating nuspec-file for nuget-package"  
 Set objFile = fileSystemObject.OpenTextFile(nuspecFile, ForReading)  
 strText = objFile.ReadAll  
 version = Replace(Replace(sitecoreVersion, "Sitecore ", ""), " rev. ", ".")  
 strNewText = Replace(strText, "{version}",version)   
 newNuspecFile = extractFolder + "Sitecore.nuspec"   
 Set objFile = fileSystemObject.CreateTextFile(newNuspecFile, true)  
 objFile.WriteLine strNewText  

 fileSystemObject.CopyFile "nuget.exe", extractFolder 

This step replaces {version} in the nuspec-file so the nuget-package gets the right version number and the right filename. Then nuget.exe is copied to the extractfolder. NB! Requires that nuget.exe is present in same folder as the script.

The nuspec-file looks like this
 <?xml version="1.0"?>  
   <description>Sitecore package</description>  
   <copyright>Copyright 2014</copyright>  
       <dependency id="HtmlAgilityPack" version="1.4.6" />  
       <dependency id="Microsoft.AspNet.Mvc" version="5.1.0" />  
       <dependency id="Microsoft.AspNet.Razor" version="3.1.0" />  
       <dependency id="Microsoft.AspNet.WebPages" version="3.1.0" />  
       <dependency id="Microsoft.Web.Infrastructure" version="" />  
       <dependency id="Newtonsoft.Json" version="6.0.5" />   
       <dependency id="Microsoft.AspNet.WebApi.Client" version="5.1.0" />  
       <dependency id="Microsoft.AspNet.WebApi.Core" version="5.1.0" />  
       <dependency id="Microsoft.AspNet.WebApi.Cors" version="5.1.0" />  
       <dependency id="Microsoft.AspNet.WebApi.WebHost" version="5.1.0" />  
       <!-- NOT SUPPORTED FOR THE VERSION Sitecore uses = Version: -->  
       <!-- dependency id="Mvp.Xml" version="2.3.0" /-->  
       <dependency id="Lucene.Net" version="3.0.3" />  
       <dependency id="Lucene.Net.Contrib" version="3.0.3" />  
      <file src="website\**" target="content" exclude="bin\*.*;Web.config.Oracle;App_Config\ConnectionStrings.config;App_Config\ConnectionStringsOracle.config" />         
      <file src="website\bin\*.*" target="lib\net40\" exclude="bin\System.*;bin\Newtonsoft.Json.*;bin\HtmlAgilityPack.*;bin\Lucene.*;bin\Microsoft.Web.Infrastructure.*" />   

In Part 2 I will show how to implement attachment of database using the nuget package. The ConnectionStrings.config has been excluded to support this.

8. Creating nuget-package

 wScript.Echo "Packing ConfigMerge nuget-package......"  
 Set objFile = fileSystemObject.CreateTextFile(extractFolder + "createNugetPackage.bat", true)  
 objFile.WriteLine "@setlocal enableextensions"  
 objFile.WriteLine "@cd /d ""%~dp0"""  
 objFile.WriteLine "nuget pack"  
 wshShell.run """" + extractFolder + "createNugetPackage.bat""", 0, TRUE  

This step creates the Sitecore nuget package. This is done by creating af createNugetPackage.bat in the extract folder. This calls nuget.exe with the "pack" parameter, which results in creation of a nuget-package using the available nuspec file.

Part 2 will show how enhancement of the nuget-package will enable attachement of the database for support for a working Sitecore site after installation of the package.

Ingen kommentarer:

Send en kommentar