Showing posts with label Build Process. Show all posts
Showing posts with label Build Process. Show all posts

June 30, 2016

Scan and Install all the packages in a folder

Sometimes ago I have published the PackageInstaller on github and on the marketplace.

This is a useful script to install a Sitecore package in command line. One of the scenarios, I like to cover with this script is the installation of the missing packages on the different machines. This mean on each developer’s machine but also on staging and production.

To do that I have developed the following script who scan a folder and install all the packages. Then it will write the installed packages into a text file to avoid the reinstallation on this machine the next time. Of course this file shouldn't be committed :-)

<#
    .SYNOPSIS
        Install all the sitecore modules who are not installed yet. And save the list of those modules to avoid to reinstall it next time.
 
    .PARAMETER  modulesPath
        The folder who contains the modules to install
 
    .PARAMETER  allreadyInstalledModulesPath
        The folder who contains the file .txt.user with the allready installed modules

    .PARAMETER  packageInstallerExe
        The path to the file Sidewalk.SC.PackageInstaller.Client.exe

    .PARAMETER  packageInstallerSln
        The path to the file \Sidewalk.SC.PackageInstaller.sln used to build the solution only if the Sidewalk.SC.PackageInstaller.Client.exe is not found

    .PARAMETER  msBuildPath
        The path to the file msbuild.exe used to build the solution only if the Sidewalk.SC.PackageInstaller.Client.exe is not found

    .PARAMETER  sitecoreUrl
        The sitecore url where the modules needs to be installed

    .PARAMETER  sitecoreDeployFolder
        The sitecore Website folder where the modules need to be installed
 
    .EXAMPLE
        InstallMissingModules.ps1 -sitecoreUrl "http://mysitecore.sandbox.local" -sitecoreDeployFolder "C:\inetpub\wwwroot\mysitecore.sandbox\Website" -Verbose
#>
[CmdletBinding()]
param(
    [Parameter(Mandatory=$false)][string]$modulesPath = "..\..\..\Modules\",
    [Parameter(Mandatory=$false)][string]$allreadyInstalledModulesPath = "..\..\..\Modules\allreadyInstalledModules.txt.user",
    [Parameter(Mandatory=$true)][string]$sitecoreUrl,
    [Parameter(Mandatory=$true)][string]$sitecoreDeployFolder,
    [switch]$whatIf
)

$fileSystemModulePath = "$currentDir\..\..\Powershell\Libraries\FileSystem.psm1"

function Get-ScriptDirectory {
    Split-Path -parent $PSCommandPath
}

$currentDir = Get-ScriptDirectory

try {
    $modulesPathFullPath = Resolve-Path $modulesPath
 Write-Verbose -Message "Module directory: $($modulesPathFullPath.Path)"
} catch {
    throw new FileNotFoundException("The modules path is not found. $($_.Exception.Message)")
}
$packageInstallerExe = "$currentDir\PackageInstaller\SC.PackageInstaller.Client.exe"

if(-not (Test-Path $packageInstallerExe)){
    Write-Verbose -Message "The package installer exe is not found."    

    #Download the zip file from github
    $modulePath = Resolve-Path $fileSystemModulePath

    Import-Module $modulePath.Path
    $zipPath = "$currentDir\PackageInstaller.zip"    
    Get-RemoteFile -url "https://github.com/VGBenjamin/PackageInstaller/raw/master/Sidewalk.PackageInstaller.zip" -targetFile $zipPath -Verbose:$PSBoundParameters['Verbose']

    Write-Verbose -Message "Extracting the zipfile"
    try
 {
  Expand-Zip -zipPath $zipPath -destination "$currentDir\PackageInstaller\" -Verbose:$PSBoundParameters['Verbose'] -createDestinationFolderIfNeeded
 } catch [Exception]
 {
  echo $_.Exception|format-list -force
 }    
}

$allreadyInstalledModules = New-Object 'System.Collections.Generic.HashSet[String]'
$allreadyInstalledModulesPathFillPath = "$currentDir$allreadyInstalledModulesPath"

if(Test-Path $allreadyInstalledModulesPathFillPath) {  
    Write-Verbose -Message "Loading the list of allready installed modules: $allreadyInstalledModulesPathFillPath"  
    Get-Content $allreadyInstalledModulesPathFillPath | ForEach-Object { $allreadyInstalledModules.Add($_ ) | Out-Null } 

    Write-Verbose -Message "Modules allready installed: $allreadyInstalledModules"
}

