Automated release management - DevConFu 2014

Preview:

Citation preview

12.04.2023 / 1

AUTOMATED RELEASE MANAGEMENT

WITH TEAMCITY & OCTOPUSDEPLOY

12.04.2023

CONTINOUS DELIVERY

/ 3

12.04.2023

Continuous Integration

/ 4

12.04.2023

Continuous Deployment

/ 5

12.04.2023

Continuous Delivery

/ 6

12.04.2023

It’s all about frequent releases

/ 7

John Allspaw: “Ops metametrics” http://slidesha.re/dsSZIr

It’s all about failing fast

It’s all about expanding your horizon

Developer responsibility horizon

•Dude, it compiles!• It works on my machine•All tests pass•QA approved it• It’s working in production

“We don’t know, man, we just don’t know.” The confident Nick of months prior shook now, leading Fred to his cubicle. “We coded the application. We debugged until it compiled without errors. When we run it- core dump!” He threw up his hands, then dropped into his swivel chair. “We’ve been pestering IBM support, but they haven’t been very helpful.”“Well, why would they be?” Fred frowned, pausing at the cube threshold. “I mean, who knows what might be wrong with the code?”“Nothing’s wrong with it. It compiles!”“So? It could still have errors.”Nick swiveled around to face him. “Dude. It compiles.”

«Nothing at facebook is anyone elses problem» - Kent Beck (Is TDD dead –part 3)

12.04.2023

The deployment pipeline

/ 11

12.04.2023

Test coverage

/ 12

http://www.industrieit.com/blog/2012/02/a-practical-guide-to-extending-continuous-integration-to-continuous-delivery/http://jamescrisp.org/2011/05/30/automated-testing-and-the-test-pyramid/

12.04.2023

Blue-green deployment

/ 13

Jez Humble: “Continous Delivery” http://www.slideshare.net/jezhumble/continuous-delivery-5359386

12.04.2023

Blue-green deployment

/ 14

Jez Humble: “Continous Delivery” http://www.slideshare.net/jezhumble/continuous-delivery-5359386

12.04.2023

Blue-green deployment

/ 15

Jez Humble: “Continous Delivery” http://www.slideshare.net/jezhumble/continuous-delivery-5359386

12.04.2023

Blue-green deployment

/ 16

Jez Humble: “Continous Delivery” http://www.slideshare.net/jezhumble/continuous-delivery-5359386

12.04.2023

Canary releasing

/ 17

Jez Humble: “Four principles or Low-Risk Software releases” http://www.informit.com/articles/article.aspx?p=1833567

12.04.2023

The arguments

/ 18

12.04.2023

The arguments

/ 19

• Before: ~30 minutes• After: 4 minutes• 4 times per day• Time spent: 8 hours• Days until investment time paid:

12.04.2023 / 20

12.04.2023

DEPLOYING A WEBSITE

/ 21

12.04.2023

Basic asp.net mvc4 website

<hgroup class="title"> <h1>Welcome to ASP.NET Web API!</h1> <br /> <h2>

@WebApiApplication.Environment - @WebApiApplication.Version

</h2></hgroup>

/ 22

12.04.2023

Web.Development.config

<?xml version="1.0"?><configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <appSettings> <add key="Environment" value="Development“

xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/> </appSettings></configuration>

/ 23

12.04.2023

Creating the Octopus NuGet package

• Why NuGet?– Metadata– Lots of available tools– Feed-based– Developers know how to use them– Already used for other purposes (check out chocolatey.org)

• Does NOT use the default NuGet conventions– Octopus deploys the exact structure of the package

/ 24

12.04.2023

mvc4webapi.nuspec

<?xml version="1.0"?><package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>Itera.NDC2013.TCOD.Web</id> <title>ASP.NET MVC 4 Web Api demo site</title> <version>1.0.0</version> <authors>Kristoffer Rolf Deinoff</authors> <owners>Kristoffer Rolf Deinoff</owners> <licenseUrl>http://itera.no</licenseUrl> <projectUrl>http://itera.no</projectUrl> <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>A sample project</description> <releaseNotes>First release</releaseNotes> </metadata></package>

/ 25

12.04.2023

Using OctoPack

