At $DAYWORK, we are using TeamCity to automate our release process. For each release, we have a set of independent builds. For the example, we will call them “Windows”, “Mac” and “Linux”. They are build from the same source code, and have the same version string for a given release.
On a release day, we want to press the “Run” button on a “Release” build in TeamCity, enter the version string (like v1.2), and that from them on, the following happens automatically:
- “Windows” is triggered with the version string as parameter
- “Mac” is triggered with the version string as parameter
- “Linux” is triggered with the version string as parameter
- All builds use the same source code, as selected
- If one of the build fails, “Release” fails too
Most of this is easy. “Release” has “Windows”, “Mac” and “Linux” as snapshot dependencies, and a “version_string” parameter of type “prompt”.
The problem is now: how to pass the version string entered by the user from “Release” to the dependencies ? TeamCity supports passing the parameters between dependencies via the dep.* parameters, but only in the other direction.
I contacted the support from JetBrains, and while TeamCity doesn’t support this use case directly, there is a workaround, documented here for the record.
The trick is to separate the preparation from the execution. There are 2 builds in addition to the 3 “real” ones:
The role of “Initialize” is to capture:
- the version string
- the revisions to use from the VCS root
While “Execute”s role is to actually execute the 3 builds.
“Initialize” has a build parameter “version_string”, of kind “prompt”, that cannot be empty, and its VCS roots are the ones used by the 3 builds.
The 3 builds have a snapshot dependency to “Initialize”. That allows them to get the right revisions, and access to the version string through “dep.Initialize.version_string”.
“Execute” has snapshot dependencies to the 3 builds and “Initialize”.
With this configuration, you can start “Initialize” manually, enter the version_string. That will not trigger the 3 builds. You have to do this manually, by promoting the “Initalize” build to “Execute”. That will trigger the builds with the right revision and version_string.
But it’s easy to automate this: add a “Finish Build Trigger” to in “Execute”, watching “Initialize”.
Note that for this exact use case (release with a specific version string), you could also use an approach where the version string is not entered manually but retrieved automatically from a branch name, as described here.