Sitecore CI Documentation Release 0.1.0-beta

Brad Christie

Jan 07, 2018

Contents:

1 Introduction 3 1.1 Scope...... 3 1.2 Prerequisites...... 3 1.3 Environment...... 3

2 Services 5 2.1 Docker for Windows...... 5 2.1.1 Nickel Tour...... 5 2.1.2 Installation...... 5 2.2 TeamCity...... 6 2.2.1 Nickel Tour...... 6 2.2.2 Installation...... 6 2.3 Octopus Deploy...... 7

3 Infrastructure 9 3.1 Clean Sitecore Image...... 9 3.1.1 Sitecore 9.0...... 9 3.1.2 Sitecore 8.2...... 9 3.2 MSBuild Image...... 9 3.3 Building a Solution...... 11

4 PowerShell Helpers 13 4.1 Easily Get Container IPs...... 13

5 Credits 15

6 Indices and tables 17

i ii Sitecore CI Documentation, Release 0.1.0-beta

Documentation on leveraging with Sitecore development.

Contents: 1 Sitecore CI Documentation, Release 0.1.0-beta

2 Contents: CHAPTER 1

Introduction

This documentation will outline how to create repeatable builds with Sitecore using tools such as Docker (for con- tainerization), Team City (for on-demand builds), and Octopus Deploy (for deploying to staging, production, etc.).

1.1 Scope

These docs demonstrate using TeamCity and Docker to create a continuous integration environment for working with Sitecore.

1.2 Prerequisites

To follow along with this guide you will need the following: • Windows 10 or Windows Server 2016 • /services/00_docker • /services/01_teamcity Docker. Please follow the services doc outlining installation and configuration of /services/00_docker

1.3 Environment

These docs will assume we’re working out of a local (to Docker) directory named C:\sitecoreci. You are free to change this location, please be mindful of quotes in path references moving forward.

3 Sitecore CI Documentation, Release 0.1.0-beta

4 Chapter 1. Introduction CHAPTER 2

Services

These docs will rely on various services in place to create the assemblance of a fully automated continuous integration. These services are described in the following documents, including their roles, how to set them up, configuration and other important details.

2.1 Docker for Windows

2.1.1 Nickel Tour

Docker in a container technology that utilized the host operating system’s kernel while placing custom code in a sandbox environment. It’s more lightweight then a virtual machine (in that it’s built using the concept of layering over snapshots), but applications need to be compatible with the host operating system. Docker currently supports both Windows and Unix. In a Windows environment, Unix is emulated using a virtual machine (“moby”) ran with Hyper-V (by default).

2.1.2 Installation

Please follow the guides specific to your environment: • Windows 10 running Docker CE • Windows Server running Docker EE Additionally, be sure to install the ‘Docker Toolbox‘_ (which includes Kitematic).

5 Sitecore CI Documentation, Release 0.1.0-beta

2.2 TeamCity

2.2.1 Nickel Tour

TeamCity is a continuous integration server that allows coordination of builds for various projects using background agents in a repeatable manner. At a very high level, TeamCity is a task scheduler that queues building, testing, merging, and other source-control related tasks. It also notifies relavent parties of the outcome of one or all of these actions. This enables teams to focus more on completing the task at hand and not waiting for a build to finish or a test to run.

2.2.2 Installation

TeamCity must be installed for the purpose of following these docs. If you already have a server, feel free to use it. Otherwise, please perform the following actions to get a simple server up. First, create a docker-compose.yml file: version:'2.1' services: teamcity: image: /teamcity-server:latest-nanoserver volumes: -./data/teamcity_data:C:/ProgramData/JetBrains/TeamCity -./data/teamcity_logs:C:/TeamCity/logs ports: - 8111:8111 mem_limit:2g teamcity-agent: image: jetbrains/teamcity-agent:latest-nanoserver environment: - SERVER_URL=http://teamcity:8111 - TEAMCITY_SERVER_MEM_OPTS=-Xmx2g-XX:ReservedCodeCacheSize=350m

Next, run the following in an elevated PowerShell window: docker-compose up

This will start the services (both the TeamCity server and a build agent), which should take anywhere from several seconds to a few minutes to warm up.

Locate the Hostname

While the instance is warming up, locate the hostname of the server by opening a new PowerShell window and typing the following: docker ps -a | where { $_ -like '*teamcity-server*'}

The first group of numbers and letters is the hostname of the server. Docker has automatically added a hosts entry for this hostname for convenience.

Tip: To get the IP address of a container, run the following and look for the IPAddress value: docker inspect