/ 26

12.04.2023

Using TeamCity

/ 27

12.04.2023

Using NuGet.exe

nuget.exe pack $nuspecFileName-OutputDirectory $contentDir-Version $version

/ 28

12.04.2023

Configuring TeamCity

/ 29

12.04.2023

Configuring TeamCity – Commit build

/ 30

12.04.2023

Configuring TeamCity – VCS root

/ 31

12.04.2023

Configuring TeamCity – Patch AssemblyInfo

/ 32

12.04.2023

Configuring TeamCity - Compile

/ 33

12.04.2023

Configuring TeamCity – Commit tests

/ 34

12.04.2023

Configuring TeamCity – Trigger on check-in

/ 35

12.04.2023

Configuring TeamCity – Build artifacts

/ 36

12.04.2023

Configuring TeamCity – NuGet Server

/ 37

12.04.2023

Configuring TeamCity – NuGet Server

/ 38

12.04.2023

Configuring OctopusDeploy - Environments

/ 39

12.04.2023

Configuring OctopusDeploy – NuGet server

/ 40

12.04.2023

Configuring OctopusDeploy – Steps

/ 41

12.04.2023

Configuring OctopusDeploy – Publish website

/ 42

12.04.2023

Configuring OctopusDeploy – Publish website

/ 43

12.04.2023

Configuring OctopusDeploy – Smoke test

/ 44

$url = ("http://" + $hostname + ":" + $port + "/")

Invoke-WebRequest $url -UseBasicParsing

12.04.2023

Configuring OctopusDeploy – UAT Verification

/ 45

12.04.2023

Configuring OctopusDeploy – Variables

/ 46

12.04.2023

Configuring OctopusDeploy – Security

/ 47

12.04.2023

Configuring OctopusDeploy – Security

/ 48

12.04.2023

Configuring TeamCity – Integration build

/ 49

12.04.2023

Configuring TeamCity – Dependencies

/ 50

12.04.2023

Configuring TeamCity – Create release

/ 51

12.04.2023

Configuring TeamCity – Integration tests

/ 52

$url = ("http://tcod-build:8080/")

$TeamCitySession = New-Object Microsoft.PowerShell.Commands.WebRequestSessionInvoke-WebRequest -Uri $url -WebSession $TeamCitySession -UseBasicParsing

12.04.2023

DEPLOYING A SERVICE

/ 53

12.04.2023

Asp.net mvc webapi as a service

/ 54

<appSettings> <add key="Environment" value="Local" /> <add key="Hostname" value="localhost" /> <add key="Port" value="8989" /> </appSettings>

12.04.2023

And then…

/ 55

12.04.2023

Differences - Steps

/ 56

12.04.2023

Differences - Publish service

/ 57

12.04.2023

Differences - Variables

/ 58

12.04.2023

Differences - Automated «Acceptance test»

/ 59

$url = ("http://tcod-build:8090/api/version")

$TeamCitySession = New-Object Microsoft.PowerShell.Commands.WebRequestSession$response = Invoke-WebRequest -Uri $url -WebSession $TeamCitySession -UseBasicParsing

if ($response.Content.Contains("Development")){ Write-Host "Correct environment(Development)."}else{ Write-Host Environment 'Development' not found. Exit 1}$buildNumber = $env:build_numberif ($response.Content.Contains($buildNumber)){ Write-Host "Correct build number($buildNumber)."}else{ Write-Host Build number '$buildNumber' not found. Exit 1}

12.04.2023

WRITING POWERSHELLS SCRIPTS

/ 60

12.04.2023

Deploy.config

/ 61

<?xml version="1.0"?><configuration>

<name>MyProject</name><nuGet>

<url>"http://www.myget.org/F/MyProject/"</url><apiKey>xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</apiKey><username>myUser</username><password>myPassword</password>

</nuGet></configuration>

12.04.2023

CreateOctopusPackage.ps1

/ 62

param ([string]$contentDir, [string]$version)

try{ $configFile = New-Object XML $configFile.Load('Deploy.config') $config = $configFile.configuration

$nuspecFileName = $config.name+'.nuspec' $targetNuspecFileName = Join-Path $contentDir $nuspecFileName

.\nuget.exe pack $targetNuspecFileName-OutputDirectory $contentDir-Version $version

}catch { Write-Error $error[0] Exit 1}

