You’d typically attach a VCS trigger to your build to cause it to queue automatically when changes are detected via a VCS root, however, the trigger itself might not always fire as expected. Here’s why:
Triggers are actually more like events and therefore won’t fire for changes that were committed prior to the point the trigger was created or enabled.
Whilst this might seem obvious to most, it becomes less so when you’re disabling and re-enabling a trigger. Consider the following example:
- Bob pauses triggers on their build configuration to make some changes to the config; meanwhile:
- Fred pushes a commit to the remote, sits back and waits for his build to run
- Bob finishes his work and enables triggers on the build configuration once again
- Fred checks TeamCity and finds no build despite his change being listed as a “Pending Change” on the build config
- Jim pushes a new commit and suddenly a build queues up with both Fred and Jim’s changes
As you can see, it’s relatively easy for teams to get into a situation where their builds don’t trigger, but they can’t immediately see why.
In these situations the only options really are to queue up a build manually, or wait for a future change to fire the trigger. Given this, I’ve started checking pending changes after activating a build’s triggers again to see if I need to manually kick off a build to avoid confusion.
A key feature of TeamCity is the ability to define properties in a build. TeamCity implements a form of inheritance for properties. If you add a dependency to another build, you can reference properties on the referenced build just as if they belong to the build you’re configuring. This is extremely handy when you’re implementing any sort of pipeline as you can allow the source build (i.e. the build which triggered a build chain etc) to define a set of properties and then simply re-use these properties throughout your subsequent builds.
There is a gotcha in all this however, and it’s as follows; your dependency configuration is absolutely critical to being able to reference inherited parameters. By this I mean, if – when you’re configuring your dependant build configuration – it cannot resolve a suitable build at the time you’re configuring it, it won’t allow you to reference the dependency parameters. This is probably best illustrated with an example:
Say you’re defining a new build configuration for your new application Foo:
You define a couple of properties on your configuration, one to store a semantic version number and another to store the build configuration (e.g. Debug or Release):
Lets ignore the fact that these would probably be better placed in a template which your configuration implemented. Whilst good practise, it’s not all that relevant for this example.
Now lets say you want to define another build configuration to actually deploy your builds of Foo:
Now, lets say you don’t want all builds of Foo to be deployed, only the ones which the developers have marked up with a tag called “stable”. So you configure an artefact dependency which picks up the last successful build with that tag:
I realise this isn’t an entirely realistic scenario, but not outside of the realms of possibility. For reference; a better solution is to have the developers use the “Promote” functionality to promote the build they’d like to the deployment build configuration.
At this point you realise that you want to reuse the semantic version property you defined in your Foo build configuration so that your deployment builds of Foo show which version was deployed. Since you’ve already defined an artefact dependency, you try and reference the property using the normal syntax (e.g. “%dep.” etc):
Now, what you’d probably expect to see at this point is a list of properties which you could reference, but instead you get the dreaded “No suggestions found” tooltip. Odd. For the sake of the example, lets assume that this might just be a UI thing and manually type out the property as you expect it to be referred to in the dependant build:
However; now when you move to the properties of the deployment build configuration, you notice this:
This happens because TeamCity doesn’t understand how to resolve the property you’ve referenced so assumes you want to define it in this build! This is actually a very handy feature of TeamCity that means you can define all your build steps without having to think about all your properties first, but in this instance it just confuses things.
So what’s going on? Well, despite properties being defined on build templates/configurations, as far as dependencies are concerned properties actually exist on builds themselves (as in, a “run” of a build configuration). In our fictitious scenario, there aren’t actually any builds with the “stable” tag, so it doesn’t have anything to interrogate to work out which properties are available.
Lets run a quick build of Foo and mark it as stable:
And now, if we go back to the Deploy build configuration and try and resolve the property again:
Everything is good in the world!
When I first encountered this, I was utterly stumped as to why my properties weren’t showing up. It took a long time and many hours of frustration to work this behaviour out. I was so convinced that this wasn’t intentional that I raised a bug with JetBrains. The response was that this was “by design”. Obviously this is JetBrains’ prerogative, but – in my opinion – it doesn’t make a whole lot of sense. I understand that properties aren’t all defined in the build configuration or template itself and that some are only actually present once you run a build, but it seems like at least displaying the list of properties which are defined for the user to select would have been a half-way-house and avoid this confusion.