6 Chapter 2. Services Sitecore CI Documentation, Release 0.1.0-beta

To distill it down to simply an IP, use the –format option:

docker inspect--format"{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}"

˓→

Initialize

Once the server is running, visit it in a browser on port 8111 and follow the guide. To keep the installation as simple as possible (when asked) choose the Internal (HSQLDB) database type (this will use a file-based database which is perfect for testing with minimal overhead).

Add Admin Account

After agreeing to the license, select Login as Super user at the bottom. Upon clicking the link, the necessary authen- tication token will be generated and appear in the console window of the server. Once logged in, be sure to create a new administrator user account. This will permit you to login in the future without referencing the console window (and allow you run the server headless in the background using the -d flag).

2.3 Octopus Deploy

Todo: rundown of using octopus to deploy built images.

2.3. Octopus Deploy 7 Sitecore CI Documentation, Release 0.1.0-beta

8 Chapter 2. Services CHAPTER 3

Infrastructure

The infrastructure are the components necessary to create a workflow from development on through to deployment. In the Docker world, these are various images used as building blocks for other functional tasks (such as building the source code or deploying to the web).

3.1 Clean Sitecore Image

Creating a baseline image for docker is very important. It allows you to have a great starting point from which other images will derive.

3.1.1 Sitecore 9.0

Per Manniche Bering has a phenomenal Sitecore 9 repository that I would be hard-pressed to compete with. Follow the README and use this repository to generate a clean sitecore image from which your custom solution can build from. The key to Docker is leveraging the layer-based system, so having a strong (and clean) foundation is important.

3.1.2 Sitecore 8.2

Todo: Coming soon.

3.2 MSBuild Image

To have a fully-automated build environment you need an image with MSBuild tooling available. This enables you to copy the current codebase into a fresh environment and run a build to ensure to missing components are present. By using build images you bring immediate attention to issues of “works on my machine” and “didn’t check in . . . ”.

9 Sitecore CI Documentation, Release 0.1.0-beta

In addition to just MSBuild, this image may also have any other frequently used tooling, such as NodeJS, , etc. loaded. Already having the proper tooling makes the focus of the task more about just building the solution and less about establishing the environment. Below is an example build image, consisting of the most common tooling found in a typical .NET project (.NET framework, MSBuild, NodeJS, git, nuget, etc.). First, setup an MSBuild base image:

# escape=` FROM microsoft/dotnet-framework:3.5-windowsservercore-1709 SHELL ["powershell","-Command","$ErrorActionPreference = 'Stop'; $ProgressPreference

˓→= 'SilentlyContinue';"]

# Build Tools 15 RUN Invoke-WebRequest "http://download.visualstudio.microsoft.com/download/pr/

˓→100404314/e64d79b40219aea618ce2fe10ebd5f0d/vs_BuildTools.exe" -OutFile "

˓→$env:TEMP\vs_BuildTools.exe" ; ` Start-Process \"$env:TEMP\vs_BuildTools.exe\" -ArgumentList \"--add Microsoft.

˓→VisualStudio.Workload.MSBuildTools --quiet\" -Wait ; ` Remove-Item -Path \"$env:TEMP\vs_BuildTools.exe\" -Force ; ` Set-ItemProperty -Path "Registry::HKEY_LOCAL_

˓→MACHINE\System\CurrentControlSet\Control\Session` Manager\Environment" -Name PATH -

˓→Value (%{'{0};{1}' -f ('{0}\\2017\BuildTools\MSBuild\15.

˓→0\Bin\' -f ${env:ProgramFiles(x86)}), $Env:Path});

RUN Invoke-WebRequest "http://download.microsoft.com/download/5/f/7/5f7acaeb-8363-

˓→451f-9425-68a90f98b238/visualcppbuildtools_full.exe" -OutFile "

˓→$env:TEMP\visualcppbuildtools_full.exe" ; ` Start-Process \"$env:TEMP\visualcppbuildtools_full.exe\" -ArgumentList \"/

˓→NoRestart /S\" -Wait ; ` Start-Process ('{0}\Microsoft Visual C++ Build Tools\vcbuildtools.bat' -f $

˓→{env:ProgramFiles(x86)}) -Wait ; ` Remove-Item -Path \"$env:TEMP\visualcppbuildtools_full.exe\" -Force ;

# Asp.NET & .NET Framework RUN Install-WindowsFeature NET-Framework-45-ASPNET ; ` Install-WindowsFeature Web-Asp-Net45

