This is an automated email from the ASF dual-hosted git repository.

dpavlov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git


The following commit(s) were added to refs/heads/master by this push:
     new 6d33d12  IGNITE-11994: Prepare new view to select base branch and 
other build parameters: Observe VISA for alternative branches - Fixes #134.
6d33d12 is described below

commit 6d33d12d02b550aca3a34cb2d94024029342b97c
Author: Dmitriy Pavlov <[email protected]>
AuthorDate: Thu Jul 18 20:46:21 2019 +0300

    IGNITE-11994: Prepare new view to select base branch and other build 
parameters: Observe VISA for alternative branches - Fixes #134.
    
    Signed-off-by: Dmitriy Pavlov <[email protected]>
---
 .../apache/ignite/ci/observer/BuildObserver.java   |  13 +-
 .../org/apache/ignite/ci/observer/BuildsInfo.java  |  22 ++-
 .../ignite/ci/observer/CompactBuildsInfo.java      |   9 +
 .../apache/ignite/ci/observer/ObserverTask.java    |   4 +-
 .../tcbot/visa/TcBotTriggerAndSignOffService.java  | 160 +++++++++++-------
 .../apache/ignite/ci/tcbot/visa/VisaStatus.java    |   3 +
 .../org/apache/ignite/ci/web/model/Version.java    |   2 +-
 .../ignite/ci/web/rest/GetTrackedBranches.java     |  42 ++++-
 .../apache/ignite/ci/web/rest/TriggerBuilds.java   |  14 +-
 .../ignite/ci/web/rest/visa/TcBotVisaService.java  |   6 +-
 .../src/main/webapp/buildtime.html                 |   5 +-
 .../src/main/webapp/js/common-1.6.js               |   1 +
 ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js |   3 +-
 .../src/main/webapp/js/testfails-2.2.js            |  75 ++++++---
 ignite-tc-helper-web/src/main/webapp/pr.html       |  76 +++++++--
 ignite-tc-helper-web/src/main/webapp/prs.html      |   7 +-
 ignite-tc-helper-web/src/main/webapp/tracked.html  | 181 +++++++++++++++++++++
 ignite-tc-helper-web/src/main/webapp/visas.html    |   5 +
 .../ci/tcbot/chain/PrChainsProcessorTest.java      |  10 +-
 .../ignite/tcbot/engine/conf/TcBotJsonConfig.java  |   7 +-
 .../ignite/tcbot/engine/pr/PrChainsProcessor.java  |  71 +++++---
 .../tracked/IDetailedStatusForTrackedBranch.java   |   2 +
 .../apache/ignite/tcbot/engine/ui/DsChainUi.java   |  10 +-
 .../apache/ignite/tcbot/engine/ui/DsSummaryUi.java |   4 +-
 24 files changed, 565 insertions(+), 167 deletions(-)

diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildObserver.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildObserver.java
index c2f3028..26f69bc 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildObserver.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildObserver.java
@@ -19,6 +19,7 @@ package org.apache.ignite.ci.observer;
 
 import java.util.Objects;
 import java.util.Timer;
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 import org.apache.ignite.ci.tcbot.ITcBotBgAuth;
 import org.apache.ignite.tcservice.model.result.Build;