foreach($module in Get-ChildItem -Path $modulesPathFullPath.Path -Include @("*.zip","*.update") -Recurse) {
    
    if(-not ($allreadyInstalledModules.Contains($module.Name))) {    
        Write-Verbose -Message "Installing the module: $($module.FullName)"
        
        if($whatIf) {
            Write-Host "WhatIf : Installing the module with the parameters: $packageInstallerExe -sitecoreUrl $sitecoreUrl -sitecoreDeployFolder $sitecoreDeployFolder -packagePath $($module.FullName) -connector tds"
        } else {
            try {
                & "$packageInstallerExe" -sitecoreUrl $sitecoreUrl -sitecoreDeployFolder $sitecoreDeployFolder -packagePath "$($module.FullName)" -connector "tds" | Out-String           
                $allreadyInstalledModules.Add($module.Name) | Out-Null
            } catch [Exception]
         {
          echo $_.Exception|format-list -force
         }
        }

        
    }
}

Set-Content -Path  $allreadyInstalledModulesPathFillPath -Value ($allreadyInstalledModules | Out-String) -WhatIf:$whatIf
This script is also available here: https://raw.githubusercontent.com/VGBenjamin/PackageInstaller/master/InstallMissingModules-github.ps1

The dependency FileSystem.psm1 is available here: https://raw.githubusercontent.com/VGBenjamin/PackageInstaller/master/FileSystem.psm1

The

November 12, 2015

Install your packages in command line

Some times ago I had publish a series of post about the automatisation of the deployment process. In this build process I install my packages in command line. I have finally rewrite and release this tool. It is now available on the marketplace and github.

The project

This project allow you to install the Sitecore packages files in command line. It support both the .zip and .update files.
If you like this project you can visit and let a comment on my blog: http://sitecoreblog.blogspot.be/

Usage

Install

You need to download and extract the PackageInstaller zip file or build the source.
Arguments
-p, --packagePath=PACKAGE PATH The PACKAGE PATH is the path to the package. The package must be located in a folder reachable by the web server.

-u, --sitecoreUrl=SITECORE URL The SITECORE URL is the url to the root of the Sitecore server.

-f, --sitecoreDeployFolder=SITECORE DEPLOY FOLDER The SITECORE DEPLOY FOLDER is the UNC path to the Sitecore web root.

-c, --connector=INSTALLATON MODE The INSTALLATON MODE could be tds or sitecore.

--pb, --publish Publish some items.

--pbc, --publishChildrenItems Publish the children items also. Need to be use with the -publish option. If you don't specify this flag you need to specify the paramter - publishRootItem

--pbsdb, --publishSourceDb=VALUE The source database to publish from (master if ommited). Need to be use with the -publish option.

--pbtdb, --publishTargetDb=VALUE The target database to publish to (web if ommited). Need to be use with the -publish option.

--pbl, --publishLanguage=VALUE The language to publish (all if ommited). Need to be use with the -publish option.

--pbi, --publishRootItem=VALUE The root item to publish (all if ommited). Need to be use with the -publish option.

--pbm, --publishMode=VALUE The publish mode must be one of those values: Full, Incremental, SingleItem, Smart (Full if ommited). Need to be use with the -publish option.

--pbt, --publishTargets=VALUE The publish target separated by a coma if multiple targets. Need to be use with the - publish option.

-h, --help Show this message and exit.

--rc, --removeconnector Remove the conenctor after the installation. it will remodify the bin folder so you should consider to let the conenctor for a better performance. --ssl Accept the self registered ssl certificate

Usage Examples
Install a sitecore package
Sidewalk.SC.PackageInstaller.Client.exe -sitecoreUrl "http://sc72rev140228" -sitecoreDeployFolder "C:\inetpub\wwwroot\sc72rev140228\Website" -packagePath "C:\temp\TestPkg.zip" -connector "sitecore"

Install a TDS package
Sidewalk.SC.PackageInstaller.Client.exe -sitecoreUrl "http://sc72rev140228" -sitecoreDeployFolder "C:\inetpub\wwwroot\sc72rev140228\Website" -packagePath "\Examples\TestPackage.TDS.update" -connector "tds"

Sources

The sources are available here: https://github.com/VGBenjamin/PackageInstaller

Issues

If you have some issues please open a ticket on https://github.com/VGBenjamin/PackageInstaller I will be notified



