Get branch information for SVcsModification

In a plugin we are trying to determine the changes which are contained in a build and figured out that 

final List<SVcsModification> modifications = runningBuild.getChanges( SelectPrevBuildPolicy.SINCE_LAST_SUCCESSFULLY_FINISHED_BUILD, false );
for ( final SVcsModification modification : modifications ) {

allows you to iterate over the modifications contained in the build since the last successful one. But what we are interested in are only the changes since the last successful build which are on a specific branch. The reason here is that e.g. a feature branch gets created from the develop and maybe the last build on develop (which is the default branch) was not successful. In this case the changes on develop prior to the branching point are not interesting.

Is there any way to achieve this and determine which branch a modification belongs to?



1 comment
Comment actions Permalink


there is no method for that out of the box, but I believe you can achieve what you want using so called BuildPromotion (every build has one, you can get it using the getBuildPromotion() method [1]. Having a build promotion you can call getPreviousBuildPromotion() [2] with same policy as for computing changes. If the previous promotion has different branch [3], then you can iterate though builds, until you reach the default branch.

Code may look like this:

BuildPromotion promotion = build.getPromotion();
BuildPromotion prevSuccessful = promotion.getPreviousBuildPromotion(SelectPrevBuildPolicy.SINCE_LAST_SUCCESSFULLY_FINISHED_BUILD);
if (Objects.equals(promotion.getBranch(), prevSuccessful.getBranch())) {
return promotion.getChanges(SelectPrevBuildPolicy.SINCE_LAST_SUCCESSFULLY_FINISHED_BUILD, false);
} else {
List<SVcsModification> result = new ArrayList<>();
do {
BuildPromotion prev = promotion.getPreviousBuildPromotion(SelectPrevBuildPolicy.SINCE_LAST_FINISHED_BUILD);
if (Objects.equals(prev.getBranch(), build.getBranch())) {
result.addAll(promotion.getChanges(SelectPrevBuildPolicy.SINCE_LAST_FINISHED_BUILD, false));
promotion = prev;
} while (Objects.equals(promotion.getBranch(), build.getBranch()));
return result;

You can also analyze a commit graph using non-open API [4] which can be changed or removed between TeamCity versions. In this case code may look like this (it assumes that the build configuration has only 1 VCS root and that VCS provides information about commit graph, e.g. it is git or mercurial):

VcsModificationHistoryEx vcsHistory; //get it as a Spring dependency
RepositoryStateManager repositoryStateManager; //get it as a Spring dependency

VcsRootInstance root = build.getVcsRootEntries().get(0).getVcsRoot();
DAG<Long> dag = vcsHistory.getModificationIdDag(root);
RepositoryState state = repositoryStateManager.getRepositoryState(root);
String defaultBranchRevision = state.getDefaultBranchRevision();
if (defaultBranchRevision != null) {
SVcsModification defaultBranchCommit = vcsHistory.findModificationByVersion(root, defaultBranchRevision);
if (defaultBranchCommit != null) {
ReachabilityPredicate predicate = VcsDAGs.createReachabilityPredicate(dag);
List<SVcsModification> result = new ArrayList<>();
for (SVcsModification change : build.getChanges(SelectPrevBuildPolicy.SINCE_LAST_SUCCESSFULLY_FINISHED_BUILD, false)) {
if (predicate.isInteresting(change.getId()))
return result;

[1] method


Please sign in to leave a comment.