• TeamCity conditional build configurations - master vs other branches

    TeamCity doesn’t currently support conditional build steps (Vote on this issue). So how can you have different steps for a master builds vs. other branches?

    This is not an uncommon scenario - you might want to perform similar build steps for all builds, but for a master build there may be some extra steps (eg. publishing NuGet/NPM packages to a repository, triggering an external activity) that you don’t want to run for a branch build (eg. a build for a pull request).

    It is possible to work around this limitation by creating multiple build configurations - one for master and another for non-master branches. But how can you do that efficiently? One approach is to enable Versioned Settings using Kotlin.

    Kotlin is a language created by JetBrains that targets the JVM (and is now the recommended language for Android development). But it’s also one of the language choices when you enable Versioned Settings in TeamCity. (The other is XML, which will look familiar if you’ve ever played with TeamCity’s meta-runners).

    I’m not a Kotlin expert, but I managed to figure out that you can use it to generate the different variations, such that when TeamCity parses the Kotlin, it ends up creating multiple build configurations.

    One thing to be aware of is that TeamCity parses the Kotlin up-front to create the build configurations. It doesn’t evaluate it as the build runs (so it isn’t possible to have an expression that tests an environment variable or parameter)

    The following example shows generating two build configurations - “Build_CI_Master” and “Build_CI_Branches”. The difference is that the Master build configuration enables package indexing. The build configurations use different branch filters to control whether they apply to master or non-master branches.

    <!– >

    import jetbrains.buildServer.configs.kotlin.v2018_2.*
    import jetbrains.buildServer.configs.kotlin.v2018_2.buildFeatures.nuGetPackagesIndexer
    import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.PowerShellStep
    import jetbrains.buildServer.configs.kotlin.v2018_2.buildSteps.powerShell
    import jetbrains.buildServer.configs.kotlin.v2018_2.projectFeatures.nuGetFeed
    import jetbrains.buildServer.configs.kotlin.v2018_2.triggers.vcs
    import jetbrains.buildServer.configs.kotlin.v2018_2.ui.*
    
    version = "2018.2"
    
    val variations = listOf("Master", "Branches")
    project {
    
        for (type in variations) {
            buildType(KotlinExample(type))
        }
    
        features {
            nuGetFeed {
                id = "repository-nuget-project_feed"
                name = "project_feed"
                description = ""
            }
        }
    }
    
    class KotlinExample(val variant: String) : BuildType({
        id("Build_CI_${variant}".toId())
    
        name = "CI $variant"
    
        buildNumberPattern = "1.0.%build.counter%"
    
        vcs {
            add(DslContext.settingsRoot.id!!)
        }
    
        triggers {
            add {
                vcs {
                    if (variant == "Master") {
                        branchFilter = "+:<default>"
                    } else {
                        branchFilter = """
                                +:*
                                -:<default>
                            """.trimIndent()
                    }
                }
            }
        }
    
        steps {
    
            step {
                /* additional steps */
            }
        }
    
        features {
            if (variant == "Master") {
                nuGetPackagesIndexer {
                    feed = "project_feed/project_feed"
                }
            }
        }
    })
    
    

  • Global DevOps Bootcamp 2019

    Yesterday (Saturday 15th) was the 3rd Global DevOps Bootcamp we’ve run in Adelaide.

    Selfie Using the great facilities of the University of South Australia, a bunch of people gathered to learning more about DevOps, and in particular this year on the ‘Run’ part of DevOps, including introducing the role of a Site Reliability Engineer (SRE).

    The day started off with a recorded introduction from international event organisers, then a keynote from Niall Murphy (Microsoft Ireland Director of Engineering for Azure Cloud Services and Site Reliability Engineering), followed by a local keynote delivered by me.

    Keynote

    After this people got into teams and worked through different challenges relating to a mythical online car-parts company that was experiencing all kinds of problems in production. Teams were encouraged to follow the pattern of ‘Detect, Respond and Recover’ - identifying the problem, putting in a quick fix to get the website back up and then implementing a long-term solution to prevent the problem from reoccurring.

    Team challenges

    The teams worked through the rest of the day, doing a great job on the challenges. The light-hearted video introductions to each challenge were a new thing this year and were a nice touch.

    All credit to Rene, Marcel, Mathias and their team of helpers who put all the content together and coordinated a massive global event together with Microsoft.

    Microsoft provided Subway for lunch and special thanks to my employer RLDatix who picked up the tab for fresh coffees for all attendees.

  • An Iced Vo Vo surprise

    Those who know me really well know that one of my favourite biscuits is Arnott’s Iced Vo Vos.

    Iced Vo Vos.jpg By Bilby - Own work, CC BY-SA 3.0, Link

    I’m not sure why - I just really enjoy the combination of the sweet biscuit base with pink icing, coconut and jam. A winning combination.

    Recently Arnott’s have been looking to diversify their product range and I saw with interest that they now have Iced Vo Vo flavoured milk and Iced Vo Vo flavoured chocolate!

    Imagine my surprise when I got home from work this week to discover a block of the latter waiting for me on my bed (together with a clever Origami bow).

    Iced Vo Vo Chocolate My youngest daughter was hanging around and asked me to guess who got it for me..

    My wife? No

    My sister? No

    My friend Andrew? No

    I was stumped.

    It was later that night that my wife tipped me off that actually it had been my daughter all along who’d bought for me with her own money! What a beautiful (and yummy) gift!