November 5, 2015

Customize the ExperienceEditor Part 2 - Override the Sitecore functions in the JS

Here is my other posts of the same series about the customization of the Sitecore client without modifying the Sitecore JS:
Today I will show you how I have inherit and override the javascript function defined by Sitecore with as few side effects as possible.
You just need to store the prototype of the original Sitecore's function, redefine this prototype and call the original function.
Here is the skeleton if the method of sitecore is:
sitecoreObject.prototype.methodName = function(param1) {
 //Do stuffs
}

This method can be override like this:
var originalProcess = sitecoreObject.prototype.methodName;
sitecoreObject.prototype.methodName = function (param1) {
    //Do my stuffs
 
    //Call teh original method and apply the correct context to this method
 originalProcess.call(this, request, command, name);    
};

Here is a real life. I will explain the client pipelines in a next post but the following method is responsible of the processing of the different processors:
scSitecore.prototype.process = function (request, command, name) {  
  name = (name == null ? command.command : name);
  this.state.pipeline = request.pipeline;
  var r;
  switch (name) {
    //The different case of the different processors names
  }
};
And I need to add my custom processor in it so basically adding another case:
var originalProcess = currentScJsWindow.scSitecore.prototype.process;
currentScJsWindow.scSitecore.prototype.process = function (request, command, name) {
    var localName = (name == null ? command.command : name);
    this.state.pipeline = request.pipeline;
    var r;

    if (localName === "ShowDialogInSidebar") {
        //Do my studd
    } else {
        //Call the normal handler
        originalProcess.call(this, request, command, name);
    }
};

June 23, 2014

Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 4: Align the version number

This is a last post of a series of post about the setup of a continuous integration for Sitecore. If you have miss the 4 previous post, here is the links:
  1. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Architecture
  2. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 1: Customize the TFS workflow
  3. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 2: Configure TFS
  4. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 3: Configure octopus
If you stop here you workflow should be ok but, I had another requirement: the version number. I would like to have the same reference number into every steps of my process:
  • The build number who appear in TFS
  • The assemblies files
  • The nuget packages
  • The octopus versions
To do that:
  1. Change the "Build number format" into the section "5. Advanced" of the TFS build definition by: $(BuildDefinitionName)_$(Date:1MMdd)$(Rev:.r). Be carefull with this number format. You can see that I have use 1MMdd and not YYYYMMdd as it is by default. The reason of that is that the Assembly number must between 0 and 65535. So you have a solution for the next 6 year by changing the 1 by another number :)
  2. Add a file .ps1 anywhere in the sources with the following content and do a check-in in TFS
  3. In the section 2.5 "Pre-build script path", refer to the powershell file you have created.
  4. In the section 2.5 "Pre-build script arguments", put the following value "-assemblyVersion 1.1.J.B -fileAssemblyVersion 1.1.J.B -nugetVersion 1.1.J.B". This mean that the powersell will replace the .J.B of the different files (assembly, assemblyVersion, nuget) by the same numbers as the build number of TFS
Here is the content of the powershell script to rename the versions:
param
(
 [string]$assemblyVersion,
 [string]$fileAssemblyVersion,
 [string]$nugetVersion
)