# NodeJS RUN Invoke-WebRequest "https://nodejs.org/dist/latest-v6.x/node-v6.12.2-x64.msi" -

˓→OutFile "$env:TEMP\node.msi" ; ` Start-Process "msiexec.exe" -ArgumentList ('/i "{0}\node.msi" /quiet' -f

˓→$env:TEMP) -Wait ; ` Remove-Item -Path \"$env:TEMP\node.msi\" -Force ;

# NuGet RUN Invoke-WebRequest "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -

˓→OutFile "$env:SYSTEMROOT\nuget.exe" ; ` $nuget = \"Set-Alias nuget $env:SYSTEMROOT\nuget.exe\" ; ` $nuget | Out-File \"$PSHome\profile.ps1\" -Append ; ` #Set-Alias nuget \"$env:SYSTEMROOT\nuget.exe\" ; ` Invoke-Expression \"$nuget\" ;

# Git for Windows RUN Invoke-WebRequest "https://github.com/git-for-windows/git/releases/download/v2.15.

˓→1.windows.2/Git-2.15.1.2-64-bit.exe" -OutFile "$env:TEMP\git.exe" ; ` Start-Process \"$env:TEMP\git.exe\" -ArgumentList '/SILENT /COMPONENTS="ext" /

˓→GitAndUnixToolsOnPath' -Wait ; `

10 Chapter 3. Infrastructure Sitecore CI Documentation, Release 0.1.0-beta

Remove-Item -Path \"$env:TEMP\git.exe\" -Force ;

SHELL ["cmd", "/S", "/C"] WORKDIR /project

Build that and tag it for use: docker build-t builder:latest.

3.3 Building a Solution

Multi-Stage builds are a fantastic way to encapsulate the build routine from the deployable result. By keeping the build separated from the release, we keep the final image lean and self sufficient (absent the tooling for Building and simply whatever is necessary to serve the content). In the next step, we establish a “build” image which is strictly building the site. Below that, we spin up a clean Sitecore instance and load the compiled result into it:

# escape=`

# # Build # FROM bchristie/builder:latest as build SHELL ["powershell","-Command","$ErrorActionPreference = 'Stop'; $ProgressPreference

˓→= 'SilentlyContinue';"]

# Retrieve latest RUN git clone https://github.com/Sitecore/Habitat.git .

# adjust configuration for build, & grab sitecore binaries and license COPY ./projects/license.xml /inetpub/wwwroot/Data RUN Expand-Archive -Path "*.zip" -DestinationPath "." ; ` Expand-Archive -Path "*_cm.*.zip" -DestinationPath "." ` Remove-Item -Path "*.zip"

# Perform build RUN mkdir \Website ; ` nuget restore Habitat.sln ; ` npm install ; ` & .\node_modules\.bin\gulp.cmd

# # Result # FROM sc9xm1cm COPY --from=build /websites/Habitat.dev.local/Website/ /inetpub/sc/

In the above example we build the Habitat solution and push the resulting output to the clean Sitecore image. Knowing that Habitat also needs database and instance access, a docker-compose file will allow us to assemble all the resources we need: version:'3.4' services: sql:

3.3. Building a Solution 11 Sitecore CI Documentation, Release 0.1.0-beta

image: sc9xm1sql cm: image: sc9xm1cm links: - sql builder: build:. links: - cm

The above instructs docker that we need a fresh Sitecore instance and associated databases. From there, begin building the above Dockerfile so rainbow may leverage their existence during the build process.

12 Chapter 3. Infrastructure CHAPTER 4

PowerShell Helpers

Looking for some help with PowerShell commands and Docker? Here are some I’ve created.

4.1 Easily Get Container IPs

Get the container IPs a little easier: foreach ($id in & docker ps -a -q) { & docker inspect --format "Container ID: {{.Config.Hostname}}`t{{range .

˓→NetworkSettings.Networks}}{{.IPAddress}}{{end}}" $id }

Clean containers matching a certain name: foreach ($id in & docker ps -f name= -a -q) { & docker rm $id }

13 Sitecore CI Documentation, Release 0.1.0-beta

14 Chapter 4. PowerShell Helpers CHAPTER 5

Credits

Some serious attribution and credit goes out to the following folks: Per Manniche Bering Put a LOT of effort into Sitecore 9 Docker Repository. Stefan Scherer Fantastic repository of Windows Dockerfiles.

15 Sitecore CI Documentation, Release 0.1.0-beta

16 Chapter 5. Credits CHAPTER 6

Indices and tables

• genindex • modindex • search

17