12.04.2023

PublishNuGet.ps1

/ 63

param ([string]$contentDir, [string]$version)

try{ $configFile = New-Object XML $configFile.Load('Deploy.config') $config = $configFile.configuration $nugetFileName = $config.name+'.'+$version+'.nupkg'

nuget sources Add -Name $config.name -Source $config.nuGet.url -Username $config.nuGet.username -Password $config.nuGet.password

nuget push $nugetFileName $config.nuGet.apiKey -Source $config.name nuget sources Remove -Name $config.name}catch { Write-Error $error[0] Exit 1}

12.04.2023

CreateMSDeployPackage.ps1

/ 64

param ([string]$sourceDir, [string]$targetPackage)

$BuildDir = (Split-Path $MyInvocation.MyCommand.Path -Parent) $msdeploy = $BuildDir + "\msdeploy.exe" $parameterFile = $BuildDir + "\parameters.xml"

$msdeploy_params = " -verb:sync"$msdeploy_params += " -source:contentPath=" + $sourceDir$msdeploy_params += " -dest:package=" + $targetPackage$msdeploy_params += " -declareParamFile:" + $parameterFile

Write-Host "creating '$targetPackage' from '$sourceDir'."try { iex "$msdeploy $msdeploy_params"}catch { Write-Error $error[0] Exit 1}

12.04.2023

Deploy.ps1

/ 65

. .\DeployUtil.ps1

$ServiceName = "Itera.NDC2013.TCOD.Service"$ServiceExecutable = $ServiceName + ".exe"

Install-WebApi-Service $ServiceName $ServiceExecutable

12.04.2023

DeployUtil.ps1

/ 66

function Install-WebApi-Service($name, $executable) { Write-Host "'$name'$executable'" $service = Get-Service $name -ErrorAction SilentlyContinue $fullPath = Resolve-Path $executable

if (! $service) { Write-Host "Installing service" $frameworkDir = Get-FrameworkDirectory Set-Alias install_util (Join-Path $frameworkDir "installutil.exe") install_util $fullPath } else { Write-Host "The service will be stopped and reconfigured" Stop-Service $name -Force & "sc.exe" config $service.Name binPath= $fullPath start= auto } $config = $executable + ".config" $port = Get-Port $config Set-User-Rights $port "NT AUTHORITY\NETWORK SERVICE" Write-Host "Starting service" Start-Service $name | Write-Host}

12.04.2023

DeployUtil.ps1

/ 67

function Get-FrameworkDirectory {$([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory())}

function Set-User-Rights($port, $user) { $uri = "http://+:$port/" $acls = (netsh http show urlacl url=$uri | Select-String -SimpleMatch $user) if ($acls.count -eq 0 ) { Write-Host "Setting rights for '$user' on $uri" netsh http add urlacl url=$uri user=$user | Write-Host } else { Write-Host "Rights already set for '$user' on $uri." }}

12.04.2023

DeployUtil.ps1

/ 68

function Get-Port($config){ Write-Host "Reading config file '$config'" $found = $FALSE $appConfig = [xml](cat .\$config) $appConfig.configuration.appSettings.add | foreach { if ($_.key -eq 'Port') { $port = $_.value $found = $TRUE } } if (-not $found) { $port = "8080“ } $($port)}

12.04.2023

AUTOMATING YOUR PROCESS

/ 69

12.04.2023

Automating your process

• Create environments and projects• Add all the automated build steps you can• Add manual steps for the rest• Automate manual steps one by one• You can have more than one tentacle on a server

– Not as a service

/ 70

12.04.2023

CONNECTING THE ISSUE TRACKER

/ 71

12.04.2023

Connecting the issue tracker

• Connect TeacmCity throught Settings – Issue Tracker• Connect your issue tracker to TeamCity• Use the Issue tracker’s web api to get issues pending user acceptance

– Add them to releasenotes while deploying

/ 72

Kristoffer Rolf DeinoffLead Technologist

@gatepoet kristoffer.deinoff@itera.no

Recommended