#Update the AssemblyInfo.cs and the .nuspec file to replace the X.X.J.B version number by the correct one depending of the number from TFS
function Update-SourceVersion
{
  param
  (
    [string]$SrcPath,
    [string]$assemblyVersion, 
    [string]$fileAssemblyVersion,
 [string]$nugetVersion
  ) 
  
    $buildNumber = $env:TF_BUILD_BUILDNUMBER
 Write-Host "env:TF_BUILD_BUILDNUMBER: $buildNumber"
 
    if ($buildNumber -eq $null)
    {
        $buildIncrementalNumber = 0
    }
    else
    {
        $splitted = $buildNumber.Split('.')
        $buildIncrementalNumber = $splitted[$splitted.Length - 1]
    }
    
    if ($fileAssemblyVersion -eq "")
    {
        $fileAssemblyVersion = $assemblyVersion
    }
     
    Write-Host "Executing Update-SourceVersion in path $SrcPath, Version is $assemblyVersion and File Version is $fileAssemblyVersion"
    
    
    $AllVersionFiles = Get-ChildItem $SrcPath AssemblyInfo.cs -recurse
    
     
    $jdate = Get-Date -format 1MMdd
 
 Write-Host "Infos: jdate: $jdate, buildIncrementalNumber: $buildIncrementalNumber"
 
    $assemblyVersion = $assemblyVersion.Replace("J", $jdate).Replace("B", $buildIncrementalNumber)
    $fileAssemblyVersion = $fileAssemblyVersion.Replace("J", $jdate).Replace("B", $buildIncrementalNumber)
     
    Write-Host "Transformed Assembly Version is $assemblyVersion and Transformed File Version is $fileAssemblyVersion"
        
    foreach ($file in $AllVersionFiles) 
    { 
        Write-Host "Modifying file " + $file.FullName
        #save the file for restore
        $backFile = $file.FullName + "._ORI"
        $tempFile = $file.FullName + ".tmp"
        Copy-Item $file.FullName $backFile
        #now load all content of the original file and rewrite modified to the same file
        Get-Content $file.FullName |
        %{$_ -replace 'AssemblyVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)', "AssemblyVersion(""$assemblyVersion"")" } |
        %{$_ -replace 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)', "AssemblyFileVersion(""$fileAssemblyVersion"")" }  > $tempFile
        Move-Item $tempFile $file.FullName -force
    }
 
 $nugetVersion = $nugetVersion.Replace("J", $jdate).Replace("B", $buildIncrementalNumber)
    Write-Host "Transformed Nuspec Version is $nugetVersion"
  
    $AllNugetFiles = Get-ChildItem $SrcPath *.nuspec -recurse
 $replaceExp = '<file src="$1" target="$2.' + $nugetVersion + '.update" />'
 
 foreach ($file in $AllNugetFiles) 
    { 
        Write-Host "Modifying file " + $file.FullName
        #save the file for restore
        $backFile = $file.FullName + "._ORI"
        $tempFile = $file.FullName + ".tmp"
        Copy-Item $file.FullName $backFile
        #now load all content of the original file and rewrite modified to the same file
        Get-Content $file.FullName |
        %{$_ -replace '<version>[0-9]+(\.([0-9]+|\*)){1,3}</version>', "<version>$nugetVersion</version>" }  |
  %{$_ -replace '<file src="(.*NationalLottery\.DeHub\..*)" target="(.*)\.[0-9]+(\.([0-9]+|\*|J|B)){1,3}.update" />', $replaceExp } > $tempFile
        Move-Item $tempFile $file.FullName -force
    } 
}

Write-Host "Running Pre Build Scripts"
 
$scriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition

$scriptRootBuildFunctions = "$scriptRoot\TFSUtils.psm1"
Write-Host "Script root: $scriptRootBuildFunctions"

if ($assemblyVersion -eq "")
{
 $assemblyVersion = "1.1.0.0"
 $fileAssemblyVersion = "1.1.J.B"
}

$srcPath = "$scriptRoot/../"

Update-SourceVersion $srcPath $assemblyVersion $fileAssemblyVersion $nugetVersion

If you use the script to create and deploy the Octopus packages as describe in the previous post, don't forget to complete the "Post-build script arguments" to "-releaseVersion 1.1.J.B" to use the same versioning system and having this number as release number in Octopus.

Ok that is it now. I hope that this tutorial will help you in your deployment process.
You also have a video presented to the Sitecore Virtual User Group who could be useful for it here: http://sitecoreug.org/events/January

Here is the index of all the post who compose this tutorial:
  1. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Architecture
  2. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 1: Customize the TFS workflow
  3. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 2: Configure TFS
  4. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 3: Configure octopus
  5. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 4: Align the version number

Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 3: Configure octopus

This is the 4th post of a series of post about the setup of a continuous integration for Sitecore.  If you have miss the 3 first post here are the links:
  1. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Architecture
  2. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 1: Customize the TFS workflow
  3. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 2: Configure TFS
Now our TFS is configured correctly, the package are created and published to the nuget server. We can focus on octopus now.

I will not explain how to setup you Octopus environments, machines, ... but only the deployment process I use. 

