More Related Content Similar to Automated release management with team city & octopusdeploy - NDC 2013 (20) More from Kristoffer Deinoff (6) Automated release management with team city & octopusdeploy - NDC 20136. It’s all about frequent releases
14.06.2013 / 6
John Allspaw: “Ops metametrics” http://slidesha.re/dsSZIr
It’s all about failing fast
8. Test coverage
14.06.2013 / 8
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/
13. Canary releasing
14.06.2013 / 13
Jez Humble: “Four principles or Low-Risk Software releases” http://www.informit.com/articles/article.aspx?p=1833567
18. Basic asp.net mvc4 website
<hgroup class="title">
<h1>Welcome to ASP.NET Web API!</h1>
<br />
<h2>
@WebApiApplication.Environment -
@WebApiApplication.Version
</h2>
</hgroup>
14.06.2013 / 18
20. 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
14.06.2013 / 20
40. Configuring OctopusDeploy – Smoke test
14.06.2013 / 40
$url = ("http://" + $hostname + ":" + $port + "/")
Invoke-WebRequest $url -UseBasicParsing
48. Configuring TeamCity – Integration tests
14.06.2013 / 48
$url = ("http://tcod-build:8080/")
$TeamCitySession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
Invoke-WebRequest -Uri $url -WebSession $TeamCitySession -UseBasicParsing
50. Asp.net mvc webapi as a service
14.06.2013 / 50
<appSettings>
<add key="Environment" value="Local" />
<add key="Hostname" value="localhost" />
<add key="Port" value="8989" />
</appSettings>
55. Differences - Automated «Acceptance test»
14.06.2013 / 55
$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_number
if ($response.Content.Contains($buildNumber)){
Write-Host "Correct build number($buildNumber)."
}
else{
Write-Host Build number '$buildNumber' not found.
Exit 1
}
57. Deploy.config
14.06.2013 / 57
<?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>
58. CreateOctopusPackage.ps1
14.06.2013 / 58
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
}
59. PublishNuGet.ps1
14.06.2013 / 59
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
}
60. CreateMSDeployPackage.ps1
14.06.2013 / 60
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
}
61. Deploy.ps1
14.06.2013 / 61
. .DeployUtil.ps1
$ServiceName = "Itera.NDC2013.TCOD.Service"
$ServiceExecutable = $ServiceName + ".exe"
Install-WebApi-Service $ServiceName $ServiceExecutable
62. DeployUtil.ps1
14.06.2013 / 62
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 AUTHORITYNETWORK SERVICE"
Write-Host "Starting service"
Start-Service $name | Write-Host
}
63. DeployUtil.ps1
14.06.2013 / 63
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."
}
}
64. DeployUtil.ps1
14.06.2013 / 64
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)
}
66. 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
14.06.2013 / 66
68. 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
14.06.2013 / 68