Quantcast
Channel: Dibbus.com
Viewing all articles
Browse latest Browse all 18

Teamcity and Octopus – part 4

$
0
0

Before rushing into all the cool automated stuff we have to dive into one important part of the flow which is… version control. You must use verion control for all your software! Period! At this moment there are lots of free version control systems available, Bitbucket, GitHub etc. Use it!
Besides the need of a VCS for Software devcelopment, I think every developer must have some a certain level of VCS knowledge. This is so important. Knowing how to handle branches, how to merge, what a tag is etc.
My advise to all developers is to dive into GIT. All major software will using GIT. Know Git, dream Git!!!
(It can cause serious nightmares too….beware)

Because this is not a Git course, I’m just writing about the concept and the importance of the VCS.

While using Git and working for a big-ass enterprise web application(well, not in our example but I think when you are using tools like TeamCity and Octopus deploy, you are not working on a personal WordPress blog) you might consider using Git-flow which is an excellent workflow system within Git. Git-flow is actually a set of predefined Git macro’s. Using Git-flow you can automate the process of creating feature branches, merge branches, create tags and releases.

Because we are using Git, we can use some meta information and use it in conjunction with NuGet. If you’ve read my previous post about creating a NuGet package you know how to create a NuGet package based upon a NuSpec file, remember?
At this point Git seems nothing to do with this process, that true. But we can use the power of Git to get some information of the project and put it into the NuSpec file.
NuSpec files is actually a definition of the package which will be generated. You can put all kind of information in this file like, Version, Title, Description and also Release notes.
Because we are working with with Octopus Deploy which is heavily based upon NuGet packages we must put as many information in the package as possible. The name, title and description seems logical, we can put it in the file itself as a static value. But what about the release notes?

One of my colleagues once said: “the best developer is a lazy developer“. Which is certainly true. However, I am not the best developer and am far from lazy. I just love to automate stuff!!!

Inserting release notes in every deployment is just not my cup of tea. Why not use information which is already there? Well, these are actually not release notes but I think we can get close.
I’m talking about the VCS commit messages. Collecting the commits from a release outputs a nice collection of changes which can be interpreted as release notes, kind of 😉

So, how can we get the release notes then?
First we have to get back to Git-flow. Git-flow is very strict in the use of different branch types. When a new release is heading to production, we can ‘Start a Release’ which will create a Release branch. We can deploy this branch to production and ‘Finish the release’ to merge it back to the master and develop branch.
Because it is a release branch a tag will be created so we have a snapshot of that release. And that is exactly what we need.
When we create a new release, at that point we need two branches to get the ‘release notes':

  1. the current release branch
  2. the tag of the previous release, which is the latest tag.

So, we can use Git log to generate the differences between both branches. That’s pretty awesome!

But… we can create great methods to deliver the best output, we must not forget that all this stuff is running in Teamcity. We have to make sure our buildserver must understand what we have designed hence Teamcity must have Git installed(which seems obvious). What we need to do is run a script that will put the release notes into the NuSpec file. To do that, we have two options:

  1. Create a powershell script and put the release notes in a Teamcity parameter.
  2. Create a powershell script and replace the release notes in the NuSpec file itself(NuSpec is just an xml file).

The easiest way is the first one, just put the output into a Teamcity variable and use it in Teamcity. However, I was facing an issue when used in conjunction with Octopus Deploy. The problem was the format, I had to use a new line(return) in my release notes to get the release notes nicely formatted in Octopus Deploy which is using a MarkDown syntax for their interface.

My Release notes had to be formatted like:
* release note 1
* release note 2
* etc.

Instead of:
* release note 1 * release note 2 * etc.
Teamcity was not able to use the first format because of the newlines. So, head over to our second option and ignore the Teamcity issues

Okay, we need a powershell script to:
1. run a Git Log
2. collect the commit messages
3. find the nuspec file in our checkout directory
4. open the nuspec file
5. find the element
6. remove the element
7. create a new element, containing the release notes
8. insert the new element
9. save the nuspec file

That’s a pretty impressive list, just for some release notes, well due to the power of Powershell, it is not that difficult 😉

And remember, this script runs on the buildserver! But we can test it locally first to check all the variables. After testing and checking the script, replace the variables by Teamcity parameter and you are good to go!

So, here’s just a simple powershell script which runs on the buildserver and is responsible for getting the commit messages between the latest tag and the current release branch and put into a variable:

param(   
    [Parameter(Mandatory = $true, HelpMessage="NuSpec filepath")]    
    [System.String]$nuspecFilePath
    )

[string]$currentBranch = git rev-parse --abbrev-ref HEAD
[string]$latestTag = git describe --abbrev=0 --tags

# Check for release branch
if($currentBranch.StartsWith('release/') -or $currentBranch.StartsWith('hotfix/')){

    Write-Output "Current $currentBranch"
    Write-Output "Tag $latestTag"

    $cmd = "git log --no-merges --pretty=format:""* %h - %s __[%an]__"" $latestTag..$currentBranch"
    $log = Invoke-Expression $cmd  

    if($log){  
        [string]$temp = $log
        $formatted = $temp
        Write-Output "Release notes:"
        Write-Output "----------------------------------"
        Write-Output $formatted.Replace(" * ", "`n* ")
        Write-Output "----------------------------------"       
    }

    #get nuspec file path
    $path = $nuspecFilePath
        
    if($path){
       [xml]$xml = Get-Content $path
       $parentNode = $xml.SelectSingleNode("//metadata")  
        $node = $xml.SelectSingleNode("//releaseNotes")        
        
        # remove existing releasenotes node
        if ($node -ne $null) {
            $parentNode = $node.ParentNode         
            $node.ParentNode.RemoveChild($node)
        } 

        # create new node
        $relNotes = $xml.CreateElement('releaseNotes')
        $relNotes.InnerText = $formatted.Replace(" * ", "`n* ")
        $parentNode.AppendChild($relNotes)
        
        # save nuspec file
        $xml.Save($path)
            
        Write-Output "NuSpec updated"
        
    } else {
        Write-Output "NuSpec file not found"
    }
}

I’ve included some Write-Output lines to view the output in the TeamCity logs.

Important to look at is the command to get the Git Log:

First define the two branches:

[string]$currentBranch = git rev-parse --abbrev-ref HEAD
[string]$latestTag = git describe --abbrev=0 --tags

And run a git log using a ‘pretty’ to format the messages:

$cmd = "git log --no-merges --pretty=format:""* %h - %s __[%an]__"" $latestTag..$currentBranch"
$log = Invoke-Expression $cmd

I’ve excluded the merge comments. You can remove the –no-merges to include the merge messages.

If all is running fine you will get a list like:

gitlog[screenshot from our buildserver]

I’ve created a powershell script in my scripts folder and added to git, so the file is just in my repository and can be used by Teamcity.

This script also extracts the version number from my release which is not that difficult. Just get the release branch, remove the ‘release-‘ prefix and you have the version number, add it to a Teamcity parameter and you can use it when Teamcity is creating the package.

More of that in the next post. I think we’ve handled all the boring stuff, up to the automated stuff!!!!!


Viewing all articles
Browse latest Browse all 18

Trending Articles