Here is the steps:
  1. Start Deployment: A notification email to the different member of the project with the details of the packages who will be deployed.
  2. Clean Environment: A cleanup of the files before the deployment to be sure that if we have remove a file it will not be on the project anymore. This is a powershell script with the following content: 
    #RootFolder : the root folder of the project (we should be able to get it from the environment)  
    $rootFolder = "E:\Websites\XXX\Website"   
    
    function Remove-Item-If-Exist
    {
     param
     (
      [string]$pathToDelete,
      [switch]$force,
      [switch]$recurse
     )
     
     If (Test-Path $pathToDelete){
      Remove-Item $pathToDelete -Force:$force -Recurse:$recurse
     }
    } 
     
    #Cleanup the old files  
    Remove-Item-If-Exist "$rootFolder\Design" -Force -Recurse  
    Remove-Item-If-Exist "$rootFolder\layouts\Layouts" -Force -Recurse  
    Remove-Item-If-Exist "$rootFolder\layouts\Sublayouts" -Force -Recurse  
    Remove-Item-If-Exist "$rootFolder\layouts\UserControls" -Force -Recurse  
    Remove-Item-If-Exist "$rootFolder\bin\PROJECTNAMESPACE.*.dll" -Force   
    Remove-Item-If-Exist "$rootFolder\App_Config\Include\PROJECTNAMESPACE.*.config" -Force
  3. Deploy Files: Deploy the NuGet package. You may have multiple time this step if you have multiple nuget package with the website files to deploy.
  4. Deploy TDS: Deploy the NuGet package with the TDS files in a temporary folder. 
  5. Install TDS Packages: This is a powershell to install and publish the TDS packages. I have create a custom tool for it who scan the files in a specific folder and install the packages. If you need to do this kind of program you should take a look at the code of TDS. Basically it install a webservice into your deploy folder, use this webservice to install your packages and then remove this webservice.
    A great alternative could be this tool: https://github.com/adoprog/Sitecore-Deployment-Helpers
To automate the creation of the release into octopus when the build is triggered into TFS we can add a post release script into TFS to create and deploy this release.

To do that:

  1. Add a new file with the extention .ps1 somewhere in your sources and chech-in this file in TFS
  2. Edit your TFS build definition 
  3. In the tab "Process", section 2.5
  4. In the section "Post-build script path", select your .ps1 file
  5. The parameter "Post-build script arguments" I have "-releaseVersion 1.1.J.B" please refer to the post "Step 4: Align the versions numbers" for this.
  6. The content of the powershell file is the following:
    param
    (
     [string]$releaseVersion
    )
     
    #Constants
    $octopusApiUrl = "http://10.0.2.50:8088/api"
    $octopusApiKey = "API-RX6UIIWTB2ZBUWU0TRIYXXXXXXX"
    
    $projectName = "XXX"
    $scriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
     
    #Functions
    
    # Get the formated TFS version number. Replace the tokens J and B by the current build number
    function Format-TFS-Version
    {
     param
     (
      [string]$versionToFormat
     )
     
     $buildNumber = $env:TF_BUILD_BUILDNUMBER
     Write-Host "env:TF_BUILD_BUILDNUMBER: $buildNumber"
     
        if ($buildNumber -eq $null)
        {
            $buildIncrementalNumber = 0
        }
        else
        {
            $splitted = $buildNumber.Split('.')
            $buildIncrementalNumber = $splitted[$splitted.Length - 1]
        }
        
     $jdate = Get-Date -format 1MMdd
     
     return $versionToFormat.Replace("J", $jdate).Replace("B", $buildIncrementalNumber)
    }
    
    #Create a release in Octopus with the specifiic version of the nuget packages
    function Octopus-Create-Release
    {
     param
     (
      [string]$releaseVersion
     )
     
     $releaseVersion = Format-TFS-Version $releaseVersion
     
     $corePackage = "--package=XXX.Core:$releaseVersion"
     $corporatePackage = "--package=XXX.Corporate:$releaseVersion"
     $scriptPackage = "--package=XXX.Tools.SqlScriptsUpdate:$releaseVersion"
     
     Write-Host "Create the octopus release by calling $scriptRoot\Octopus\octo.exe create-release --project=$projectName --server=$octopusApiUrl --apiKey=$octopusApiKey --version $releaseVersion $corePackage $corporatePackage $scriptPackage"
     
     &$scriptRoot\Octopus\octo.exe create-release --project=$projectName --server=$octopusApiUrl --apiKey=$octopusApiKey --version $releaseVersion $corePackage $corporatePackage $scriptPackage  
    }
    
    #Deploy a release in Octopus
    function Octopus-Deploy-Release
    {
     param
     (
      [string]$releaseVersion,
      [string]$deployToEnvironment
     )
     
     Write-Host "Deploy the octopus release by calling $scriptRoot\Octopus\octo.exe  deploy-release --project=$projectName --version=$releaseVersion --deployto=$deployToEnvironment --server=$octopusApiUrl --apiKey=$octopusApiKey"
    
     &$scriptRoot\Octopus\octo.exe deploy-release --project=$projectName --version=$releaseVersion --deployto=$deployToEnvironment --server=$octopusApiUrl --apiKey=$octopusApiKey
    }
    
    
    
    #Main program
    $releaseVersion = Format-TFS-Version $releaseVersion
    Write-Host "Release version: $releaseVersion"
    
    Octopus-Create-Release $releaseVersion
    
    Octopus-Deploy-Release $releaseVersion Integration
    


