Starting with TeamCity 8.x you can now “extract” repetitive tasks into build runners, called meta-runners, that you can re-use without the need for coding a plugin, or as JetBrains themselves like to put it:
With a meta-runner, you can easily reuse existing runners, create new runners for typical tasks (e.g. publish to FTP, delete directory, etc.), you can simplify your build configuration and decrease a number of build steps.
With this post I aim to show you how I learned how to create such meta-runners and the take-aways from the process that someone else might experience from.
So, the first step in creating a meta-runner is of course that you got a build step that you think other build configurations could benefit from. Or maybe you have already started to copy the step/s between build configurations…that’s probably a god indicator.
A meta-runner is in itself usually a little “mini-process” inside your bigger delivery process. Let’s see an example:
There I have some build step that uses PSGet to install the Pester PS module onto the build server. I see that in some other places I can re-use the PowerShell code I’ve written to install other types of PowerShell modules in the same manner. A PSGet Installer idea is born.
The first thing I need to do is to “generalize” the PowerShell code a bit.
That essentially means that I need to identify places where I have hard-coded values and extract these into TeamCity parameters (%[Parameter]%):
When I’ve done this the parameters will show up on the ‘Build Parameters’ page and you can use the UI to edit the specification of your parameters (easier than working with the generated xml).
Create the meta-runner
OK, now that you’re done with the parameters you think you need just extract the meta-runner. I’ve extracted mine to the <ROOT> project because I want it available to all my projects.
Once you’ve extracted the definition it’s available through the UI (you can even edit the generated xml) and as an xml file on the TC server.
UI or XML?
This is how far I usually go with using the UI. This is where I usually copy that xml file from the server and start working with it offline (so to say).
And remember, it doesn’t matter if you update the UI xml view or the actual xml file…TeamCity will pick up the changes you make anyway.
One disadvantage of using the UI to extract the meta-runner is that if your build configuration, from where you extracted from, has multiple steps all of them will be included in the extracted xml along with all the build parameters etc. In short, you probably need to perform a bit of cleanup in the xml. Just saying…
Just a word or two about the definition xml.
From the xml structure above you can see that on top we have our parameters that defined earlier. Please also note the specification, spec, of the parameters that we defined through the UI earlier.
Here it is pretty easy to create new ones, which I usually do via the UI and copy the spec into the xml.
Next is the actual build runner (OOB) that we based the meta-runner off of. In my case it’s the PowerShell runner. And therefore…it’s a bunch of script in the xml. I usually extract that code into a file of its own simply because it’s easier to work with than inside the xml. I then copy from the external file into the xml…just my flavor of doing it.
I usually create a ‘playground’, test project, where I can try out my meta-runner before I “ship it” so to say. Test it in isolation.
Ain’t that pretty…all the parameters I’ve created show up within the UI, just like any other build runner. Try that TFS Team Build 😉
A meta-runner is based on a definition file (xml) so once you have such a file put it into <TeamCity Data Directory>/config/projects/<Project ID>/pluginData/metaRunners/ directory.
<Project ID> is the identifier of a project where you want to place the meta-runner. If you want it available globally use the <Root> project.
note: you can find the location of the TC Data Directory through the TC parameters. Mine was at: C:\ProgramData\JetBrains\TeamCity\
Once you place the file on disk, TeamCity will detect it and load the meta-runner, no server restart is required. If the meta-runner is loaded successfully you should see its name in the list of build runners on build configuration ‘Build Steps’ page.
And now you can use them as ‘regular’ build steps.
I think meta-runners is a great feature and I will probably use it more and more. I’ve created a repo up on GitHub with some of the runners that I’ve created.
The code for the PSGet runner that I’ve created during this post is there as well as others. Check it out!
Update 2013-10-13: The meta-runners I’ve created are now part of the JetBrains meta-runner power-pack.