Creating a changelog file in TeamCity

As part of the deployment process it’s good to know what changes is in every build. The first step to accomplish this is to create a changelog file.
To-do that as part of the build process in TeamCity we need to write some custom PowerShell scripts.

Step 1 Create an authorization head that we can use to call the TeamCity REST API. This can be one time off task or be part of the final script.

$acctname = "username";
$password = "password";
$header = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$($acctname):$($password)"));

Step 2 Add an parameter named “ChangelogFile” with the full file path for the new changelog file. For example “%env.TMP%\Changelog.txt”

Step 3 Add a new build PowerShell build step for the build.

Step 4 Add bellow script

$buildId = %teamcity.build.id%
$teamCityUrl = "http://fsdfdsfsd:8088"
$header = @{ "Authorization" = "Basic cWc1KT1SZXbbb3c4" }
$buildChangesUrl = $teamCityUrl + "/httpAuth/app/rest/changes?build=id:" + $buildId
 
$buildChangesResponse = Invoke-WebRequest $buildChangesUrl -Headers $header | select -ExpandProperty Content
$changesList = ([Xml]$buildChangesResponse).GetElementsByTagName("change")
 
$stream = [System.IO.StreamWriter] "%ChangelogFile%"
Foreach ($buildChange in $changesList)
{    
    $changeUrl = $teamCityUrl  + $buildChange.href
    $changeResponse = Invoke-WebRequest $changeUrl -Headers $header | select -ExpandProperty Content
    $change = ([Xml]$changeResponse).GetElementsByTagName("change")
    $version = $change.version
    $user =$change.username
    $comment = $change.GetElementsByTagName("comment").InnerXml
    $stream.WriteLine("Commit #" +$version + " :: " + $user)
    $stream.WriteLine("Comment:" + $comment)
 
    $stream.WriteLine("Files:")
    $files = $change.GetElementsByTagName("file")
    Foreach ($file in $files)
    {
        $stream.WriteLine($file.file)
    }
    $stream.WriteLine("")
}
$stream.Flush()
$stream.close()

Step 5 Add this file to the artefact output, nuget package or attach the data to an Octopus Deploy release note for example.

Change vmsize for a azure cloud service in octopus deploy

A common cases when running a test/staging and production environment using Azure Cloud Service is that you don’t want to use the same vmsize for all environments. It can actual be very expensive. To solve this we need to-do some variable substitution in the azure cloud service package. Doing variable substitution on ServiceConfiguration.XXX.cscfg is done by default when using the built in template “Deploy an Azure Cloud Service” but it doesn’t support variable substitution on ServiceDefinition.csde by default where the vmsize is defined. To accomplish this we need to create a pre-deployment PowerShell script.

1. In you process step based on “Deploy an Azure Cloud Service” click on enable features
2. Check mark “Custom deployment scripts” and apply the change
3. You can now add script for pre-deployment, deployment, and post-deployment.
4. The last thing is to add the variable Deploy.WebApiRoleVMSize setting the vmsize you want for different scope or environments.

Add this scrip to the “Pre-deployment” section and replace “NNN” with the name of the webrole.

write-host "Starting Service Definition rewrite" 
 
$def = "ServiceDefinition\ServiceDefinition.csdef"
 
$csdeffile = Get-Item $def 
[xml]$csdefcontent = get-content $csdeffile 
 
#Find the webrole we want in a multi-webrole cloud service. Assume this exists 
$webrole = $csdefcontent.ServiceDefinition.WebRole | where {$_.name -eq "NNNN"}
 
##Update the vmsize. Add if not available 
$webrole.SetAttribute("vmsize",$OctopusParameters['Deploy.WebApiRoleVMSize']) 
write-host "Using VMSize '" $OctopusParameters['Deploy.WebApiRoleVMSize'] "' for NNNNN"
 
#Save the changes 
$csdefcontent.Save($csdeffile.FullName)
 
write-host "Service Definition rewrite successful"