@@ -93,13 +94,15 @@ public class BuildObserver {
 
     /**
      * @param srvId Server id.
-     * @param prov Credentials.
-     * @param branchForTc Branch for TC.
      * @param ticket JIRA ticket name.
+     * @param branchForTc Branch for TC.
+     * @param baseBranchForTc Base branch in TC identification.
+     * @param userName
      */
-    public void observe(String srvId, ITcBotUserCreds prov, String ticket, 
String branchForTc, String parentSuiteId,
-                        Build... builds) {
-        BuildsInfo buildsInfo = new BuildsInfo(srvId, prov, ticket, 
branchForTc, parentSuiteId, builds);
+    public void observe(String srvId, String ticket, String branchForTc, 
String parentSuiteId,
+        @Nullable String baseBranchForTc, String userName,
+        Build... builds) {
+        BuildsInfo buildsInfo = new BuildsInfo(srvId, ticket, branchForTc, 
parentSuiteId, baseBranchForTc, userName, builds);
 
         observerTask.addInfo(buildsInfo);
     }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildsInfo.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildsInfo.java
index 3fbb3ea..7d6a623 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildsInfo.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/BuildsInfo.java
@@ -24,12 +24,12 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
-import org.apache.ignite.tcservice.model.result.Build;
-import org.apache.ignite.tcbot.persistence.IStringCompactor;
-import org.apache.ignite.tcignited.ITeamcityIgnited;
+import javax.annotation.Nullable;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
-import org.apache.ignite.ci.user.ITcBotUserCreds;
 import org.apache.ignite.ci.web.model.ContributionKey;
+import org.apache.ignite.tcbot.persistence.IStringCompactor;
+import org.apache.ignite.tcignited.ITeamcityIgnited;
+import org.apache.ignite.tcservice.model.result.Build;
 
 /**
  * Represents parameters to determine context of observed builds, list of 
build IDs which were requested for observing
@@ -65,6 +65,9 @@ public class BuildsInfo {
     /** */
     public final Date date;
 
+    /** Base TC Branch name. */
+    @Nullable public final String baseBranchForTc;
+
     /** Finished builds. */
     private final List<Integer> builds = new ArrayList<>();
 
@@ -76,25 +79,28 @@ public class BuildsInfo {
         this.ticket = strCompactor.getStringFromId(compactBuildsInfo.ticket());
         this.branchForTc = 
strCompactor.getStringFromId(compactBuildsInfo.branchForTc());
         this.buildTypeId = 
strCompactor.getStringFromId(compactBuildsInfo.buildTypeId());
+        this.baseBranchForTc = 
strCompactor.getStringFromId(compactBuildsInfo.baseBranchForTc());
         this.builds.addAll(compactBuildsInfo.getBuilds());
     }
 
     /**
+     * @param userName
      * @param srvId Server id.
-     * @param prov Prov.
      * @param branchForTc Branch for TC.
      * @param ticket Ticket.
      * @param builds Builds.
      */
-    public BuildsInfo(String srvId, ITcBotUserCreds prov, String ticket, 
String branchForTc, String parentSuiteId,
-                      Build... builds) {
-        this.userName = prov.getUser(srvId);
+    public BuildsInfo(String srvId, String ticket, String branchForTc, String 
parentSuiteId,
+        @Nullable String baseBranchForTc, String userName,
+        Build... builds) {
+        this.userName = userName;
         this.date = Calendar.getInstance().getTime();
         this.srvId = srvId;
         this.ticket = ticket;
         this.branchForTc = branchForTc;
         this.buildTypeId = Strings.isNullOrEmpty(parentSuiteId) ?
             (builds.length == 1 ? builds[0].buildTypeId : 
"IgniteTests24Java8_RunAll") : parentSuiteId;
+        this.baseBranchForTc = baseBranchForTc;
 
         for (Build build : builds)
             this.builds.add(build.getId());
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/CompactBuildsInfo.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/CompactBuildsInfo.java
index 9a526f6..26ecbf7 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/CompactBuildsInfo.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/CompactBuildsInfo.java
@@ -43,6 +43,9 @@ public class CompactBuildsInfo {
     /** JIRA ticket full name. */
     private int ticket;
 
+    /** Base branch ID. By default represents null */
+    private int baseBranchForTc = -1;
+
     /** */
     private Date date;
 
@@ -62,6 +65,7 @@ public class CompactBuildsInfo {
         this.ticket = strCompactor.getStringId(buildsInfo.ticket);
         this.branchForTc = strCompactor.getStringId(buildsInfo.branchForTc);
         this.buildTypeId = strCompactor.getStringId(buildsInfo.buildTypeId);
+        this.baseBranchForTc = 
strCompactor.getStringId(buildsInfo.baseBranchForTc);
         this.builds.addAll(buildsInfo.getBuilds());
     }
 
@@ -185,6 +189,11 @@ public class CompactBuildsInfo {
     }
 
     /** */
+    public int baseBranchForTc() {
+        return baseBranchForTc;
+    }
+
+    /** */
     public void addBuild(int... arr) {
         for (int i = 0; i < arr.length; i++)
             builds.add(arr[i]);
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/ObserverTask.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/ObserverTask.java
index b45c5d2..3064252 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/ObserverTask.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/observer/ObserverTask.java
@@ -184,8 +184,10 @@ public class ObserverTask extends TimerTask {
                 Visa visa = 
visasHistStorage.getLastVisaRequest(info.getContributionKey()).getResult();
 
                 if (!visa.isSuccess()) {
+                    String baseBranchForTc = info.baseBranchForTc;
+
                     Visa updatedVisa = visaIssuer.notifyJira(info.srvId, 
creds, info.buildTypeId,
-                        info.branchForTc, info.ticket);
+                        info.branchForTc, info.ticket, baseBranchForTc);
 
                     
visasHistStorage.updateLastVisaRequest(info.getContributionKey(), (req -> 
req.setResult(updatedVisa)));
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
index da034a0..2a9b971 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
@@ -36,33 +36,13 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.annotation.Nonnull;
 import javax.inject.Inject;
-import javax.ws.rs.QueryParam;
-
-import org.apache.ignite.tcbot.engine.pr.BranchTicketMatcher;
-import org.apache.ignite.tcservice.ITeamcity;
 import org.apache.ignite.ci.github.GitHubBranch;
 import org.apache.ignite.ci.github.GitHubUser;
 import org.apache.ignite.ci.github.PullRequest;
-import org.apache.ignite.githubignited.IGitHubConnIgnited;
-import org.apache.ignite.githubignited.IGitHubConnIgnitedProvider;
-import org.apache.ignite.jiraignited.IJiraIgnited;
-import org.apache.ignite.jiraignited.IJiraIgnitedProvider;
-import org.apache.ignite.jiraservice.Ticket;
 import org.apache.ignite.ci.observer.BuildObserver;
 import org.apache.ignite.ci.observer.BuildsInfo;
 import org.apache.ignite.ci.tcbot.ITcBotBgAuth;
-import org.apache.ignite.tcbot.engine.pr.PrChainsProcessor;
-import org.apache.ignite.tcbot.common.conf.IGitHubConfig;
-import org.apache.ignite.tcbot.common.conf.IJiraServerConfig;
-import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
-import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
-import org.apache.ignite.tcservice.model.mute.MuteInfo;
-import org.apache.ignite.tcservice.model.result.Build;
 import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
-import org.apache.ignite.tcbot.persistence.IStringCompactor;
-import org.apache.ignite.tcignited.ITeamcityIgnited;
-import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
-import org.apache.ignite.tcignited.SyncMode;
 import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeCompacted;
 import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeRefCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
@@ -72,11 +52,29 @@ import org.apache.ignite.ci.web.model.JiraCommentResponse;
 import org.apache.ignite.ci.web.model.SimpleResult;
 import org.apache.ignite.ci.web.model.Visa;
 import org.apache.ignite.ci.web.model.VisaRequest;
-import org.apache.ignite.tcbot.engine.ui.DsSuiteUi;
-import org.apache.ignite.tcbot.engine.ui.DsTestFailureUi;
-import org.apache.ignite.tcbot.engine.ui.DsHistoryStatUi;
 import org.apache.ignite.ci.web.model.hist.VisasHistoryStorage;
+import org.apache.ignite.githubignited.IGitHubConnIgnited;
+import org.apache.ignite.githubignited.IGitHubConnIgnitedProvider;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.jiraignited.IJiraIgnited;
+import org.apache.ignite.jiraignited.IJiraIgnitedProvider;
+import org.apache.ignite.jiraservice.Ticket;
+import org.apache.ignite.tcbot.common.conf.IGitHubConfig;
+import org.apache.ignite.tcbot.common.conf.IJiraServerConfig;
+import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
+import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
+import org.apache.ignite.tcbot.engine.pr.BranchTicketMatcher;
+import org.apache.ignite.tcbot.engine.pr.PrChainsProcessor;
+import org.apache.ignite.tcbot.engine.ui.DsHistoryStatUi;
+import org.apache.ignite.tcbot.engine.ui.DsSuiteUi;
+import org.apache.ignite.tcbot.engine.ui.DsTestFailureUi;
+import org.apache.ignite.tcbot.persistence.IStringCompactor;
+import org.apache.ignite.tcignited.ITeamcityIgnited;
+import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
+import org.apache.ignite.tcignited.SyncMode;
+import org.apache.ignite.tcservice.ITeamcity;
+import org.apache.ignite.tcservice.model.mute.MuteInfo;
+import org.apache.ignite.tcservice.model.result.Build;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
@@ -144,12 +142,12 @@ public class TcBotTriggerAndSignOffService {
     }
 
     /** */
-    public List<VisaStatus> getVisasStatus(String srvId, ITcBotUserCreds prov) 
{
+    public List<VisaStatus> getVisasStatus(String srvCode, ITcBotUserCreds 
prov) {
         List<VisaStatus> visaStatuses = new ArrayList<>();
 
-        ITeamcityIgnited ignited = tcIgnitedProv.server(srvId, prov);
+        ITeamcityIgnited tcIgn = tcIgnitedProv.server(srvCode, prov);
 
-        IJiraIgnited jiraIntegration = jiraIgnProv.server(srvId);
+        IJiraIgnited jiraIntegration = jiraIgnProv.server(srvCode);
 
         for (VisaRequest visaRequest : visasHistStorage.getVisas()) {
             VisaStatus visaStatus = new VisaStatus();
@@ -166,10 +164,11 @@ public class TcBotTriggerAndSignOffService {
             visaStatus.ticket = info.ticket;
             visaStatus.buildTypeId = info.buildTypeId;
 
-            BuildTypeRefCompacted bt = 
ignited.getBuildTypeRef(info.buildTypeId);
+            BuildTypeRefCompacted bt = tcIgn.getBuildTypeRef(info.buildTypeId);
             visaStatus.buildTypeName = (bt != null ? bt.name(compactor) : 
visaStatus.buildTypeId);
+            visaStatus.baseBranchForTc = info.baseBranchForTc;
 
-            String buildsStatus = visaStatus.status = info.getStatus(ignited, 
strCompactor);
+            String buildsStatus = visaStatus.status = info.getStatus(tcIgn, 
strCompactor);
 
             if (FINISHED_STATUS.equals(buildsStatus)) {
                 if (visa.isSuccess()) {
@@ -189,7 +188,7 @@ public class TcBotTriggerAndSignOffService {
                 visaStatus.status = buildsStatus;
 
             if (isObserving)
-                visaStatus.cancelUrl = "/rest/visa/cancel?server=" + srvId + 
"&branch=" + info.branchForTc;
+                visaStatus.cancelUrl = "/rest/visa/cancel?server=" + srvCode + 
"&branch=" + info.branchForTc;
 
             visaStatuses.add(visaStatus);
         }
@@ -249,7 +248,7 @@ public class TcBotTriggerAndSignOffService {
     }
 
     @NotNull public String triggerBuildsAndObserve(
-        @Nullable String srvId,
+        @Nullable String srvCodeOrAlias,
         @Nullable String branchForTc,
         @Nonnull String parentSuiteId,
         @Nonnull String suiteIdList,
@@ -257,12 +256,13 @@ public class TcBotTriggerAndSignOffService {
         @Nullable Boolean observe,
         @Nullable String ticketId,
         @Nullable String prNum,
+        @Nullable String baseBranchForTc,
         @Nullable ITcBotUserCreds prov) {
         String jiraRes = "";
 
-        ITeamcityIgnited teamcity = tcIgnitedProv.server(srvId, prov);
+        ITeamcityIgnited teamcity = tcIgnitedProv.server(srvCodeOrAlias, prov);
 
-        IGitHubConnIgnited ghIgn = gitHubConnIgnitedProvider.server(srvId);
+        IGitHubConnIgnited ghIgn = 
gitHubConnIgnitedProvider.server(srvCodeOrAlias);
 
         if(!Strings.isNullOrEmpty(prNum)) {
             try {
@@ -289,7 +289,7 @@ public class TcBotTriggerAndSignOffService {
             builds[i] = teamcity.triggerBuild(suiteIds[i], branchForTc, false, 
top != null && top, new HashMap<String, Object>());
 
         if (observe != null && observe)
-            jiraRes += observeJira(srvId, branchForTc, ticketId, prov, 
parentSuiteId, builds);
+            jiraRes += observeJira(srvCodeOrAlias, branchForTc, ticketId, 
prov, parentSuiteId, baseBranchForTc, builds);
 
         return jiraRes;
     }
@@ -299,6 +299,7 @@ public class TcBotTriggerAndSignOffService {
      * @param branchForTc Branch for TeamCity.
      * @param ticketFullName JIRA ticket number.
      * @param prov Credentials.
+     * @param baseBranchForTc Reference branch in TC identification.
      * @param builds Builds.
      * @return Message with result.
      */
@@ -308,6 +309,7 @@ public class TcBotTriggerAndSignOffService {
         @Nullable String ticketFullName,
         ITcBotUserCreds prov,
         String parentSuiteId,
+        String baseBranchForTc,
         Build... builds
     ) {
         try {
@@ -320,7 +322,11 @@ public class TcBotTriggerAndSignOffService {
                 + e.getMessage();
         }
 
-        buildObserverProvider.get().observe(srvId, prov, ticketFullName, 
branchForTc, parentSuiteId, builds);
+        String user = prov.getUser(srvId);
+        if (user == null)
+            user = prov.getPrincipalId();
+
+        buildObserverProvider.get().observe(srvId, ticketFullName, 
branchForTc, parentSuiteId, baseBranchForTc, user, builds);
 
         if (!tcBotBgAuth.isServerAuthorized())
             return "Ask server administrator to authorize the Bot to enable 
JIRA notifications.";
@@ -333,14 +339,16 @@ public class TcBotTriggerAndSignOffService {
      * @param branchForTc Branch for tc.
      * @param suiteId Suite id.
      * @param ticketFullName Ticket full name with IGNITE- prefix.
+     * @param baseBranchForTc base branch in TC identification
      * @param prov Prov.
      */
     @NotNull
     public SimpleResult commentJiraEx(
-        @QueryParam("serverId") @Nullable String srvId,
-        @QueryParam("branchName") @Nullable String branchForTc,
-        @QueryParam("suiteId") @Nullable String suiteId,
-        @QueryParam("ticketId") @Nullable String ticketFullName,
+        @Nullable String srvId,
+        @Nullable String branchForTc,
+        @Nullable String suiteId,
+        @Nullable String ticketFullName,
+        @Nullable String baseBranchForTc,
         ITcBotUserCreds prov) {
 
         try {
@@ -348,10 +356,14 @@ public class TcBotTriggerAndSignOffService {
         }
         catch (BranchTicketMatcher.TicketNotFoundException e) {
             logger.info("", e);
-            return new SimpleResult("JIRA wasn't commented.<br>" + 
e.getMessage());
+            return new SimpleResult("JIRA wasn't commented: 
TicketNotFoundException: <br>" + e.getMessage());
         }
 
-        BuildsInfo buildsInfo = new BuildsInfo(srvId, prov, ticketFullName, 
branchForTc, suiteId);
+        String user = prov.getUser(srvId);
+        if (user == null)
+            user = prov.getPrincipalId();
+
+        BuildsInfo buildsInfo = new BuildsInfo(srvId, ticketFullName, 
branchForTc, suiteId, baseBranchForTc, user);
 
         VisaRequest lastVisaReq = 
visasHistStorage.getLastVisaRequest(buildsInfo.getContributionKey());
 
@@ -360,7 +372,7 @@ public class TcBotTriggerAndSignOffService {
                 " \"Re-run possible blockers & Comment JIRA\" was triggered 
for current branch." +
                 " Wait for the end or cancel exsiting observing.");
 
-        Visa visa = notifyJira(srvId, prov, suiteId, branchForTc, 
ticketFullName);
+        Visa visa = notifyJira(srvId, prov, suiteId, branchForTc, 
ticketFullName, baseBranchForTc);
 
         visasHistStorage.put(new VisaRequest(buildsInfo).setResult(visa));
 
@@ -726,7 +738,7 @@ public class TcBotTriggerAndSignOffService {
         CurrentVisaStatus status = new CurrentVisaStatus();
 
         List<DsSuiteUi> suitesStatuses
-            = prChainsProcessor.getBlockersSuitesStatuses(buildTypeId, 
tcBranch, srvCode, prov, SyncMode.NONE);
+            = prChainsProcessor.getBlockersSuitesStatuses(buildTypeId, 
tcBranch, srvCode, prov, SyncMode.NONE, null);
 
         if (suitesStatuses == null)
             return status;
@@ -745,6 +757,7 @@ public class TcBotTriggerAndSignOffService {
      * @param buildTypeId Build type ID, for which visa was ordered.
      * @param branchForTc Branch for TeamCity.
      * @param ticket JIRA ticket full name. E.g. IGNITE-5555
+     * @param baseBranchForTc Base branch in TC identification
      * @return {@link Visa} instance.
      */
     public Visa notifyJira(
@@ -752,8 +765,8 @@ public class TcBotTriggerAndSignOffService {
         ITcBotUserCreds prov,
         String buildTypeId,
         String branchForTc,
-        String ticket
-    ) {
+        String ticket,
+        @Nullable String baseBranchForTc) {
         ITeamcityIgnited tcIgnited = tcIgnitedProv.server(srvId, prov);
 
         IJiraIgnited jira = jiraIgnProv.server(srvId);
@@ -775,12 +788,15 @@ public class TcBotTriggerAndSignOffService {
         JiraCommentResponse res;
 
         try {
-            List<DsSuiteUi> suitesStatuses = 
prChainsProcessor.getBlockersSuitesStatuses(buildTypeId, build.branchName, 
srvId, prov);
+            String baseBranch = Strings.isNullOrEmpty(baseBranchForTc) ? 
prChainsProcessor.dfltBaseTcBranch(tcIgnited) : baseBranchForTc;
 
-            if (suitesStatuses == null)
-                return new Visa("JIRA wasn't commented - no finished builds to 
analyze.");
+            List<DsSuiteUi> suitesStatuses = 
prChainsProcessor.getBlockersSuitesStatuses(buildTypeId, build.branchName, 
srvId, prov,
+                SyncMode.RELOAD_QUEUED,
+                baseBranch);
 
-            String comment = generateJiraComment(suitesStatuses, build.webUrl, 
buildTypeId, tcIgnited);
+            if (suitesStatuses == null)
+                return new Visa("JIRA wasn't commented - no finished builds to 
analyze." +
+                    " Check builds availabiliy for branch: " + 
build.branchName + "/" + baseBranch);
 
             blockers = suitesStatuses.stream()
                 .mapToInt(suite -> {
@@ -791,6 +807,9 @@ public class TcBotTriggerAndSignOffService {
                 })
                 .sum();
 
+            String comment = generateJiraComment(suitesStatuses, build.webUrl, 
buildTypeId, tcIgnited, blockers, build.branchName, baseBranch);
+
+
             res = objMapper.readValue(jira.postJiraComment(ticket, comment), 
JiraCommentResponse.class);
         }
         catch (Exception e) {
@@ -810,25 +829,36 @@ public class TcBotTriggerAndSignOffService {
      * @param webUrl Build URL.
      * @param buildTypeId Build type ID, for which visa was ordered.
      * @param tcIgnited TC service.
+     * @param blockers Count of blockers.
+     * @param branchName TC Branch name, which was tested.
+     * @param baseBranch TC Base branch used for comment
      * @return Comment, which should be sent to the JIRA ticket.
      */
     private String generateJiraComment(List<DsSuiteUi> suites, String webUrl, 
String buildTypeId,
-                                       ITeamcityIgnited tcIgnited) {
+        ITeamcityIgnited tcIgnited, int blockers, String branchName, String 
baseBranch) {
         BuildTypeRefCompacted bt = tcIgnited.getBuildTypeRef(buildTypeId);
 
         String suiteNameUsedForVisa = (bt != null ? bt.name(compactor) : 
buildTypeId);
 
         StringBuilder res = new StringBuilder();
 
+        String baseBranchDisp = (Strings.isNullOrEmpty(baseBranch) || 
ITeamcity.DEFAULT.equals(baseBranch))
+            ? "master" :  baseBranch ;
         for (DsSuiteUi suite : suites) {
-            
res.append("{color:#d04437}").append(jiraEscText(suite.name)).append("{color}");
-            res.append(" [[tests ").append(suite.failedTests);
+            res.append("{color:#d04437}");
+
+            res.append(jiraEscText(suite.name)).append("{color}");
+
+            int totalBlockerTests = suite.testFailures.size();
+            res.append(" [[tests ").append(totalBlockerTests);
 
             if (suite.result != null && !suite.result.isEmpty())
                 res.append(' ').append(suite.result);
 
             res.append('|').append(suite.webToBuild).append("]]\\n");
 
+            int cnt = 0;
+
             for (DsTestFailureUi failure : suite.testFailures) {
                 res.append("* ");
 
@@ -842,31 +872,47 @@ public class TcBotTriggerAndSignOffService {
                 if (recent != null) {
                     if (recent.failureRate != null) {
                         res.append(" - ").append(recent.failureRate).append("% 
fails in last ")
-                            .append(recent.runs).append(" master runs.");
+                            .append(recent.runs).append(" 
").append(jiraEscText(baseBranchDisp)).append(" runs.");
                     }
                     else if (recent.failures != null && recent.runs != null) {
                         res.append(" - ").append(recent.failures).append(" 
fails / ")
-                            .append(recent.runs).append(" master runs.");
+                            .append(recent.runs).append(" 
").append(jiraEscText(baseBranchDisp)).append(" runs.");
                     }
                 }
 
                 res.append("\\n");
+
+                cnt++;
+                if (cnt > 10) {
+                    res.append("... and ").append(totalBlockerTests - 
cnt).append(" tests blockers\\n");
+
+                    break;
+                }
             }
 
             res.append("\\n");
         }
 
+        String suiteNameForComment = jiraEscText(suiteNameUsedForVisa);
+
+        String branchNameForComment = jiraEscText("Branch: [" + branchName + 
"] ");
+
+        String baseBranchForComment = jiraEscText("Base: [" + baseBranchDisp + 
"] ");
+        String branchVsBaseComment = branchNameForComment + 
baseBranchForComment;
+
         if (res.length() > 0) {
-            res.insert(0, "{panel:title=" + jiraEscText(suiteNameUsedForVisa) 
+ ": Possible Blockers|" +
-                "borderStyle=dashed|borderColor=#ccc|titleBGColor=#F7D6C1}\\n")
+            String hdrPanel = "{panel:title=" + branchVsBaseComment + ": 
Possible Blockers (" + blockers + ")|" +
+                "borderStyle=dashed|borderColor=#ccc|titleBGColor=#F7D6C1}\\n";
+
+            res.insert(0, hdrPanel)
                 .append("{panel}");
         }
         else {
-            
res.append("{panel:title=").append(jiraEscText(suiteNameUsedForVisa)).append(": 
No blockers found!|")
+            res.append("{panel:title=").append(branchVsBaseComment).append(": 
No blockers found!|")
                 
.append("borderStyle=dashed|borderColor=#ccc|titleBGColor=#D6F7C1}{panel}");
         }
 
-        res.append("\\n").append("[TeamCity 
*").append(jiraEscText(suiteNameUsedForVisa)).append("* 
Results|").append(webUrl).append(']');
+        res.append("\\n").append("[TeamCity 
*").append(suiteNameForComment).append("* Results|").append(webUrl).append(']');
 
         return xmlEscapeText(res.toString());
     }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/VisaStatus.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/VisaStatus.java
index 7347894..20fac4b 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/VisaStatus.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/VisaStatus.java
@@ -51,5 +51,8 @@ public class VisaStatus {
     @Nullable public String buildTypeName;
 
     /** */
+    @Nullable public String baseBranchForTc;
+
+    /** */
     public int blockers;
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
index f7b95d6..aa3d063 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/Version.java
@@ -28,7 +28,7 @@ package org.apache.ignite.ci.web.model;
     public static final String GITHUB_REF = 
"https://github.com/apache/ignite-teamcity-bot";;
 
     /** TC Bot Version. */
-    public static final String VERSION = "20190717";
+    public static final String VERSION = "20190718";
 
     /** Java version, where Web App is running. */
     public String javaVer;
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
index 67e210f..cdb687f 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
@@ -22,6 +22,7 @@ import com.google.inject.Injector;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.annotation.Nullable;
 import javax.annotation.security.PermitAll;
 import javax.servlet.ServletContext;
@@ -38,10 +39,13 @@ import org.apache.ignite.ci.tcbot.TcBotGeneralService;
 import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
 import org.apache.ignite.tcbot.engine.conf.ITrackedBranch;
 import org.apache.ignite.tcbot.engine.conf.ITrackedBranchesConfig;
+import org.apache.ignite.tcbot.engine.conf.ITrackedChain;
+import org.apache.ignite.tcignited.ITeamcityIgnited;
 import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.user.ITcBotUserCreds;
 import org.apache.ignite.ci.web.CtxListener;
 import org.apache.ignite.ci.web.model.Version;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Service for returning tracked branches, servers, and the bot version.
@@ -67,19 +71,23 @@ public class GetTrackedBranches {
     @GET
     @Path("getIds")
     public List<String> getIdsIfAccessible() {
+        Stream<ITrackedBranch> stream = accessibleTrackedBranches();
+        return stream
+                .map(ITrackedBranch::name)
+                .collect(Collectors.toList());
+    }
+
+    @NotNull public Stream<ITrackedBranch> accessibleTrackedBranches() {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
         Injector injector = CtxListener.getInjector(ctx);
         ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
         ITeamcityIgnitedProvider tcProv = 
injector.getInstance(ITeamcityIgnitedProvider.class);
 
         return cfg.getTrackedBranches().branchesStream()
-                .filter(bt ->
-                        bt.chainsStream().anyMatch(chain-> 
tcProv.hasAccess(chain.serverCode(), prov)))
-                .map(ITrackedBranch::name)
-                .collect(Collectors.toList());
+            .filter(bt ->
+                bt.chainsStream().anyMatch(chain -> 
tcProv.hasAccess(chain.serverCode(), prov)));
     }
 
-
     /**
      * Get Unique suites involved into tracked branches
      * @param trackedBranches
@@ -108,7 +116,7 @@ public class GetTrackedBranches {
             .stream()
             .filter(chainAtSrv ->
                 Strings.isNullOrEmpty(srvId)
-                    || srvId.equals(chainAtSrv.serverId))
+                    || srvId.equals(chainAtSrv.getServerId()))
             .filter(chainAtServer -> tcProv.hasAccess(chainAtServer.serverId, 
prov))
             .collect(Collectors.toSet());
     }
@@ -130,4 +138,26 @@ public class GetTrackedBranches {
             .collect(Collectors.toSet());
     }
 
+
+    /**
+     * Finds all registere unique teamcity branches.
+     * @param srvCodeOrAlias Server code or its alisas.
+     */
+    @GET
+    @Path("tcBranches")
+    public Set<String> tcBranches(@Nullable @QueryParam("srvCode") String 
srvCodeOrAlias) {
+        ITeamcityIgnited srv = CtxListener.getInjector(ctx)
+            .getInstance(ITeamcityIgnitedProvider.class)
+            .server(srvCodeOrAlias, ITcBotUserCreds.get(req));
+
+        String srvCode = srv.serverCode();
+
+        return accessibleTrackedBranches()
+            .flatMap(tb -> {
+                return tb.chainsStream().filter(tc ->
+                    Strings.isNullOrEmpty(srvCode)
+                        || srvCode.equals(tc.serverCode()));
+            })
+            .map(ITrackedChain::tcBranch).collect(Collectors.toSet());
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
index b2466ca..76c0a2b 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
@@ -61,26 +61,27 @@ public class TriggerBuilds {
     @GET
     @Path("trigger")
     public TriggerResult triggerBuilds(
-        @Nullable @QueryParam("serverId") String srvCode,
+        @Nullable @QueryParam("srvCode") String srvCodeOrAlias,
         @Nullable @QueryParam("branchName") String branchForTc,
         @Nonnull @QueryParam("parentSuiteId") String parentSuiteId,
         @Nonnull @QueryParam("suiteIdList") String suiteIdList,
         @Nullable @QueryParam("top") Boolean top,
         @Nullable @QueryParam("observe") Boolean observe,
         @Nullable @QueryParam("ticketId") String ticketId,
-        @Nullable @QueryParam("prNum") String prNum
+        @Nullable @QueryParam("prNum") String prNum,
+        @Nullable @QueryParam("baseBranchForTc") String baseBranchForTc
     ) {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
         Injector injector = CtxListener.getInjector(ctx);
 
-        
injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCode, prov);
+        
injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvCodeOrAlias,
 prov);
 
         if (isNullOrEmpty(suiteIdList))
             return new TriggerResult("Error: nothing to run.");
 
         String jiraRes = injector
             .getInstance(TcBotTriggerAndSignOffService.class)
-            .triggerBuildsAndObserve(srvCode, branchForTc, parentSuiteId, 
suiteIdList, top, observe, ticketId, prNum, prov);
+            .triggerBuildsAndObserve(srvCodeOrAlias, branchForTc, 
parentSuiteId, suiteIdList, top, observe, ticketId, prNum, baseBranchForTc, 
prov);
 
         return new TriggerResult("Tests started." + (!jiraRes.isEmpty() ? 
"<br>" + jiraRes : ""));
     }
@@ -97,7 +98,8 @@ public class TriggerBuilds {
         @Nullable @QueryParam("serverId") String srvCode,
         @Nullable @QueryParam("branchName") String branchForTc,
         @Nullable @QueryParam("suiteId") String suiteId,
-        @Nullable @QueryParam("ticketId") String ticketId
+        @Nullable @QueryParam("ticketId") String ticketId,
+        @Nullable @QueryParam("baseBranchForTc") String baseBranchForTc
     ) {
         ITcBotUserCreds prov = ITcBotUserCreds.get(req);
 
@@ -107,7 +109,7 @@ public class TriggerBuilds {
 
         return injector
             .getInstance(TcBotTriggerAndSignOffService.class)
-            .commentJiraEx(srvCode, branchForTc, suiteId, ticketId, prov);
+            .commentJiraEx(srvCode, branchForTc, suiteId, ticketId, 
baseBranchForTc, prov);
     }
 
     @GET
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
index fc997fe..a45a2d0 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java
@@ -64,14 +64,14 @@ public class TcBotVisaService {
     }
 
     /**
-     * @param srvId Server id.
+     * @param srvCode Server id.
      */
     @GET
     @Path("history")
-    public Collection<VisaStatus> history(@Nullable @QueryParam("serverId") 
String srvId) {
+    public Collection<VisaStatus> history(@Nullable @QueryParam("serverId") 
String srvCode) {
         return CtxListener.getInjector(ctx)
             .getInstance(TcBotTriggerAndSignOffService.class)
-            .getVisasStatus(srvId, ITcBotUserCreds.get(req));
+            .getVisasStatus(srvCode, ITcBotUserCreds.get(req));
     }
 
     /**
diff --git a/ignite-tc-helper-web/src/main/webapp/buildtime.html 
b/ignite-tc-helper-web/src/main/webapp/buildtime.html
index 7090beb..7c1b373 100644
--- a/ignite-tc-helper-web/src/main/webapp/buildtime.html
+++ b/ignite-tc-helper-web/src/main/webapp/buildtime.html
@@ -3,9 +3,6 @@
     <title>Apache Ignite Teamcity Bot - Build Time Analytics</title>
     <link rel="icon" href="img/leaf-icon-png-7066.png">
 
-    <link rel="stylesheet" 
href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css";>
-
-
     <script src="https://code.jquery.com/jquery-1.12.4.js";></script>
     <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js";></script>
 
@@ -16,8 +13,10 @@
 
     <script 
src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js";></script>
     <link 
href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
 rel="stylesheet">
+
     <link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css"; 
rel="stylesheet">
 
+    <link rel="stylesheet" 
href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css";>
     <link rel="stylesheet" href="css/style-1.5.css">
 
     <script src="js/common-1.6.js"></script>
diff --git a/ignite-tc-helper-web/src/main/webapp/js/common-1.6.js 
b/ignite-tc-helper-web/src/main/webapp/js/common-1.6.js
index 17cdad5..1f80079 100644
--- a/ignite-tc-helper-web/src/main/webapp/js/common-1.6.js
+++ b/ignite-tc-helper-web/src/main/webapp/js/common-1.6.js
@@ -169,6 +169,7 @@ function showMenu(menuData) {
         res += "<a href=\"/guard.html\" title='Monitoring: Current test 
failures in tracked Branches'>Test Status</a>";
         res += "<a href=\"/trends.html\" title='Monitoring: Test failures 
trends and graphs'>Master Trends</a>";
         res += "<a href=\"/longRunningTestsReport.html\" title='Monitoring: 
Long running tests report''>Test Durations</a>";
+        res += "<a href=\"/buildtime.html\" title='Top suites time 
usage'>Suite Durations</a>";
         res += "<a href=\"/compare.html\" title='Compare builds tests 
test'>Compare builds</a>";
         res += "<a href=\"/issues.html\" title='Detected issues list'>Issues 
history</a>";
         res += "<a href=\"/visas.html\" title='Issued TC Bot Visa 
history'>Visas history</a>";
diff --git a/ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js 
b/ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js
index a80622f..e92ab77 100644
--- a/ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js
+++ b/ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js
@@ -433,7 +433,8 @@ function showContributionStatus(status, prId, row, srvId, 
suiteIdSelected) {
                 "\"" + srvId + "\", " +
                 "\"" + finishedBranch + "\", " +
                 "\"" + suiteIdSelected + "\", " +
-                "\"" + row.jiraIssueId + "\"" +
+                "\"" + row.jiraIssueId + "\"," +
+                "\"\"" + // base TC branch
                 "); " +
                 replaintCall +
                 "'";
diff --git a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js 
b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
index 3af5429..88e9348 100644
--- a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
+++ b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
@@ -178,16 +178,19 @@ function showChainCurrentStatusData(chain, settings) {
         cntFailed++;
     }
 
-    if (suitesFailedList.length !== 0 && 
isDefinedAndFilled(chain.tcServerCode) && isDefinedAndFilled(chain.branchName)) 
{
+    //chain.tcServerCode can represent reference to a service generated using 
alias.
+    let srvCodeForTriggering = chain.serverCode;
+
+    if (suitesFailedList.length !== 0 && 
isDefinedAndFilled(srvCodeForTriggering) && 
isDefinedAndFilled(chain.branchName)) {
         moreInfoTxt += "Trigger failed " + cntFailed + " builds";
         moreInfoTxt += " <a href='javascript:void(0);' ";
-        moreInfoTxt += " onClick='triggerBuilds(\"" + chain.tcServerCode + 
"\", \"" + parentSuitId + "\", " +
-            "\"" + suitesFailedList + "\", \"" + chain.branchName + "\", 
false, false, null, \"" + chain.prNum + "\")' ";
+        moreInfoTxt += " onClick='triggerBuilds(\"" + srvCodeForTriggering + 
"\", \"" + parentSuitId + "\", " +
+            "\"" + suitesFailedList + "\", \"" + chain.branchName + "\", 
false, false, null, \"" + chain.prNum + "\", null)' ";
         moreInfoTxt += " title='trigger builds'>in queue</a> ";
 
         moreInfoTxt += " <a href='javascript:void(0);' ";
-        moreInfoTxt += " onClick='triggerBuilds(\"" + chain.tcServerCode + 
"\", \"" + parentSuitId + "\", " +
-            "\"" + suitesFailedList + "\", \"" + chain.branchName + "\", true, 
false, null, \"" + chain.prNum + "\")' ";
+        moreInfoTxt += " onClick='triggerBuilds(\"" + srvCodeForTriggering + 
"\", \"" + parentSuitId + "\", " +
+            "\"" + suitesFailedList + "\", \"" + chain.branchName + "\", true, 
false, null, \"" + chain.prNum + "\", null)' ";
         moreInfoTxt += " title='trigger builds'>on top</a><br>";
     }
 
@@ -241,10 +244,13 @@ function showChainCurrentStatusData(chain, settings) {
     //     res += "<button onclick='notifyGit()'>Update PR status</button>";
     // }
 
-    if (settings.isJiraAvailable() && isDefinedAndFilled(chain.serverCode)) {
-        let serverCode = chain.serverCode; //chain.tcServerCode can represent 
reference to a service generated using alias.
-        res += "<button onclick='commentJira(\"" + serverCode + "\", \"" + 
chain.branchName + "\", \""
-            + parentSuitId + "\")'>Comment JIRA</button>&nbsp;&nbsp;";
+    let baseBranchForTc = chain.baseBranchForTc;
+    if (settings.isJiraAvailable() && 
isDefinedAndFilled(srvCodeForTriggering)) {
+        res += "<button onclick='commentJira(\"" + srvCodeForTriggering + "\", 
" +
+            "\"" + chain.branchName + "\", " +
+            "\"" + parentSuitId + "\", " +
+            "\"\", " + // ticket id
+            "\"" + baseBranchForTc + "\")'>Comment JIRA</button>&nbsp;&nbsp;";
 
         var blockersList = "";
 
@@ -261,16 +267,33 @@ function showChainCurrentStatusData(chain, settings) {
             }
         }
 
-        res += "<button onclick='triggerBuilds(\"" + chain.tcServerCode + "\", 
\"" + parentSuitId + "\", \"" +
-            blockersList + "\", \"" + chain.branchName + "\", false, false, 
null,  \"" + + chain.prNum + "\")'> " +
+        res += "<button onclick='triggerBuilds(" +
+            "\"" + srvCodeForTriggering + "\", " +
+            "\"" + parentSuitId + "\", " +
+            "\"" + blockersList + "\", " +
+            "\"" + chain.branchName + "\", " +
+            "false, " + //top
+            "false, " + //observe
+            "null, " + // ticketId
+            "\"" + + chain.prNum + "\", " +
+            "\"" + baseBranchForTc + "\" " +
+            ")'> " +
             "Re-run possible blockers</button><br>";
 
-        res += "<button onclick='triggerBuilds(\"" + chain.tcServerCode + "\", 
\"" + parentSuitId + "\", \"" +
-            blockersList + "\", \"" + chain.branchName + "\", false, true, 
null, \"" + + chain.prNum +"\")'> " +
+        res += "<button onclick='triggerBuilds(" +
+            "\"" + srvCodeForTriggering + "\", " +
+            "\"" + parentSuitId + "\", " +
+            "\"" + blockersList + "\", " +
+            "\"" + chain.branchName + "\", " +
+            "false, " + //top
+            "true, " + //observe
+            "null, " + // ticketId
+            "\"" + chain.prNum + "\", " + //prNum
+            "\"" + baseBranchForTc + "\")'> " +
             "Re-run possible blockers & Comment JIRA</button><br>";
     }
 
-    if (isDefinedAndFilled(chain.baseBranchForTc)) {
+    if (isDefinedAndFilled(baseBranchForTc)) {
         // if (settings.isGithubAvailable())
         //     res+="<br>";
 
@@ -278,7 +301,7 @@ function showChainCurrentStatusData(chain, settings) {
             res += "<br>";
 
         res += "Base branch";
-        res += ": " + chain.baseBranchForTc.replace(/&/g, 
"&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+        res += ": " + baseBranchForTc.replace(/&/g, "&amp;").replace(/</g, 
"&lt;").replace(/>/g, "&gt;");
     }
 
     res += "&nbsp;</td></tr>";
@@ -373,7 +396,7 @@ function filterPossibleBlocker(suite) {
     return null;
 }
 
-function triggerBuilds(tcServerCode, parentSuiteId, suiteIdList, branchName, 
top, observe, ticketId, prNum) {
+function triggerBuilds(tcServerCode, parentSuiteId, suiteIdList, branchName, 
top, observe, ticketId, prNum, baseBranchForTc) {
     var queueAtTop = isDefinedAndFilled(top) && top;
     var observeJira = isDefinedAndFilled(observe) && observe;
     var suiteIdsNotExists = !isDefinedAndFilled(suiteIdList) || 
suiteIdList.length === 0;
@@ -430,14 +453,15 @@ function triggerBuilds(tcServerCode, parentSuiteId, 
suiteIdList, branchName, top
         $.ajax({
             url: 'rest/build/trigger',
             data: {
-                "serverId": tcServerCode,
+                "srvCode": tcServerCode,
                 "branchName": branchName,
                 "parentSuiteId" : parentSuite,
                 "suiteIdList": suiteIdList,
                 "top": queueAtTop,
                 "observe": observeJira,
                 "ticketId": ticketId,
-                "prNum": prNum
+                "prNum": prNum,
+                "baseBranchForTc": baseBranchForTc
             },
             success: successDialog,
             error: showErrInLoadStatus
@@ -479,7 +503,7 @@ function branchForTc(pr) {
     return pr;
 }
 
-function commentJira(serverCode, branchName, parentSuiteId, ticketId) {
+function commentJira(serverCode, branchName, parentSuiteId, ticketId, 
baseBranchForTc) {
     var branchNotExists = !isDefinedAndFilled(branchName) || branchName.length 
=== 0;
     branchName = branchNotExists ? null : branchForTc(branchName);
     ticketId = (isDefinedAndFilled(ticketId) && ticketId.length > 0) ? 
ticketId : null;
@@ -509,12 +533,13 @@ function commentJira(serverCode, branchName, 
parentSuiteId, ticketId) {
             "serverId": serverCode, //general Servers code
             "suiteId": parentSuiteId,
             "branchName": branchName,
-            "ticketId": ticketId
+            "ticketId": ticketId,
+            "baseBranchForTc": baseBranchForTc
         },
         success: function(result) {
             $("#notifyJira").html("");
 
-            var needTicketId = result.result.lastIndexOf("enter ticket id") 
!== -1;
+            var needTicketId = 
result.result.lastIndexOf("TicketNotFoundException") !== -1;
 
             if (needTicketId) {
                 var buttons = {
@@ -523,7 +548,7 @@ function commentJira(serverCode, branchName, parentSuiteId, 
ticketId) {
 
                         ticketId = $("#enterTicketId").val();
 
-                        commentJira(serverCode, branchName, parentSuiteId, 
ticketId)
+                        commentJira(serverCode, branchName, parentSuiteId, 
ticketId, baseBranchForTc)
                     },
                     "Cancel": function () {
                         $(this).dialog("close");
@@ -540,7 +565,7 @@ function commentJira(serverCode, branchName, parentSuiteId, 
ticketId) {
 
             var dialog = $("#triggerDialog");
 
-            dialog.html("Trigger builds at server: " + serverCode + "<br>" +
+            dialog.html("Comment ticket for server: " + serverCode + "<br>" +
                 " Suite: " + parentSuiteId + "<br>Branch:" + branchName +
                 "<br><br> Result: " + result.result +
                 (needTicketId ? ("<br><br>Enter JIRA ticket number: <input 
type='text' id='enterTicketId'>") : ""));
@@ -656,12 +681,12 @@ function showSuiteData(suite, settings, prNum) {
         mInfo += " Trigger build: ";
         mInfo += "<a href='javascript:void(0);' ";
         mInfo += " onClick='triggerBuilds(\"" + suite.serverId + "\", null, 
\"" +
-            suite.suiteId + "\", \"" + suite.branchName + "\", false, false, 
null, \"" + prNum + "\")' ";
+            suite.suiteId + "\", \"" + suite.branchName + "\", false, false, 
null, \"" + prNum + "\", null)' ";
         mInfo += " title='trigger build' >queue</a> ";
 
         mInfo += "<a href='javascript:void(0);' ";
         mInfo += " onClick='triggerBuilds(\"" + suite.serverId + "\", null, 
\"" +
-            suite.suiteId + "\", \"" + suite.branchName + "\", true, false, 
null, \"" + prNum + "\")' ";
+            suite.suiteId + "\", \"" + suite.branchName + "\", true, false, 
null, \"" + prNum + "\", null)' ";
         mInfo += " title='trigger build at top of queue'>top</a><br>";
     }
 
diff --git a/ignite-tc-helper-web/src/main/webapp/pr.html 
b/ignite-tc-helper-web/src/main/webapp/pr.html
index 01d644b..b9f097d 100644
--- a/ignite-tc-helper-web/src/main/webapp/pr.html
+++ b/ignite-tc-helper-web/src/main/webapp/pr.html
@@ -8,24 +8,65 @@
           
integrity="sha384-/rXc/GQVaYpyDdyxK+ecHPVYJSN9bmVFBvjA/9eOB+pb3F2w2N6fc5qB9Ew5yIns"
 crossorigin="anonymous">
     <script src="https://code.jquery.com/jquery-1.12.4.js";></script>
     <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js";></script>
+
+    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js";></script>
+    <!-- production version, optimized for size and speed -->
+    <!--<script src="https://cdn.jsdelivr.net/npm/vue";></script>-->
     <script src="js/common-1.6.js"></script>
     <script src="js/testfails-2.2.js"></script>
 </head>
 <body>
 <script>
     var g_shownDataHashCodeHex = "";
+    var gVue;
+
+    function showQueryForm() {
+        gVue = new Vue({
+            el: '#vueQueryForm',
+            data: {
+                baseBranchSelected: '',
+                tcBranchesForSrv: []
+            },
+            methods: {
+                formChanged: function () {
+                    checkForUpdate();
+                }
+            }
+        });
+
+        let srvCode = findGetParameter("serverId");
+        $.ajax({
+            url: "/rest/branches/tcBranches?srvCode=" + (srvCode == null ? "" 
: srvCode),
+            success: function (result) {
+                for (var i = 0; i < result.length; i++) {
+                    var id = result[i];
+                    gVue.$data.tcBranchesForSrv.push(id);
+                }
 
-$(document).ready(function() {
-    $.getScript("js/testfails-2.2.js", function(data, textStatus, jqxhr){ });
+                var baseBranchForTc = findGetParameter("baseBranchForTc");
+                if (baseBranchForTc != null) {
+                    gVue.$data.tcBranchesForSrv.push(baseBranchForTc);
+                    gVue.$data.baseBranchSelected = baseBranchForTc;
+                }
+            },
+            error: showErrInLoadStatus
+        });
 
-    $( document ).tooltip();
-    loadData();
-     //todo fix setInterval(checkForUpdate, 30000);
+    }
 
-    var branch = findGetParameter("branch");
 
-    $.ajax({ url: "rest/branches/version",  success: showVersionInfo, error: 
showErrInLoadStatus });
-});
+    $(document).ready(function () {
+        $.getScript("js/testfails-2.2.js", function (data, textStatus, jqxhr) 
{});
+
+        $(document).tooltip();
+        showQueryForm();
+        loadData();
+        //todo fix setInterval(checkForUpdate, 30000);
+
+        var branch = findGetParameter("branch");
+
+        $.ajax({url: "rest/branches/version", success: showVersionInfo, error: 
showErrInLoadStatus});
+    });
 
 function parmsForRest() {
     var curReqParms = "";
@@ -54,7 +95,7 @@ function parmsForRest() {
         curReqParms += "&count=" + count;
     }
 
-    var baseBranchForTc = findGetParameter("baseBranchForTc");
+    var baseBranchForTc =  gVue.$data.baseBranchSelected;
     if(baseBranchForTc != null) {
         curReqParms += "&baseBranchForTc=" + baseBranchForTc;
     }
@@ -151,10 +192,21 @@ function showData(result) {
 </script>
 
 <div id="loadStatus"></div>
-<div><a href=".">Home</a><br></div>
-<div id="divFailures"></div>
+<div id="vueQueryForm" class="h-25">
+    <v-app id="prQueryForm" name="prQueryForm" class="h-25">
+        <span>Base branch: </span>
+        <select v-model="baseBranchSelected" @change="formChanged">
+            <option disabled value="">Please select one</option>
+
+            <option v-for="option in tcBranchesForSrv" v-bind:value="option">
+                {{ option }}
+            </option>
+        </select>
+        <div id="divFailures"></div>
+    </v-app>
+</div>
 
 <div id="version"></div>
-<div style="visibility:none"><div id="triggerConfirm" title="Trigger 
Confirmation"></div><div id="triggerDialog" title="Trigger Result"></div></div>
+<div style="visibility:hidden"><div id="triggerConfirm" title="Trigger 
Confirmation"></div><div id="triggerDialog" title="Trigger Result"></div></div>
 </body>
 </html>
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/webapp/prs.html 
b/ignite-tc-helper-web/src/main/webapp/prs.html
index 9d168e3..473591a 100644
--- a/ignite-tc-helper-web/src/main/webapp/prs.html
+++ b/ignite-tc-helper-web/src/main/webapp/prs.html
@@ -180,8 +180,9 @@
             var branchName = fields.namedItem("branchForTc").value;
             var ticketId = fields.namedItem("ticketId").value;
 
-            //todo prNum
-            triggerBuilds(srvId, suiteId, branchName, false, trigCase !== 
"tests", ticketId);
+            let parentSuiteId  = suiteId;
+            let observe = trigCase !== "tests";
+            triggerBuilds(srvId, parentSuiteId , suiteId, branchName, false, 
observe, ticketId, null, null);
         }
 
         /**
@@ -195,7 +196,7 @@
             var branchName = fields.namedItem("branchForTc").value;
             var ticketId = fields.namedItem("ticketId").value;
 
-            commentJira(srvId, suiteId, branchName, ticketId)
+            commentJira(srvId, branchName, suiteId, ticketId, "");
         }
 
         function showFormAndSuitesForPrCheck(result) {
diff --git a/ignite-tc-helper-web/src/main/webapp/tracked.html 
b/ignite-tc-helper-web/src/main/webapp/tracked.html
new file mode 100644
index 0000000..3203e9b
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/webapp/tracked.html
@@ -0,0 +1,181 @@
+<html>
+<head>
+    <title>Apache Ignite Teamcity Bot - Tracked branch - Detailed status of 
failures</title>
+    <link rel="icon" href="img/leaf-icon-png-7066.png">
+
+    <script src="https://code.jquery.com/jquery-1.12.4.js";></script>
+    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js";></script>
+
+    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js";></script>
+    <!-- production version, optimized for size and speed -->
+    <!--<script src="https://cdn.jsdelivr.net/npm/vue";></script>-->
+
+    <script 
src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js";></script>
+   <link 
href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons"
 rel="stylesheet">
+
+    <link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css"; 
rel="stylesheet">
+
+    <link rel="stylesheet" 
href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css";>
+    <link rel="stylesheet" href="css/style-1.5.css">
+
+    <script src="js/common-1.6.js"></script>
+</head>
+<body>
+<script>
+    var g_shownDataHashCodeHex = "";
+    let gVue;
+
+    $(document).ready(function() {
+        $.getScript("js/testfails-2.2.js", function(data, textStatus, jqxhr){ 
});
+
+        $( document ).tooltip();
+        showQueryForm();
+
+        $.ajax({ url: "/rest/branches/version",  success: showVersionInfo, 
error: showErrInLoadStatus });
+    });
+
+    function showQueryForm() {
+        gVue = new Vue({
+            el: '#vueQueryForm',
+            data: {
+                baseBranchSelected: ''
+            },
+            methods: {
+                formChanged: function () {
+                    $("#divFailures").html(parmsForRest());
+                }
+            }
+        });
+    }
+
+
+    function parmsForRest() {
+        var curReqParms = "";
+        var branch = findGetParameter("branch");
+        if (branch != null) {
+            curReqParms += "?branch=" + branch;
+        }
+
+        if (gVue.$data.baseBranchSelected != null) {
+            curReqParms += "?baseBranch=" +  gVue.$data.baseBranchSelected;
+        }
+
+        var checkAllLogs = findGetParameter("checkAllLogs");
+        if (checkAllLogs != null) {
+            curReqParms += "&checkAllLogs=" + checkAllLogs;
+        }
+
+        var trustedTests = findGetParameter("trustedTests");
+        if (trustedTests != null) {
+            curReqParms += "&trustedTests=" + trustedTests;
+        }
+
+        return curReqParms;
+    }
+
+    function checkForUpdate() {
+        var curFailuresUrl = "rest/tracked/updates" + parmsForRest();
+
+        $.ajax({
+            url: curFailuresUrl,
+            success: function (result) {
+                if (g_shownDataHashCodeHex !== "" && 
isDefinedAndFilled(result.hashCodeHex)) {
+                    if (g_shownDataHashCodeHex === result.hashCodeHex) {
+                        var fastCheckNeeded = 
isDefinedAndFilled(result.runningUpdates) && result.runningUpdates > 0;
+                        var ms = fastCheckNeeded ? 3000 : 30000;
+
+                        setTimeout(checkForUpdate, ms);
+
+                        $("#loadStatus").html("");
+                    } else {
+                        loadData(); // data changed, show new
+                    }
+                } else {
+                    loadData();
+                }
+            },
+            error: showErrInLoadStatus
+        });
+    }
+
+    function loadData() {
+        var curFailuresUrl = "rest/tracked/results" + parmsForRest();
+
+        $("#loadStatus").html("<img 
src='https://www.wallies.com/filebin/images/loading_apple.gif' width=20px 
height=20px> Please wait");
+        setTimeout(loadPartialData, 3000);
+
+        $.ajax({
+            url: curFailuresUrl,
+            success: function (result) {
+                if (isDefinedAndFilled(result.runningUpdates) && 
result.runningUpdates > 0) {
+                    setTimeout(checkForUpdate, 3000);
+
+                    $("#loadStatus").html("<img 
src='https://www.wallies.com/filebin/images/loading_apple.gif' width=20px 
height=20px> Updating");
+                } else {
+                    $("#loadStatus").html("");
+                }
+                showData(result);
+                g_shownDataHashCodeHex = 
isDefinedAndFilled(result.hashCodeHex) ? result.hashCodeHex : "";
+            },
+            error: showErrInLoadStatus
+        });
+    }
+
+    function loadPartialData() {
+        var curFailuresUrl = "rest/tracked/resultsNoSync" + parmsForRest();
+
+        if (g_shownDataHashCodeHex !== "") {
+            return;
+        }
+        $.ajax({
+            url: curFailuresUrl,
+            success: function (result) {
+                if (g_shownDataHashCodeHex !== "") {
+                    return;
+                }
+
+                var validResult = true;
+                for (var i = 0; i < result.servers.length; i++) {
+                    var server = result.servers[i];
+
+                    if (isDefinedAndFilled(server.buildNotFound) && 
server.buildNotFound) {
+                        validResult = false;
+                        break;
+                    }
+                }
+                if (validResult)
+                    showData(result);
+
+                setTimeout(loadPartialData, 3000);
+            },
+            error: showErrInLoadStatus
+        });
+    }
+
+    function showData(result) {
+        //var txtUrl = "rest/tracked/results/txt" + parmsForRest();
+
+        $("#divFailures").html(showChainOnServersResults(result));
+        //        + " <a href='"+ txtUrl + "'>txt</a>");
+    }
+
+</script>
+
+<div id="loadStatus"></div>
+<div id="vueQueryForm" class="h-25">
+    <v-app id="queryForm" class="h-25">
+        <select v-model="baseBranchSelected" @change="formChanged">
+            <option disabled value="">Please select one</option>
+            <option>A</option>
+            <option>B</option>
+            <option>C</option>
+        </select>
+        <span>Base branch: {{ baseBranchSelected }}</span>
+    </v-app>
+</div>
+<div id="divFailures"></div>
+
+<div id="version"></div>
+<div style="visibility:hidden;"><div id="triggerConfirm" title="Trigger 
Confirmation"></div><div id="triggerDialog" title="Trigger Result"></div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/webapp/visas.html 
b/ignite-tc-helper-web/src/main/webapp/visas.html
index 7fb062a..028b4bb 100644
--- a/ignite-tc-helper-web/src/main/webapp/visas.html
+++ b/ignite-tc-helper-web/src/main/webapp/visas.html
@@ -32,6 +32,7 @@
                 <th>.</th>
                 <th>.</th>
                 <th>.</th>
+                <th>.</th>
             </tr>
         </thead>
     </table>
@@ -139,6 +140,10 @@ function showVisasTable(result) {
                 title: "Branch"
             },
             {
+                "data": "baseBranchForTc",
+                title: "Base Branch"
+            },
+            {
                 "data": "ticket",
                 title: "Ticket"
             },
diff --git 
a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
 
b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
index d4e93f6..23c69fe 100644
--- 
a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
+++ 
b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessorTest.java
@@ -30,6 +30,7 @@ import java.util.function.Predicate;
 
 import org.apache.ignite.tcbot.common.TcBotConst;
 import org.apache.ignite.tcbot.engine.pr.PrChainsProcessor;
+import org.apache.ignite.tcignited.SyncMode;
 import org.apache.ignite.tcservice.ITeamcity;
 import org.apache.ignite.tcservice.model.conf.BuildType;
 import org.apache.ignite.tcservice.model.hist.BuildRef;
@@ -42,7 +43,6 @@ import org.apache.ignite.tcbot.persistence.IStringCompactor;
 import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedProviderMock;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
-import org.apache.ignite.ci.teamcity.ignited.runhist.InvocationData;
 import org.apache.ignite.ci.user.ITcBotUserCreds;
 import org.apache.ignite.tcbot.engine.ui.DsSuiteUi;
 import org.apache.ignite.tcbot.engine.ui.DsTestFailureUi;
@@ -117,8 +117,7 @@ public class PrChainsProcessorTest {
         initBuildChainAndMasterHistory(c, btId, branch);
 
         PrChainsProcessor prcp = injector.getInstance(PrChainsProcessor.class);
-        final List<DsSuiteUi> blockers = prcp.getBlockersSuitesStatuses(btId,
-            branch, SRV_ID, mock(ITcBotUserCreds.class));
+        final List<DsSuiteUi> blockers = prcp.getBlockersSuitesStatuses(btId, 
branch, SRV_ID, mock(ITcBotUserCreds.class), SyncMode.RELOAD_QUEUED, null);
 
         System.out.println(blockers);
         assertNotNull(blockers);
@@ -164,8 +163,7 @@ public class PrChainsProcessorTest {
         initHistory(c);
 
         PrChainsProcessor prcp = injector.getInstance(PrChainsProcessor.class);
-        final List<DsSuiteUi> blockers = prcp.getBlockersSuitesStatuses(btId,
-            branch, SRV_ID, mock(ITcBotUserCreds.class));
+        final List<DsSuiteUi> blockers = prcp.getBlockersSuitesStatuses(btId, 
branch, SRV_ID, mock(ITcBotUserCreds.class), SyncMode.RELOAD_QUEUED, null);
 
         System.out.println(blockers);
 
@@ -442,7 +440,7 @@ public class PrChainsProcessorTest {
 
         PrChainsProcessor prcp = injector.getInstance(PrChainsProcessor.class);
 
-        final List<DsSuiteUi> blockers = prcp.getBlockersSuitesStatuses(btId, 
branch, SRV_ID, mock(ITcBotUserCreds.class));
+        final List<DsSuiteUi> blockers = prcp.getBlockersSuitesStatuses(btId, 
branch, SRV_ID, mock(ITcBotUserCreds.class), SyncMode.RELOAD_QUEUED, null);
 
         System.out.println(blockers);
 
diff --git 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/TcBotJsonConfig.java
 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/TcBotJsonConfig.java
index ed29560..818ba5a 100644
--- 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/TcBotJsonConfig.java
+++ 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/conf/TcBotJsonConfig.java
@@ -20,6 +20,7 @@ package org.apache.ignite.tcbot.engine.conf;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -83,15 +84,15 @@ public class TcBotJsonConfig implements 
ITrackedBranchesConfig {
     }
 
     public Optional<TcServerConfig> getTcConfig(String code) {
-        return tcServers.stream().filter(s -> 
code.equals(s.getCode())).findAny();
+        return tcServers.stream().filter(s -> Objects.equals(code, 
s.getCode())).findAny();
     }
 
     public Optional<JiraServerConfig> getJiraConfig(String code) {
-        return jiraServers.stream().filter(s -> 
code.equals(s.getCode())).findAny();
+        return jiraServers.stream().filter(s -> Objects.equals(code, 
s.getCode())).findAny();
     }
 
     public Optional<GitHubConfig> getGitHubConfig(String code) {
-        return gitHubConfigs.stream().filter(s -> 
code.equals(s.code())).findAny();
+        return gitHubConfigs.stream().filter(s -> Objects.equals(code, 
s.getCode())).findAny();
     }
 
     @Nullable
diff --git 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
index e60aea1..8c1640e 100644
--- 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
+++ 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
@@ -19,6 +19,7 @@ package org.apache.ignite.tcbot.engine.pr;
 import com.google.common.base.Strings;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 import javax.annotation.Nullable;
@@ -35,6 +36,9 @@ import org.apache.ignite.tcbot.engine.chain.FullChainRunCtx;
 import org.apache.ignite.tcbot.engine.chain.LatestRebuildMode;
 import org.apache.ignite.tcbot.engine.chain.ProcessLogsMode;
 import org.apache.ignite.tcbot.engine.chain.TestCompactedMult;
+import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
+import org.apache.ignite.tcbot.engine.conf.ITrackedBranch;
+import org.apache.ignite.tcbot.engine.conf.ITrackedChain;
 import org.apache.ignite.tcbot.engine.ui.DsChainUi;
 import org.apache.ignite.tcbot.engine.ui.DsSuiteUi;
 import org.apache.ignite.tcbot.engine.ui.DsSummaryUi;
@@ -74,14 +78,16 @@ public class PrChainsProcessor {
 
     @Inject private IStringCompactor compactor;
 
+    @Inject private ITcBotConfig cfg;
+
     /**
      * @param creds Credentials.
-     * @param srvCode Server id.
+     * @param srvCodeOrAlias Server code or alias.
      * @param suiteId Suite id.
      * @param branchForTc Branch name in TC identification.
      * @param act Action.
      * @param cnt Count.
-     * @param baseBranchForTc Base branch name in TC identification.
+    * @param tcBaseBranchParm Base branch name in TC identification.
      * @param checkAllLogs Check all logs
      * @param mode TC Server Sync Mode
      * @return Test failures summary.
@@ -89,23 +95,22 @@ public class PrChainsProcessor {
     @AutoProfiling
     public DsSummaryUi getTestFailuresSummary(
         ICredentialsProv creds,
-        String srvCode,
+        String srvCodeOrAlias,
         String suiteId,
         String branchForTc,
         String act,
         Integer cnt,
-        @Nullable String baseBranchForTc,
+        @Nullable String tcBaseBranchParm,
         @Nullable Boolean checkAllLogs,
         SyncMode mode) {
         final DsSummaryUi res = new DsSummaryUi();
         final AtomicInteger runningUpdates = new AtomicInteger();
 
-        //using here non persistent TC allows to skip update statistic
-        ITeamcityIgnited tcIgnited = tcIgnitedProvider.server(srvCode, creds);
+        ITeamcityIgnited tcIgnited = tcIgnitedProvider.server(srvCodeOrAlias, 
creds);
 
-        IGitHubConnIgnited gitHubConnIgnited = 
gitHubConnIgnitedProvider.server(srvCode);
+        IGitHubConnIgnited gitHubConnIgnited = 
gitHubConnIgnitedProvider.server(srvCodeOrAlias);
 
-        IJiraIgnited jiraIntegration = jiraIgnProv.server(srvCode);
+        IJiraIgnited jiraIntegration = jiraIgnProv.server(srvCodeOrAlias);
 
         res.setJavaFlags(gitHubConnIgnited.config(), jiraIntegration.config());
 
@@ -133,7 +138,7 @@ public class PrChainsProcessor {
 
         List<Integer> hist = tcIgnited.getLastNBuildsFromHistory(suiteId, 
branchForTc, buildResMergeCnt);
 
-        String baseBranch = Strings.isNullOrEmpty(baseBranchForTc) ? 
ITeamcity.DEFAULT : baseBranchForTc;
+        String baseBranchForTc = Strings.isNullOrEmpty(tcBaseBranchParm) ? 
dfltBaseTcBranch(tcIgnited) : tcBaseBranchParm;
 
         FullChainRunCtx ctx = buildChainProcessor.loadFullChainContext(
             tcIgnited,
@@ -141,12 +146,12 @@ public class PrChainsProcessor {
             rebuild,
             logs,
             buildResMergeCnt == 1,
-            baseBranch,
+            baseBranchForTc,
             mode);
 
-        DsChainUi chainStatus = new DsChainUi(srvCode, tcIgnited.serverCode(), 
branchForTc);
+        DsChainUi chainStatus = new DsChainUi(srvCodeOrAlias, 
tcIgnited.serverCode(), branchForTc);
 
-        chainStatus.baseBranchForTc = baseBranch;
+        chainStatus.baseBranchForTc = baseBranchForTc;
 
         if (ctx.isFakeStub())
             chainStatus.setBuildNotFound(true);
@@ -157,7 +162,7 @@ public class PrChainsProcessor {
                 runningUpdates.addAndGet(cnt0);
 
             //fail rate reference is always default (master)
-            chainStatus.initFromContext(tcIgnited, ctx, baseBranch, compactor, 
false); // don't need for PR
+            chainStatus.initFromContext(tcIgnited, ctx, baseBranchForTc, 
compactor, false); // don't need for PR
 
             initJiraAndGitInfo(chainStatus, jiraIntegration, 
gitHubConnIgnited);
         }
@@ -170,6 +175,26 @@ public class PrChainsProcessor {
     }
 
     /**
+     * Gets deafault TC identified base (reference) branch
+     * @param tcIgnited Tc ignited.
+     */
+    public String dfltBaseTcBranch(ITeamcityIgnited tcIgnited) {
+        String dfltTrackedBranch = tcIgnited.config().defaultTrackedBranch();
+        Optional<ITrackedBranch> branch = 
cfg.getTrackedBranches().get(dfltTrackedBranch);
+
+        if(!branch.isPresent())
+            return ITeamcity.DEFAULT;
+
+        Optional<ITrackedChain> chainAtSrv = 
branch.get().chainsStream().filter(chain ->
+            Objects.equals(chain.serverCode(), 
tcIgnited.serverCode())).findAny();
+
+        if (!chainAtSrv.isPresent())
+            return ITeamcity.DEFAULT;
+
+        return chainAtSrv.get().tcBranch();
+    }
+
+    /**
      * Set up ticket and PR related information.
      *  @param chainStatus Ticket matcher.
      * @param jiraIntegration Jira integration.
@@ -214,24 +239,24 @@ public class PrChainsProcessor {
      * @param branchForTc Branch for TeamCity.
      * @param srvId Server id.
      * @param prov Credentials.
+     * @param syncMode
+     * @param baseBranchForTc
      * @return List of suites with possible blockers.
      */
-    @Nullable public List<DsSuiteUi> getBlockersSuitesStatuses(String 
buildTypeId,
-                                                               String 
branchForTc,
-                                                               String srvId,
-                                                               
ICredentialsProv prov) {
-        return getBlockersSuitesStatuses(buildTypeId, branchForTc, srvId, 
prov, SyncMode.RELOAD_QUEUED);
-    }
-
     @Nullable
-    public List<DsSuiteUi> getBlockersSuitesStatuses(String buildTypeId, 
String branchForTc, String srvId,
-                                                     ICredentialsProv prov, 
SyncMode syncMode) {
+    public List<DsSuiteUi> getBlockersSuitesStatuses(
+        String buildTypeId,
+        String branchForTc,
+        String srvId,
+        ICredentialsProv prov,
+        SyncMode syncMode,
+        @Nullable String baseBranchForTc) {
         //using here non persistent TC allows to skip update statistic
         ITeamcityIgnited tcIgnited = tcIgnitedProvider.server(srvId, prov);
 
         List<Integer> hist = tcIgnited.getLastNBuildsFromHistory(buildTypeId, 
branchForTc, 1);
 
-        String baseBranch = ITeamcity.DEFAULT;
+        String baseBranch = Strings.isNullOrEmpty(baseBranchForTc) ? 
dfltBaseTcBranch(tcIgnited) : baseBranchForTc;
 
         FullChainRunCtx ctx = buildChainProcessor.loadFullChainContext(
             tcIgnited,
diff --git 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/tracked/IDetailedStatusForTrackedBranch.java
 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/tracked/IDetailedStatusForTrackedBranch.java
index b0bd425..8b9372c 100644
--- 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/tracked/IDetailedStatusForTrackedBranch.java
+++ 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/tracked/IDetailedStatusForTrackedBranch.java
@@ -40,4 +40,6 @@ public interface IDetailedStatusForTrackedBranch {
         ICredentialsProv creds,
         SyncMode syncMode,
         boolean calcTrustedTests);
+
+    //  * @param baseTrackedBranch Branch tracked branch in Bot, has a 
priority if both TC & Bot branches (baseBranchForTcParm) present.
 }
diff --git 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
index a0e191a..a6904c7 100644
--- 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
+++ 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
@@ -54,10 +54,13 @@ public class DsChainUi {
     @Deprecated
     public final String serverId;
 
-    /** General server (service) code: JIRA, GH, TC. But if TC aliased {@link 
#tcServerCode} is used for TC. */
+    /**
+     * General server (service) code: JIRA, GH, TC. But if TC aliased {@link 
#tcServerCode} is used for TC.
+     * Should be used for triggering, where JIRA is involved.
+     */
     public final String serverCode;
 
-    /** Teamcity connection server (service) code. Same with {@link 
#serverCode} */
+    /** Teamcity connection server (service) code. Same with {@link 
#serverCode} in case aliases not used. */
     public final String tcServerCode;
 
     /** Branch name in teamcity identification. */
@@ -307,8 +310,9 @@ public class DsChainUi {
             logConsumers, buildNotFound, baseBranchForTc);
     }
 
-    public void setBuildNotFound(boolean buildNotFound) {
+    public DsChainUi setBuildNotFound(boolean buildNotFound) {
         this.buildNotFound = buildNotFound;
+        return this;
     }
 
     /** {@inheritDoc} */
diff --git 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsSummaryUi.java 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsSummaryUi.java
index 8c23f54..0a6cd24 100644
--- 
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsSummaryUi.java
+++ 
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsSummaryUi.java
@@ -43,7 +43,7 @@ public class DsSummaryUi extends UpdateInfo {
     @Nullable
     private String trackedBranch;
 
-    public void addChainOnServer(DsChainUi chainStatus) {
+    public DsSummaryUi addChainOnServer(DsChainUi chainStatus) {
         servers.add(chainStatus);
 
         if (chainStatus.failedToFinish != null) {
@@ -59,6 +59,8 @@ public class DsSummaryUi extends UpdateInfo {
 
             failedTests += chainStatus.failedTests;
         }
+
+        return this;
     }
 
     public void postProcess(int running) {

Reply via email to