Ok now your process should be completed. The last post is optional but allow you to have a single ID during the whole build process.

Next steps:
  1. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Architecture
  2. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 1: Customize the TFS workflow
  3. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 2: Configure TFS
  4. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 3: Configure octopus
  5. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 4: Align the version number

Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 2: Configure TFS

This is the third post of a series of post about the setup of a continuous integration for Sitecore.  If you have miss the 2 first post here are the links:
  1. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Architecture
  2. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 1: Customize the TFS workflow
Now that we have our custom build template we are ready to configure it.

TDS settings:
  1. Set "TDS : Generate packages" to true to generate the TDS packages
  2. Set "TFS : IsDesktopBuild" to false because I don't want to deploy my TDS packages on the current server which is the build server. I need to embed those packages into nuget packages.
Octopus settings:
  1. Set "Octopack : API Key of the nuget server". You can find this setting into the app setting  "apiKey" of the nuget server
  2. Set "Octopack : Publish packaged to http" to the url of the nuget server it should look like : "http://YOUR_DOMAIN/api/v2/package/"
  3. Set "Octopack : Run OctoPack" to true. This will run the octopack command to generate and publish the nuget packages to the server.
Octopack:
To generate the octopus packages, I use the nuget package called OctoPack. It is really easy to use: you just need to install this nuget package in every web project. This will generate the package for you when you build with msbuild with the custom parameters we have set. 
I also create another project who will be used to deploy my TDS packages and install the Octopack package in this project. To do that, you can create an empty project (a console project in my case) and add a .nuspec file. The content of this nuspec should refer the different .update packages generated by TDS as in the following example:
<?xml version="1.0"?>
<package >
  <metadata>
    <id>XXX.TDSDeploy</id>
    <version>1.0.0</version>
    <authors>Vangansewinkel Benjamin</authors>
    <owners>Vangansewinkel Benjamin</owners>
    <projectUrl>http://www.xxx.be</projectUrl>
    <iconUrl>http://www.xxx.be/design/images/generalImages/favicon.ico</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>XXX TDS package</description>
    <releaseNotes></releaseNotes>
    <copyright>Copyright 2014</copyright>
  </metadata>

  <files>
    <file src="..\..\..\..\..\bin\_Packages\XXX.CoreTDS\XXX.CoreTDS.scitems.update" target="content\TdsPackages\XXX.CoreTDS.1.1.J.B.update" />
    <file src="..\..\..\..\..\bin\_Packages\XXX.LayoutsTDS\XXX.LayoutsTDS.scitems.update" target="content\TdsPackages\XXX.LayoutsTDS.1.1.J.B.update" />
    <file src="..\..\..\..\..\bin\_Packages\XXX.TemplatesTDS\XXX.TemplatesTDS.scitems.update" target="content\TdsPackages\XXX.TemplatesTDS.1.1.J.B.update" />
  </files>
</package>

Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 1: Customize the TFS workflow

This is the second part of my series of post about how to Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus. If you didn't have read the post about the general architecture you should read it first.

The first step of this tutorial is: "How to customize the Team Foundation Server (TFS) 2013 workflow".
  1. Into the TFS "build" tab of visual studio, right click on the build definition to customize and click on "Edit Build Definition"
  2. In the "Process" tab, click on show details and then download you current template. This will download a xaml file. Save it somewhere in your project and rename the file.
  3. Now you can open this file in visual studio or in a notepad++ for example. I will use both tools depending of what I need to change. Sometime it is easier to edit in notepad, sometime in visual studio.
  4. First thing to do is adding a section with the octopus parameter and another one with the TDS options as in this screenshot:
  5. To do that, wa need to create 5 new variables by adding the following code before </x:Members>
    <x:Property Name="Octopus_OctoPackPublishApiKey" Type="InArgument(x:String)" />
    <x:Property Name="Octopus_OctoPackPublishPackageToHttp" Type="InArgument(x:String)" />
    <x:Property Name="Octopus_RunOctoPack" Type="InArgument(x:Boolean)" />
    <x:Property Name="TDS_IsDesktopBuild" Type="InArgument(x:Boolean)" />
    <x:Property Name="TDS_GeneratePackage" Type="InArgument(x:Boolean)" />
  6. Add those parameter into the UI by adding the following code before </mtbw:ProcessParameterMetadataCollection>
    <mtbw:ProcessParameterMetadata BrowsableWhen="Always" Category="#500 Octopus" Description="Set this to true to run OctoPack" DisplayName="OctoPack : Run OctoPack" ParameterName="Octopus_RunOctoPack" />
    <mtbw:ProcessParameterMetadata BrowsableWhen="Always" Category="#500 Octopus" Description="Url where the octopack need to be published" DisplayName="OctoPack : Publish package to http" ParameterName="Octopus_OctoPackPublishPackageToHttp" />
    <mtbw:ProcessParameterMetadata BrowsableWhen="Always" Category="#500 Octopus" Description="API Key of the nuget server for the publish" DisplayName="OctoPack : API Key of the nuget server" ParameterName="Octopus_OctoPackPublishApiKey" />
    <mtbw:ProcessParameterMetadata BrowsableWhen="Always" Category="#600 TDS" Description="Set this to true if it is a desktop build" DisplayName="TDS : IsDesktopBuild" ParameterName="TDS_IsDesktopBuild" />
    <mtbw:ProcessParameterMetadata BrowsableWhen="Always" Category="#600 TDS" Description="Set this to true to generate the packages" DisplayName="TDS : Generate packages" ParameterName="TDS_GeneratePackage" />
  7. Switch to Visual Studio because it will be easier to edit. Click on the "Run MsBuild" and the in the properties window, replace the "CommandLineArgument" by the following one:
    String.Format("/p:SkipInvalidConfigurations=true {0} /p:OctoPackPublishPackageToHttp={1} /p:OctoPackPublishApiKey={2} /p:RunOctoPack={3} /p:IsDesktopBuild={4} /p:GeneratePackage={5}", AdvancedBuildSettings.GetValue(Of String)("MSBuildArguments", String.Empty), [Octopus_OctoPackPublishPackageToHttp], [Octopus_OctoPackPublishApiKey], [Octopus_RunOctoPack], [TDS_IsDesktopBuild], [TDS_GeneratePackage])
    If you prefer to do that in notepad, don't forget to escape the characters.
    This change will add some extra parameters to the msbuild command.
  8. Check-in this workflow into TFS.
  9. Edit your build definition again. In the "Process" tab, expand the "Build process template" section and click on "New..."
With those steps you should have your TFS template with your custom fields. In the next post I will explain how to use it.

Next steps:
  1. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Architecture
  2. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 1: Customize the TFS workflow
  3. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 2: Configure TFS
  4. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 3: Configure octopus
  5. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 4: Align the version number

June 18, 2014

Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus

This week I have setup a complete fully automatic continuous integration for a website in Sitecore.

I have use the following architecture

Here is the workflow:
  1. The TFS 2013 Build Server get the sources from TFS 2013 Source Control
  2. The TFS 2013 Build Server execute a pre-build powershell to:
    1. Rename the versions into the AssemblyInfo.cs
    2. Rename the versions into the NuSpec files
  3. The TFS 2013 Build Server execute a msbuild command. This msbuild command do the following stuff:
    1. Create the Team Developpment for Sitecore (TDS) packages
    2. Create the Octopus nuget packages
    3. Push the Octopus nuget packages on the nuget server
  4. The TFS 2013 Build Server execute a post-build powershell to:
    1. Create an Octopus release
    2. Deploy the Octopus release on integration. This will:
      1. Send an email to the administrator
      2. Cleanup the old files
      3. Deploy my Octopus nuget packages of code
      4. Deploy my Octopus nuget packages of TDS
      5. Install the SQL Scripts
      6. Install the TDS packages and modules


The configuration of those different steps are detailed here:
  1. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Architecture
  2. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 1: Customize the TFS workflow
  3. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 2: Configure TFS
  4. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 3: Configure octopus
  5. Setup a continuous integration for Sitecore with TDS - TFS 2013 and Octopus - Step 4: Align the version number